Created
January 31, 2015 03:33
-
-
Save fmpwizard/61b9c4091c5b355be82a to your computer and use it in GitHub Desktop.
mysql proxy lua file database key value store with replication
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ $%BEGINLICENSE%$ | |
Copyright (C) 2009 MySQL AB, 2009 Sun Microsystems, Inc | |
This program is free software; you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation; version 2 of the License. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program; if not, write to the Free Software | |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
$%ENDLICENSE%$ --]] | |
-- Updated with emulation of mysql server | |
-- To make query parsing easier | |
local tokenizer = require("proxy.tokenizer") | |
-- We assign the value of the same table to itself | |
-- or initialize it if not existent | |
proxy.global.db = proxy.global.db or {} | |
--[[ ====================================================================== ]]-- | |
function packet_auth(fields) | |
fields = fields or { } | |
return "\010" .. -- proto version | |
(fields.version or "5.0.45-proxy") .. -- version | |
"\000" .. -- term-null | |
"\001\000\000\000" .. -- thread-id | |
"\065\065\065\065" .. | |
"\065\065\065\065" .. -- challenge - part I | |
"\000" .. -- filler | |
"\001\130" .. -- server cap (long pass, 4.1 proto) | |
"\008" .. -- charset | |
"\002\000" .. -- status | |
("\000"):rep(13) .. -- filler | |
"\065\065\065\065".. | |
"\065\065\065\065".. | |
"\065\065\065\065".. | |
"\000" -- challenge - part II | |
end | |
--[[ ====================================================================== ]]-- | |
function connect_server() | |
-- emulate a server | |
proxy.response = { | |
type = proxy.MYSQLD_PACKET_RAW, | |
packets = { | |
packet_auth() | |
} | |
} | |
return proxy.PROXY_SEND_RESULT | |
end | |
--[[ ====================================================================== ]]-- | |
function read_query( packet ) | |
if string.byte(packet) == proxy.COM_QUERY then | |
-- We tokenize the query | |
local tokens = tokenizer.tokenize(packet:sub(2)) | |
-- We loop over the query | |
for i = 1, #tokens do | |
-- print the token and what we know about it | |
local token = tokens[i] | |
-- print(i .. ": " .. " { " .. token["token_name"] .. ", " .. token["text"] .. " }" ) | |
-- Based on the tokens we find, do something | |
if token["token_name"] == 'TK_SQL_SELECT' | |
and tokens[i + 1]["token_name"] == 'TK_STAR' then | |
return show_all() | |
elseif token["token_name"] == 'TK_SQL_SELECT' then | |
-- we pass the text of the next token | |
return get(tokens[i + 1]["text"]) | |
elseif token["token_name"] == 'TK_SQL_INSERT' then | |
-- we pass the text of the next token and we skip | |
-- the equal sign | |
return add(tokens[i + 1]["text"], tokens[i + 3]["text"]) | |
elseif token["token_name"] == 'TK_SQL_DELETE' then | |
-- we pass the text of the next token | |
return delete(tokens[i + 1]["text"]) | |
elseif token["token_name"] == 'TK_SQL_DROP' then | |
-- TK_SQL_TRUNCATE does not exist (need to file a bug on it) | |
-- We do not need any parameter for this one | |
return truncate() | |
else | |
-- Unkown query | |
return error_result ( | |
"I haven't learnt how to handle that query" | |
, '101' | |
, '!101') | |
end | |
end | |
end | |
end -- End of read_query() | |
--[[ ====================================================================== ]]-- | |
function error_result (msg, code, state) | |
proxy.response = { | |
type = proxy.MYSQLD_PACKET_ERR, | |
errmsg = msg, | |
errcode = code, | |
sqlstate = state, | |
} | |
return proxy.PROXY_SEND_RESULT | |
end | |
--[[ ====================================================================== ]]-- | |
function get( key ) | |
-- if the key is not found, return an error | |
if proxy.global.db[key] == nil then | |
return error_result( | |
'No value found for key "' .. key .. '"' , -- error message | |
100, -- error code | |
'!100' -- SQL state | |
) | |
end | |
proxy.response.type = proxy.MYSQLD_PACKET_OK | |
proxy.response.resultset = { | |
fields = { | |
{ type = proxy.MYSQL_TYPE_STRING, name = "key", }, | |
{ type = proxy.MYSQL_TYPE_STRING, name = "value", } | |
}, | |
rows = {} | |
} | |
-- Add the result to a nice mysql resulset | |
table.insert( | |
proxy.response.resultset.rows, | |
{ key , proxy.global.db[key] }) | |
return proxy.PROXY_SEND_RESULT | |
end | |
--[[ ====================================================================== ]]-- | |
function add( key, value ) | |
-- We add the key value pair to the global table | |
proxy.global.db[key] = value | |
-- we return a nice "affected rows count" | |
proxy.response.type = proxy.MYSQLD_PACKET_OK | |
proxy.response.affected_rows = 1 | |
proxy.response.insert_id = 0 | |
return proxy.PROXY_SEND_RESULT | |
end | |
--[[ ====================================================================== ]]-- | |
function show_all() | |
-- the more key => value pairs you have, the slower this | |
-- will be | |
-- * Values are not retrieved on the same order they were inserted | |
proxy.response.type = proxy.MYSQLD_PACKET_OK | |
proxy.response.resultset = { | |
fields = { | |
{ type = proxy.MYSQL_TYPE_STRING, name = "key", }, | |
{ type = proxy.MYSQL_TYPE_STRING, name = "value", } | |
}, | |
rows = {} | |
} | |
for k,v in pairs(proxy.global.db) do | |
table.insert( | |
proxy.response.resultset.rows, | |
{ k , v }) | |
end | |
return proxy.PROXY_SEND_RESULT | |
end | |
--[[ ====================================================================== ]]-- | |
function truncate() | |
-- simple way to truncate the table | |
proxy.global.db = {} | |
-- we return a nice "affected rows count" | |
proxy.response.type = proxy.MYSQLD_PACKET_OK | |
proxy.response.affected_rows = 0 | |
proxy.response.insert_id = 0 | |
return proxy.PROXY_SEND_RESULT | |
end | |
--[[ ====================================================================== ]]-- | |
function delete( key ) | |
-- using table.remove only works with numeric indexes :( | |
proxy.global.db[key] = nil | |
-- we return a nice "affected rows count" | |
proxy.response.type = proxy.MYSQLD_PACKET_OK | |
proxy.response.affected_rows = 1 | |
proxy.response.insert_id = 0 | |
return proxy.PROXY_SEND_RESULT | |
end | |
--[[ ====================================================================== ]]-- | |
--[[ | |
How to use: | |
It supports 3 types of queries | |
mysql> INSERT "key" = "value"; | |
mysql> SELECT "key"; | |
mysql> DELETE "key"; | |
mysql> SELECT *; | |
mysql> DROP; | |
--]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment