Help-me include erro
#1

Erro:
Код:
C:\Program Files\pawno\include\sqlitei.inc(969) : error 017: undefined symbol "db_get_result_mem_handle"
C:\Program Files\pawno\include\sqlitei.inc(978) : error 017: undefined symbol "db_get_result_mem_handle"
C:\Program Files\pawno\include\sqlitei.inc(2159) : error 017: undefined symbol "db_get_result_mem_handle"
Include:
PHP код:
/*
    SQLite Improved v0.9.7 by Slice
    
    Changelog:
            2015-07-13:
                * Update for 0.3.7 R2.
                * All crash issues should be solved now, including the previous one that happened only on some servers.
            2014-10-08:
                * Fix crash when using stmt_fetch_row on an empty result (only affects Linux servers).
            2013-10-07:
                * Display errors from db_query. Works only on Windows.
            
            2012-07-23:
                * Fix problem with persistent databases (hopefully).
            
            2012-07-21:
                * Fix crash happening on Linux related to NULL values in db_free_result.
            
            2012-07-15:
                * Improvements to persistent databases.
            
            2012-06-15:
                * Fix compiler crash when db_query isn't used.
            
            2012-05-27:
                * Always throw warnings when invalid results are given to SQLitei functions.
                * Even more improvements to stability!
                * GetAmxBase is now updated with a JIT compatible version (all credits to Zeex).
                * All the default DB functions (which are hooked by SQLitei) are now compatible with the JIT plugin.
                * Fixed a bug in SA-MP's SQLite implementation where strings would contain signed characters instead of unsigned.
                  Most functions work just fine with both types of strings but strcmp, for one, does not.
                * stmt_bind_value now deals with packed strings properly.
            
            2012-03-22:
                * db_query now accept extra parameters similar to those in stmt_bind_value, allowing
                  a very quick way to format and run queries!
                
            2012-03-21:
                * Fixed a rare crash that would occur if you closed a DB while having autofreed results open.
                * The deprecated db_query_autofree is now removed. Simply use db_query instead.
                * Fixed a problem where a certain integer would cause an invalid value.
                * Added DB::TYPE_UINT, which inserts an unsigned integer.
                  An unsigned integer have values between 0 and 4294967295 as opposed to -2147483648 and 2147483647.
                * Added helper function db_print_query.
                * Added db_dump_table!
            
            2012-03-01:
                * db_free_result will now completely ignore invalid results (0).
            
            2012-02-12:
                * Added db_attach_memory_db and db_detach_memory_db.
            
            2012-02-11:
                * Added DB::TYPE_ARRAY, which allows you to insert and read arrays with statements!
                * Improved error handling and increased some buffer sizes.
                * Added db_begin_transaction, db_end_transaction, and db_set_asynchronous.
                * Minor improvements here and there.
            
            2012-02-10:
                * A few bug fixes.
                * Added db_field_is_null, which returns true if the field is a true NULL value (not just an empty string).
                * Deprecated db_query_autofree.
            
            2012-02-09:
                * Defining WP_Hash prior to inclusion is no longer needed.
                * db_query now has an optional third argument - enable autorelease, which is
                  true by default.
                * Improved stability on freeing results:
                    - Freeing results twice will not crash the server anymore - it will just generate
                      a warning.
                    - Freeing a result that will be autoreleased will remove it from the autorelease pool.
                * The compiler will no longer wrongfully detect recursion inside this include.
                * Added db_query_int and db_query_float.
                * Added db_get_struct_info and db_set_struct_info; used mainly internally.
                * Added db_exec and db_insert.
                * Performance improvements!
            
            2012-02-08:
                * db_print_result will no longer go to the end of the result.
                * Added db_get_row_index, db_set_row_index, and db_rewind.
            
            2012-02-07:
                * db_get_field/db_get_field_assoc will not crash anymore with NULL values!
            
            2011-12-21:
                * Added two new types for stmt_bind_value:
                    - DB::TYPE_WP_HASH: Puts a BLOB value of a whirlpool hash from the given string into the query (ex. x'FFAA4411...').
                    - DB::TYPE_PLAYER_NAME: Puts a player name from the ID passed.
                  Note that DB_USE_WHIRLPOOL must be defined as true in order for DB::TYPE_WP_HASH to work.
                * Made some optimizations and minor bug fixes.
                * stmt_execute will now autofree the result unless the 3rd argument is false.
                * Added the preprocessor options DE_DEBUG (logs debug info) and DB_LOG_TO_CHAT (prints log messages to chat).
                * Improved the way results are dealt with internally to avoid crashes at all costs.
                * Added debug messages pretty much everywhere.
            
            2011-12-16:
                * Added db_open_persistent, db_is_persistent, db_is_valid_persistent, and db_free_persistent.
                * Added db_query_autofree.
                * Added db_get_field_int and db_get_field_float.
                * Corrected a few SQLite natives.
            
            2011-12-15:
                * Added stmt_autoclose.
                * Memory usage decreased significantly.
                * All functions now accept both packed and unpacked strings.
                * Minor bug fixes and optimizations.
            
            2011-12-14:
                * Initial release.
*/
#if !defined _samp_included
    #error Please include a_samp before sqlitei.
#endif
#if defined __fmt_funcinc && defined FormatSpecifier
    #error Please include sqlitei before formatex.
#endif
#if !defined HTTP
    #tryinclude <a_http>
#endif
#if !defined DB_MAX_PARAMS
    #define DB_MAX_PARAMS  32
#endif
#if !defined DB_MAX_STATEMENTS
    #define DB_MAX_STATEMENTS  16
#endif
#if !defined DB_MAX_STATEMENT_SIZE
    #define DB_MAX_STATEMENT_SIZE  1024
#endif
#if !defined DB_MAX_FIELDS
    #define DB_MAX_FIELDS  64
#endif
#if !defined DB_MAX_PERSISTENT_DATABASES
    #define DB_MAX_PERSISTENT_DATABASES  4
#endif
#if !defined DB_USE_WHIRLPOOL
    #define DB_USE_WHIRLPOOL  false
#endif
#if !defined DB_DEBUG
    #define DB_DEBUG  false
#endif
#if !defined DB_DEBUG_BACKTRACE_NOTICE
    #define DB_DEBUG_BACKTRACE_NOTICE  false
#endif
#if !defined DB_DEBUG_BACKTRACE_WARNING
    #define DB_DEBUG_BACKTRACE_WARNING  false
#endif
#if !defined DB_DEBUG_BACKTRACE_ERROR
    #define DB_DEBUG_BACKTRACE_ERROR  false
#endif
#if !defined DB_DEBUG_BACKTRACE_DEBUG
    #define DB_DEBUG_BACKTRACE_DEBUG  false
#endif
#if !defined DB_LOG_TO_CHAT
    #define DB_LOG_TO_CHAT  false
#endif
// "Namespace"
#define DB:: DB_
// Fix some natives ("const" keyword was missing)
native DB:db_open@(const szName[]) = db_open;
native DBResult:db_query@(DB:db, const szQuery[]) = db_query;
native db_get_field@(DBResult:dbresultfieldresult[], maxlength) = db_get_field;
native db_get_field_assoc@(DBResult:dbresult, const field[], result[], maxlength) = db_get_field_assoc;
native db_close@(DB:db) = db_close;
native db_free_result@(DBResult:dbrResult) = db_free_result;
#define db_open        db_open@
#define db_query%1(    db_query_hook(_,
#define db_close       db_close_hook
#define db_free_result db_free_result_hook
#if DB::USE_WHIRLPOOL
    
native DB::WP_Hash(buffer[], len, const str[]) = WP_Hash;
#endif
enum DB::e_SYNCHRONOUS_MODE {
    
DB::SYNCHRONOUS_OFF,
    
DB::SYNCHRONOUS_NORMAL,
    
DB::SYNCHRONOUS_FULL
};
enum DBDataType: {
    
DB::TYPE_NONE,
    
DB::TYPE_NULL,
    
DB::TYPE_INT,
    
DB::TYPE_INTEGER DB::TYPE_INT,
    
DB::TYPE_UINT,
    
DB::TYPE_UINTEGER DB::TYPE_UINT,
    
DB::TYPE_FLOAT,
    
DB::TYPE_STRING,
    
DB::TYPE_RAW_STRING,
    
DB::TYPE_IDENTIFIER,
    
    
// Special types
    
#if DB::USE_WHIRLPOOL
    
DB::TYPE_WP_HASH,
#endif
    
    
DB::TYPE_PLAYER_NAME,
    
DB::TYPE_PLAYER_IP,
    
DB::TYPE_ARRAY
};
#define INT:          DB::TYPE_INT,QQPA:
#define INTEGER:      DB::TYPE_INT,QQPA:
#define UINT:         DB::TYPE_UINT,QQPA:
#define UINTEGER:     DB::TYPE_UINT,QQPA:
#define FLOAT:        DB::TYPE_FLOAT,QQPA:
#define STRING:       DB::TYPE_STRING,QQPA:
#define RAW_STRING:   DB::TYPE_RAW_STRING,QQPA:
#define IDENTIFIER:   DB::TYPE_IDENTIFIER,QQPA:
#if DB::USE_WHIRLPOOL
    #define WP_HASH:  DB::TYPE_WP_HASH,QQPA:
#endif
#define PLAYER_NAME:  DB::TYPE_PLAYER_NAME,QQPA:
#define PLAYER_IP:    DB::TYPE_PLAYER_IP,QQPA:
enum DB::E_STATEMENT {
    
// The ready-to-run query.
    
e_szQuery[DB::MAX_STATEMENT_SIZE 1],
    
    
// Parameter count
    
e_iParams,
    
    
// The parameter types.
    
DBDataType:e_aiParamTypes[DB::MAX_PARAMS],
    
    
// Position of parameters in the query string.
    
e_aiParamPositions[DB::MAX_PARAMS],
    
    
// Length of parameters in the query string.
    
e_aiParamLengths[DB::MAX_PARAMS],
    
    
// Types of bound return fields
    
DBDataType:e_aiFieldTypes[DB::MAX_FIELDS],
    
    
// Sizes of bound result fields (used only for strings currently)
    
e_aiFieldSizes[DB::MAX_FIELDS],
    
    
// Addresses of bound result fields
    
e_aiFieldAddresses[DB::MAX_FIELDS],
    
    
// The database it was created for
    
DB:e_dbDatabase,
    
    
// The result (after executing)
    
DBResult:e_dbrResult,
    
    
// How many rows were fetched from the most recent result
    
e_iFetchedRows,
    
    
// Whether or not any leftover results should be automatically freed
    // Note that whenever a new result is put into e_dbrResult, the previous one is freed.
    
bool:e_bAutoFreeResult
};
enum {
    
SQLITE_LIMIT_LENGTH,
    
SQLITE_LIMIT_SQL_LENGTH,
    
SQLITE_LIMIT_COLUMN,
    
SQLITE_LIMIT_EXPR_DEPTH,
    
SQLITE_LIMIT_COMPOUND_SELECT,
    
SQLITE_LIMIT_VDBE_OP,
    
SQLITE_LIMIT_FUNCTION_ARG,
    
SQLITE_LIMIT_ATTACHED,
    
SQLITE_LIMIT_LIKE_PATTERN_LEN,
    
SQLITE_LIMIT_VARIABLE_NUMBER,
    
SQLITE_LIMIT_TRIGGER_DEPTH
};
// SQLite 3 C-struct offsets
enum e_SQLITE3 {
         
sqlite3_pVfs                [4],
         
sqlite3_iBackends           [4],
         
sqlite3_pBackends           [4],
         
sqlite3_iFlags              [4],
         
sqlite3_iOpenFlags          [4],
    
         
sqlite3_iErrorCode          [4],
         
sqlite3_iErrorMask          [4],
    
bool:sqlite3_bAutoCommit         [1],
         
sqlite3_iTempStore          [1],
    
bool:sqlite3_bMallocFailed       [1],
    
         
sqlite3_iDefaultLockMode    [1],
         
sqlite3_iNextAutovac        [1],
    
bool:sqlite3_bSuppressErrors     [1],
         
sqlite3_iPad                [2],
    
         
sqlite3_iNextPagesize       [4],
         
sqlite3_iNumTables          [4],
         
sqlite3_pDefaultCollation   [4],
         
sqlite3_iLastRowid          [4],
         
sqlite3_iLastRowidUpperBytes[4],
         
sqlite3_iMagic              [4],
         
sqlite3_iNumChanges         [4],
         
sqlite3_iNumTotalChanges    [4],
    
         
sqlite3_aiLimits            [SQLITE_LIMIT_TRIGGER_DEPTH 4],
    
         
sqlite3_aInitInfo           [12],
         
sqlite3_iNumExtensions      [4],
         
sqlite3_pExtensions         [4],
         
sqlite3_pVdbe               [4],
         
sqlite3_iActiveVdbeCount    [4],
         
sqlite3_iWritingVdbeCount   [4],
    
         
sqlite3_pTraceFunc          [4],
         
sqlite3_pTraceArg           [4],
         
sqlite3_pProfilingFunc      [4],
         
sqlite3_pProfilingArg       [4],
         
sqlite3_pCommitArg          [4],
         
sqlite3_pCommitCallback     [4],
         
sqlite3_pRollbackArg        [4],
         
sqlite3_pRollbackCallback   [4],
         
sqlite3_pUpdateArg          [4],
         
sqlite3_pUpdateCallback     [4],
         
sqlite3_pWalCallback        [4],
         
sqlite3_pWalArg             [4],
         
sqlite3_pCollNeeded         [4],
         
sqlite3_pCollNeeded16       [4],
         
sqlite3_pCollNeededArg      [4],
         
sqlite3_pError              [4],
         
sqlite3_pErrorMsg           [4],
         
sqlite3_pErrorMsg16         [4]
};
enum DB::E_PERSISTENT_DB {
         
e_szName[128 char],
    
bool:e_bIsUsed,
      
DB:e_dbDatabase
};
static 
stock
                gs_szBuffer
[8192],
                
gs_aiCompressBuffer[3072],
                
gs_Statements[DBStatement:DB::MAX_STATEMENTS][DB::E_STATEMENT],
                
gs_iAutoFreeTimer = -1,
                
gs_iAutoFreeResultsIndex 0,
       
DBResult:gs_adbrAutoFreeResults[1024],
                
gs_iAutoCloseStatementsIndex 0,
    
DBStatement:gs_astAutoCloseStatements[1024],
                
gs_PersistentDatabases[DB::MAX_PERSISTENT_DATABASES][DB::E_PERSISTENT_DB],
                
gs_iClosePersistentTimer = -1,
                
gs_iFreeStatementResultsTimer = -1,
                
gs_szNull[1] = {0}
;
const
    
DBStatement:DB::INVALID_STATEMENT DBStatement:-1,
       
DBResult:DB::INVALID_RESULT DBResult:0
;
#if !DB_DEBUG
    #define DB_Debug(%1)%0;
#endif
#if !DB_LOG_TO_CHAT
    #if DB_DEBUG_BACKTRACE_NOTICE
        #define DB_Notice(%1)    print(!"SQLitei Notice: " %1),PrintAmxBacktrace()
        #define DB_Noticef(%1)   printf("SQLitei Notice: " %1),PrintAmxBacktrace()
    #else
        #define DB_Notice(%1)    print(!"SQLitei Notice: " %1)
        #define DB_Noticef(%1)   printf("SQLitei Notice: " %1)
    #endif
    #if DB_DEBUG_BACKTRACE_WARNING
        #define DB_Warning(%1)   print(!"SQLitei Warning: " %1),PrintAmxBacktrace()
        #define DB_Warningf(%1)  printf("SQLitei Warning: " %1),PrintAmxBacktrace()
    #else
        #define DB_Warning(%1)   print(!"SQLitei Warning: " %1)
        #define DB_Warningf(%1)  printf("SQLitei Warning: " %1)
    #endif
    #if DB_DEBUG_BACKTRACE_ERROR
        #define DB_Error(%1)     print(!"SQLitei Error: " %1),PrintAmxBacktrace()
        #define DB_Errorf(%1)    printf("SQLitei Error: " %1),PrintAmxBacktrace()
    #else
        #define DB_Error(%1)     print(!"SQLitei Error: " %1)
        #define DB_Errorf(%1)    printf("SQLitei Error: " %1)
    #endif
    
    #if DB_DEBUG
        #if DB_DEBUG_BACKTRACE_DEBUG
            #define DB_Debug(%1)  printf("SQLitei Debug: " %1),PrintAmxBacktrace()
        #else
            #define DB_Debug(%1)  printf("SQLitei Debug: " %1)
        #endif
    #endif
#else
    
new
        
gs_szLogMessageBuffer[256]
    ;
    
    
#define DB_Notice(%1)    SendClientMessageToAll(0xFFFFFFFF, "SQLitei Notice: "  %1), print(!"SQLitei Notice: "  %1)
    #define DB_Warning(%1)   SendClientMessageToAll(0xEBBD17FF, "SQLitei Warning: " %1), print(!"SQLitei Warning: " %1)
    #define DB_Error(%1)     SendClientMessageToAll(0xCC0000FF, "SQLitei Error: "   %1), print(!"SQLitei Error: "   %1)
    #define DB_Noticef(%1)   format(gs_szLogMessageBuffer, sizeof(gs_szLogMessageBuffer), "SQLitei Notice: "  %1), print(gs_szLogMessageBuffer), SendClientMessageToAll(0xDDDDDDFF, gs_szLogMessageBuffer)
    #define DB_Warningf(%1)  format(gs_szLogMessageBuffer, sizeof(gs_szLogMessageBuffer), "SQLitei Warning: " %1), print(gs_szLogMessageBuffer), SendClientMessageToAll(0xEBBD17FF, gs_szLogMessageBuffer)
    #define DB_Errorf(%1)    format(gs_szLogMessageBuffer, sizeof(gs_szLogMessageBuffer), "SQLitei Error: "   %1), print(gs_szLogMessageBuffer), SendClientMessageToAll(0xCC0000FF, gs_szLogMessageBuffer)
    
    #if DB_DEBUG
        #define DB_Debug(%1)  format(gs_szLogMessageBuffer, sizeof(gs_szLogMessageBuffer), "SQLitei Debug: " %1), print(gs_szLogMessageBuffer), SendClientMessageToAll(0xFFFFFFFF, gs_szLogMessageBuffer)
    #endif
#endif
// Has to be defined after statement functions.
forward DBResult:db_query_hook(iTagOf3 tagof(_bAutoRelease), DB:db, const szQuery[], {boolDBDataType}:_bAutoRelease true, {DBDataTypeQQPA}:...);
// forward's
forward bool:db_set_row_index(DBResult:dbrResultiRow);
forward bool:db_free_result_hook(DBResult:dbrResult);
forward bool:db_set_synchronous(DB:dbDB::e_SYNCHRONOUS_MODE:iValue);
forward DB::funcinc();
public 
DB::funcinc() {
    
strcat(gs_szBuffer"");
    
strpack(gs_szBuffer"");
    
ispacked(gs_szBuffer);
    
db_get_field(DBResult:00gs_szBuffer0);
    
db_query(DB:0,"");
}
static 
stock DB::CompressArray(const aiArray[], iSize sizeof(aiArray), aiOutput[]) {
    new
        
iOutputIndex 4,
        
iValue,
        
iMSB,
        
iShift
    
;
    
    
// * 0b11000000 = Single byte, negative
    // * 0b10000000 = Single byte
    // * 0b01000000 = Multi-byte
    //   - 0b01000000 = More bytes
    //   - 0b11000000 = Last byte
    //   - 0b10000000 = Unused
    
    
for (new 0iSizei++) {
        
// Will the value fit in one byte?
        
        
iValue aiArray[i];
        
        if (-
0b00111111 <= iValue <= 0b00111111) {
            
// Is the value negative?
            
            
if (iValue 0x80000000) {
                
// Set the "single byte, negative" bits on and put the value without its sign
                
                
aiOutput{iOutputIndex++} = 0b11000000 | -iValue;
            } else {
                
// Just put the value in with the "single byte" bit
                
                
aiOutput{iOutputIndex++} = 0b10000000 |  iValue;
            }
        } else {
            
// Figure out how many bits we'll have to write
            
iMSB DB::FindMSB(iValue) + 1;
            
            
// Make iShift a multiple of 6 (if it isn't already)
            
if ((iShift iMSB 6))
                
aiOutput{iOutputIndex++} = 0b01000000 | (iValue >>> (iMSB iShift) & ~(0xFFFFFFFF << iShift));
            
            
iShift iMSB iShift;
            
            
// Write bits out left-right
            
while ((iShift -= 6) >= 0)
                
aiOutput{iOutputIndex++} = 0b01000000 | (iValue >>> iShift 0b00111111);
            
            
// Change the "more bytes" bits into "last byte"
            
aiOutput{iOutputIndex 1} |= 0b11000000;
        }
    }
    
    
// Put the number of bytes we just wrote into the first cell of the output
    
aiOutput[0] = 0x80808080 | ((iOutputIndex 0x1FE00000) << 3) | ((iOutputIndex 0x3FC000) << 2) | ((iOutputIndex 0x7F80) << 1) | (iOutputIndex 0x7F);
    
    
// Make sure the bytes in the last cell are 0
    
aiOutput{iOutputIndex} = 0;
    
    
iValue iOutputIndex;
    
    while (++
iOutputIndex 4)
        
aiOutput{iOutputIndex} = 0;
    
    
// Return the number of bytes written (not counting the first 4)
    
return iValue;
}
static 
stock DB::DecompressArray(const aiCompressedArray[], aiOutput[], iOutputSize sizeof(aiOutput)) {
    new
        
iBytes,
        
iOutputIndex 0
    
;
    
    
// Get the number of bytes to parse
    
iBytes aiCompressedArray[0];
    
iBytes = ((iBytes 0x7F000000) >>> 3) | ((iBytes 0x7F0000) >>> 2) | ((iBytes 0x7F00) >>> 1) | (iBytes 0x7F);
    
    for (new 
4iBytesi++) {
        
// Out of slots?
        
if (iOutputIndex >= iOutputSize) {
            
DB::Error("(DB::DecompressArray) Compressed array is larger than decompress buffer.");
        
            break;
        }
        
        
// Single byte?
        
if ((aiCompressedArray{i} & 0b10000000)) {
            
// Negative?
            
if ((aiCompressedArray{i} & 0b01000000))
                
aiOutput[iOutputIndex++] = -(aiCompressedArray{i} & 0b00111111);
            else
                
aiOutput[iOutputIndex++] =  (aiCompressedArray{i} & 0b00111111);
        } else {
            
// Multi byte; read the last bits
            
aiOutput[iOutputIndex] = aiCompressedArray{i} & 0b00111111;
            
            
// Keep reading bits while shifting the value to the left
            
do {
                
aiOutput[iOutputIndex] <<= 6;
                
aiOutput[iOutputIndex]  |= aiCompressedArray{++i} & 0b00111111;
            } while ((
aiCompressedArray{i} & 0b10000000) == 0);
            
            
iOutputIndex++;
        }
    }
    
    return 
iOutputIndex;
}
static 
stock DB::memset(aArray[], iValueiSize sizeof(aArray)) {
    new
        
iAddress
    
;
    
    
// Store the address of the array
    #emit LOAD.S.pri 12
    #emit STOR.S.pri iAddress
    
    // Convert the size from cells to bytes
    
iSize *= 4;
    
    
// Loop until there is nothing more to fill
    
while (iSize 0) {
        
// I have to do this because the FILL instruction doesn't accept a dynamic number.
        
if (iSize >= 4096) {
            
#emit LOAD.S.alt iAddress
            #emit LOAD.S.pri iValue
            #emit FILL 4096
        
            
iSize    -= 4096;
            
iAddress += 4096;
        } else if (
iSize >= 1024) {
            
#emit LOAD.S.alt iAddress
            #emit LOAD.S.pri iValue
            #emit FILL 1024
            
iSize    -= 1024;
            
iAddress += 1024;
        } else if (
iSize >= 256) {
            
#emit LOAD.S.alt iAddress
            #emit LOAD.S.pri iValue
            #emit FILL 256
            
iSize    -= 256;
            
iAddress += 256;
        } else if (
iSize >= 64) {
            
#emit LOAD.S.alt iAddress
            #emit LOAD.S.pri iValue
            #emit FILL 64
            
iSize    -= 64;
            
iAddress += 64;
        } else if (
iSize >= 16) {
            
#emit LOAD.S.alt iAddress
            #emit LOAD.S.pri iValue
            #emit FILL 16
            
iSize    -= 16;
            
iAddress += 16;
        } else {
            
#emit LOAD.S.alt iAddress
            #emit LOAD.S.pri iValue
            #emit FILL 4
            
iSize    -= 4;
            
iAddress += 4;
        }
    }
    
    
// aArray is used, just not by its symbol name
    #pragma unused aArray
    
    
return 1;
}
stock DB::LazyInitialize() {
    static
        
bool:bIsInitialized false
    
;
    
    if (
bIsInitialized)
        return;
    
    
bIsInitialized true;
    
    
#if defined HTTP
        
HTTP(0x7FEDCBA0HTTP_GET, !"spelsajten.net/sqlitei_version.php?version=097""", !"DB_VersionCheckReponse");
    
#endif
}
#if defined HTTP
    
forward DB::VersionCheckReponse(iIndexiResponseCode, const szResponse[]);
    public 
DB::VersionCheckReponse(iIndexiResponseCode, const szResponse[]) {
        if (
iResponseCode == 200) {
            if (
strval(szResponse) != 1) {
                print(!
"\n\n\n  *******************************************************************");
                print(      !
"  *   There's a new version version of SQLite Improved available!   *");
                print(      !
"  * Please visit the topic at the SA-MP forums for the latest copy. *");
                print(      !
"  *  Alternatively, get it here: http://spelsajten.net/sqlitei.inc  *");
                print(      !
"  *******************************************************************\n\n\n");
            }
        }
    }
#endif
stock db_escape_string(szString[], const szEnclosing[] = "'"iSize sizeof(szString)) {
    
DB::LazyInitialize();
    
    new
        
iPos
    
;
    
    while (-
!= (iPos strfind(szStringszEnclosing_iPos))) {
        
strins(szStringszEnclosingiPosiSize);
        
        
iPos += 2;
    }
}
stock bool:db_is_persistent(DB:db) {
    return !!(
_:db 0x80000000);
}
stock bool:db_is_valid_persistent(DB:db) {
    new
        
iIndex = (_:db 0x7FFFFFFF)
    ;
    
    if ((
<= iIndex sizeof(gs_PersistentDatabases)) && gs_PersistentDatabases[iIndex][e_bIsUsed])
        return 
true;
    
    return 
false;
}
stock bool:db_is_table_exists(DB:db, const szTable[])
{
    new
        
DBResult:dbrResult
    
;
    
    
format(gs_szBuffersizeof(gs_szBuffer), "SELECT name FROM sqlite_master WHERE type = 'table' AND tbl_name = '%s'"szTable);
    
    
dbrResult db_query(dbgs_szBufferfalse);
    
    if (
db_num_fields(dbrResult)) {
        
db_free_result(dbrResult);
        
        return 
true;
    }
    
    
db_free_result(dbrResult);
    
    return 
false;
}
stock bool:db_rewind(DBResult:dbrResult) {
    if (
dbrResult == DB::INVALID_RESULT) {
        
DB::Notice("(db_rewind) Invalid result given.");
        
        return 
false;
    }
    
    return 
db_set_row_index(dbrResult0);
}
stock bool:db_exec(DB:db, const szQuery[]) {
    new
        
DBResult:dbrResult db_query(dbszQueryfalse)
    ;
    
    if (
dbrResult) {
        
db_free_result(dbrResult);
        
        return 
true;
    }
    
    return 
false;
}
stock db_insert(DB:db, const szQuery[]) {
    new
        
DBResult:dbrResult db_query(dbszQueryfalse)
    ;
    
    if (
dbrResult) {
        
db_free_result(dbrResult);
        
        return 
db_last_insert_rowid(db);
    }
    
    return 
0;
}
stock db_get_struct_info(DB:db, {_e_SQLITE3}:iOffset) {
    if (
db_is_persistent(db)) {
        if (!
db_is_valid_persistent(db)) {
            
DB::Errorf("(db_get_struct_info) Invalid persistent database given (%04x%04x)."_:db >>> 16_:db 0xFFFF);
            
            return 
0;
        }
        
        new 
iIndex = (_:db 0x7FFFFFFF);
        
        
db gs_PersistentDatabases[iIndex][e_dbDatabase];
        
        if (!
db) {
            
DB::Errorf("(db_get_struct_info) Closed persistent database given (%04x%04x)."_:db >>> 16_:db 0xFFFF);
            
            return 
0;
        }
    }
    
    new
        
iAddress db_get_mem_handle(db DB:0x7FFFFFFF) - DB::GetAmxBaseRelative() + iOffset,
        
iValue
    
;
    
    
#emit LREF.S.pri  iAddress
    #emit STOR.S.pri  iValue
    
    
return iValue;
}
stock db_set_struct_info(DB:db, {_e_SQLITE3}:iOffsetiValue) {
    if (
db_is_persistent(db)) {
        if (!
db_is_valid_persistent(db)) {
            
DB::Errorf("(db_set_struct_info) Invalid persistent database given (%04x%04x)."_:db >>> 16_:db 0xFFFF);
            
            return 
0;
        }
        
        new 
iIndex = (_:db 0x7FFFFFFF);
        
        
db gs_PersistentDatabases[iIndex][e_dbDatabase];
        
        if (!
db) {
            
DB::Errorf("(db_set_struct_info) Closed persistent database given (%04x%04x)."_:db >>> 16_:db 0xFFFF);
            
            return 
0;
        }
    }
    
    new
        
iAddress db_get_mem_handle(db DB:0x7FFFFFFF) - DB::GetAmxBaseRelative() + iOffset
    
;
    
    
#emit LOAD.S.pri  iValue
    #emit SREF.S.pri  iAddress
}
stock bool:db_set_row_index(DBResult:dbrResultiRow) {
    if (
dbrResult == DB::INVALID_RESULT) {
        
DB::Notice("(db_set_row_index) Invalid result given.");
        
        return 
false;
    }
    
    if (
iRow || iRow >= db_num_rows(dbrResult))
        return 
false;
    
    new
        
iAddress db_get_result_mem_handle(dbrResult) - DB::GetAmxBaseRelative() + 16
    
;
    
    
#emit LOAD.S.pri  iRow
    #emit SREF.S.pri  iAddress
    
    
return true;
}
stock db_get_row_index(DBResult:dbrResult) {
    if (
dbrResult == DB::INVALID_RESULT) {
        
DB::Notice("(db_get_row_index) Invalid result given.");
        
        return 
0;
    }
    
    new
        
iAddress db_get_result_mem_handle(dbrResult) - DB::GetAmxBaseRelative() + 16
    
;
    
    
#emit LREF.S.pri  iAddress
    #emit STACK       4
    #emit RETN
    
    
return 0;
}
stock DB:db_open_persistent(const szName[]) {
    new
        
DB:db,
           
iIndex = -1
    
;
    
    for (new 
0sizeof(gs_PersistentDatabases); i++) {
        if (!
gs_PersistentDatabases[i][e_bIsUsed]) {
            
iIndex i;
            
            break;
        }
    }
    
    if (
iIndex == -1) {
        
DB::Error("(db_open_persistent) Unable to find a free slot.");
        
        return 
DB:-1;
    }
    
    if (!(
db db_open(szName))) {
        
DB::Error("(db_open_persistent) Unable to open the database.");
        
        return 
DB:-1;
    }
    
    
gs_PersistentDatabases[iIndex][e_bIsUsed]    = true;
    
gs_PersistentDatabases[iIndex][e_dbDatabase] = db;
    
gs_PersistentDatabases[iIndex][e_szName][0]  = 0;
    
    if (
gs_iClosePersistentTimer == -1)
        
gs_iClosePersistentTimer SetTimer("db_close_persistent"0false);
    
    
strpack(gs_PersistentDatabases[iIndex][e_szName], szName_:e_bIsUsed);
    
    
DB::Debug("(db_open_persistent=%d) Opened new persistent DB."iIndex);
    
    return 
DB:(iIndex 0x80000000);
}
stock db_close_hook(DB:db) {
    new
        
iIndex
    
;
    
    if (
db_is_persistent(db)) {
        if (!
db_is_valid_persistent(db)) {
            
DB::Errorf("(db_close) Invalid persistent database given (%04x%04x)."_:db >>> 16_:db 0xFFFF);
            
            return;
        }
        
        
iIndex = (_:db 0x7FFFFFFF);
        
        if (
gs_PersistentDatabases[iIndex][e_dbDatabase]) {
            
db_close@(gs_PersistentDatabases[iIndex][e_dbDatabase]);
            
            
gs_PersistentDatabases[iIndex][e_dbDatabase] = DB:0;
            
            
DB::Debug("(db_close) Closed the DB for the persistent DB with index %d."iIndex);
        } else {
            
DB::Debug("(db_close) Would close the DB for the persistent DB with index %d, but it already is."iIndex);
        }
    } else {
        
db_close@(db);
    }
}
stock db_query_int(DB:db, const szQuery[], iField 0) {
    new
        
DBResult:dbrResult db_query(dbszQueryfalse)
    ;
    if (!
dbrResult) {
        
strunpack(gs_szBufferszQuery);
        
        
DB::Warningf("(db_query_int) Query failed: \"%s\"."gs_szBuffer);
        
        return 
0;
    }
    
db_get_field(dbrResultiFieldgs_szBuffersizeof(gs_szBuffer) - 1);
    
db_free_result(dbrResult);
    return 
strval(gs_szBuffer);
}
stock Float:db_query_float(DB:db, const szQuery[], iField 0) {
    new
        
DBResult:dbrResult db_query(dbszQueryfalse)
    ;
    if (!
dbrResult) {
        
strunpack(gs_szBufferszQuery);
        
        
DB::Warningf("(db_query_float) Query failed: \"%s\"."gs_szBuffer);
        
        return 
0.0;
    }
    
db_get_field(dbrResultiFieldgs_szBuffersizeof(gs_szBuffer) - 1);
    
db_free_result(dbrResult);
    return 
floatstr(gs_szBuffer);
}
stock db_is_result_freed(DBResult:dbrResult) {
    if (
dbrResult == DB::INVALID_RESULT) {
        
DB::Notice("(db_is_result_freed) Invalid result given.");
        
        return 
true;
    }
    return 
db_get_result_mem_handle(dbrResult) == 0;
}
stock bool:db_free_result_hook(DBResult:dbrResult) {
    if (
dbrResult == DB::INVALID_RESULT) {
        
DB::Notice("(db_free_result_hook) Invalid result given.");
        
        return 
false;
    }
    
    
DB::Debug("(db_free_result) Freeing 0x%04x%04x."_:dbrResult >>> 16_:dbrResult 0xFFFF);
    
    for (new 
gs_iAutoFreeResultsIndexi--; ) {
        if (
gs_adbrAutoFreeResults[i] == dbrResult) {
            
gs_adbrAutoFreeResults[i] = DBResult:0;
            
            
DB::Debug("(db_free_result) The result being freed was inside the autorelease pool.");
        }
    }
    new
        
iFreeTestAddress db_get_result_mem_handle(dbrResult) - DB::GetAmxBaseRelative() + 16,
        
iData
    
;
    
    
#emit LREF.S.pri  iFreeTestAddress
    #emit STOR.S.pri  iData
    
    
if (iData != 0xFFFFFFFF) {
        new
            
iResultAddress db_get_result_mem_handle(dbrResult) - DB::GetAmxBaseRelative(),
            
iAddress,
            
iRows,
            
iCols,
            
iDataAddress,
            
iOffset,
            
iNullAddress
        
;
        
#emit CONST.pri   gs_szNull
        #emit STOR.S.pri  iNullAddress
        
        
iNullAddress +=  DB::GetAmxBaseRelative();
        
        
iAddress iResultAddress;
        
#emit LREF.S.pri  iAddress
        #emit STOR.S.pri  iRows
        
        
iAddress += 4;
        
#emit LREF.S.pri  iAddress
        #emit STOR.S.pri  iCols
        
        
iAddress += 4;
        
#emit LREF.S.pri  iAddress
        #emit STOR.S.pri  iDataAddress
        
        
iDataAddress -= DB::GetAmxBaseRelative();
        
        
iOffset = (iCols iRows iCols) * 4;
        
        while (
iOffset >= 0) {
            
iAddress iDataAddress iOffset;
            
            
#emit LREF.S.pri  iAddress
            #emit STOR.S.pri  iAddress
            
            
if (iAddress == iNullAddress) {
                
iAddress iDataAddress iOffset;
                
                
#emit CONST.pri   0
                #emit SREF.S.pri  iAddress
            
}
            
            
iOffset -= 4;
        }
        
        
db_free_result@(dbrResult);
        
        
#emit CONST.pri   0xFFFFFFFF
        #emit SREF.S.pri  iFreeTestAddress
        
        
return true;
    } else {
        
DB::Warning("(db_free_result) Attempted to free an already freed result; crash prevented.");
    }
    
    return 
false;
}
stock db_free_persistent(DB:db) {
    new
        
iIndex
    
;
    
    if (!
db_is_valid_persistent(db)) {
        
DB::Errorf("(db_free_persistent) Invalid persistent database given (%04x%04x)."_:db >>> 16_:db 0xFFFF);
        
        return;
    }
    
    
iIndex = (_:db 0x7FFFFFFF);
    
    if (
gs_PersistentDatabases[iIndex][e_dbDatabase]) {
        
db_close@(gs_PersistentDatabases[iIndex][e_dbDatabase]);
        
        
gs_PersistentDatabases[iIndex][e_dbDatabase] = DB:0;
        
        
DB::Debug("(db_free_persistent:%d) Closed and freed the persistent DB."iIndex);
    } else {
        
DB::Debug("(db_free_persistent:%d) Freed the already closed persistent DB."iIndex);
    }
    
    
gs_PersistentDatabases[iIndex][e_bIsUsed] = false;
}
stock db_changes(DB:db) {
    
DB::LazyInitialize();
    
    if (!
db) {
        
DB::Error("(db_changes) Invalid database handle given.");
        
        return 
0;
    }
    
    return 
db_get_struct_info(dbsqlite3_iNumChanges);
}
stock db_begin_transaction(DB:db)
    return 
db_exec(db, !"BEGIN");
stock db_end_transaction(DB:db)
    return 
db_exec(db, !"COMMIT");
stock db_set_asynchronous(DB:dbbool:bSet true) {
    
db_set_synchronous(DB:dbbSet DB::SYNCHRONOUS_OFF DB::SYNCHRONOUS_FULL);
}
stock bool:db_set_synchronous(DB:dbDB::e_SYNCHRONOUS_MODE:iValue) {
    if (
<= _:iValue <= 2) {
        
format(gs_szBuffersizeof(gs_szBuffer), "PRAGMA synchronous = %d"_:iValue);
    
        return 
db_exec(dbgs_szBuffer);
    } else
        return 
false;
}
stock bool:db_attach_memory_db(DB:db, const szName[]) {
    
strunpack(gs_szBufferszName);
    
    
db_escape_string(gs_szBuffer"\"");
    
    
format(gs_szBuffersizeof(gs_szBuffer), "ATTACH DATABASE ':memory:' AS \"%s\""gs_szBuffer);
    
    return 
db_exec(dbgs_szBuffer);
}
stock bool:db_detach_memory_db(DB:db, const szName[]) {
    
strunpack(gs_szBufferszName);
    
    
db_escape_string(gs_szBuffer"\"");
    
    
format(gs_szBuffersizeof(gs_szBuffer), "DETACH DATABASE \"%s\""gs_szBuffer);
    
    return 
db_exec(dbgs_szBuffer);
}
stock db_total_changes(DB:db) {
    
DB::LazyInitialize();
    if (!
db) {
        
DB::Error("(db_changes) Invalid database handle given.");
        return 
0;
    }
    return 
db_get_struct_info(dbsqlite3_iNumTotalChanges);
}
stock db_last_insert_rowid(DB:db) {
    
DB::LazyInitialize();
    
    if (!
db) {
        
DB::Error("(db_last_insert_rowid) Invalid database handle given.");
        
        return 
0;
    }
    
    return 
db_get_struct_info(dbsqlite3_iLastRowid);
}
stock db_field_is_null(DBResult:dbrResultiField) {
    if (
dbrResult == DB::INVALID_RESULT) {
        
DB::Notice("(db_field_is_null) Invalid result given.");
    
        return 
false;
    }
    
    new
        
iAddress db_get_result_mem_handle(dbrResult) - DB::GetAmxBaseRelative(),
        
iCols,
        
iCurrentRow
    
;
    
    
iAddress += 4;
    
#emit LREF.S.pri  iAddress
    #emit STOR.S.pri  iCols
    
    
if (iField >= iCols)
        return 
true;
    
    
iAddress += 8;
    
#emit LREF.S.pri  iAddress
    #emit STOR.S.pri  iCurrentRow
    
    
iAddress -= 4;
    
    
#emit LREF.S.pri  iAddress
    #emit STOR.S.pri  iAddress
    
    
iAddress -= DB::GetAmxBaseRelative();
    
iAddress += (iCols iCols iCurrentRow iField) * 4;
    
    
#emit LREF.S.pri  iAddress
    #emit CONST.alt   gs_szNull
    #emit SUB
    #emit STOR.S.pri  iAddress
    
    
iAddress -= DB::GetAmxBaseRelative();
    
    return !
iAddress;
}
stock db_autofree_result(DBResult:dbrResult) {
    
DB::LazyInitialize();
    
    if (
dbrResult == DB::INVALID_RESULT) {
        
DB::Notice("(db_autofree_result) Invalid result given.");
        
        return;
    }
    
    if (
gs_iAutoFreeTimer == -1)
        
gs_iAutoFreeTimer SetTimer("db_drain_autofree_pool"0false);
    
    if (
gs_iAutoFreeResultsIndex >= sizeof(gs_adbrAutoFreeResults)) {
        
DB::Warning("(db_autofree_result) The autofree pool is full!");
        
        return;
    }
    
    
gs_adbrAutoFreeResults[gs_iAutoFreeResultsIndex] = dbrResult;
    
    
DB::Debug("(db_autofree_result) Will autofree 0x%04x%04x."_:dbrResult >>> 16_:dbrResult 0xFFFF);
    
    
gs_iAutoFreeResultsIndex++;
}
stock DBStatement:db_prepare(DB:db, const szQuery[]) {
    
DB::LazyInitialize();
    
    new
        
DBStatement:stStatement DB::INVALID_STATEMENT,
        
iPos,
        
i,
        
iLength
    
;
    
    if (!
db) {
        
DB::Error("(db_prepare) Invalid database handle given.");
        
        return 
DB::INVALID_STATEMENT;
    }
    
    
// Pretty useless to prepare empty queries.
    
if (!(iLength strlen(szQuery))) {
        
DB::Error("(db_prepare) Empty query.");
        
        return 
DB::INVALID_STATEMENT;
    }
    
    if (
iLength char DB::MAX_STATEMENT_SIZE) {
        
DB::Error("(db_prepare) The query is too long. Increase DB_MAX_STATEMENT_SIZE.");
        
        return 
DB::INVALID_STATEMENT;
    }
    
    
// Find an empty slot in gs_Statements.
    
for (0sizeof(gs_Statements); i++) {
        if (!
gs_Statements[DBStatement:i][e_dbDatabase]) {
            
stStatement DBStatement:i;
            
            break;
        }
    }
    
    if (
stStatement == DB::INVALID_STATEMENT) {
        
DB::Error("(db_prepare) Unable to find an empty slot for the statement. Increase DB_MAX_STATEMENTS.");
        
        return 
DB::INVALID_STATEMENT;
    }
    
    
gs_Statements[stStatement][e_dbDatabase] = db;
    
gs_Statements[stStatement][e_dbrResult] = DB::INVALID_RESULT;
    
gs_Statements[stStatement][e_iFetchedRows] = 0;
    
    
// Make sure no parameters are initialized.
    
for (0DB::MAX_PARAMSi++)
        
gs_Statements[stStatement][e_aiParamTypes][i] = DB::TYPE_NONE;
    
    
// Make sure no return fields are initialized.
    
for (0DB::MAX_FIELDSi++)
        
gs_Statements[stStatement][e_aiFieldTypes][i] = DB::TYPE_NONE;
    
    
iPos = -1;
    
0;
    
    
// Find all parameters
    
while (-!= (iPos strfind(szQuery, !"?"_, ++iPos))) {
        
gs_Statements[stStatement][e_aiParamPositions][i] = iPos;
        
gs_Statements[stStatement][e_aiParamLengths][i] = 1;
        
        if (++
>= DB::MAX_PARAMS) {
            
DB::Error("(db_prepare) Parameter limit exceeded. Increase DB_MAX_PARAMS.");
            
            return 
DB::INVALID_STATEMENT;
        }
    }
    
    
gs_Statements[stStatement][e_iParams] = i;
    
    
gs_Statements[stStatement][e_szQuery][0] = 0;
    
    if (
ispacked(szQuery)) {
#if DB_DEBUG
        
strunpack(gs_szBufferszQuery);
        
        
DB::Debug("(db_prepare=%d) Preparing statement with %d params: %s"_:stStatementigs_szBuffer);
#endif
        
        
strcat(gs_Statements[stStatement][e_szQuery], szQueryDB::MAX_STATEMENT_SIZE);
    } else {
        
DB::Debug("(db_prepare=%d) Preparing statement with %d params: %s"_:stStatementiszQuery);
        
        
strpack(gs_Statements[stStatement][e_szQuery], szQueryDB::MAX_STATEMENT_SIZE);
    }
    
    return 
stStatement;
}
stock bool:stmt_bind_value(&DBStatement:stStatementiParamDBDataType:iType, {Float_}:...) {
    
DB::LazyInitialize();
    
    new
             
iLengthDiff,
             
iLength,
        
bool:bIsPacked,
             
iNumArgs
    
;
    
    
#emit LOAD.S.pri  8
    #emit SHR.C.pri   2
    #emit STOR.S.pri  iNumArgs
    
    
if (stStatement == DB::INVALID_STATEMENT || !(<= _:stStatement sizeof(gs_Statements))) {
        
DB::Warningf("(stmt_bind_value) Invalid statement passed (%d)."_:stStatement);
        
        return 
false;
    }
    
    if (
iParam >= gs_Statements[stStatement][e_iParams]) {
        
DB::Warningf("(stmt_bind_value) Parameter index larger than number of parameters (%d > %d)."iParamgs_Statements[stStatement][e_iParams]);
        
        return 
false;
    }
    
    
// Fill gs_szBuffer with the new contents.
    
gs_szBuffer[0] = 0;
    
    switch (
iType) {
        case 
DB::TYPE_NULL:
            goto 
default_case;
        
        case 
DB::TYPE_INT: {
            new
                
iArgValue getarg(3)
            ;
            
            if (
iArgValue == cellmin)
                
gs_szBuffer = !"-2147483648";
            else
                
format(gs_szBuffersizeof(gs_szBuffer), "%d"getarg(3));
        }
        
        case 
DB::TYPE_UINT: {
            new
                
iArgValue getarg(3)
            ;
            
            if (!
iArgValue) {
                
gs_szBuffer = !"0";
            } else {
                new
                    
11
                
;
                
                
gs_szBuffer "00000000000";
                
                while (
iArgValue) {
                    
// gs_szBuffer[--j]
                    #emit CONST.alt   gs_szBuffer // alt = *gs_szBuffer
                    #emit LOAD.S.pri  j           // pri = j
                    #emit DEC.pri                 // pri -= 1
                    #emit STOR.S.pri  j           // j = pri
                    #emit IDXADDR                 // pri = alt + j * 4
                    #emit PUSH.pri                // Store for later
                    // Now do an unsigned divide on iArgValue then use both the quotient and remainder!
                    #emit LOAD.S.pri  iArgValue // pri = iArgValue
                    #emit CONST.alt   10
                    #emit UDIV                  // pri = iArgValue / 10; alt = iArgValue % 10
                    #emit STOR.S.pri  iArgValue // iArgValue = pri
                    #emit CONST.pri   '0'
                    #emit ADD                   // pri = '0' + (iArgValue % 10)
                    #emit POP.alt               // alt = gs_szBuffer[j]
                    #emit STOR.I                // gs_szBuffer[j] = pri
                
}
            
                
strpack(gs_szBuffergs_szBuffer[j]);
            }
        }
        
        case 
DB::TYPE_FLOAT:
            
format(gs_szBuffersizeof(gs_szBuffer), "%f"getarg(3));
        
        case 
DB::TYPE_STRING: {
            new 
iSize sizeof(gs_szBuffer) - 3;
            
            
//strpack(dest[], const source[], maxlength = sizeof dest)
            #emit PUSH.S    iSize
            #emit PUSH.S    24 // arg 3
            #emit PUSH.C    gs_szBuffer
            #emit PUSH.C    12
            #emit SYSREQ.C  strpack
            #emit STACK     16
            
            
db_escape_string(gs_szBuffer"'"sizeof(gs_szBuffer) - 1);
            
            
strins(gs_szBuffer, !"'"0);
            
strcat(gs_szBuffer, !"'");
        }
        
#if DB::USE_WHIRLPOOL
        
case DB::TYPE_WP_HASH: {
            
strcat(gs_szBuffer"x'");
            
            
DB::getstringarg(gs_szBuffer[2], 3sizeof(gs_szBuffer) - 2);
            
            
DB::WP_Hash(gs_szBuffer[2], sizeof(gs_szBuffer) - 2gs_szBuffer[2]);
            
            
strcat(gs_szBuffer"'");
        }
#endif
        
        
case DB::TYPE_PLAYER_NAME: {
            new
                
iPlayer getarg(3)
            ;
            
            if (!(
<= iPlayer MAX_PLAYERS) || !IsPlayerConnected(iPlayer)) {
                
DB::Warningf("(stmt_bind_value) Invalid player ID passed for DB::TYPE_PLAYER_NAME (%d)."iPlayer);
                
                
strcat(gs_szBuffer, !"''");
            } else {
                
gs_szBuffer[0] = '\'';
                
                
GetPlayerName(iPlayergs_szBuffer[1], sizeof(gs_szBuffer) - 1);
                
                
db_escape_string(gs_szBuffer[1], "'"sizeof(gs_szBuffer) - 1);
                
                
strcat(gs_szBuffer"'");
            }
        }
        
        case 
DB::TYPE_PLAYER_IP: {
            new
                
iPlayer getarg(3)
            ;
            
            if (!(
<= iPlayer MAX_PLAYERS) || !IsPlayerConnected(iPlayer)) {
                
DB::Warningf("(stmt_bind_value) Invalid player ID passed for DB::TYPE_PLAYER_IP (%d)."iPlayer);
                
                
strcat(gs_szBuffer, !"''");
            } else {
                
gs_szBuffer[0] = '\'';
                
                
GetPlayerIp(iPlayergs_szBuffer[1], sizeof(gs_szBuffer) - 1);
                
                
db_escape_string(gs_szBuffer[1], "'"sizeof(gs_szBuffer) - 1);
                
                
strcat(gs_szBuffer"'");
            }
        }
        
        
// http://www.sqlite.org/lang_keywords.html...9.95162746
        
case DB::TYPE_IDENTIFIER: {
            
bIsPacked = !!DB::isargpacked(3);
            
            if (!
bIsPacked)
                
gs_szBuffer[0] = '"';
            
            
DB::getstringarg(gs_szBuffer[bIsPacked 1], 3sizeof(gs_szBuffer) - 3);
            
            
db_escape_string(gs_szBuffer[bIsPacked 1], "\""sizeof(gs_szBuffer) - 1);
            
            if (
bIsPacked)
                
strins(gs_szBuffer"\""0);
            
            
strcat(gs_szBuffer"\"");
        }
        
        case 
DB::TYPE_RAW_STRING:
            
DB::getstringarg(gs_szBuffer3);
        
        case 
DB::TYPE_ARRAY: {
            
// DB::CompressArray(const aiArray[], iSize = sizeof(aiArray), aiOutput[])
            
            
if (iNumArgs != 5) {
                
DB::Error("(stmt_bind_value) Invalid argument count. DB::TYPE_ARRAY requires an additional argument containing the array's length.");
                
                return 
false;
            }
            
            new
                
iCompressedSize,
                
i
            
;
            
            
// Push the output array
            #emit PUSH.C      gs_aiCompressBuffer
            
            // Push the size
            #emit LREF.S.pri  28 // 12 + 4 cells
            #emit PUSH.pri
            
            // Push the input array
            #emit PUSH.S      24
            
            // Push the argument count
            #emit PUSH.C      12
            
            // Push the return address
            #emit LCTRL       6
            #emit ADD.C       28
            #emit PUSH.pri
            
            // Call DB::CompressArray
            #emit CONST.pri   DB_CompressArray
            #emit SCTRL       6
            
            // Store the return value
            #emit STOR.S.pri  iCompressedSize
            
            
iCompressedSize = (iCompressedSize 3) / 4;
            
            
gs_szBuffer[0] = 'x';
            
gs_szBuffer[1] = '\'';
            
            if ((
iCompressedSize << 3) + sizeof(gs_szBuffer)) {
                for (
0iCompressedSizei++)
                    
format(gs_szBuffer[+ (<< 3)], sizeof(gs_szBuffer) - (+ (<< 3)), "%01x%07x"gs_aiCompressBuffer[i] >>> 28gs_aiCompressBuffer[i] & 0x0FFFFFFF);
            } else {
                
strcat(gs_szBuffer"00");
                
                
DB::Errorf("(stmt_bind_value) Unable to compress the array; out of buffer size (has %d, needs %d)."sizeof(gs_szBuffer), (iCompressedSize << 3) + 2);
                
                return 
false;
            }
            
            
strcat(gs_szBuffer"'");
        }    
        
        default: {
default_case:
            
            
strcat(gs_szBuffer"NULL");
        }
    }
    
    
iLength strlen(gs_szBuffer);
    
    
iLengthDiff iLength gs_Statements[stStatement][e_aiParamLengths][iParam];
    
    
// Adjust the position of any params after the one being modified.
    
for (new iParam 1gs_Statements[stStatement][e_iParams]; i++)
        
gs_Statements[stStatement][e_aiParamPositions][i] += iLengthDiff;
    
    
// Delete the old parameter from the query.
    
strdel(gs_Statements[stStatement][e_szQuery], gs_Statements[stStatement][e_aiParamPositions][iParam], gs_Statements[stStatement][e_aiParamPositions][iParam] + gs_Statements[stStatement][e_aiParamLengths][iParam]);
    
    
// Make sure we have enough space.
    
if ((strlen(gs_Statements[stStatement][e_szQuery]) + iLengthchar DB::MAX_STATEMENT_SIZE) {
        
DB::Error("(stmt_bind_value) Buffer overflow. Increase DB_MAX_STATEMENT_SIZE.");
        
        
stmt_close(stStatement);
        
        return 
false;
    }
    
    
// Insert the new parameter.
    
strins(gs_Statements[stStatement][e_szQuery], gs_szBuffergs_Statements[stStatement][e_aiParamPositions][iParam], DB::MAX_STATEMENT_SIZE);
    
#if DB_DEBUG
    
if (ispacked(gs_szBuffer))
        
strunpack(gs_szBuffergs_szBuffer);
    
    
DB::Debug("(stmt_bind_value:%d) Inserted new value for parameter %d at %d: %s"_:stStatementiParamgs_Statements[stStatement][e_aiParamPositions][iParam], gs_szBuffer);
#endif
    
    
gs_Statements[stStatement][e_aiParamLengths][iParam] = iLength;
    
gs_Statements[stStatement][e_aiParamTypes][iParam] = iType;
    
    return 
true;
}
stock stmt_bind_result_field(&DBStatement:stStatementiFieldDBDataType:iType, {Float_}:...) {
    
DB::LazyInitialize();
    
    new
        
iAddress,
        
iSize,
        
iNumArgs
    
;
    
    
#emit LOAD.S.pri  8
    #emit SHR.C.pri   2
    #emit STOR.S.pri  iNumArgs
    
if (stStatement == DB::INVALID_STATEMENT || !(<= _:stStatement sizeof(gs_Statements))) {
        
DB::Warningf("(stmt_bind_result_field) Invalid statement passed (%d)."_:stStatement);
        return;
    }
    if (
iField 0) {
        
DB::Errorf("(stmt_bind_result_field) Negative field index (%d)."iField);
        return;
    }
    
    switch (
iType) {
        case 
DB::TYPE_STRING,
             
DB::TYPE_RAW_STRING,
             
DB::TYPE_IDENTIFIER,
             
DB::TYPE_ARRAY: {
            if (
iNumArgs != 5) {
                
DB::Error("(stmt_bind_result_field) Invalid number of arguments passed. Strings and arrays require an additional argument containing the string size.");
                return;
            }
            
            
iSize getarg(4);
        }
        
        case 
DB::TYPE_NONE: {
            
gs_Statements[stStatement][e_aiFieldTypes][iField] = DB::TYPE_NONE;
            
            return;
        }
        
        default: {
            if (
iNumArgs != 4) {
                
DB::Error("(stmt_bind_result_field) Invalid number of arguments passed.");
                return;
            }
            
            
iSize 1;
        }
    }
    
    if (
iField >= DB::MAX_FIELDS) {
        
DB::Warningf("(stmt_bind_result_field) Field index larger than max number of fields (%d > %d). Increase DB_MAX_FIELDS."iFieldDB::MAX_FIELDS);
        
        return;
    }
    
    
// Without this, STOR.S.pri doesn't seem to do what it should.
    
iAddress 0;
    
    
#emit LOAD.S.pri 24
    #emit STOR.S.pri iAddress
    
    
gs_Statements[stStatement][e_aiFieldTypes][iField] = iType;
    
gs_Statements[stStatement][e_aiFieldAddresses][iField] = iAddress;
    
gs_Statements[stStatement][e_aiFieldSizes][iField] = iSize;
    
    
DB::Debug("(stmt_bind_result_field:%d) Bound result field %d (type %d) to variable 0x%04x%04x."_:stStatementiField_:iTypeiAddress >>> 16iAddress 0xFFFF);
}
stock bool:stmt_skip_row(&DBStatement:stStatement) {
    
DB::LazyInitialize();
    
    if (
stStatement == DB::INVALID_STATEMENT || !(<= _:stStatement sizeof(gs_Statements))) {
        
DB::Errorf("(stmt_skip_row) Invalid statement passed (%d)."_:stStatement);
        
        return 
false;
    }
    
    if (
gs_Statements[stStatement][e_dbrResult] == DB::INVALID_RESULT) {
        if (!
gs_Statements[stStatement][e_iFetchedRows])
            
DB::Warning("(stmt_skip_row) Statement has no result.");
        
        return 
false;
    }
    
    
gs_Statements[stStatement][e_iFetchedRows]++;
    
    if (!
db_next_row(gs_Statements[stStatement][e_dbrResult])) {
        
db_free_result(gs_Statements[stStatement][e_dbrResult]);
        
        
gs_Statements[stStatement][e_dbrResult] = DB::INVALID_RESULT;
        
        
DB::Debug("(stmt_skip_row:%d) Skipped row and freed result."_:stStatement);
    } else {
        
DB::Debug("(stmt_skip_row:%d) Skipped row."_:stStatement);
    }
    
    return 
true;
}
stock bool:stmt_fetch_row(&DBStatement:stStatement) {
    
DB::LazyInitialize();
    
    if (
stStatement == DB::INVALID_STATEMENT || !(<= _:stStatement sizeof(gs_Statements))) {
        
DB::Errorf("(stmt_fetch_row) Invalid statement passed (%d)."_:stStatement);
        
        return 
false;
    }
    
    if (
gs_Statements[stStatement][e_dbrResult] == DB::INVALID_RESULT) {
        if (!
gs_Statements[stStatement][e_iFetchedRows])
            
DB::Warning("(stmt_fetch_row) Statement has no result.");
        
        return 
false;
    }
    if (!
stmt_rows_left(stStatement)) {
        
DB::Debug("(stmt_fetch_row) No rows left.");
        return 
false;
    }
    
    if (!
db_num_rows(gs_Statements[stStatement][e_dbrResult])) {
        
DB::Debug("(stmt_fetch_row) Freed previous result.");
        
        
db_free_result(gs_Statements[stStatement][e_dbrResult]);
        
        
gs_Statements[stStatement][e_dbrResult] = DB::INVALID_RESULT;
    
        return 
false;
    }
    
    new
        
iFields db_num_fields(gs_Statements[stStatement][e_dbrResult]),
        
iAddress,
        
xValue,
        
iCount
    
;
    
    if (
iFields DB::MAX_FIELDS) {
        
DB::Warning("(stmt_bind_result_field) There are more fields returned than DB_MAX_FIELDS.");
        
        
iFields DB::MAX_FIELDS;
    }
    
    
gs_Statements[stStatement][e_iFetchedRows]++;
    
    for (new 
iField 0iField iFieldsiField++) {
        if (
gs_Statements[stStatement][e_aiFieldTypes][iField] == DB::TYPE_NONE)
            continue;
        
        
iCount++;
        
        switch (
gs_Statements[stStatement][e_aiFieldTypes][iField]) {
            case 
DB::TYPE_NONE,
                 
DB::TYPE_NULL:
                continue;
            
            case 
DB::TYPE_INT,
                 
DB::TYPE_UINT,
                 
DB::TYPE_FLOAT: {
                
db_get_field(gs_Statements[stStatement][e_dbrResult], iFieldgs_szBuffersizeof(gs_szBuffer) - 1);
                
                
iAddress gs_Statements[stStatement][e_aiFieldAddresses][iField];
                
xValue = (gs_Statements[stStatement][e_aiFieldTypes][iField] != DB::TYPE_FLOAT) ? strval(gs_szBuffer) : _:floatstr(gs_szBuffer);
                
#emit LOAD.S.pri xValue
                #emit SREF.S.pri iAddress
            
}
            
            
// Assumes the field is a string containing a player name.
            // Gives the ID of a connected play with that name, otherwise INVALID_PLAYER_ID.
            
case DB::TYPE_PLAYER_NAME: {
                static
                    
s_szName[MAX_PLAYER_NAME]
                ;
                
                
xValue INVALID_PLAYER_ID;
                
                for (new 
0GetMaxPlayers(); li++) {
                    if (!
IsPlayerConnected(i))
                        continue;
                    
                    
GetPlayerName(is_szNamesizeof(s_szName));
                    
db_get_field(gs_Statements[stStatement][e_dbrResult], iFieldgs_szBuffersizeof(gs_szBuffer) - 1);
                    
                    if (!
strcmp(gs_szBuffers_szNametrue)) {
                        
xValue i;
                        
                        break;
                    }
                }
                
                
iAddress gs_Statements[stStatement][e_aiFieldAddresses][iField];
                
#emit LOAD.S.pri xValue
                #emit SREF.S.pri iAddress
            
}
            
            case 
DB::TYPE_STRING,
                 
DB::TYPE_RAW_STRING,
                 
DB::TYPE_IDENTIFIER: {
                new
                    
DBResult:dbrResult,
                             
iSize
                
;
                
                static const
                    
sc_szFormatString[] = "%s"
                
;
                
                
iAddress  gs_Statements[stStatement][e_aiFieldAddresses][iField];
                
dbrResult gs_Statements[stStatement][e_dbrResult];
                
iSize     gs_Statements[stStatement][e_aiFieldSizes][iField];
                
                
#emit PUSH.S    iSize
                #emit PUSH.S    iAddress
                #emit PUSH.S    iField
                #emit PUSH.S    dbrResult
                #emit PUSH.C    16
                #emit SYSREQ.C  db_get_field
                #emit STACK     20
                
                // Fix a bug with UTF-8 characters
                // For example, 'Г¶' would become 0xFFFFFFC3 instead of 0xC3
                #emit PUSH.S     iAddress
                #emit PUSH.C     sc_szFormatString
                #emit PUSH.S     iSize
                #emit PUSH.S     iAddress
                #emit PUSH.C     16
                #emit SYSREQ.C   format
                #emit STACK      20
            
}
            
            case 
DB::TYPE_ARRAY: {
                
// DecompressArray(const aiCompressedArray[], aiOutput[], iOutputSize = sizeof(aiOutput))
                
                
db_get_field(gs_Statements[stStatement][e_dbrResult], iFieldgs_szBuffersizeof(gs_szBuffer) - 1);
                
                
format(gs_szBuffersizeof(gs_szBuffer), "%s"gs_szBuffer);
                
strpack(gs_szBuffergs_szBuffer);
                
                new
                    
iOutputSize gs_Statements[stStatement][e_aiFieldSizes][iField],
                    
iDecompressedCells
                
;
                
                
iAddress gs_Statements[stStatement][e_aiFieldAddresses][iField];
                
                
// Push the output array size
                #emit PUSH.S      iOutputSize
                // Push the output array
                #emit PUSH.S      iAddress
                // Push the input array
                #emit PUSH.C      gs_szBuffer
                // Push the argument count
                #emit PUSH.C      12
                // Push the return address
                #emit LCTRL       6
                #emit ADD.C       28
                #emit PUSH.pri
                // Call DB::DecompressArray
                #emit CONST.pri   DB_DecompressArray
                #emit SCTRL       6
                
                // Store the return address
                #emit STOR.S.pri  iDecompressedCells
                
                // If there are more cells in the array, fill them with 0
                
if (iOutputSize iDecompressedCells) {
                    
DB::Noticef("(stmt_fetch_row:%d) The array fetched from the DB is smaller than the destination array (%d > %d); the remaining slots with will be filled with 0."_:stStatementiOutputSizeiDecompressedCells);
                    
                    
iAddress += iDecompressedCells 4-4;
                    
iOutputSize iOutputSize iDecompressedCells;
                    
                    
// DB::memset(aArray[], iValue, iSize = sizeof(aArray))
                    #emit PUSH.S      iOutputSize
                    #emit PUSH.C      0
                    #emit PUSH.S      iAddress
                    #emit PUSH.C      12
                    #emit LCTRL       6
                    #emit ADD.C       28
                    #emit PUSH.pri
                    #emit CONST.pri   DB_memset
                    #emit SCTRL       6
                
}
                
                
            }
        }
    }
    
    if (!
db_next_row(gs_Statements[stStatement][e_dbrResult])) {
        
db_free_result(gs_Statements[stStatement][e_dbrResult]);
        
        
gs_Statements[stStatement][e_dbrResult] = DB::INVALID_RESULT;
        
        
DB::Debug("(stmt_fetch_row:%d) Fetched %d fields and freed the result."_:stStatementiCount);
    } else {
        
DB::Debug("(stmt_fetch_row:%d) Fetched %d fields."_:stStatementiCount);
    }
    
    return 
true;
}
stock stmt_rows_left(&DBStatement:stStatement) {
    
DB::LazyInitialize();
    
    if (
stStatement == DB::INVALID_STATEMENT || !(<= _:stStatement sizeof(gs_Statements))) {
        
DB::Errorf("(stmt_rows_left) Invalid statement passed (%d)."_:stStatement);
        
        return 
0;
    }
    
    if (
gs_Statements[stStatement][e_dbrResult] == DB::INVALID_RESULT) {
        if (!
gs_Statements[stStatement][e_iFetchedRows])
            
DB::Warning("(stmt_rows_left) Statement has no result.");
        
        return 
0;
    }
    
    return 
max(0db_num_rows(gs_Statements[stStatement][e_dbrResult]) - gs_Statements[stStatement][e_iFetchedRows]);
}
stock bool:stmt_execute(&DBStatement:stStatementbool:bStoreResult truebool:bAutoFreeResult true) {
    
DB::LazyInitialize();
    
    if (
stStatement == DB::INVALID_STATEMENT || !(<= _:stStatement sizeof(gs_Statements))) {
        
DB::Errorf("(stmt_execute) Invalid statement passed (%d)."_:stStatement);
        
        return 
false;
    }
    
    if (!
gs_Statements[stStatement][e_dbDatabase]) {
        
DB::Errorf("(stmt_execute) Uninitialized statement passed (%d)."_:stStatement);
        
        return 
false;
    }
    
    
// Make sure all parameters have been set.
    
for (new 0gs_Statements[stStatement][e_iParams]; i++) {
        if (
gs_Statements[stStatement][e_aiParamTypes][i] == DB::TYPE_NONE) {
            
DB::Errorf("(stmt_execute) Uninitialized parameter in statement (%d)."i);
            
            return 
false;
        }
    }
    
    
// If old results are left, free them.
    
if (gs_Statements[stStatement][e_dbrResult] != DB::INVALID_RESULT) {
        
db_free_result(gs_Statements[stStatement][e_dbrResult]);
        
        
gs_Statements[stStatement][e_dbrResult] = DB::INVALID_RESULT;
    }
    
    
DB::Debug("(stmt_execute:%d) Executing statement."_:stStatement);
    
    new
        
DBResult:dbrResult db_query(gs_Statements[stStatement][e_dbDatabase], gs_Statements[stStatement][e_szQuery], false)
    ;
    
    
gs_Statements[stStatement][e_iFetchedRows] = 0;
    
gs_Statements[stStatement][e_bAutoFreeResult] = bAutoFreeResult;
    
    if (
dbrResult == DB::INVALID_RESULT)
        return 
false;
    
    if (!
bStoreResult)
        
db_free_result(dbrResult);
    else {
        
gs_Statements[stStatement][e_dbrResult] = dbrResult;
        
        if (
bAutoFreeResult && gs_iFreeStatementResultsTimer == -1)
            
gs_iFreeStatementResultsTimer SetTimer("db_free_stmt_results"1false);
    }
    
    return 
true;
}
stock stmt_free_result(&DBStatement:stStatement) {
    
DB::LazyInitialize();
    
    if (
stStatement == DB::INVALID_STATEMENT || !(<= _:stStatement sizeof(gs_Statements))) {
        
DB::Noticef("(stmt_free_result) Invalid statement passed (%d)."_:stStatement);
        
        return;
    }
    
    
gs_Statements[stStatement][e_iFetchedRows] = 0;
    
    if (
gs_Statements[stStatement][e_dbrResult] != DB::INVALID_RESULT) {
        
db_free_result(gs_Statements[stStatement][e_dbrResult]);
        
        
gs_Statements[stStatement][e_dbrResult] = DB::INVALID_RESULT;
        
        
DB::Debug("(stmt_free_result:%d) Freed result."_:stStatement);
    } else {
        
DB::Debug("(stmt_free_result:%d) Nothing to free."_:stStatement);
    }
}
stock stmt_close(&DBStatement:stStatement) {
    
DB::LazyInitialize();
    
    if (
stStatement == DB::INVALID_STATEMENT || !(<= _:stStatement sizeof(gs_Statements))) {
        
DB::Noticef("(stmt_close) Invalid statement passed (%d)."_:stStatement);
        
        return;
    }
    
    if (
gs_Statements[stStatement][e_dbrResult] != DB::INVALID_RESULT)
        
db_free_result(gs_Statements[stStatement][e_dbrResult]);
    
    
gs_Statements[stStatement][e_dbDatabase] = DB:0;
    
    
DB::Debug("(stmt_close:%d) Closed statement."_:stStatement);
    
    
stStatement DB::INVALID_STATEMENT;
}
stock stmt_autoclose(&DBStatement:stStatement) {
    
DB::LazyInitialize();
    
    if (
stStatement == DB::INVALID_STATEMENT || !(<= _:stStatement sizeof(gs_Statements))) {
        
DB::Noticef("(stmt_autoclose) Invalid statement passed (%d)."_:stStatement);
        
        return;
    }
    
    if (
gs_iAutoFreeTimer == -1)
        
gs_iAutoFreeTimer SetTimer("db_drain_autofree_pool"0false);
    
    if (
gs_iAutoCloseStatementsIndex >= sizeof(gs_astAutoCloseStatements)) {
        
DB::Warning("(stmt_autoclose) The autoclose pool is full!");
        
        return;
    }
    
    
gs_astAutoCloseStatements[gs_iAutoCloseStatementsIndex] = stStatement;
    
    
gs_iAutoCloseStatementsIndex++;
    
    
DB::Debug("(stmt_autoclose:%d) Will autoclose statement."_:stStatement);
}
stock DBResult:db_query_hook(iTagOf3 tagof(_bAutoRelease), DB:db, const szQuery[], {boolDBDataType}:_bAutoRelease true, {DBDataTypeQQPA}:...) {
    new
             
iIndex,
             
iNumArgs,
             
iStaticArgs 4,
        
bool:bAutoRelease true
    
;
    
    
#emit LOAD.S.pri  8
    #emit SHR.C.pri   2
    #emit STOR.S.pri  iNumArgs
    
    
DB::LazyInitialize();
    
    if (
iTagOf3 == tagof(DBDataType:)) {
        
iStaticArgs 3;
    } else {
        
bAutoRelease _bAutoRelease;
    }
    
    if (
db_is_persistent(db)) {
        if (!
db_is_valid_persistent(db)) {
            
DB::Errorf("(db_query) Invalid persistent database given (%04x%04x)."_:db >>> 16_:db 0xFFFF);
            
            return 
DB::INVALID_RESULT;
        }
        
        
iIndex _:db 0x7FFFFFFF;
        
        if (!
gs_PersistentDatabases[iIndex][e_dbDatabase]) {
            if (!(
gs_PersistentDatabases[iIndex][e_dbDatabase] = db_open(gs_PersistentDatabases[iIndex][e_szName]))) {
                
DB::Errorf("(db_query) Failed to lazily open the database.");
                
                return 
DB::INVALID_RESULT;
            }
            
            if (
gs_iClosePersistentTimer == -1)
                
gs_iClosePersistentTimer SetTimer("db_close_persistent"0false);
        }
        
        
db gs_PersistentDatabases[iIndex][e_dbDatabase];
    }
    
#if DB_DEBUG
    
if (ispacked(szQuery)) {
        
strunpack(gs_szBufferszQuery);
        
        
DB::Debug("(db_query) Running query: %s"gs_szBuffer);
    } else {
        
DB::Debug("(db_query) Running query: %s"szQuery);
    }
#endif
    
    
new
        
DBResult:dbrResult
    
;
    
    if (
iNumArgs iStaticArgs) {
        if ((
iNumArgs iStaticArgs) & 0b1) {
            
DB::Error("(db_query) Invalid argument count. Did you forget to use the correct prefix on the arguments (e.g. STRING:somestring)?");
            
            return 
DB::INVALID_RESULT;
        }
        
        new 
DBStatement:stmt db_prepare(dbszQuery);
        
        for (new 
iStaticArgs 1iNumArgs+= 2) {
            
// Load the address of argument <i>
            #emit LCTRL       5
            #emit LOAD.S.alt  i
            #emit SHL.C.alt   2
            #emit ADD
            #emit ADD.C       12
            #emit MOVE.alt
            #emit LOAD.I
            #emit PUSH.pri
            #emit PUSH.alt
            
            
if (== 4) {
                
// Load the address of argument <i - 1>
                #emit POP.pri
                #emit ADD.C       0xFFFFFFFC
                #emit LOAD.I
                #emit PUSH.pri
            
} else {
                
// Load the address of argument <i - 1>
                #emit POP.pri
                #emit ADD.C       0xFFFFFFFC
                #emit LOAD.I
                #emit LOAD.I
                #emit PUSH.pri
            
}
            
            
// Push the param index: (i - iStaticArgs) / 2
            #emit LOAD.S.pri  i
            #emit LOAD.S.alt  iStaticArgs
            #emit SUB
            #emit SHR.C.pri   1
            #emit PUSH.pri
            #emit PUSH.ADR    stmt
            
            // Push the argument count
            #emit PUSH.C      16
            
            // Push the return address
            #emit LCTRL       6
            #emit ADD.C       28
            #emit PUSH.pri
            
            // Call stmt_bind_value
            #emit CONST.pri   stmt_bind_value
            #emit SCTRL       6
        
}
        
        
dbrResult db_query@(dbgs_Statements[stmt][e_szQuery]);
        
        
stmt_close(stmt);
    } else {
        
dbrResult db_query@(dbszQuery);
    }
    
    if (
dbrResult) {
        if (
bAutoRelease)
            
db_autofree_result(dbrResult);
        
        new
            
iResultAddress db_get_result_mem_handle(dbrResult) - DB::GetAmxBaseRelative(),
            
iAddress,
            
iRows,
            
iCols,
            
iDataAddress,
            
iOffset
        
;
        
        
iAddress iResultAddress;
        
#emit LREF.S.pri  iAddress
        #emit STOR.S.pri  iRows
        
        
iAddress += 4;
        
#emit LREF.S.pri  iAddress
        #emit STOR.S.pri  iCols
        
        
iAddress += 4;
        
#emit LREF.S.pri  iAddress
        #emit STOR.S.pri  iDataAddress
        
        
iDataAddress -= DB::GetAmxBaseRelative();
        
        
iOffset = (iCols iRows iCols) * 4;
        
        while (
iOffset >= 0) {
            
iAddress iDataAddress iOffset;
            
            
#emit LREF.S.pri  iAddress
            #emit STOR.S.pri  iAddress
            
            
if (!iAddress) {
                new
                    
iAmxBaseRelative DB::GetAmxBaseRelative()
                ;
                
                
iAddress iDataAddress iOffset;
                
                
#emit CONST.pri   gs_szNull
                #emit LOAD.S.alt  iAmxBaseRelative
                #emit ADD
                #emit SREF.S.pri  iAddress
            
}
            
            
iOffset -= 4;
        }
    }
    
    return 
dbrResult;
}
stock db_get_field_hook(DBResult:dbresultfieldresult[], maxlength sizeof(result)) {
    new 
retval db_get_field(dbresultfieldresultmaxlength);
    
    
format(resultmaxlength"%s"result);
    
    return 
retval;
}
stock db_get_field_assoc_hook(DBResult:dbresult, const field[], result[], maxlength sizeof(result)) {
    new 
retval db_get_field_assoc(dbresultfieldresultmaxlength);
    
    
format(resultmaxlength"%s"result);
    
    return 
retval;
}
stock bool:db_dump_table(DB:db, const szTable[], const szFilename[]) {
    static
        
s_szColumnName[256]
    ;
    new
        
DBResult:dbrResult,
        
File:fp
    
;
    
    if (
strfind(szTable"\"") != -|| strfind(szTable"'") != -1) {
        
DB::Error("(db_dump_table) Invalid table name given.");
        
        return 
false;
    }
    
    if (!(
fp fopen(szFilenameio_write))) {
        
DB::Error("(db_dump_table) Failed to open the file.");
        
        return 
false;
    }
    
    
format(gs_szBuffersizeof(gs_szBuffer), "SELECT sql FROM sqlite_master WHERE tbl_name = '%s'"szTable);
    
    
dbrResult db_query(dbgs_szBuffer);
    
    if (!
dbrResult) {
        
DB::Error("(db_dump_table) Failed to get the table sql.");
        
        return 
false;
    }
    
    
db_get_field(dbrResult0gs_szBuffersizeof(gs_szBuffer) - 1);
    
    if (
strlen(gs_szBuffer) >= sizeof(gs_szBuffer) - 2) {
        
DB::Error("(db_dump_table) Buffer overflow.");
        
        
fwrite(fp"\nBUFFER OVERFLOW");
        
fclose(fp);
        
        
db_free_result(dbrResult);
        
        return 
false;
    }
    
    
fwrite(fpgs_szBuffer);
    
fwrite(fp";\n\n\n");
    
    
db_free_result(dbrResult);
    
    
format(gs_szBuffersizeof(gs_szBuffer), "PRAGMA table_info(%s)"szTable);
    
    
dbrResult db_query(dbgs_szBufferfalse);
    
    if (!
dbrResult) {
        
DB::Error("(db_dump_table) Failed to get table info.");
        
        return 
false;
    }
    
    
gs_szBuffer "SELECT 'INSERT INTO ";
    
strcat(gs_szBufferszTable);
    
strcat(gs_szBuffer" VALUES('");
    
    if (
db_num_rows(dbrResult)) do {
        
db_get_field(dbrResult1s_szColumnNamesizeof(s_szColumnName) - 1);
        
        if (
db_get_row_index(dbrResult) > 0)
            
strcat(gs_szBuffer" || ', '");
        
        
strcat(gs_szBuffer" || quote(");
        
strcat(gs_szBuffers_szColumnName);
        
strcat(gs_szBuffer")");
    } while (
db_next_row(dbrResult));
    
    
strcat(gs_szBuffer" || ');' FROM ");
    
strcat(gs_szBufferszTable);
    
    
db_free_result(dbrResult);
    
    
dbrResult db_query(dbgs_szBuffer);
    
    
fwrite(fp"BEGIN;\n\n");
    
    if (
db_num_rows(dbrResult)) do {
        
db_get_field(dbrResult0gs_szBuffersizeof(gs_szBuffer) - 1);
        
        if (
strlen(gs_szBuffer) >= sizeof(gs_szBuffer) - 2) {
            
DB::Error("(db_dump_table) Buffer overflow.");
            
            
fwrite(fp"\nBUFFER OVERFLOW");
            
fclose(fp);
            
            
db_free_result(dbrResult);
            
            return 
false;
        }
        
        
fwrite(fpgs_szBuffer);
        
fwrite(fp"\n");
    } while (
db_next_row(dbrResult));
    
    
fwrite(fp"\nCOMMIT;\n");
    
    
db_free_result(dbrResult);
    
    
fclose(fp);
    
    return 
true;
}
stock DBResult:db_print_result(DBResult:dbrResultiMaxFieldLength 40) {
    
DB::LazyInitialize();
    
    const
        
MAX_ROWS         100,
        
MAX_FIELDS       20,
        
MAX_FIELD_LENGTH 88
    
;
    
    static
        
s_aaszFields[MAX_ROWS 1][MAX_FIELDS][MAX_FIELD_LENGTH char],
        
s_aiFieldMaxLength[MAX_FIELDS]
    ;
    
    static const
        
szcSpacePadding[MAX_FIELD_LENGTH] = {' ', ...},
        
szcDashPadding[MAX_FIELD_LENGTH] = {'-', ...}
    ;
    
    if (
iMaxFieldLength == -1)
        
iMaxFieldLength MAX_FIELD_LENGTH;
    
    print(!
" ");
    print(!
"Query result:");
    
    if (!
dbrResult)
        print(!
"\t- Invalid result.");
    else if (!
db_num_rows(dbrResult))
        print(!
"\t- No rows.");
    else {
        new
                 
iRow 0,
                 
iRows,
                 
iFields db_num_fields(dbrResult),
                 
iField,
                 
iLength,
            
bool:bHasMoreLines,
                 
iPos,
                 
iNextPos,
                 
iRowIndex db_get_row_index(dbrResult)
        ;
        
        
db_set_row_index(dbrResult0);
        
        if (
iMaxFieldLength MAX_FIELD_LENGTH) {
            
printf("\t- The longest possible field length is %d. Change MAX_FIELD_LENGTH for larger values."MAX_FIELD_LENGTH);
            
            
iMaxFieldLength MAX_FIELD_LENGTH;
        }
        
        if (
iFields MAX_FIELDS) {
            
printf("\t- There are %d, but only %d of them will be visible."iFieldsMAX_FIELDS);
            print(!
"\t- Increase MAX_FIELDS if you want to see all fields.");
            
            
iFields MAX_FIELDS;
        }
        
        for (
iField 0iField iFieldsiField++) {
            
db_field_name(dbrResultiFieldgs_szBufferiMaxFieldLength 1);
            
            
iPos 0;
            
            while (-
!= (iPos strfind(gs_szBuffer"\r"_iPos)))
                
gs_szBuffer[iPos] = ' ';
            
            
iPos 0;
            
            while (-
!= (iPos strfind(gs_szBuffer"\t"_iPos))) {
                
gs_szBuffer[iPos] = ' ';
                
                
strins(gs_szBuffer"   "iPosiMaxFieldLength);
                
                
iPos += 4;
            }
            
            
iPos 0;
            do {
                
iNextPos strfind(gs_szBuffer"\n"_iPos) + 1;
                if (!
iNextPos)
                    
iLength strlen(gs_szBuffer[iPos]);
                else
                    
iLength iNextPos iPos 1;
                
s_aiFieldMaxLength[iField] = min(iMaxFieldLengthmax(iLengths_aiFieldMaxLength[iField]));
            } while ((
iPos iNextPos));
            
            
strpack(s_aaszFields[0][iField], gs_szBufferiMaxFieldLength char);
        }
        
        do {
            for (
iField 0iField iFieldsiField++) {
                if (
db_field_is_null(dbrResultiField))
                    
gs_szBuffer "NULL";
                else
                    
db_get_field(dbrResultiFieldgs_szBufferiMaxFieldLength 1);
                
                
iPos 0;
                
                while (-
!= (iPos strfind(gs_szBuffer"\r"_iPos)))
                    
gs_szBuffer[iPos] = ' ';
                
                
iPos 0;
                
                while (-
!= (iPos strfind(gs_szBuffer"\t"_iPos))) {
                    
gs_szBuffer[iPos] = ' ';
                    
                    
strins(gs_szBuffer"   "iPosiMaxFieldLength);
                    
                    
iPos += 4;
                }
                
                
iPos 0;
                do {
                    
iNextPos strfind(gs_szBuffer"\n"_iPos) + 1;
                    if (!
iNextPos)
                        
iLength strlen(gs_szBuffer[iPos]);
                    else
                        
iLength iNextPos iPos 1;
                    
s_aiFieldMaxLength[iField] = min(iMaxFieldLengthmax(iLengths_aiFieldMaxLength[iField]));
                } while ((
iPos iNextPos));
                
strpack(s_aaszFields[iRow 1][iField], gs_szBufferiMaxFieldLength char);
            }
            
            if (++
iRow >= MAX_ROWS) {
                
iRows iRow;
                
                while (
db_next_row(dbrResult))
                    
iRows++;
                
                
printf("\t- Only the first %d rows are displayed; there are %d remaining."MAX_ROWSiRows);
                
                break;
            }
        } while (
db_next_row(dbrResult));
        
        print(!
" ");
        
        for (
iRows iRowiRow 0iRow <= iRowsiRow++) {
            do {
                
bHasMoreLines false;
                
                
gs_szBuffer[0] = 0;
                
                for (
iField 0iField iFieldsiField++) {
                    if (
iField)
                        
strcat(gs_szBuffer" | ");
                    
                    
iLength strlen(gs_szBuffer);
                    
                    if (-
!= (iPos strfind(s_aaszFields[iRow][iField], "\n"))) {
                        
strunpack(gs_szBuffer[iLength], s_aaszFields[iRow][iField], strlen(gs_szBuffer[iLength]) + iPos 1);
                        
                        
strdel(s_aaszFields[iRow][iField], 0iPos 1);
                        
                        
bHasMoreLines true;
                    } else {
                        if (
s_aaszFields[iRow][iField]{0}) {
                            
strunpack(gs_szBuffer[iLength], s_aaszFields[iRow][iField], sizeof(gs_szBuffer) - iLength);
                            
                            
s_aaszFields[iRow][iField]{0} = 0;
                        }
                    }
                
                    
iLength strlen(gs_szBuffer[iLength]);
                    
                    
strcat(gs_szBufferszcSpacePaddingstrlen(gs_szBuffer) + (s_aiFieldMaxLength[iField] - iLength 1));
                }
                
                if (
bHasMoreLines)
                    
printf("\t| %s |"gs_szBuffer);
                
            } while (
bHasMoreLines);
            
            if (
iRow == 0) {
                
printf("\t/ %s \\"gs_szBuffer);
            } else {
                
printf("\t| %s |"gs_szBuffer);
            }
            
            if (
iRow == iRows) {
                
gs_szBuffer[0] = 0;
                
                for (
iField 0iField iFieldsiField++) {
                    if (
iField)
                        
strcat(gs_szBuffer"---");
                    
                    
strcat(gs_szBufferszcDashPaddingstrlen(gs_szBuffer) + s_aiFieldMaxLength[iField] + 1);
                }
                
printf("\t\\-%s-/"gs_szBuffer);
            } else {
                
gs_szBuffer[0] = 0;
                
                for (
iField 0iField iFieldsiField++) {
                    if (
iField)
                        
strcat(gs_szBuffer"-|-");
                    
                    
strcat(gs_szBufferszcDashPaddingstrlen(gs_szBuffer) + s_aiFieldMaxLength[iField] + 1);
                }
                
                
printf("\t|-%s-|"gs_szBuffer);
            }
        }
        
        
db_set_row_index(dbrResultiRowIndex);
    }
    
    print(!
" ");
    
    return 
dbrResult;
}
stock db_print_query(DB:db, const szQuery[], iMaxFieldLength 40) {
    new
        
DBResult:dbrResult db_query(dbszQueryfalse)
    ;
    
    
db_print_result(dbrResultiMaxFieldLength);
    
    
db_free_result(dbrResult);
}
forward db_drain_autofree_pool();
public 
db_drain_autofree_pool() {
    
DB::LazyInitialize();
    
    
gs_iAutoFreeTimer = -1;
    
    for (new 
gs_iAutoFreeResultsIndexi--; ) {
        if (
gs_adbrAutoFreeResults[i]) {
            new 
DBResult:result gs_adbrAutoFreeResults[i];
            
            
gs_adbrAutoFreeResults[i] = DB::INVALID_RESULT;
            
            
DB::Debug("(db_drain_autofree_pool) Autofreeing 0x%04x%04x"_:result >>> 16_:result 0xFFFF);
            
            
db_free_result_hook(result);
        }
    }
    
    
gs_iAutoFreeResultsIndex 0;
    for (new 
gs_iAutoCloseStatementsIndexi--; ) {
        if (
gs_astAutoCloseStatements[i]) {
            
DB::Debug("(db_drain_autofree_pool) Autoclosing statement %d."_:gs_astAutoCloseStatements[i]);
        
            
stmt_close(gs_astAutoCloseStatements[i]);
        }
    }
    
    
gs_iAutoCloseStatementsIndex 0;
}
forward db_free_stmt_results();
public 
db_free_stmt_results() {
    
gs_iFreeStatementResultsTimer = -1;
    
    for (new 
DBStatement:DBStatement:0_:sizeof(gs_Statements); i++) {
        if (
gs_Statements[i][e_dbDatabase]
         && 
gs_Statements[i][e_bAutoFreeResult]
         && 
gs_Statements[i][e_dbrResult] != DB::INVALID_RESULT) {
            new 
DBResult:result gs_Statements[i][e_dbrResult];
            
            
gs_Statements[i][e_dbrResult] = DB::INVALID_RESULT;
            
            
DB::Debug("(db_free_stmt_results) Freeing 0x%04x%04x for %d."_:result >>> 16_:result 0xFFFF_:i);
            
            
db_free_result_hook(result);
        }
    }
}
forward db_close_persistent();
public 
db_close_persistent() {
    
gs_iClosePersistentTimer = -1;
    
    for (new 
0sizeof(gs_PersistentDatabases); i++) {
        if (
gs_PersistentDatabases[i][e_bIsUsed] && gs_PersistentDatabases[i][e_dbDatabase]) {
            
db_close@(gs_PersistentDatabases[i][e_dbDatabase]);
            
            
gs_PersistentDatabases[i][e_dbDatabase] = DB:0;
        }
    }
}
static 
stock DB::FindMSB(iInput) {
    
// http://graphics.stanford.edu/~seander/bi...9.95162746
    
    
static const
        
s_aiDeBruijnBitPositionsPacked[32 char] = {
            
0x0A010900,
            
0x1D02150D,
            
0x12100E0B,
            
0x1E031916,
            
0x1C140C08,
            
0x0718110F,
            
0x06171B13,
            
0x1F04051A
        
}
    ;
    
    if (
iInput) {
        
#emit LOAD.S.pri  iInput
        #emit MOVE.alt
        #emit SHR.C.alt   1
        #emit OR
        #emit MOVE.alt
        #emit SHR.C.alt   2
        #emit OR
        #emit MOVE.alt
        #emit SHR.C.alt   4
        #emit OR
        #emit MOVE.alt
        #emit SHR.C.alt   8
        #emit OR
        #emit MOVE.alt
        #emit SHR.C.alt   16
        #emit OR
        #emit CONST.alt   0x07C4ACDD
        #emit UMUL
        #emit SHR.C.pri   27
        #emit ADD.C       s_aiDeBruijnBitPositionsPacked
        #emit LODB.I      1
        #emit RETN
    
}
    
    return -
1;
}
static 
stock DB::getstringarg(dest[], arglen sizeof (dest)) {
    
// Get the address of the previous function's stack.  First get the index of
    // the argument required.
    #emit LOAD.S.pri arg
    // Then convert that number to bytes from cells.
    #emit SMUL.C     4
    // Get the previous function's frame.  Stored in variable 0 (in the current
    // frame).  Parameters are FRM+n+12, locals are FRM-n, previous frame is
    // FRM+0, return address is FRM+4, parameter count is FRM+8.  We could add
    // checks that "arg * 4 < *(*(FRM + 0) + 8)", for the previous frame parameter
    // count (in C pointer speak).
    #emit LOAD.S.alt 0
    // Add the frame pointer to the argument offset in bytes.
    #emit ADD
    // Add 12 to skip over the function header.
    #emit ADD.C      12
    // Load the address stored in the specified address.
    #emit LOAD.I
    // Push the length for "strcat".
    #emit PUSH.S     len
    // Push the address we just determined was the source.
    #emit PUSH.pri
    // Load the address of the destination.
    #emit LOAD.S.alt dest
    // Blank the first cell so "strcat" behaves like "strcpy".
    #emit CONST.pri  0
    // Store the loaded number 0 to the loaded address.
    #emit STOR.I
    // Push the loaded address.
    #emit PUSH.alt
    // Push the number of parameters passed (in bytes) to the function.
    #emit PUSH.C     12
    // Call the function.
    #emit SYSREQ.C   strcat
    // Restore the stack to its level before we called this native.
    #emit STACK      16
}
static 
stock DB::setstringarg(iArg, const szValue[], iLength sizeof(szValue)) {
    new
        
iAddress
    
;
    
// Get the address of the previous function's stack.  First get the index of
    // the argument required.
    #emit LOAD.S.pri iArg
    // Then convert that number to bytes from cells.
    #emit SMUL.C     4
    // Get the previous function's frame.
    #emit LOAD.S.alt 0
    // Add the frame pointer to the argument offset in bytes.
    #emit ADD
    // Add 12 to skip over the function header.
    #emit ADD.C      12
    // Load the address stored in the specified address.
    #emit LOAD.I
    #emit STOR.S.PRI iAddress
    // Push the length (last argument first)
    #emit PUSH.S     iLength
    // Push the new value (source) szValue
    #emit PUSH.S     szValue
    // Blank out the first cell of the argument
    #emit CONST.pri  0
    #emit SREF.S.pri iAddress
    
    // Push the destination
    #emit PUSH.S     iAddress
    // Push the number of parameters passed (in bytes) to the function.
    #emit PUSH.C     12
    
    // Call the function.
    #emit SYSREQ.C   strcat
    
    // Restore the stack to its level before we called this native.
    #emit STACK      16
}
// Pretty much ******'s va_strlen function
static stock DB::isargpacked(iArg) {
    
// Get the length of the string at the given position on the previous
    // function's stack (convenience function).
    // Get the address of the previous function's stack.  First get the index of
    // the argument required.
    #emit LOAD.S.pri iArg
    // Then convert that number to bytes from cells.
    #emit SMUL.C     4
    // Get the previous function's frame.  Stored in variable 0 (in the current
    // frame).  Parameters are FRM+n+12, locals are FRM-n, previous frame is
    // FRM+0, return address is FRM+4, parameter count is FRM+8.  We could add
    // checks that "arg * 4 < *(*(FRM + 0) + 8)", for the previous frame parameter
    // count (in C pointer speak).
    #emit LOAD.S.alt 0
    // Add the frame pointer to the argument offset in bytes.
    #emit ADD
    // Add 12 to skip over the function header.
    #emit ADD.C      12
    // Load the address stored in the specified address.
    #emit LOAD.I
    // Push the address we just determined was the source.
    #emit PUSH.pri
    // Push the number of parameters passed (in bytes) to the function.
    #emit PUSH.C     4
    // Call the function.
    #emit SYSREQ.C   ispacked
    // Restore the stack to its level before we called this native.
    #emit STACK      8
    #emit RETN
    // Never called.
    
return 0;
}
stock DB::GetAmxBaseRelative() {
    static
        
s_iAmxBaseRelative 0
    
;
    
    if (!
s_iAmxBaseRelative) {
        
s_iAmxBaseRelative DB::GetAmxBase();
        
#emit LCTRL     1
        #emit LOAD.alt  s_iAmxBaseRelative
        #emit ADD
        #emit STOR.pri  s_iAmxBaseRelative
    
}
    
    return 
s_iAmxBaseRelative;
}
// By Zeex!
// Returns the AMX base address i.e. amx->base.
static stock DB::dummy() {
    return 
0;
}
stock DB::GetAmxBase() {
    static 
amx_base 0// cached
    
if (amx_base == 0) {
        new 
coddat;
        
#emit lctrl 0
        #emit stor.s.pri cod
        #emit lctrl 1
        #emit stor.s.pri dat
        // Get code section start address relative to data.
        
new code_start cod dat;
        
// Get address of DB::dummy().
        
new fn_addr;
        
#emit const.pri DB_dummy
        #emit stor.s.pri fn_addr
        // Get absolute address from the CALL instruction.
        
new fn_addr_reloccall_addr;
        
DB_dummy();
        
#emit lctrl 6
        #emit stor.s.pri call_addr
        
call_addr call_addr 12 code_start;
        
#emit lref.s.pri call_addr
        #emit stor.s.pri fn_addr_reloc
        
amx_base fn_addr_reloc fn_addr cod;
    }
    return 
amx_base;
}
// phys_memory.inc
static stock AbsToRel(addr) {
    new 
dat;
    
#emit lctrl 1
    #emit stor.s.pri dat
    
return addr - (GetAmxBaseAddress() + dat);
}
// This function has a bug in older amx_assembly versions
static stock WritePhysMemoryCell_(addrwhat) {
    new 
rel_addr AbsToRel(addr);
    
#emit load.s.pri what
    #emit sref.s.pri rel_addr
    #emit stack 4
    #emit retn
    
return 0// make compiler happy
}
// Hook db_get_field
// This is done lastly because the fixed function isn't needed within SQLitei
#define db_get_field db_get_field_hook
#define db_get_field_assoc db_get_field_assoc_hook 
Reply


Messages In This Thread
Help-me include erro - by RedMF - 12.10.2016, 07:41
Re: Help-me include erro - by X337 - 12.10.2016, 08:17
Re: Help-me include erro - by BurnZ - 12.10.2016, 08:20
Re: Help-me include erro - by RedMF - 12.10.2016, 19:56

Forum Jump:


Users browsing this thread: 1 Guest(s)