Premium Реклама Spotlight Bundles Boost Банери Кредити
Основно Начало Сървъри Marketplace Форум Сървъри
Общности Хостинг Добави Auction Boost
Ресурси
Библиотеки Карти Видеа Магазин Bundles
Инструменти
Builder Demo CFG HUD
AMXX API
Вход Регистрация
TOP SERVER
[IG] Easy Surf | Ramp Fix | RANKS | REPLAYS
Counter-Strike 1.6
surf_flyin_fortress
40.160.19.36:27015
18.05 18:49
8/64
186ms
/ Библиотеки / sqlvault.inc

sqlvault.inc

debug idea found from xs.inc

.inc 39.1 KB 1642 реда 04.04.2026
Pawn / AMX Mod X
#if defined _sqlv_included
	#endinput
#endif
#define _sqlv_included

#include <amxmodx>
#include <sqlx>

#if AMXX_VERSION_NUM >= 175
	#pragma reqlib sqlite
	#if !defined AMXMODX_NOAUTOLOAD
		#pragma loadlib sqlite
	#endif
#else
	#pragma library sqlite
#endif

// debug idea found from xs.inc
//#define SQLVAULT_DEBUG_LIB

#if defined SQLVAULT_DEBUG_LIB
	#define SQLVAULT_FUNC_ATTRIB
	#define SQLVAULT_VAR_ATTRIB new
#else
	#define SQLVAULT_FUNC_ATTRIB stock
	#define SQLVAULT_VAR_ATTRIB stock
#endif

SQLVAULT_VAR_ATTRIB const SQLVAULT_VERSION[] = "0.0.3";

SQLVAULT_VAR_ATTRIB __SQLVAULT_ERRCODE;
SQLVAULT_VAR_ATTRIB __SQLVAULT_ERROR[128];
SQLVAULT_VAR_ATTRIB __SQLVAULT_TEMPSTRING[1024];

enum SQLVault
{
	Invalid_SQLVault = 0
};

/*
 * Structure used for sqlv_read_all()
 * 
 * @elem		SQLV_Key - String that holds the key
 * @elem		SQLV_Data - String that holds the data
 * @elem		SQLV_TimeStamp - Integer that holds the timestamp
 * 
 */
enum _:SQLVaultEntry
{
	SQLV_Key[64],
	SQLV_Data[512],
	SQLV_TimeStamp
};

/*
 * Opens a vault database
 * 
 * @param		szHost - The host used to connect to the database
 * @param		szUser - The user used to connect to the database
 * @param		szPass - The password used to connect to the database
 * @param		szDb - The name of the database to connect to
 * @param		szVaultName - The vault name to open
 * @param		bAutoInit - If true, sqlv_init() is called inside the function. If false, sqlv_init() is not called.
 * 
 * @return		Returns a valid vault handle on success, Invalid_SQLVault on failure.
 * 
 */
SQLVAULT_FUNC_ATTRIB SQLVault:sqlv_open(szHost[], szUser[], szPass[], szDb[], szVaultName[], bool:bAutoInit = true)
{
	new Handle:hTuple = SQL_MakeDbTuple(szHost, szUser, szPass, szDb);
	
	if(hTuple == Empty_Handle)
	{
		log_amx("Could not create SQL tuple");
		
		return Invalid_SQLVault;
	}
	
	QuoteString(szVaultName, '`');
	
	new Trie:tVaultData = TrieCreate();
	
	TrieSetCell(tVaultData, "tuple", hTuple);
	TrieSetString(tVaultData, "vaultname", szVaultName);
	
	UnQuoteString(szVaultName, '`');
	
	if(bAutoInit && !sqlv_init(SQLVault:tVaultData))
	{
		SQL_FreeHandle(hTuple);
		
		TrieDestroy(tVaultData);
		
		return Invalid_SQLVault;
	}
	
	return SQLVault:tVaultData;
}

/*
 * Opens a vault database based on the amx_sql_* cvars in addons/amxmodx/configs/sql.cfg
 * 
 * @param		szVaultName - The vault name to open
 * @param		bAutoInit - If true, sqlv_init() is called inside the function. If false, sqlv_init() is not called.
 * 
 * @return		Returns a valid vault handle on success, Invalid_SQLVault on failure.
 * 
 */
SQLVAULT_FUNC_ATTRIB SQLVault:sqlv_open_default(szVaultName[], bool:bAutoInit = true)
{
	// code taken from SQL_MakeStdTuple()
	
	new szConfigsDir[64];
	get_localinfo("amxx_configsdir", szConfigsDir, charsmax(szConfigsDir));
	
	server_cmd("exec %s/sql.cfg", szConfigsDir);
	server_exec();
	
	new szHost[64], szUser[64], szPass[64], szDb[64], szSetType[12];
	get_cvar_string("amx_sql_host",	szHost,		charsmax(szHost));
	get_cvar_string("amx_sql_user",	szUser,		charsmax(szUser));
	get_cvar_string("amx_sql_pass",	szPass,		charsmax(szPass));
	get_cvar_string("amx_sql_db",	szDb,		charsmax(szDb));
	get_cvar_string("amx_sql_type",	szSetType,	charsmax(szSetType));
	
	if(!sqlv_affinity(szSetType))
	{
		return Invalid_SQLVault;
	}
	
	return sqlv_open(szHost, szUser, szPass, szDb, szVaultName, bAutoInit);
}

/*
 * Opens a local vault database using the sqlite module
 * 
 * @param		szVaultName - The vault name to open
 * @param		bAutoInit - If true, sqlv_init() is called inside the function. If false, sqlv_init() is not called.
 * 
 * @return		Returns a valid vault handle on success, Invalid_SQLVault on failure.
 * 
 */
SQLVAULT_FUNC_ATTRIB SQLVault:sqlv_open_local(szVaultName[], bool:bAutoInit = true)
{
	static SQLITE_HOST[] =	"127.0.0.1";
	static SQLITE_USER[] =	"root";
	static SQLITE_PASS[] =	"";
	static SQLITE_DB[] =	"amx";
	
	// added requirement for "sqlite" library at top of .inc
	/*if(!is_module_loaded("sqlite"))
	{
		log_amx("SQLite module needs to be enabled in modules.ini to open local database!");
		
		return Invalid_SQLVault;
	}*/
	
	if(!sqlv_affinity("sqlite"))
	{
		return Invalid_SQLVault;
	}
	
	return sqlv_open(SQLITE_HOST, SQLITE_USER, SQLITE_PASS, SQLITE_DB, szVaultName, bAutoInit);
}

/*
 * Sets the SQL driver
 * 
 * @param		szSetType - The driver to set
 * 
 * @return		Returns 1 on success, 0 on failure.
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_affinity(szSetType[])
{
	new szGetType[12];
	SQL_GetAffinity(szGetType, charsmax(szGetType));
	
	if(!equali(szGetType, szSetType) && !SQL_SetAffinity(szSetType))
	{
		log_amx("Failed to set affinity from %s to %s.", szGetType, szSetType);
		
		return 0;
	}
	
	return 1;
}

/*
 * Closes the vault
 * 
 * @param		hVault - The vault to close
 * 
 * @return		No return
 * 
 * @note		The vault handle is set to Invalid_SQLVault after it is closed.
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_close(&SQLVault:hVault)
{
	if(hVault == Invalid_SQLVault)
	{
		return;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	SQL_FreeHandle(hTuple);
	
	if(TrieGetCell(Trie:hVault, "connection", hTuple))
	{
		SQL_FreeHandle(hTuple);
	}
	
	TrieDestroy(Trie:hVault);
	
	hVault = Invalid_SQLVault;
}

/*
 * Connects to the vault database
 * 
 * @param		hVault - The vault to connect to
 * 
 * @return		Returns 1 on success, 0 on failure.
 * 
 * @note		This does not open the vault!
 * 			It only creates a cached connection.
 * 
 * @note		This should be used when multiple vault functions are used in a row
 * 			Doing this will reduce CPU usage in connecting/disconnecting each time those functions are used.
 * 
 * @note		After those functions are used, this connection should be closed.
 * 
 * @note		It is not recommended to keep the connection open the whole time the plugin is running.
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_connect(SQLVault:hVault)
{
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	if(TrieKeyExists(Trie:hVault, "connection"))
	{
		return 1;
	}
	
	new Handle:hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
	
	if(hConnection == Empty_Handle)
	{
		log_amx("Connection failed in sqlv_connect() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
		
		return 0;
	}
	
	TrieSetCell(Trie:hVault, "connection", hConnection);
	
	return 1;
}

/*
 * Disconnects from the vault database
 * 
 * @param		hVault - The vault to disconnect
 * 
 * @return		Returns 1 if disconnected, 0 on error or no connection existed.
 * 
 * @note		This does not close the vault!
 * 			It only closes the cached connection made.
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_disconnect(SQLVault:hVault)
{
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	new Handle:hConnection;
	
	if(!TrieGetCell(Trie:hVault, "connection", hConnection))
	{
		return 0;
	}
	
	SQL_FreeHandle(hConnection);
	
	TrieDeleteKey(Trie:hVault, "connection");
	
	return 1;
}

/*
 * Initializes the vault for use
 * 
 * @param		hVault - The vault to initialize
 * 
 * @return		Returns 1 on success, 0 on failure
 * 
 * @note		This must be used before any other vault functions are used (except open and close)!
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_init(SQLVault:hVault)
{
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	new Handle:hConnection, bool:bNewConnection = false;
	
	if(!TrieGetCell(Trie:hVault, "connection", hConnection))
	{
		hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
		
		if(hConnection == Empty_Handle)
		{
			log_amx("Connection failed in sqlv_init() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
			
			return 0;
		}
		
		bNewConnection = true;
	}
	
	new szVaultName[32];
	TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
	
	new Handle:hQuery = SQL_PrepareQuery(hConnection,\
		"CREATE TABLE IF NOT EXISTS `%s` \
		(`key` VARCHAR(64) NOT NULL PRIMARY KEY, \
		`data` VARCHAR(512) NOT NULL, \
		`timestamp` INT(11) NOT NULL, \
		`permanent` INT(11) NOT NULL);",
		szVaultName);
	
	new iReturn = 1;
	
	if(!SQL_Execute(hQuery))
	{
		SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
		log_amx("Error in sqlv_init(): %s", __SQLVAULT_ERROR);
		
		iReturn = 0;
	}
	
	SQL_FreeHandle(hQuery);
	
	if(bNewConnection)
	{
		SQL_FreeHandle(hConnection);
	}
	
	return iReturn;
}

/*
 * Gets a string value from a vault
 * 
 * @param		hVault - The vault to get the data from
 * @param		szKey - The key holding the data
 * @param		szData - The buffer to hold the data
 * @param		iDataLen - The max length of the data buffer
 * @param		iTimeStamp - The byref variable holding the timestamp
 * 
 * @return		Returns 1 on success, 0 on failure
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_get_data(SQLVault:hVault, szKey[], szData[], iDataLen, &iTimeStamp = 0)
{
	szData[0] = 0;
	
	iTimeStamp = 0;
	
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	new Handle:hConnection, bool:bNewConnection = false;
	
	if(!TrieGetCell(Trie:hVault, "connection", hConnection))
	{
		hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
		
		if(hConnection == Empty_Handle)
		{
			log_amx("Connection failed in sqlv_get_data() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
			
			return 0;
		}
		
		bNewConnection = true;
	}
	
	new szVaultName[32];
	TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
	
	QuoteString(szKey);
	
	new Handle:hQuery = SQL_PrepareQuery(hConnection,\
		"SELECT `data`, `timestamp` \
		FROM `%s` \
		WHERE `key` = '%s';",
		szVaultName, szKey);
	
	UnQuoteString(szKey);
	
	new iReturn = 0;
	
	if(!SQL_Execute(hQuery))
	{
		SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
		log_amx("Error in sqlv_get_data(): %s", __SQLVAULT_ERROR);
	}
	else if((iReturn = SQL_NumResults(hQuery)))
	{
		SQL_ReadResult(hQuery, 0, szData, iDataLen);
		
		iTimeStamp = SQL_ReadResult(hQuery, 1);
	}
	
	SQL_FreeHandle(hQuery);
	
	if(bNewConnection)
	{
		SQL_FreeHandle(hConnection);
	}
	
	return iReturn;
}

/*
 * Gets an integer value from a vault
 * 
 * @param		hVault - The vault to get the data from
 * @param		szKey - The key holding the data
 * @param		iTimeStamp - The byref variable holding the timestamp
 * 
 * @return		Returns the integer value on success, 0 on failure
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_get_num(SQLVault:hVault, szKey[], &iTimeStamp = 0)
{
	if(sqlv_get_data(hVault, szKey, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING), iTimeStamp))
	{
		return str_to_num(__SQLVAULT_TEMPSTRING);
	}
	
	return 0;
}

/*
 * Gets a float value from a vault
 * 
 * @param		hVault - The vault to get the data from
 * @param		szKey - The key holding the data
 * @param		iTimeStamp - The byref variable holding the timestamp
 * 
 * @return		Returns the float value on success, 0.0 on failure
 * 
 */
SQLVAULT_FUNC_ATTRIB Float:sqlv_get_float(SQLVault:hVault, szKey[], &iTimeStamp = 0)
{
	if(sqlv_get_data(hVault, szKey, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING), iTimeStamp))
	{
		return str_to_float(__SQLVAULT_TEMPSTRING);
	}
	
	return 0.0;
}

/*
 * Checks if a key exists in a vault
 * 
 * @param		hVault - The vault to look in
 * @param		szKey - The key to look for
 * 
 * @return		Returns 1 if exists, 0 if it doesn't.
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_key_exists(SQLVault:hVault, szKey[])
{
	return sqlv_get_data(hVault, szKey, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING));
}

/*
 * Sets a vault entry to a string value
 * 
 * @param		hVault - The vault to set the data in
 * @param		szKey - The key to hold the data
 * @param		szData - The string value to set
 * 
 * @return		Returns 1 on success, 0 on failure.
 * 
 * @note		Use "*" for the key to set all entries to that data.
 * 			This will update all the timestamps and also set all to non-permanent (even permanent entries)!
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_set_data(SQLVault:hVault, szKey[], szData[])
{
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	new Handle:hConnection, bool:bNewConnection = false;
	
	if(!TrieGetCell(Trie:hVault, "connection", hConnection))
	{
		hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
		
		if(hConnection == Empty_Handle)
		{
			log_amx("Connection failed in sqlv_set_data() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
			
			return 0;
		}
		
		bNewConnection = true;
	}
	
	new szVaultName[32];
	TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
	
	QuoteString(szData);
	
	new Handle:hQuery;
	
	if(equal(szKey, "*"))
	{
		hQuery = SQL_PrepareQuery(hConnection,\
			"UPDATE `%s` \
			SET `data` = '%s' \
			AND `timestamp` = %d \
			AND `permanent` = 0;",\
			szVaultName, szData, get_systime());
	}
	else
	{
		QuoteString(szKey);
		
		hQuery = SQL_PrepareQuery(hConnection,\
			"REPLACE INTO `%s` \
			(`key`, `data`, `timestamp`, `permanent`) \
			VALUES \
			('%s', '%s', %d, 0);",\
			szVaultName, szKey, szData, get_systime());
		
		UnQuoteString(szKey);
	}
	
	UnQuoteString(szData);
	
	new iReturn = 0;
	
	if(!SQL_Execute(hQuery))
	{
		SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
		log_amx("Error in sqlv_set_data(): %s", __SQLVAULT_ERROR);
	}
	else
	{
		iReturn = 1;
	}
	
	SQL_FreeHandle(hQuery);
	
	if(bNewConnection)
	{
		SQL_FreeHandle(hConnection);
	}
	
	return iReturn;
}

/*
 * Sets a vault entry to an integer value
 * 
 * @param		hVault - The vault to set the data in
 * @param		szKey - The key to hold the data
 * @param		iData - The integer value to set
 * 
 * @return		Returns 1 on success, 0 on failure.
 * 
 * @note		Use "*" for the key to set all entries to that data.
 * 			This will update all the timestamps and also set all to non-permanent (even permanent entries)!
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_set_num(SQLVault:hVault, szKey[], const iData)
{
	num_to_str(iData, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING));
	
	return sqlv_set_data(hVault, szKey, __SQLVAULT_TEMPSTRING);
}

/*
 * Sets a vault entry to a float value
 * 
 * @param		hVault - The vault to set the data in
 * @param		szKey - The key to hold the data
 * @param		flData - The float value to set
 * 
 * @return		Returns 1 on success, 0 on failure.
 * 
 * @note		Use "*" for the key to set all entries to that data.
 * 			This will update all the timestamps and also set all to non-permanent (even permanent entries)!
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_set_float(SQLVault:hVault, szKey[], Float:flData)
{
	float_to_str(flData, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING));
	
	return sqlv_set_data(hVault, szKey, __SQLVAULT_TEMPSTRING);
}

/*
 * Sets a vault entry to a string value with a permanent entry
 * 
 * @param		hVault - The vault to set the data in
 * @param		szKey - The key to hold the data
 * @param		szData - The string value to set
 * 
 * @return		Returns 1 on success, 0 on failure.
 * 
 * @note		Permanent means that the entry cannot be deleted by sqlv_prune().
 * 
 * @note		Use "*" for the key to set all entries to that data.
 * 			This will update all the timestamps and also set all to permanent (even non-permanent entries)!
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_pset_data(SQLVault:hVault, szKey[], szData[])
{
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	new Handle:hConnection, bool:bNewConnection = false;
	
	if(!TrieGetCell(Trie:hVault, "connection", hConnection))
	{
		hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
		
		if(hConnection == Empty_Handle)
		{
			log_amx("Connection failed in sqlv_pset_data() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
			
			return 0;
		}
		
		bNewConnection = true;
	}
	
	new szVaultName[32];
	TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
	
	QuoteString(szData);
	
	new Handle:hQuery;
	
	if(equal(szKey, "*"))
	{
		hQuery = SQL_PrepareQuery(hConnection,\
			"UPDATE `%s` \
			SET `data` = '%s' \
			AND `timestamp` = %d \
			AND `permanent` = 1;",\
			szVaultName, szData, get_systime());
	}
	else
	{
		QuoteString(szKey);
		
		hQuery = SQL_PrepareQuery(hConnection,\
			"REPLACE INTO `%s` \
			(`key`, `data`, `timestamp`, `permanent`) \
			VALUES \
			('%s', '%s', %d, 1);",\
			szVaultName, szKey, szData, get_systime());
		
		UnQuoteString(szKey);
	}
	
	UnQuoteString(szData);
	
	new iReturn = 0;
	
	if(!SQL_Execute(hQuery))
	{
		SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
		log_amx("Error in sqlv_set_data(): %s", __SQLVAULT_ERROR);
	}
	else
	{
		iReturn = 1;
	}
	
	SQL_FreeHandle(hQuery);
	
	if(bNewConnection)
	{
		SQL_FreeHandle(hConnection);
	}
	
	return iReturn;
}

/*
 * Sets a vault entry to an integer value with a permanent entry
 * 
 * @param		hVault - The vault to set the data in
 * @param		szKey - The key to hold the data
 * @param		iData - The integer value to set
 * 
 * @return		Returns 1 on success, 0 on failure.
 * 
 * @note		Permanent means that the entry cannot be deleted by sqlv_prune().
 * 
 * @note		Use "*" for the key to set all entries to that data.
 * 			This will update all the timestamps and also set all to permanent (even non-permanent entries)!
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_pset_num(SQLVault:hVault, szKey[], const iData)
{
	num_to_str(iData, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING));
	
	return sqlv_pset_data(hVault, szKey, __SQLVAULT_TEMPSTRING);
}

/*
 * Sets a vault entry to a float value with a permanent entry
 * 
 * @param		hVault - The vault to set the data in
 * @param		szKey - The key to hold the data
 * @param		flData - The float value to set
 * 
 * @return		Returns 1 on success, 0 on failure.
 * 
 * @note		Permanent means that the entry cannot be deleted by sqlv_prune().
 * 
 * @note		Use "*" for the key to set all entries to that data.
 * 			This will update all the timestamps and also set all to permanent (even non-permanent entries)!
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_pset_float(SQLVault:hVault, szKey[], Float:flData)
{
	float_to_str(flData, __SQLVAULT_TEMPSTRING, charsmax(__SQLVAULT_TEMPSTRING));
	
	return sqlv_pset_data(hVault, szKey, __SQLVAULT_TEMPSTRING);
}

/*
 * Removes a key from a vault
 * 
 * @param		hVault - The vault to delete the key from
 * @param		szKey - The key to delete
 * 
 * @return		Returns 1 on success, 0 on failure.
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_remove(SQLVault:hVault, szKey[])
{
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	new Handle:hConnection, bool:bNewConnection = false;
	
	if(!TrieGetCell(Trie:hVault, "connection", hConnection))
	{
		hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
		
		if(hConnection == Empty_Handle)
		{
			log_amx("Connection failed in sqlv_remove() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
			
			return 0;
		}
		
		bNewConnection = true;
	}
	
	new szVaultName[32];
	TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
	
	QuoteString(szKey);
	
	new Handle:hQuery = SQL_PrepareQuery(hConnection,\
		"DELETE FROM `%s` \
		WHERE `key` = '%s';",
		szVaultName, szKey);
	
	UnQuoteString(szKey);
	
	new iReturn = 0;
	
	if(!SQL_Execute(hQuery))
	{
		SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
		log_amx("Error in sqlv_remove(): %s", __SQLVAULT_ERROR);
	}
	else if(!(iReturn = SQL_AffectedRows(hQuery)))
	{
		iReturn = 1;
	}
	
	SQL_FreeHandle(hQuery);
	
	if(bNewConnection)
	{
		SQL_FreeHandle(hConnection);
	}
	
	return iReturn;
}

/*
 * Removes all non-permanent entries in a vault that have a timestamp between the start and end timestamps
 * 
 * @param		hVault - The vault to prune
 * @param		iStart - The start timestamp
 * @param		iEnd - The end timestamp
 * 
 * @return		Returns the number of deleted entries (or 1 if none deleted) on success, 0 on failure.
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_prune(SQLVault:hVault, iStart, iEnd)
{
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	new Handle:hConnection, bool:bNewConnection = false;
	
	if(!TrieGetCell(Trie:hVault, "connection", hConnection))
	{
		hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
		
		if(hConnection == Empty_Handle)
		{
			log_amx("Connection failed in sqlv_prune() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
			
			return 0;
		}
		
		bNewConnection = true;
	}
	
	new szVaultName[32];
	TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
	
	new Handle:hQuery = SQL_PrepareQuery(hConnection,\
		"DELETE FROM `%s` \
		WHERE `permanent` = 0 \
		AND %d <= `timestamp` \
		AND `timestamp` <= %d;",
		szVaultName, iStart, iEnd);
	
	new iReturn = 0;
	
	if(!SQL_Execute(hQuery))
	{
		SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
		log_amx("Error in sqlv_prune(): %s", __SQLVAULT_ERROR);
	}
	else if(!(iReturn = SQL_AffectedRows(hQuery)))
	{
		iReturn = 1;
	}
	
	SQL_FreeHandle(hQuery);
	
	if(bNewConnection)
	{
		SQL_FreeHandle(hConnection);
	}
	
	return iReturn;
}

/*
 * Updates the timestamp for a key in a vault
 * 
 * @param		hVault - The vault to update the key in
 * @param		szKey - The key to update the timestamp for
 * @param		iTimeStamp - The timestamp to set for the vault (optional, default is -1)
 * 
 * @return		Returns 1 on success, 0 on failure.
 * 
 * @note		Use -1 for timestamp to update with the current timestamp
 * 
 * @note		Use "*" for the key to touch all entries.
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_touch(SQLVault:hVault, szKey[], iTimeStamp = -1)
{
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	new Handle:hConnection, bool:bNewConnection = false;
	
	if(!TrieGetCell(Trie:hVault, "connection", hConnection))
	{
		hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
		
		if(hConnection == Empty_Handle)
		{
			log_amx("Connection failed in sqlv_touch() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
			
			return 0;
		}
		
		bNewConnection = true;
	}
	
	new szVaultName[32];
	TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
	
	if(iTimeStamp < 0)
	{
		iTimeStamp = get_systime();
	}
	
	new Handle:hQuery;
	
	if(equal(szKey, "*"))
	{
		hQuery = SQL_PrepareQuery(hConnection,\
			"UPDATE `%s` \
			SET `timestamp` = %d;",
			szVaultName, iTimeStamp);
	}
	else
	{
		QuoteString(szKey);
		
		hQuery = SQL_PrepareQuery(hConnection,\
			"UPDATE `%s` \
			SET `timestamp` = %d \
			WHERE `key` = '%s';",
			szVaultName, iTimeStamp, szKey);
		
		UnQuoteString(szKey);
	}
	
	new iReturn = 0;
	
	if(!SQL_Execute(hQuery))
	{
		SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
		log_amx("Error in sqlv_touch(): %s", __SQLVAULT_ERROR);
	}
	else if(!(iReturn = SQL_AffectedRows(hQuery)))
	{
		iReturn = 1;
	}
	
	SQL_FreeHandle(hQuery);
	
	if(bNewConnection)
	{
		SQL_FreeHandle(hConnection);
	}
	
	return iReturn;
}

/*
 * Deletes all entries in a vault
 * 
 * @param		hVault - The vault to delete entries from
 * @param		bSavePermanent - If true, deletes only entries that are not permanent. If false, deletes all entries. (optional, default is false)
 * 
 * @return		Returns total entries deleted (or 1 if empty) on success, 0 on failure.
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_clear(SQLVault:hVault, bool:bSavePermanent = false)
{
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	new Handle:hConnection, bool:bNewConnection = false;
	
	if(!TrieGetCell(Trie:hVault, "connection", hConnection))
	{
		hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
		
		if(hConnection == Empty_Handle)
		{
			log_amx("Connection failed in sqlv_clear() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
			
			return 0;
		}
		
		bNewConnection = true;
	}
	
	new szVaultName[32];
	TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
	
	new Handle:hQuery = SQL_PrepareQuery(hConnection,\
		"DELETE FROM `%s`%s;",
		szVaultName, bSavePermanent ? " WHERE `permanent` = 0" : "");
	
	new iReturn = 0;
	
	if(!SQL_Execute(hQuery))
	{
		SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
		log_amx("Error in sqlv_clear(): %s", __SQLVAULT_ERROR);
	}
	else if(!(iReturn = SQL_AffectedRows(hQuery)))
	{
		iReturn = 1;
	}
	
	SQL_FreeHandle(hQuery);
	
	if(bNewConnection)
	{
		SQL_FreeHandle(hConnection);
	}
	
	return iReturn;
}

/*
 * Gets the total number of entries in the vault
 * 
 * @param		hVault - The vault to find the size of
 * 
 * @return		Returns the total number of entries in the vault
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_size(SQLVault:hVault)
{
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	new Handle:hConnection, bool:bNewConnection = false;
	
	if(!TrieGetCell(Trie:hVault, "connection", hConnection))
	{
		hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
		
		if(hConnection == Empty_Handle)
		{
			log_amx("Connection failed in sqlv_size() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
			
			return 0;
		}
		
		bNewConnection = true;
	}
	
	new szVaultName[32];
	TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
	
	new Handle:hQuery = SQL_PrepareQuery(hConnection,\
		"SELECT COUNT(*) FROM `%s`;",
		szVaultName);
	
	new iReturn = 0;
	
	if(!SQL_Execute(hQuery))
	{
		SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
		log_amx("Error in sqlv_size(): %s", __SQLVAULT_ERROR);
	}
	else if(SQL_NumResults(hQuery))
	{
		iReturn = SQL_ReadResult(hQuery, 0);
	}
	
	SQL_FreeHandle(hQuery);
	
	if(bNewConnection)
	{
		SQL_FreeHandle(hConnection);
	}
	
	return iReturn;
}

/*
 * Reads a vault by key index
 * 
 * @param		hVault - The vault to read from
 * @param		iKeyIndex - The key index to read
 * @param		szKey - The string to hold the key (optional)
 * @param		iKeyLen - The max length of the key buffer (optional)
 * @param		szData - The string to hold the data (optional)
 * @param		iDataLen - The max length of the data buffer (optional)
 * @param		iTimeStamp - The byref variable that holds the timestamp (optional)
 * @param		szWhere - The where condition for selecting specific vault data (optional)
 * @param		szSort - The method to sort the vault data by (optional)
 * 
 * @return		Returns 1 on success, 0 on failure.
 * 
 * @note		Key indexes start at 0 and stop at 1 before the size of the vault (sqlv_size() - 1)
 * 
 * @note		If you want to read all keys in the vault, use sqlv_read_all().
 * 
 * @note		If a vault is changed by setting data, changing timestamps, deleteing, etc. then the key indexes may change.
 * 			Therefore, those type of actions should not be done if more than 1 key is being read.
 * 
 * @note		The where condition is the same as the where clause from MySQL's SELECT statement.
 * 			Do not include "WHERE" inside the where clause.
 * 
 * @note		Sorting the vault data can be done 2 ways:
 * 			1. Pass "asc" to sort in ascending order by the data value
 * 			   Pass "desc" to sort in descending order by the data value
 * 			2. Pass any other string to format the ORDER BY clause from MySQL
 * 			Do not include "ORDER BY" inside the sort string
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_read(SQLVault:hVault, iKeyIndex, szKey[] = "", iKeyLen = 0, szData[] = "", iDataLen = 0, &iTimeStamp = 0, const szWhere[] = "", const szSort[] = "")
{
	if(iKeyLen)
	{
		szKey[0] = 0;
	}
	
	if(iDataLen)
	{
		szData[0] = 0;
	}
	
	iTimeStamp = 0;
	
	new szFixedWhere[256], szFixedSort[256];
	
	if(szWhere[0])
	{
		formatex(szFixedWhere, charsmax(szFixedWhere), " WHERE %s", szWhere);
	}
	
	if(szSort[0])
	{
		if(equali(szSort, "asc") || equali(szSort, "desc"))
		{
			formatex(szFixedSort, charsmax(szFixedSort), " ORDER BY `data` %s", szSort);
		}
		else
		{
			formatex(szFixedSort, charsmax(szFixedSort), " ORDER BY %s", szSort);
		}
	}
	
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	new Handle:hConnection, bool:bNewConnection = false;
	
	if(!TrieGetCell(Trie:hVault, "connection", hConnection))
	{
		hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
		
		if(hConnection == Empty_Handle)
		{
			log_amx("Connection failed in sqlv_read() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
			
			return 0;
		}
		
		bNewConnection = true;
	}
	
	new szVaultName[32];
	TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
	
	new Handle:hQuery = SQL_PrepareQuery(hConnection,\
		"SELECT `key`, `data`, `timestamp` FROM `%s`%s%s LIMIT %d, 1;",
		szVaultName, iKeyIndex, szFixedWhere, szFixedSort);
	
	new iReturn = 0;
	
	if(!SQL_Execute(hQuery))
	{
		SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
		log_amx("Error in sqlv_read(): %s", __SQLVAULT_ERROR);
	}
	else if(SQL_NumResults(hQuery))
	{
		iReturn = 1;
		
		if(iKeyLen)
		{
			SQL_ReadResult(hQuery, 0, szKey, iKeyLen);
		}
		
		if(iDataLen)
		{
			SQL_ReadResult(hQuery, 1, szData, iDataLen);
		}
		
		iTimeStamp = SQL_ReadResult(hQuery, 2);
	}
	
	SQL_FreeHandle(hQuery);
	
	if(bNewConnection)
	{
		SQL_FreeHandle(hConnection);
	}
	
	return iReturn;
}

/*
 * Reads all of the vault data into a cell array
 * 
 * @param		hVault - The vault to read from
 * @param		aVaultData - The cell array to hold the data
 * @param		szWhere - The where condition for selecting specific vault data (optional)
 * @param		szSort - The method to sort the vault data by (optional)
 * 
 * @return		Returns the total number of vault entries
 * 
 * @note		The where condition is the same as the where clause from MySQL's SELECT statement.
 * 			Do not include "WHERE" inside the where clause.
 * 
 * @note		Sorting the vault data can be done 2 ways:
 * 			1. Pass "asc" to sort in ascending order by the data value
 * 			   Pass "desc" to sort in descending order by the data value
 * 			2. Pass any other string to format the ORDER BY clause from MySQL
 * 			Do not include "ORDER BY" inside the sort string
 * 
 * @note		The cell array contains arrays that correspond to the SQLVaultEntry enum
 * 			
 * @note		Example:
 * 			
 * 			new Array:aVaultData;
 * 			new iVaultKeys = sqlv_read_all(hVault, aVaultData);
 * 			
 * 			new eVaultData[SQLVaultEntry];
 * 			
 * 			for(new i = 0; i < iVaultKeys; i++)
 * 			{
 * 				ArrayGetArray(aVaultData, i, eVaultData);
 * 				
 * 				eVaultData[SQLV_Key] = key
 * 				eVaultData[SQLV_Data] = data
 * 				eVaultData[SQLV_TimeStamp] = timestamp
 * 			}
 * 			
 * 			ArrayDestroy(aVaultData);
 * 
 * @note		The cell array should not be created.
 * 			It is auto-created in the function.
 * 			If the cell array already contains a handle, it is destroyed first.
 * 
 * @note		The cell array needs to be destroyed after being used
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_read_all(SQLVault:hVault, &Array:aVaultData, const szWhere[] = "", const szSort[] = "")
{
	if(aVaultData != Invalid_Array)
	{
		ArrayDestroy(aVaultData);
	}
	
	aVaultData = ArrayCreate(SQLVaultEntry);
	
	new szFixedWhere[256], szFixedSort[256];
	
	if(szWhere[0])
	{
		formatex(szFixedWhere, charsmax(szFixedWhere), " WHERE %s", szWhere);
	}
	
	if(szSort[0])
	{
		if(equali(szSort, "asc") || equali(szSort, "desc"))
		{
			formatex(szFixedSort, charsmax(szFixedSort), " ORDER BY `data` %s", szSort);
		}
		else
		{
			formatex(szFixedSort, charsmax(szFixedSort), " ORDER BY %s", szSort);
		}
	}
	
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	new Handle:hConnection, bool:bNewConnection = false;
	
	if(!TrieGetCell(Trie:hVault, "connection", hConnection))
	{
		hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
		
		if(hConnection == Empty_Handle)
		{
			log_amx("Connection failed in sqlv_read_all() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
			
			return 0;
		}
		
		bNewConnection = true;
	}
	
	new szVaultName[32];
	TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
	
	new Handle:hQuery = SQL_PrepareQuery(hConnection,\
		"SELECT `key`, `data`, `timestamp` FROM `%s`%s%s;",
		szVaultName);
	
	new iReturn = 0;
	
	if(!SQL_Execute(hQuery))
	{
		SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
		log_amx("Error in sqlv_read_all(): %s", __SQLVAULT_ERROR);
	}
	else if((iReturn = SQL_NumResults(hQuery)))
	{
		new eVaultData[SQLVaultEntry];
		
		while(SQL_MoreResults(hQuery))
		{
			SQL_ReadResult(hQuery, 0, eVaultData[SQLV_Key], charsmax(eVaultData[SQLV_Key]));
			SQL_ReadResult(hQuery, 1, eVaultData[SQLV_Data], charsmax(eVaultData[SQLV_Data]));
			eVaultData[SQLV_TimeStamp] = SQL_ReadResult(hQuery, 2);
			
			ArrayPushArray(aVaultData, eVaultData);
			
			SQL_NextRow(hQuery);
		}
	}
	
	SQL_FreeHandle(hQuery);
	
	if(bNewConnection)
	{
		SQL_FreeHandle(hConnection);
	}
	
	return iReturn;
}

/*
 * Reads a set of the vault data into an array
 * 
 * @param		hVault - The vault to read from
 * @param		eOutputData - The array to store all of the selected set
 * @param		iOutputSize - The size of the set to select
 * @param		iStart - The offset of the vault to start at
 * @param		szWhere - The where condition for selecting specific vault data (optional)
 * @param		szSort - The method to sort the vault data by (optional)
 * 
 * @return		Returns the total number of vault entries
 * 
 * @note		The where condition is the same as the where clause from MySQL's SELECT statement.
 * 			Do not include "WHERE" inside the where clause.
 * 
 * @note		Sorting the vault data can be done 2 ways:
 * 			1. Pass "asc" to sort in ascending order by the data value
 * 			   Pass "desc" to sort in descending order by the data value
 * 			2. Pass any other string to format the ORDER BY clause from MySQL
 * 			Do not include "ORDER BY" inside the sort string
 * 			
 * @note		Example for grabbing top entries:
 * 			
 * 			new eVaultData[10][SQLVaultEntry];
 * 			new iVaultKeys = sqlv_read_set(hVault, eVaultData, sizeof(eVaultData), _, _, "desc");
 * 			
 * 			for(new i = 0; i < iVaultKeys; i++)
 * 			{
 * 				eVaultData[i][SQLV_Key] = key
 * 				eVaultData[i][SQLV_Data] = data
 * 				eVaultData[i][SQLV_TimeStamp] = timestamp
 * 			}
 * 
 */
SQLVAULT_FUNC_ATTRIB sqlv_read_set(SQLVault:hVault, eOutputData[][SQLVaultEntry], iOutputSize, iStart = 0, const szWhere[] = "", const szSort[] = "")
{
	new szFixedWhere[256], szFixedSort[256];
	
	if(szWhere[0])
	{
		formatex(szFixedWhere, charsmax(szFixedWhere), " WHERE %s", szWhere);
	}
	
	if(szSort[0])
	{
		if(equali(szSort, "asc") || equali(szSort, "desc"))
		{
			formatex(szFixedSort, charsmax(szFixedSort), " ORDER BY `data` %s", szSort);
		}
		else
		{
			formatex(szFixedSort, charsmax(szFixedSort), " ORDER BY %s", szSort);
		}
	}
	
	if(hVault == Invalid_SQLVault)
	{
		return 0;
	}
	
	new Handle:hTuple;
	TrieGetCell(Trie:hVault, "tuple", hTuple);
	
	if(hTuple == Empty_Handle)
	{
		return 0;
	}
	
	new Handle:hConnection, bool:bNewConnection = false;
	
	if(!TrieGetCell(Trie:hVault, "connection", hConnection))
	{
		hConnection = SQL_Connect(hTuple, __SQLVAULT_ERRCODE, __SQLVAULT_ERROR, 127);
		
		if(hConnection == Empty_Handle)
		{
			log_amx("Connection failed in sqlv_read_set() (%d): %s", __SQLVAULT_ERRCODE, __SQLVAULT_ERROR);
			
			return 0;
		}
		
		bNewConnection = true;
	}
	
	new szVaultName[32];
	TrieGetString(Trie:hVault, "vaultname", szVaultName, charsmax(szVaultName));
	
	new Handle:hQuery = SQL_PrepareQuery(hConnection,\
		"SELECT `key`, `data`, `timestamp` FROM `%s`%s%s LIMIT %d, %d;",
		szVaultName, szFixedWhere, szFixedSort, iStart, iOutputSize);
	
	new iReturn = 0;
	
	if(!SQL_Execute(hQuery))
	{
		SQL_QueryError(hQuery, __SQLVAULT_ERROR, charsmax(__SQLVAULT_ERROR));
		log_amx("Error in sqlv_read_set(): %s", __SQLVAULT_ERROR);
	}
	else if(SQL_NumResults(hQuery))
	{
		while(iReturn < iOutputSize && SQL_MoreResults(hQuery))
		{
			SQL_ReadResult(hQuery, 0, eOutputData[iReturn][SQLV_Key], charsmax(eOutputData[][SQLV_Key]));
			SQL_ReadResult(hQuery, 1, eOutputData[iReturn][SQLV_Data], charsmax(eOutputData[][SQLV_Data]));
			eOutputData[iReturn][SQLV_TimeStamp] = SQL_ReadResult(hQuery, 2);
			
			iReturn++;
			
			SQL_NextRow(hQuery);
		}
	}
	
	SQL_FreeHandle(hQuery);
	
	if(bNewConnection)
	{
		SQL_FreeHandle(hConnection);
	}
	
	return iReturn;
}

/*
 * Makes a string safe to be held in the vault
 * 
 * @param		szString - The string to be made safe
 * 
 * @return		Returns the length of the string
 * 
 * @note		This overwrites the string's contents, so constants cannot be used.
 * 
 */
SQLVAULT_FUNC_ATTRIB QuoteString(szString[], cRemoveChar = ''')
{
	new i, cChar;
	
	while((cChar = szString[i]))
	{
		if(cChar == cRemoveChar)
		{
			szString[i] = 30;
		}
		
		i++;
	}
	
	return i;
}

/*
 * Restores the strings original state after being used by QuoteString()
 * 
 * @param		szString - The string to be restored
 * 
 * @return		Returns the length of the string
 * 
 * @note		This overwrites the string's contents, so constants cannot be used.
 * 
 */
SQLVAULT_FUNC_ATTRIB UnQuoteString(szString[], cRemoveChar = ''')
{
	new i, cChar;
	
	while((cChar = szString[i]))
	{
		if(cChar == 30)
		{
			szString[i] = cRemoveChar;
		}
		
		i++;
	}
	
	return i;
}
/* AMXX-Studio Notes - DO NOT MODIFY BELOW HERE
*{\\ rtf1\\ ansi\\ deff0{\\ fonttbl{\\ f0\\ fnil Tahoma;}}\n\\ viewkind4\\ uc1\\ pard\\ lang11274\\ f0\\ fs16 \n\\ par }
*/
РЕКЛАМИРАЙ ПРИ НАС!
AMXX-BG.INFO
КАК ДА ИЗПОЛЗВАМ
Добави в началото на .sma файла:
#include <sqlvault>
1. Изтегли
Свали файла от бутона по-горе
2. Копирай
Постави в scripting/include/
3. Включи
Добави #include директивата
4. Компилирай
Използвай amxxpc или scripting/compile.exe
PrivateServ.NET