--[[ $%BEGINLICENSE%$
 Copyright (c) 2007, 2008, 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%$ --]]

local tokenizer    = require("proxy.tokenizer")
local parser       = require("proxy.parser")
local commands     = require("proxy.commands")
local auto_config  = require("proxy.auto-config")

-- init global counters

if not proxy.global.config.histogram then
    proxy.global.config.histogram = {
        collect_queries = true,
        collect_tables = true
    }
end

-- init query counters
if not proxy.global.norm_queries then
    proxy.global.norm_queries = { }
end

-- init table-usage
if not proxy.global.tables then
    proxy.global.tables = { }
end

function read_query(packet)
    local cmd = commands.parse(packet)

    local r = auto_config.handle(cmd)
    if r then return r end

    if cmd.type == proxy.COM_QUERY then
        local tokens     = assert(tokenizer.tokenize(cmd.query))
        local norm_query = tokenizer.normalize(tokens)

        -- print("normalized query: " .. norm_query)

        if norm_query == "SELECT * FROM `histogram` . `queries` " then
            proxy.response = {
                type = proxy.MYSQLD_PACKET_OK,
                resultset = {
                    fields = { 
                        { type = proxy.MYSQL_TYPE_STRING,
                          name = "query" },
                        { type = proxy.MYSQL_TYPE_LONG,
                          name = "count" },
                        { type = proxy.MYSQL_TYPE_LONG,
                          name = "max_query_time" },
                        { type = proxy.MYSQL_TYPE_FLOAT,
                          name = "avg_query_time" },
                    }
                }
            }

            local rows = {}
            if proxy.global.norm_queries then
                for k, v in pairs(proxy.global.norm_queries) do
                    rows[#rows + 1] = { 
                        k, 
                        v.count,
                        v.max_query_time,
                        v.avg_query_time,
                    }
                end
            end
            
            proxy.response.resultset.rows = rows

            return proxy.PROXY_SEND_RESULT
        elseif norm_query == "DELETE FROM `histogram` . `queries` " then
            proxy.response = {
                type = proxy.MYSQLD_PACKET_OK,
            }

            proxy.global.norm_queries = {}
            return proxy.PROXY_SEND_RESULT
        elseif norm_query == "SELECT * FROM `histogram` . `tables` " then
            proxy.response = {
                type = proxy.MYSQLD_PACKET_OK,
                resultset = {
                    fields = { 
                        { type = proxy.MYSQL_TYPE_STRING,
                          name = "table" },
                        { type = proxy.MYSQL_TYPE_LONG,
                          name = "reads" },
                        { type = proxy.MYSQL_TYPE_LONG,
                          name = "writes" },
                      }
                }
            }

            local rows = {}
            if proxy.global.tables then
                for k, v in pairs(proxy.global.tables) do
                    rows[#rows + 1] = { 
                        k, 
                        v.reads,
                        v.writes,
                    }
                end
            end
            
            proxy.response.resultset.rows = rows

            return proxy.PROXY_SEND_RESULT
        elseif norm_query == "DELETE FROM `histogram` . `tables` " then
            proxy.response = {
                type = proxy.MYSQLD_PACKET_OK,
            }

            proxy.global.tables = {}
            return proxy.PROXY_SEND_RESULT
        end

        if proxy.global.config.histogram.collect_queries or
           proxy.global.config.histogram.collect_tables then
            proxy.queries:append(1, packet)

            return proxy.PROXY_SEND_QUERY
        end
    end
end

function read_query_result(inj) 
    local cmd = commands.parse(inj.query)

    if cmd.type == proxy.COM_QUERY then
        local tokens     = assert(tokenizer.tokenize(cmd.query))
        local norm_query = tokenizer.normalize(tokens)

        if proxy.global.config.histogram.collect_queries then
            if not proxy.global.norm_queries[norm_query] then
                proxy.global.norm_queries[norm_query] = {
                    count = 0,
                    max_query_time = 0,
                    avg_query_time = 0
                }
            end
    
            -- set new max if necessary
            if inj.query_time > proxy.global.norm_queries[norm_query].max_query_time then
                proxy.global.norm_queries[norm_query].max_query_time = inj.query_time
            end
    
            -- build rolling average
            proxy.global.norm_queries[norm_query].avg_query_time = 
                ((proxy.global.norm_queries[norm_query].avg_query_time * proxy.global.norm_queries[norm_query].count) +
                    inj.query_time) / (proxy.global.norm_queries[norm_query].count + 1)
            
            proxy.global.norm_queries[norm_query].count = proxy.global.norm_queries[norm_query].count + 1
        end
    
        if proxy.global.config.histogram.collect_tables then
            -- extract the tables from the queries
            tables = parser.get_tables(tokens)
    
            for table, qtype in pairs(tables) do
                if not proxy.global.tables[table] then
                    proxy.global.tables[table] = {
                        reads = 0,
                        writes = 0
                    }
                end
    
                if qtype == "read" then
                    proxy.global.tables[table].reads = proxy.global.tables[table].reads + 1
                else
                    proxy.global.tables[table].writes = proxy.global.tables[table].writes + 1
                end
            end
        end
    end
end
