Raised This Month: $114 Target: $400
 28% 

SQL Connection Manager


Post New Thread Reply   
 
Thread Tools Display Modes
Plugin Info:     Modification:   ALL        Category:   Technical/Development        Approver:   ConnorMcLeod (74)
Zefir
Member
Join Date: Oct 2007
Location: Kiev, Ukraine
Old 04-18-2011 , 14:53   SQL Connection Manager
Reply With Quote #1

SQL Connection Manager
version 1.0
by Zefir

SQL Manager (sqlm) although an amxx plugin, but by itself does not perform any visible action. It is a library providing a more convenient functionality for working with SQL servers.

The main purpose of this plugin, it automatically reconnects when disconnected, and the ability to transparently work with several drivers databases.

Description

In sqlm no concept of connection. There is a connection tuple, keeps all the necessary data. The connection is created and updated as necessary. Handle queries are used as usual.

All functions except running's handle, work only with the name of the tuple.

Include sqlm.inc to use this plugin. Required constants from sql_manager.inc will be included automatically.

Depends (Required)
  • Modules
    • sqlx
    • vdf
    • fakemeta
  • Library
    • hashx.inc
    • bits.inc
    • text.inc

API

When connecting to or after the restoration of communication at breakage, called forward sqlm_connection_established function receives as a parameter the name of the raised tuple and name of the driver (mysql or sqlite …).

Forward
  • sqlm_connection_established(tuple[], driver[])
    - Forward function is called when you first connect to the database or after the break when the connection is restored.

Native
  • sqlm_affected_rows(Handle:query);
    - Returns the number of affected rows.
  • bool:sqlm_connected(tuple[] = "default");
    - Returns state of connection.
  • sqlm_exec(Handle:query);
    - Execute a query prepared function .
  • sqlm_field_name_to_num(Handle:query, const name[]);
    - Returns the field number by name in the result set.
  • sqlm_field_num_to_name(Handle:query, num, name[], maxlen);
    - Returns the name of the field by its number in the resulting query.
  • sqlm_free_handle(Handle:query);
    - Releases the handle to the query.
  • sqlm_get_insert_id(Handle:query);
    - Returns the ID of the last inserted row. Used mainly when working with MySQL databases.
  • sqlm_get_query_string(Handle:query, querystring[], maxlen);
    - Returns the original query string for a handle.
  • sqlm_is_null(Handle:query, column);
    - Tells whether a specific column in the current row is NULL or not
  • sqlm_more_results(Handle:query);
    - Returns true if the result is still unread row
  • bool:sqlm_next_row(Handle:query);
    - Checks for available lines in the data set, and if reading the next one.
  • sqlm_num_columns(Handle:query);
    - Returns number of fields in the dataset.
  • sqlm_num_results(Handle:query);
    - Returns the total number of resulting rows.
  • Handle:sqlm_prepare_query(const tuple[SQL_NAME], const fmt[], {Float,_}:...);
    - The function prepares a synchronous request to run.
  • sqlm_query_error(Handle:query, error[], maxlen);
    - Returns the last database driver error
  • sqlm_quote_string(const tuple[SQL_NAME], buffer[], buflen, const fmt[], {Float,_}:...);
    - Escapes a string according to the rules database.
  • sqlm_read_result(Handle:query, column, {Float,_}:...);
    - Reads the value of fields in the current row result set.
  • sqlm_simple_query(const tuple[SQL_NAME], const query_string[], {Float,_}:...);
    - The function sends the request and ignores the result of execution. Often used for logging, etc.
  • sqlm_simple_upd_ins(const tuple[SQL_NAME], const update_string[], const insert_string[]);
    - Assumes the existence of a processing line. Sends two requests, first to update a row, and the second to add, if such a line yet.
  • sqlm_thread_query(const tuple[SQL_NAME], const func[], const query_string[], data);
    - The function creates and sends an asynchronous request to the database. That is when a driver receives a response, it will call the specified function to which the answer will be given.


Configuration file

Configuration is stored in the file config/sql_manager.vdf format Valve Data Format. Tuple default if it does not, create based on standard parameters of sql.cfg.

Code:
"Servers"
{
    "default"
    {
        "type" "mysql"
        "host" "127.0.0.1"
        "db"  "amx"
        "user" "admin"
        "pass" "admin_pass"
        "timeout" "0.000"
        "autoconnect" "1"
    }
    "local"
    {
        "type" "sqlite"
        "host" ""
        "db"  "local"
        "user" ""
        "pass" ""
        "timeout" "0.000"
        "autoconnect" "1"
    }
    "remote"
    {
        "type" "mysql"
        "host" "example.tld"
        "db"  "remote_db"
        "user" "admin"
        "pass" "admin_pass"
        "timeout" "0.000"
        "autoconnect" "0"
    }
    "test"
    {
        "type" "mysql"
        "host" "example.tld"
        "db"  "test_db"
        "user" "admin"
        "pass" "admin_pass"
        "timeout" "0.000"
        "autoconnect" "-1"
    }

}
  • default, local, remote, test - random tuple names which are used for the treatment of plug-ins.
  • type - defines the driver used for the tuple. Available mysql and sqlite.
  • host, db, user, pass - as usual
  • timeout - corresponds to the same parameter for the function SQL _MakeDbTuple, and defines the connection timeout.
  • autoconnect - manages the restoration of connections:
    • -1: Allows you to disable unused profile without removing it from the file.
    • 0: the connection to demand. If the link is often broken, but it should be infrequent, for example, only when the map changes, it will not pull the connection constantly.
    • 1: a persistent connection. Disconnection and attempts to connect will always occur.

Debugging

These two constants in sql_manager.sma include debugging and tracing queries:

Code:
#define DEBUG
#define SQL_TRACE
Comment out their to disable debugging.

Statistics

Command sqlm_stats [tuple_name] will show the current state of tuple and statistics queries:

Code:
sqlm_stats db1

SQL Connection Manager, version 1.0, by Zefir
  Statistic for Tuple:............ 'db1'
    Direct Queries:...............  0
    Threaded Queries:.............  6
  Errors:
    Reconnect count:..............  0
    Error count:..................  1
    First Error:.................. (1) 'table 'nets' already exists'
    Last Error:................... (1) 'table 'nets' already exists'
Links

Libs:
Attached Files
File Type: gz sql_manager.tar.gz (7.6 KB, 241 views)
File Type: gz sql_manager_full.tar.gz (67.1 KB, 155 views)
File Type: zip sql_manager_full.zip (69.9 KB, 278 views)
__________________

Last edited by Zefir; 04-19-2011 at 16:16.
Zefir is offline
Send a message via ICQ to Zefir
Xalus
Veteran Member
Join Date: Dec 2009
Location: Belgium
Old 04-19-2011 , 05:19   Re: SQL Connection Manager
Reply With Quote #2

Upload .zip ;)
I don't know .tar.gz is allowed.
__________________
Retired.
Xalus is offline
Arkshine
AMX Mod X Plugin Approver
Join Date: Oct 2005
Old 04-19-2011 , 05:40   Re: SQL Connection Manager
Reply With Quote #3

Yes, ZIP should be used.

Btw, it's nice to see people making API.
__________________
Arkshine is offline
Zefir
Member
Join Date: Oct 2007
Location: Kiev, Ukraine
Old 04-19-2011 , 07:09   Re: SQL Connection Manager
Reply With Quote #4

Ok, .zip attached.

Arkshine, tnx
__________________
Zefir is offline
Send a message via ICQ to Zefir
abalad
Junior Member
Join Date: Oct 2010
Location: Parana-BR
Old 06-06-2011 , 00:59   Re: SQL Connection Manager
Reply With Quote #5

Friend would like to know how that works just fine this plugin since put him in vdf AutoConnect 1 as an option but when the server Cai and I turn again he does not carry the data bank. Only after the exchange of map data it can load the table.

Sorry for the english Google translator: D
abalad is offline
Send a message via MSN to abalad Send a message via Skype™ to abalad
Zefir
Member
Join Date: Oct 2007
Location: Kiev, Ukraine
Old 06-06-2011 , 01:45   Re: SQL Connection Manager
Reply With Quote #6

Hi, abalad!

Please show sqlm_stats 'db_name'.

Also enable debug and show log.
In source code, uncomment this string:
Code:
#define DEBUG
#define SQL_TRAC
and recompile library.

PS: And show your code, please
__________________

Last edited by Zefir; 06-06-2011 at 01:50.
Zefir is offline
Send a message via ICQ to Zefir
abalad
Junior Member
Join Date: Oct 2010
Location: Parana-BR
Old 06-06-2011 , 11:13   Re: SQL Connection Manager
Reply With Quote #7

Hello Friend. First thanks for Responding. I thought That Was Already in oFF TOPIC: D.

Friend put the command in the console Following by HLSW.

Yes friend got this in the console appeared to give me

SQL Connection Manager, version 1.0, by Zefir
Statistic for Tuple :............ 'default'
Direct Query :............... 0
Threaded Query :............. 0
Errors:
Reconnect count :.............. 0
Error count :.................. 0
First Error :.................. (0)''
Last Error :................... (0)''

But not itendi which the functionality of this command .. what good is it? What about the bug that had helped him?

Last edited by abalad; 06-06-2011 at 12:47.
abalad is offline
Send a message via MSN to abalad Send a message via Skype™ to abalad
Zefir
Member
Join Date: Oct 2007
Location: Kiev, Ukraine
Old 06-06-2011 , 18:01   Re: SQL Connection Manager
Reply With Quote #8

Hi, abalad!

Please show code of your plugin.
And show 'configs/sql_manager.vdf'
__________________
Zefir is offline
Send a message via ICQ to Zefir
abalad
Junior Member
Join Date: Oct 2010
Location: Parana-BR
Old 06-06-2011 , 18:12   Re: SQL Connection Manager
Reply With Quote #9

Hello friend look over the code vo te he ta mexi ORIGINAL not in it at all so I changed the line that you told me about SQL_TRAC.

PHP Code:
#pragma dynamic 16000

#include    <amxmisc>
#include    <sqlx>
#include    <hashx>
#include    <bits>
#include    <text>
#include    <vdf>
#include    <sql_manager>

#define PLUGIN "SQL Connection Manager"
#define VERSION "1.0"
#define AUTHOR "Zefir"

#define FLAG_CONNECTED        (1 << 0)
#define FLAG_RECONNECTING    (1 << 1)

#define DEBUG
#define SQL_TRACE

new bool:PLUGIN_END false

enum e_cvars 
{
    
amx_sql_host,
    
amx_sql_type,
    
amx_sql_db,
    
amx_sql_user,
    
amx_sql_pass
}
new 
pcvar[e_cvars]

//Tuples
enum e_SQLTuple {
    
tuple_flags,
    
tuple_name[SQL_NAME],
    
Handle:tuple_handle,
    
tuple_driver[SQL_NAME],
    
tuple_user[SQL_NAME],
    
tuple_pass[SQL_NAME],
    
tuple_host[SQL_HOST],
    
tuple_db[SQL_NAME],
    
tuple_timeout,
    
tuple_autoconnect,
    
//Connection
    
Handle:tuple_connect_handle,
    
// Statistics
    
tuple_Reconnected,
    
tuple_Threaded_Query,
    
tuple_Direct_Query,
    
// Errors stat and messages
    
tuple_Error_Query// error count
    
tuple_First_Error,
    
tuple_Last_Error,
    
tuple_First_Error_Msg[SQL_ERROR_LENGTH],
    
tuple_Last_Error_Msg[SQL_ERROR_LENGTH]
}
new 
cur_SQLTuple[e_SQLTuple], tmp_SQLTuple[e_SQLTuple]
new 
HashX:gSQLTuple

enum e_thread 
{
    
th_tuple_name[SQL_NAME],
    
th_plugin_id,
    
th_func_id,
    
th_data
}
new 
tmp_thread[e_thread]
new Array:
gThreads

// Handles
new Hash:gSQLHandle

// Forwards
new fw_connection_established    // pointer to forward callback

log_sql(fmt[], any:...) {
    static 
buffer[SQL_ERROR_LENGTH]
    
vformat(buffercharsmax(buffer), fmt2)

#if defined DEBUG
//    server_print("[SQLM] %s", buffer)
//    server_print("[SQLM Flags]: <%s> FLAG_CONNECTED: %d, FLAG_RECONNECTING: %d", cur_SQLTuple[tuple_name], get_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED), get_bits(cur_SQLTuple[tuple_flags], FLAG_RECONNECTING))
    
log_amx("[SQLM:%s] %s"cur_SQLTuple[tuple_name], buffer)
//    return log_error(AMX_ERR_NATIVE, "[SQLM] %s", buffer)
#endif
}

public 
sqlm_stats(id) {
    new 
name[SQL_NAME]
    
read_argv(1namecharsmax(name))

    new 
old_tuple[SQL_NAME]
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    if (!
set_tuple(name))
        return

    
console_print(id"^n%s, version %s, by %s"PLUGINVERSIONAUTHOR)
    
console_print(id"  Statistic for Tuple:............ '%s'"cur_SQLTuple[tuple_name])
    
console_print(id"    Direct Queryes:...............  %d"cur_SQLTuple[tuple_Direct_Query])
    
console_print(id"    Threaded Queryes:.............  %d"cur_SQLTuple[tuple_Threaded_Query])
    
console_print(id"  Errors:")
    
console_print(id"    Reconnect count:..............  %d"cur_SQLTuple[tuple_Reconnected])
    
console_print(id"    Error count:..................  %d"cur_SQLTuple[tuple_Error_Query])
    
console_print(id"    First Error:.................. (%d) '%s'"cur_SQLTuple[tuple_First_Error], cur_SQLTuple[tuple_First_Error_Msg])
    
console_print(id"    Last Error:................... (%d) '%s'"cur_SQLTuple[tuple_Last_Error], cur_SQLTuple[tuple_Last_Error_Msg])

    
set_tuple(old_tuple)
}

/*=============================================================================

    FORWARDS

=============================================================================*/

public plugin_init() {

    
register_plugin(PLUGINVERSIONAUTHOR)

    
pcvar[amx_sql_host]    = register_cvar("amx_sql_host""")
    
pcvar[amx_sql_type]    = register_cvar("amx_sql_type""")
    
pcvar[amx_sql_db]    = register_cvar("amx_sql_db""")
    
pcvar[amx_sql_user]    = register_cvar("amx_sql_user""")
    
pcvar[amx_sql_pass]    = register_cvar("amx_sql_pass""")

    
gSQLTuple    HashXCreate()
    
gSQLHandle    HashCreate()
    
gThreads    ArrayCreate(e_thread)

    
fw_connection_established CreateMultiForward("sqlm_connection_established"ET_IGNOREFP_STRINGFP_STRING)

    
register_srvcmd("sqlm_stats""sqlm_stats")

    new 
config_dir[PATH_LENGTH]
    
get_configsdir(config_dircharsmax(config_dir))

    
server_cmd("exec %s/sql.cfg"config_dir)

//    set_task(5.0, "sqlm_init")
}

public 
plugin_modules()
    
require_module("vdf");


public 
plugin_cfg() {
    
server_exec();
    
sqlm_init();
}

public 
plugin_end() {
    
PLUGIN_END true;
    
HashXForEach(0gSQLTuple"sqlm_close_tuple");
    
ArrayDestroy(gThreads);
    
HashXDestroy(gSQLTuple);
    
HashDestroy(gSQLHandle);
}

/*=============================================================================

    FUNCTIONS

=============================================================================*/
sqlm_init() {
    static 
name[SQL_NAME], host[SQL_HOST], user[SQL_NAME], pass[SQL_NAME], db[SQL_NAME]
    static 
type[SQL_NAME], timeoutautoconnecttmp_str[16]

    
get_pcvar_string(pcvar[amx_sql_host], hostcharsmax(host))
    
get_pcvar_string(pcvar[amx_sql_user], usercharsmax(user))
    
get_pcvar_string(pcvar[amx_sql_pass], passcharsmax(pass))
    
get_pcvar_string(pcvar[amx_sql_type], typecharsmax(type))
    
get_pcvar_string(pcvar[amx_sql_db], dbcharsmax(db))
    
timeout 0
    autoconnect 
0

//    sqlm_register_tuple(DEFAULT_TUPLE_NAME, type, host, user, pass, db, timeout)

    
log_sql("INIT Complete")

    new 
config_dir[PATH_LENGTH], filename[PATH_LENGTH]
    
get_configsdir(config_dircharsmax(config_dir))
    
formatex(filenamecharsmax(filename), "%s/sql_manager.vdf"config_dir)

//    vdf load
    
new VdfTree:treeVdfNode:nodeVdfNode:tuple_nodekey[SQL_NAME]
    if ((
tree vdf_open(filename))) {
        
node vdf_get_root_node(tree)
        if ((
node vdf_find_in_branch(node"Tuples")) && (tuple_node vdf_get_child_node(node))) {
            do {
                
vdf_get_node_key(tuple_nodenamecharsmax(name))
                
node vdf_get_child_node(tuple_node)

                do {
                    
vdf_get_node_key(nodekeycharsmax(key))
                    
trim(key)
                    if (
equali(key"type"))
                        
vdf_get_node_value(nodetypecharsmax(type))
                    else if (
equali(key"host"))
                        
vdf_get_node_value(nodehostcharsmax(host))
                    else if (
equali(key"user"))
                        
vdf_get_node_value(nodeusercharsmax(user))
                    else if (
equali(key"pass"))
                        
vdf_get_node_value(nodepasscharsmax(pass))
                    else if (
equali(key"db"))
                        
vdf_get_node_value(nodedbcharsmax(db))
                    else if (
equali(key"timeout")) {
                        
vdf_get_node_value(nodetmp_strcharsmax(tmp_str))
                        
timeout 0
                        
if (is_str_num(tmp_str))
                            
timeout str_to_num(tmp_str)
                    } else if (
equali(key"autoconnect")) {
                        
vdf_get_node_value(nodetmp_strcharsmax(tmp_str))
                        
autoconnect 0
                        
if (is_str_num(tmp_str))
                            
autoconnect str_to_num(tmp_str)
                    }
                } while ((
node vdf_get_next_node(node)))
                
sqlm_register_tuple(nametypehostuserpassdbtimeoutautoconnect)
            } while ((
tuple_node vdf_get_next_node(tuple_node)))

        } else {
            
// if not exists "default" tuple
            
vdf_set_default_tuple(treetypehostuserpassdb)
            
sqlm_register_tuple(DEFAULT_TUPLE_NAMEtypehostuserpassdb)
        }
    } else {
        
// if vdf is not exists
        
tree vdf_create_tree(filename)
        
vdf_set_default_tuple(treetypehostuserpassdb)
        
sqlm_register_tuple(DEFAULT_TUPLE_NAMEtypehostuserpassdb)
    }

    
set_tuple(DEFAULT_TUPLE_NAME)

    
log_sql("Configuration loaded")
}

vdf_set_default_tuple(VdfTree:treetype[], host[], user[], pass[], db[]) {
    new 
VdfNode:node vdf_get_root_node(tree)
    
node vdf_append_node(treenode"Tuples")
    
node vdf_append_child_node(treenodeDEFAULT_TUPLE_NAME)

    
vdf_append_child_node(treenode"type"type)
    
vdf_append_child_node(treenode"host"host)
    
vdf_append_child_node(treenode"user"user)
    
vdf_append_child_node(treenode"pass"pass)
    
vdf_append_child_node(treenode"db"db)
    
vdf_append_child_node(treenode"timeout""0")
    
vdf_append_child_node(treenode"autoconnect""0")

    
vdf_save(tree)
}
/*================================================================

    Tuples

================================================================*/

bool:sqlm_register_tuple(const name[SQL_NAME], const driver[], const host[], const user[], const pass[], const db[], timeout 0autoconnect 0) {
    static 
old_driver[SQL_NAME], old_tuple[SQL_NAME];

    
scopy(old_tuplecur_SQLTuple[tuple_name]);

    
copy(cur_SQLTuple[tuple_name], charsmax(cur_SQLTuple[tuple_name]), name);
    
copy(cur_SQLTuple[tuple_driver], charsmax(cur_SQLTuple[tuple_driver]), driver);
    
copy(cur_SQLTuple[tuple_host], charsmax(cur_SQLTuple[tuple_host]), host);
    
copy(cur_SQLTuple[tuple_user], charsmax(cur_SQLTuple[tuple_user]), user);
    
copy(cur_SQLTuple[tuple_pass], charsmax(cur_SQLTuple[tuple_pass]), pass);
    
copy(cur_SQLTuple[tuple_db], charsmax(cur_SQLTuple[tuple_db]), db);
    
cur_SQLTuple[tuple_timeout] = timeout;
    
cur_SQLTuple[tuple_autoconnect] = autoconnect;
    
clr_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED);

    
SQL_GetAffinity(old_drivercharsmax(old_driver));
    if (!
equali(old_driverdriver) && !SQL_SetAffinity(driver)) {
        
log_sql("ERROR: Driver '%s' is not loaded"driver);
//        SQL_SetAffinity(old_driver)
    
} else {

        if (
HashXKeyExists(gSQLTuplename))
            
log_sql("WARNING: Tuple name '%s' already еxists, reinit"name);
        else if (
autoconnect >= 0)  {
            
log_sql("Attempt register tuple: '%s' driver: '%s', host: '%s', user: '%s', pass: ***, db: '%s'"namedriverhostuserdb);
            if ((
cur_SQLTuple[tuple_handle] = fixed:SQL_MakeDbTuple(hostuserpassdbtimeout))) {
                
set_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED);
                
log_sql("Connection successful: %s"name);
            } else
                
log_sql("Connection error: %s"name);
        } else
            
log_sql("Tuple: '%s': disabled"name);

    }
    
HashXSetArray(gSQLTuplenamecur_SQLTuplesizeof(cur_SQLTuple));

    if (
get_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED)) {
        static 
rtv;
        
ExecuteForward(fw_connection_establishedrtvnamecur_SQLTuple[tuple_driver]);
    } else {
        if (
autoconnect 0)
            
sqlm_reconnect();
        
set_tuple(old_tuple);
        return 
false;
    }

    return 
true;
}

bool:set_tuple(const s_name[SQL_NAME]) {
    if (
PLUGIN_END) return false

    
new name[SQL_NAME]
    
scopy(names_name)
    
trim(name)

    
// If name empty, use default
    
if (name[0] == EOS) {
        
log_sql("WARN: Tuple name is empty ('%s'), set to 'default'."name)
        
scopy(nameDEFAULT_TUPLE_NAME)
//        scopy(name, cur_SQLTuple[tuple_name])
//        return false
    


    if (!
HashXGetArray(gSQLTuplenametmp_SQLTuplee_SQLTuple)) {
        
log_sql("ERROR: Tuple '%s' is not defined."name)
        return 
false
    
}

#if defined SQL_TRACE
//    log_sql("Tuple Set to '%s:%s'.", tmp_SQLTuple[tuple_driver], name)
#endif

    
if (!equal(cur_SQLTuple[tuple_name], name)) {
        if (
SQL_SetAffinity(tmp_SQLTuple[tuple_driver])) {

            
cur_SQLTuple tmp_SQLTuple
            HashXSetArray
(gSQLTuplenamecur_SQLTuplee_SQLTuple)
        } else {
            
log_sql("ERROR: Tuple '%s' is not defined."name)
            return 
false
        
}
    } else {

        new 
old_driver[SQL_NAME]
        
SQL_GetAffinity(old_drivercharsmax(old_driver))
        if (!
equali(old_drivertmp_SQLTuple[tuple_driver]) && !SQL_SetAffinity(tmp_SQLTuple[tuple_driver])) {
            
log_sql("ERROR: Cannot set affinity '%s', restore to '%s'."tmp_SQLTuple[tuple_driver], old_driver)
            
SQL_SetAffinity(old_driver)
            return 
false
        
}
    }

//    server_exec()
    
return true
}

Handle:get_tuple(const name[SQL_NAME]) {
    if (!
equal(cur_SQLTuple[tuple_name], name)) {
        if (
HashXGetArray(gSQLTuplenametmp_SQLTuplee_SQLTuple))
            return 
tmp_SQLTuple[tuple_handle]
        else {
            
log_sql("ERROR: Tuple '%s' is not defined."name)
            return 
Empty_Handle
        
}
    }

    return 
cur_SQLTuple[tuple_handle]
}

public 
sqlm_close_tuple(id, const name[SQL_NAME]) {

    new 
old_tuple[SQL_NAME]
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(name) && get_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED))
        
SQL_FreeHandle(cur_SQLTuple[tuple_handle])

    
set_tuple(old_tuple)

//    if (HashXGetArray(gSQLTuple, name, tmp_SQLTuple, e_SQLTuple) && get_bits(tmp_SQLTuple[tuple_flags], FLAG_CONNECTED))
//        SQL_FreeHandle(tmp_SQLTuple[tuple_handle])

}


/*==============================================
    Associate tuple name to handle
==============================================*/

store_tuple(const name[SQL_NAME], Handle:handle) {
    static 
key[8]
    
num_to_str(fixed:handlekeycharsmax(key))
    
HashSetString(gSQLHandlekeyname)
}

/*==============================================
    Find tuple name by handle
==============================================*/
find_tuple(Handle:handle) {
    static 
key[8], name[SQL_NAME]
    
name[0] = EOS
    num_to_str
(fixed:handlekeycharsmax(key))
    
HashGetString(gSQLHandlekeynamecharsmax(name))
    return 
name
}


// store current touple state in hash
sqlm_sync(index 0) {
    if (
index)
        
cur_SQLTuple[e_SQLTuple:index]++
    
HashXSetArray(gSQLTuplecur_SQLTuple[tuple_name], cur_SQLTuplee_SQLTuple)
}

store_error(Handle:handle) {
    static 
err_str[SQL_ERROR_LENGTH], err_num
    err_num 
SQL_QueryError(handleerr_strcharsmax(err_str))
    
log_sql("--> Error code: %d (Message: ^"%s^")"err_numerr_str)

    if (!
cur_SQLTuple[tuple_First_Error] && cur_SQLTuple[tuple_First_Error_Msg][0] == EOS) {
        
cur_SQLTuple[tuple_First_Error] = err_num
        copy
(cur_SQLTuple[tuple_First_Error_Msg], charsmax(cur_SQLTuple[tuple_First_Error_Msg]), err_str)
    }

    
cur_SQLTuple[tuple_Last_Error] = err_num
    copy
(cur_SQLTuple[tuple_Last_Error_Msg], charsmax(cur_SQLTuple[tuple_Last_Error_Msg]), err_str)

    
sqlm_sync(tuple_Error_Query)
}

/*=============================================================================

    Reconnect feathures

=============================================================================*/

#define tuple_reconnecting() bool:(get_bits(cur_SQLTuple[tuple_flags], FLAG_RECONNECTING))
reconnect_attempt(const name[SQL_NAME]) {
    
HashXGetArray(gSQLTuplenametmp_SQLTuplee_SQLTuple)
    if (
get_bits(tmp_SQLTuple[tuple_flags], FLAG_RECONNECTING) || PLUGIN_END)
        return
    
set_bits(tmp_SQLTuple[tuple_flags], FLAG_RECONNECTING)
    
HashXSetArray(gSQLTuplenametmp_SQLTuplee_SQLTuple)

    
log_sql("Reconnect tuple <%s><%d> called as '%s'"tmp_SQLTuple[tuple_name], tmp_SQLTuple[tuple_handle], name)
    
SQL_ThreadQuery(tmp_SQLTuple[tuple_handle], "reconnect_stub"";"namesizeof(name))
}

public 
reconnect_stub(failstateHandle:queryerr_str[], err_numdata[SQL_NAME], sizeFloat:queuetime) {
    if (
PLUGIN_END) return

    
log_sql("Reconnect stub <%s> result: %d"datafailstate)

    
HashXGetArray(gSQLTupledatatmp_SQLTuplee_SQLTuple)
    
clr_bits(tmp_SQLTuple[tuple_flags], FLAG_RECONNECTING)
    
HashXSetArray(gSQLTupledatatmp_SQLTuplee_SQLTuple)
    if (
failstate == TQUERY_CONNECT_FAILED) {
        
store_error(query)
        
reconnect_attempt(data)
    } else {
        
set_bits(tmp_SQLTuple[tuple_flags], FLAG_CONNECTED)
        
HashXSetArray(gSQLTupledatatmp_SQLTuplee_SQLTuple)
        
log_sql("Connection established: %s!"data)
        static 
rtv
        ExecuteForward
(fw_connection_establishedrtvdatatmp_SQLTuple[tuple_driver])
    }
}

/*================================================================

    Connections

================================================================*/

Handle:get_connection(const name[SQL_NAME] = DEFAULT_TUPLE_NAME) {
    
set_tuple(name)
/*
    if (cur_SQLTuple[tuple_cur_con_index]
        && ArrayGetArray(gSQLConnect, cur_SQLTuple[tuple_cur_con_index], cur_SQLConnect)
        && get_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED))

        return cur_SQLTuple[tuple_cur_con_handle]

    else
        new_connection(name)
*/
    
if (!get_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED))
        
sqlm_reconnect()

    return 
cur_SQLTuple[tuple_connect_handle]

/*
    static Handle:conn_size, Handle:i, tmp_SQLConnect[e_SQLConnect]
    conn_size = Handle:ArraySize(gSQLConnect)

    for (i = HANDLE_NULL; i < conn_size; i++)
        if (ArrayGetArray(gSQLConnect, fixed:i, tmp_SQLConnect)
            && equal(tmp_SQLConnect[owner_name], name)
            && set_connect(i))
            return i

    arrayset(cur_SQLConnect, 0, e_SQLConnect)
    copy(cur_SQLConnect[owner_name], charsmax(cur_SQLConnect[owner_name]), name)
    cur_SQLTuple[tuple_index] = ArraySize(gSQLConnect)
    set_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED)
    ArrayPushArray(gSQLConnect, cur_SQLConnect)
    set_task(0.1, "sqlm_reconnect", fixed:cur_SQLTuple[tuple_index])
    return cur_SQLTuple[tuple_index]
*/
}

/*
close_connect(Handle:handle)
    if (set_connection(handle)) {
        set_bits(cur_SQLTuple[tuple_flags], SQL_CONNECT_CLOSED);
        clr_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED)
        SQL_FreeHandle(cur_SQLTuple[tuple_connect_handle])
        sqlm_sync()
    }
*/

bool:sqlm_connected(name[SQL_NAME] = DEFAULT_TUPLE_NAME) {
    if (
HashXGetArray(gSQLTuplenametmp_SQLTuplee_SQLTuple))
        return 
bool:get_bits(tmp_SQLTuple[tuple_flags], FLAG_CONNECTED)
    return 
false
}

//#define sqlm_connected() bool:(get_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED))
#define sqlm_get_handle() Handle:(cur_SQLTuple[tuple_connect_handle])
/*
bool:set_connection(Handle:handle) {
    static name[SQL_NAME], key[sizeof(handle) + 1]
    num_to_str(fixed:handle, key, charsmax(key))
    HashGetString(gSQLHandle, key, name, charsmax(name))
    return get_connection(name)
}
*/

// •сли б‹ла ооˆибка соединения ‚о э‚а „ƒнк†ия поп€обƒе‚ вос‚‚анови‚Œ соединение момен‚алŒно, в€оде ни‡его и не п€оизоˆло.
// если же соединение не восс‚ановилосŒ, ‚о бƒдƒ‚ на‡а‚‹ по‚оков‹е поп‹‚ки соедини‚ся с се€ве€ом.
bool:sqlm_reconnect() {
    static 
name[SQL_NAME]
    if (
cur_SQLTuple[tuple_connect_handle] != Empty_Handle && !get_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED))
        return 
false


    
static err_numerr_str[SQL_ERROR_LENGTH]
    
clr_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED)
    if ((
cur_SQLTuple[tuple_connect_handle] = fixed:SQL_Connect(cur_SQLTuple[tuple_handle], err_numerr_strcharsmax(err_str)))) {
        
set_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED)
    } else {
        
scopy(namecur_SQLTuple[tuple_name])
        
reconnect_attempt(name)
    }

    
log_sql("Reconnect '%s' = %d"cur_SQLTuple[tuple_name], get_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED))

    
sqlm_sync(tuple_Reconnected)

    return 
sqlm_connected()
}


/*=============================================================================

    NATIVES

=============================================================================*/

public plugin_natives() {
    
register_library("sql_manager")

//    register_native("sqlm_register_tuple",        "_sqlm_register_tuple")
    
register_native("sqlm_connected",            "_sqlm_connected")

    
register_native("sqlm_quote_string",        "_sqlm_quote_string")
    
register_native("sqlm_prepare_query",        "_sqlm_prepare_query")
    
register_native("sqlm_exec",                "_sqlm_exec")
    
register_native("sqlm_simple_query",        "_sqlm_simple_query")
    
register_native("sqlm_simple_upd_ins",        "_sqlm_simple_upd_ins")
    
register_native("sqlm_thread_query",        "_sqlm_thread_query")

    
register_native("sqlm_affected_rows",        "_sqlm_affected_rows")
    
register_native("sqlm_field_name_to_num",    "_sqlm_field_name_to_num")
    
register_native("sqlm_field_num_to_name",    "_sqlm_field_num_to_name")
    
register_native("sqlm_free_handle",            "_sqlm_free_handle")
    
register_native("sqlm_get_insert_id",        "_sqlm_get_insert_id")
    
register_native("sqlm_get_query_string",    "_sqlm_get_query_string")
    
register_native("sqlm_is_null",                "_sqlm_is_null")
    
register_native("sqlm_more_results",        "_sqlm_more_results")
    
register_native("sqlm_next_row",            "_sqlm_next_row")
    
register_native("sqlm_num_columns",            "_sqlm_num_columns")
    
register_native("sqlm_num_results",            "_sqlm_num_results")
    
register_native("sqlm_query_error",            "_sqlm_query_error")
    
register_native("sqlm_read_result",            "_sqlm_read_result")
}

/*
//sqlm_register_tuple(const name[SQL_NAME], const driver[], const host[], const user[], const pass[], const db[], timeout = 0)
public bool:_sqlm_register_tuple(plugin_id, param_count) {
    new name[SQL_NAME], driver[SQL_NAME], host[SQL_HOST], user[SQL_NAME], pass[SQL_NAME], db[SQL_NAME]
    get_string(1, name, charsmax(name))
    get_string(2, driver, charsmax(driver))
    get_string(3, host, charsmax(host))
    get_string(4, user, charsmax(user))
    get_string(5, pass, charsmax(pass))
    get_string(6, db, charsmax(db))
    return sqlm_register_tuple(name, driver, host, user, pass, db, get_param(7))
}
*/

public bool:_sqlm_connected(plugin_idparam_count) {
    static 
tuple[SQL_NAME]
    
get_string(1tuplecharsmax(tuple))
    return 
sqlm_connected(tuple)
}

//sqlm_quote_string(const name[SQL_NAME], buffer[], buflen, const fmt[], {Float,_}:...) {
public _sqlm_quote_string(plugin_idparam_count) {
    static 
name[SQL_NAME], buffer[SQL_QUERY], buffer2[SQL_QUERY]
    
vdformat(buffer2charsmax(buffer2), 45)
    
get_string(1namecharsmax(name))

//    sqlm_quote_string(name, buffer, charsmax(buffer), buffer2)

    
new old_tuple[SQL_NAME]
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    
set_tuple(name)
    static 
retvalueHandle:connect
    connect 
get_connection(name)
    if (!
connect) {
        
set_tuple(old_tuple)
        return -
1
    
}
    
    
retvalue SQL_QuoteString(connectbuffercharsmax(buffer), buffer2)
    if (
retvalue 0)
        
reconnect_attempt(name)

    
set_string(2bufferget_param(3))

    
set_tuple(old_tuple)
    return 
retvalue
}

//Handle:sqlm_prepare_query (const fmt[], {Float,_}:...)
//Handle:sqlm_prepare_query (const name[SQL_NAME], const fmt[], {Float,_}:...) {
public Handle:_sqlm_prepare_query(plugin_idparam_count) {
    static 
name[SQL_NAME], buffer[SQL_QUERY]
    
get_string(1namecharsmax(name))

    static 
Handle:handleHandle:connect

    
new old_tuple[SQL_NAME]
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    if ((
connect get_connection(name))) {
        
vdformat(buffercharsmax(buffer), 23)
        
handle SQL_PrepareQuery(connectbuffer)
        
store_tuple(namehandle)
        if (!
handle)
            
reconnect_attempt(name)
        
set_tuple(old_tuple)
        return 
handle
    
}
    
set_tuple(old_tuple)
    return 
Empty_Handle
}

//sqlm_exec(Handle:handle)
public _sqlm_exec(plugin_idparam_count) {
    static 
retvalueHandle:handlename[SQL_NAME]
    
handle Handle:get_param(1)
    
name find_tuple(handle)
    
retvalue 0

    
new old_tuple[SQL_NAME]
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(name)) {
        if (!(
retvalue SQL_Execute(handle))) {
            
store_error(handle)
            
reconnect_attempt(name)
        }
    }

    
sqlm_sync(tuple_Direct_Query)
#if defined SQL_TRACE
    
static querystring[SQL_QUERY]
    
SQL_GetQueryString(handlequerystringcharsmax(querystring))
    
log_sql("Execute query: (%s)%s"namequerystring)
#endif

    
set_tuple(old_tuple)
    return 
retvalue
}


/*-----------------------------------------------------------------------------
Simple threaded query
-----------------------------------------------------------------------------*/

//sqlm_simple_query(const name[SQL_NAME], const query_string[], {Float,_}:...)
public _sqlm_simple_query(plugin_idparam_count) {
    static 
name[SQL_NAME]
    
get_string(1namecharsmax(name))

    new 
old_tuple[SQL_NAME]
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    static 
retvalue
    retvalue 
0

    
if (set_tuple(name)) {

//    if (tuple_reconnecting(name))
//        return 0

        
sqlm_sync(tuple_Threaded_Query)

        static 
querystring[SQL_QUERY]
        
vdformat(querystringcharsmax(querystring), 23)

        
log_sql("Threaded query: %s"querystring)

        
retvalue SQL_ThreadQuery(get_tuple(name), "sqlm_simple_stub"querystringnamesizeof(name))
    }

    
set_tuple(old_tuple)
    return 
retvalue
}

public 
sqlm_simple_stub(failstateHandle:queryerr_str[], err_numdata[SQL_NAME], sizeFloat:queuetime) {
//    set_tuple(name)

    
new old_tuple[SQL_NAME]
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    if (!
set_tuple(data)) {
        
log_sql("ERROR: Tuple name error! --> Error code: %d (Message: ^"%s^")"err_numerr_str)
        return 
PLUGIN_CONTINUE
    
}

    static 
querystring[SQL_QUERY]
    
SQL_GetQueryString(queryquerystringcharsmax(querystring))

#if defined SQL_TRACE
    
log_sql("Resolved query %d of tuple '%s', took %f seconds"querydataqueuetime)
    
log_sql("--> Original query: %s"querystring)
#endif

    
if (failstate) {
        
store_error(query)
        if (
failstate == TQUERY_CONNECT_FAILED) {
            
clr_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED)
            
log_sql("ERROR: Connection failed!")
            if (
querystring[0] == EOSSQL_GetQueryString(queryquerystringcharsmax(querystring))
            
SQL_FreeHandle(query)
            
reconnect_attempt(data)
//            if (sqlm_reconnect(cur_SQLTuple[tuple_index]))
//                sqlm_thread_exec(querystring)
        
} else if (failstate == TQUERY_QUERY_FAILED)
            
log_sql("ERROR: Query failed!")
        
log_sql("--> Error code: %d (Message: ^"%s^")"err_numerr_str)
    }

    
set_tuple(old_tuple)
    return 
PLUGIN_HANDLED
}

/*-----------------------------------------------------------------------------
UpdateOrInsert threaded query
-----------------------------------------------------------------------------*/

//sqlm_simple_upd_ins(const name[SQL_NAME], const update_string[], const insert_string[]) {
public _sqlm_simple_upd_ins(plugin_idparam_count) {
    new 
name[SQL_NAME], update_string[SQL_QUERY], insert_string[SQL_QUERY]
    
get_string(1namecharsmax(name))
    
get_string(2update_stringcharsmax(update_string))
    
get_string(3insert_stringcharsmax(insert_string))

    new 
old_tuple[SQL_NAME]
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    static 
retvalue
    retvalue 
0

    
if (set_tuple(name)) {
        
sqlm_sync(tuple_Threaded_Query)
        new 
data[SQL_NAME]
        
formatex(datacharsmax(data), "%s;%s"nameinsert_string)

        
retvalue SQL_ThreadQuery(get_tuple(name), "insertStub"update_stringdatasizeof(data))
    }

    
set_tuple(old_tuple)
    return 
retvalue
}

public 
insertStub(failstateHandle:queryerr_str[], err_numdata[], sizeFloat:queuetime) {
    static 
delimname[SQL_NAME]
    if ((
delim contain(data";")) > -1) {
        
data[delim] = EOS
        scopy
(namedata)
    }

    new 
old_tuple[SQL_NAME]
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    
set_tuple(name)

    static 
querystring[SQL_QUERY]
#if defined SQL_TRACE
    
log_sql("--> UPDATE took %f seconds"queuetime)
#endif

    
new insert_string[SQL_QUERY]
    
copy(insert_stringcharsmax(insert_string), data[delim 1])

    if (
failstate) {
        
store_error(query)
        if (
failstate == TQUERY_CONNECT_FAILED)
        {
            
clr_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED)
            
log_sql("ERROR: Connection failed!")
            
SQL_GetQueryString(queryquerystringcharsmax(querystring))
            
SQL_FreeHandle(query)
            
reconnect_attempt(name)
//            if (sqlm_reconnect(cur_SQLTuple[tuple_index]))
//                sqlm_thread_upd_ins(querystring, insert_string)
        
} else if (failstate == TQUERY_QUERY_FAILED)
            
log_sql("ERROR: Query failed!")
        
log_sql("--> Error code: %d (Message: ^"%s^")"err_numerr_str)

    } else if (!
SQL_AffectedRows(query)) {
        
log_sql("--> NOT UPDATE, attempt INSERT %s"insert_string)
//        sqlm_simple_query(name, insert_string)

        
sqlm_sync(tuple_Threaded_Query)

        
log_sql("Threaded query: %s"insert_string)

        
SQL_ThreadQuery(get_tuple(name), "sqlm_simple_stub"insert_stringnamesizeof(name))
    }

    
set_tuple(old_tuple)
    return 
PLUGIN_HANDLED
}


/*-----------------------------------------------------------------------------
Callback threaded query
-----------------------------------------------------------------------------*/
//sqlm_thread_query(const tuple[SQL_NAME], const func[], const query_string[], data)
public _sqlm_thread_query(plugin_idparam_count) {
    static 
name[SQL_NAME], func[SQL_NAME], query_string[SQL_QUERY], l_data[2]
    
get_string(1tmp_thread[th_tuple_name], charsmax(tmp_thread[th_tuple_name]))
    
scopy(nametmp_thread[th_tuple_name])

    static 
retvalue
    retvalue 
0

    
new old_tuple[SQL_NAME]
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(name)) {

        
tmp_thread[th_plugin_id] = plugin_id
        get_string
(2funccharsmax(func))
        
tmp_thread[th_func_id] = get_func_id(funcplugin_id)
        
get_string(3query_stringcharsmax(query_string))
        
tmp_thread[th_data] = get_param(4)
        
l_data[0] = ArraySize(gThreads)
        
ArrayPushArray(gThreadstmp_thread)

        
sqlm_sync(tuple_Threaded_Query)

        
retvalue SQL_ThreadQuery(get_tuple(name), "sqlm_callback"query_stringl_datasizeof(l_data))
    }

    
set_tuple(old_tuple)

    return 
retvalue
}

public 
sqlm_callback(failstateHandle:queryerr_str[], err_numdata[], sizeFloat:queuetime) {
    if (
gThreads && !ArrayGetArray(gThreadsdata[0], tmp_thread)) {
        
log_sql("ERROR: Data error!")
        return 
PLUGIN_CONTINUE
    
}

    new 
old_tuple[SQL_NAME]
    
scopy(old_tuplecur_SQLTuple[tuple_name])
    static 
name[SQL_NAME]
    
scopy(nametmp_thread[th_tuple_name])

    if (!
set_tuple(name)) {
        
log_sql("ERROR: Tuple name error! --> Error code: %d (Message: ^"%s^")"err_numerr_str)
        return 
PLUGIN_CONTINUE
    
}

    static 
querystring[SQL_QUERY]
    
SQL_GetQueryString(queryquerystringcharsmax(querystring))

#if defined SQL_TRACE
    
log_sql("Resolved query %d of tuple '%s', took %f seconds"querynamequeuetime)
    
log_sql("--> Original query: %s"querystring)
#endif


    
store_tuple(namequery)

    if (
failstate) {
        
store_error(query)
        if (
failstate == TQUERY_CONNECT_FAILED) {
            
clr_bits(cur_SQLTuple[tuple_flags], FLAG_CONNECTED)
            
log_sql("ERROR: Connection failed!")
            if (
querystring[0] == EOSSQL_GetQueryString(queryquerystringcharsmax(querystring))
            if (
sqlm_reconnect())
                
SQL_ThreadQuery(get_tuple(name), "sqlm_callback"querystringdatasize)
        } else if (
failstate == TQUERY_QUERY_FAILED)
            
log_sql("ERROR: Query failed!")
        
log_sql("--> Error code: %d (Message: ^"%s^")"err_numerr_str)
    } else {
        
ArrayGetArray(gThreadsdata[0], tmp_thread)

        if (
callfunc_begin_i(tmp_thread[th_func_id], tmp_thread[th_plugin_id]) == 1) {
            
callfunc_push_int(failstate)
            
callfunc_push_int(fixed:query)
            
callfunc_push_str(err_str)
            
callfunc_push_int(err_num)
            
callfunc_push_int(tmp_thread[th_data])
            
callfunc_push_float(queuetime)
            
callfunc_end()
        }

    }

    
set_tuple(old_tuple)

    return 
PLUGIN_HANDLED
}

/*===================================================================================

    FUNCTIONS for QUERY Handle

=====================================================================================*/

// SQL_AffectedRows 
// sqlm_affected_rows(Handle:query)
public _sqlm_affected_rows(plugin_idparam_count) {
    new 
old_tuple[SQL_NAME], Handle:query Handle:get_param(1), retvalue 0
    scopy
(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(find_tuple(query)))
        
retvalue SQL_AffectedRows(query)

    
set_tuple(old_tuple)
    return 
retvalue
}

// SQL_FieldNameToNum
// sqlm__field_name_to_num(Handle:query, const name[])
public _sqlm_field_name_to_num(plugin_idparam_count) {
    new 
old_tuple[SQL_NAME], Handle:query Handle:get_param(1), retvalue 0name[SQL_NAME]
    
get_string(2namecharsmax(name))
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(find_tuple(query)))
        
retvalue SQL_FieldNameToNum(queryname)

    
set_tuple(old_tuple)
    return 
retvalue
}

// SQL_FieldNumToName
// sqlm__field_num_to_name(Handle:query, num, name[], maxlength)
public _sqlm_field_num_to_name(plugin_idparam_count) {
    new 
old_tuple[SQL_NAME], Handle:query Handle:get_param(1), retvalue 0name[SQL_NAME]
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(find_tuple(query)) && (retvalue SQL_FieldNumToName(queryget_param(2), namecharsmax(name))))
        
set_string(3nameget_param(4))

    
set_tuple(old_tuple)
    return 
retvalue
}

// SQL_FreeHandle
// sqlm_free_handle(Handle:query)
public _sqlm_free_handle(plugin_idparam_count) {
    new 
old_tuple[SQL_NAME], Handle:query Handle:get_param(1), retvalue 0
    scopy
(old_tuplecur_SQLTuple[tuple_name])

    
set_tuple(find_tuple(query))
    
retvalue SQL_FreeHandle(query)

    
set_tuple(old_tuple)
    return 
retvalue
}

// SQL_GetInsertId
// sqlm_get_insert_id(Handle:query)
public _sqlm_get_insert_id(plugin_idparam_count) {
    new 
old_tuple[SQL_NAME], Handle:query Handle:get_param(1), retvalue 0
    scopy
(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(find_tuple(query)))
        
retvalue SQL_GetInsertId(query)

    
set_tuple(old_tuple)
    return 
retvalue
}

// SQL_GetQueryString
// sqlm_get_query_string(Handle:query, buffer[], maxlength)
public _sqlm_get_query_string(plugin_idparam_count) {
    new 
old_tuple[SQL_NAME], Handle:query Handle:get_param(1), retvalue 0buffer[SQL_QUERY]
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(find_tuple(query))) {
        
retvalue SQL_GetQueryString(querybuffercharsmax(buffer))
        
set_string(2bufferget_param(3))
    }

    
set_tuple(old_tuple)
    return 
retvalue
}

// SQL_IsNull
// sqlm_is_null(Handle:query, column)
public _sqlm_is_null(plugin_idparam_count) {
    new 
old_tuple[SQL_NAME], Handle:query Handle:get_param(1), retvalue 0
    scopy
(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(find_tuple(query)))
        
retvalue SQL_IsNull(queryget_param(2))

    
set_tuple(old_tuple)
    return 
retvalue
}

// SQL_MoreResults
// sqlm_more_results(Handle:query)
public _sqlm_more_results(plugin_idparam_count) {
    new 
old_tuple[SQL_NAME], Handle:query Handle:get_param(1), retvalue 0
    scopy
(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(find_tuple(query)))
        
retvalue SQL_MoreResults(query)

    
set_tuple(old_tuple)
    return 
retvalue
}

// SQL_NextRow
// sqlm_next_row(Handle:query)
public _sqlm_next_row(plugin_idparam_count) {
    new 
old_tuple[SQL_NAME], Handle:query Handle:get_param(1), retvalue 0
    scopy
(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(find_tuple(query))) {
        
SQL_NextRow(query)
        
retvalue SQL_MoreResults(query)
    }

    
set_tuple(old_tuple)
    return 
retvalue
}

// SQL_NumColumns
// sqlm_num_columns(Handle:query)
public _sqlm_num_columns(plugin_idparam_count) {
    new 
old_tuple[SQL_NAME], Handle:query Handle:get_param(1), retvalue 0
    scopy
(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(find_tuple(query)))
        
retvalue SQL_NumColumns(query)

    
set_tuple(old_tuple)
    return 
retvalue
}

// SQL_NumResults
// sqlm_num_results(Handle:query)
public _sqlm_num_results(plugin_idparam_count) {
    new 
old_tuple[SQL_NAME], Handle:query Handle:get_param(1), retvalue 0
    scopy
(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(find_tuple(query)))
        
retvalue SQL_NumResults(query)

    
set_tuple(old_tuple)
    return 
retvalue
}

// SQL_QueryError
// sqlm_query_error(Handle:query, error[], maxlength)
public _sqlm_query_error(plugin_idparam_count) {
    new 
old_tuple[SQL_NAME], Handle:query Handle:get_param(1), retvalue 0buffer[SQL_QUERY]
    
scopy(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(find_tuple(query))) {
        
retvalue SQL_QueryError(querybuffercharsmax(buffer))
        
set_string(2bufferget_param(3))
    }

    
set_tuple(old_tuple)
    return 
retvalue
}

// SQL_ReadResult
// sqlm_read_result(Handle:query, column[], {Float,_}:...)
public _sqlm_read_result(plugin_idparam_count) {
    new 
old_tuple[SQL_NAME], Handle:query Handle:get_param(1), retvalue 0buffer[SQL_QUERY], Float:flt
    scopy
(old_tuplecur_SQLTuple[tuple_name])

    if (
set_tuple(find_tuple(query))) {
        switch (
param_count) {
            case 
2:
                
retvalue SQL_ReadResult(queryget_param(2))
            case 
3: {
                
retvalue SQL_ReadResult(queryget_param(2), flt)
                
set_float_byref(3flt)
            }
            case 
4: {
                
retvalue SQL_ReadResult(queryget_param(2), buffercharsmax(buffer))
                
set_string(3bufferget_param(4))
            }
        }
    }

    
set_tuple(old_tuple)
    return 
retvalue
}

[/
quote]

As 
you can see the code is intact.

[
QUOTE]// The last node has a value which's the command to be executed
// This won't work with commandmenu.txt (that's not a vdf file)

"Tuples"
{
    
"default"
    
{
        
"type" "mysql"
        "host" "dbmy0024.whservidor.com"
        "db"  "impactgami1_7"
        "user" "impactgami1_7"
        "pass" "ma******"
        "timeout" "0.000"
        "autoconnect" "1"
    
}

__________________

Last edited by Arkshine; 10-06-2011 at 06:55.
abalad is offline
Send a message via MSN to abalad Send a message via Skype™ to abalad
Zefir
Member
Join Date: Oct 2007
Location: Kiev, Ukraine
Old 06-07-2011 , 04:19   Re: SQL Connection Manager
Reply With Quote #10

Hi abalad!

Please show YOUR plugin with using library 'SQL_Manager'.

"SQL Connection Manager" is not plugin, this is library for simple manipulate connections.
__________________
Zefir is offline
Send a message via ICQ to Zefir
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 11:55.


Powered by vBulletin®
Copyright ©2000 - 2020, vBulletin Solutions, Inc.
Theme made by Freecode