--[[ $%BEGINLICENSE%$
 Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.

 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., 51 Franklin St, Fifth Floor, Boston, MA
 02110-1301  USA

 $%ENDLICENSE%$ --]]

module("proxy.commands", package.seeall)

---
-- map the constants to strings 
-- lua starts at 1
local command_names = {
	"COM_SLEEP",
	"COM_QUIT",
	"COM_INIT_DB",
	"COM_QUERY",
	"COM_FIELD_LIST",
	"COM_CREATE_DB",
	"COM_DROP_DB",
	"COM_REFRESH",
	"COM_SHUTDOWN",
	"COM_STATISTICS",
	"COM_PROCESS_INFO",
	"COM_CONNECT",
	"COM_PROCESS_KILL",
	"COM_DEBUG",
	"COM_PING",
	"COM_TIME",
	"COM_DELAYED_INSERT",
	"COM_CHANGE_USER",
	"COM_BINLOG_DUMP",
	"COM_TABLE_DUMP",
	"COM_CONNECT_OUT",
	"COM_REGISTER_SLAVE",
	"COM_STMT_PREPARE",
	"COM_STMT_EXECUTE",
	"COM_STMT_SEND_LONG_DATA",
	"COM_STMT_CLOSE",
	"COM_STMT_RESET",
	"COM_SET_OPTION",
	"COM_STMT_FETCH",
	"COM_DAEMON",
	"COM_BINLOG_DUMP"
}

---
-- split a MySQL command packet into its parts
--
-- @param packet a network packet
-- @return a table with .type, .type_name and command specific fields 
function parse(packet)
	local cmd = {}

	cmd.type = packet:byte()
	cmd.type_name = command_names[cmd.type + 1]
	
	if cmd.type == proxy.COM_QUERY then
		cmd.query = packet:sub(2)
	elseif cmd.type == proxy.COM_QUIT or
	       cmd.type == proxy.COM_PING or
	       cmd.type == proxy.COM_SHUTDOWN then
		-- nothing to decode
	elseif cmd.type == proxy.COM_STMT_PREPARE then
		cmd.query = packet:sub(2)
	-- the stmt_handler_id is at the same position for both STMT_EXECUTE and STMT_CLOSE
	elseif cmd.type == proxy.COM_STMT_EXECUTE or cmd.type == proxy.COM_STMT_CLOSE then
		cmd.stmt_handler_id = string.byte(packet, 2) + (string.byte(packet, 3) * 256) + (string.byte(packet, 4) * 256 * 256) + (string.byte(packet, 5) * 256 * 256 * 256)
	elseif cmd.type == proxy.COM_FIELD_LIST then
		cmd.table = packet:sub(2)
	elseif cmd.type == proxy.COM_INIT_DB or
	       cmd.type == proxy.COM_CREATE_DB or
	       cmd.type == proxy.COM_DROP_DB then
		cmd.schema = packet:sub(2)
	elseif cmd.type == proxy.COM_SET_OPTION then
		cmd.option = packet:sub(2)
	elseif cmd.type == proxy.COM_BINLOG_DUMP then
		-- nothing to decode
	else
		print("[debug] (command) unhandled type name:" .. tostring(cmd.type_name) .. " byte:" .. tostring(cmd.type))
	end

	return cmd
end

function pretty_print(cmd)
	if cmd.type == proxy.COM_QUERY or
	   cmd.type == proxy.COM_STMT_PREPARE then
		return ("[%s] %s"):format(cmd.type_name, cmd.query)
	elseif cmd.type == proxy.COM_INIT_DB then
		return ("[%s] %s"):format(cmd.type_name, cmd.schema)
	elseif cmd.type == proxy.COM_QUIT or
	       cmd.type == proxy.COM_PING or
	       cmd.type == proxy.COM_SHUTDOWN then
		return ("[%s]"):format(cmd.type_name)
	elseif cmd.type == proxy.COM_FIELD_LIST then
		-- should have a table-name
		return ("[%s]"):format(cmd.type_name)
	elseif cmd.type == proxy.COM_STMT_EXECUTE then
		return ("[%s] %s"):format(cmd.type_name, cmd.stmt_handler_id)
	end

	return ("[%s] ... no idea"):format(cmd.type_name)
end

