2008-03-30 09:00:22 +02:00
|
|
|
#include <sourcemod>
|
2014-06-05 10:00:54 +02:00
|
|
|
#include <testing>
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
public Plugin:myinfo =
|
|
|
|
{
|
|
|
|
name = "SQL Testing Lab",
|
|
|
|
author = "AlliedModders LLC",
|
|
|
|
description = "Tests basic function calls",
|
|
|
|
version = "1.0.0.0",
|
|
|
|
url = "http://www.sourcemod.net/"
|
|
|
|
};
|
|
|
|
|
|
|
|
public OnPluginStart()
|
|
|
|
{
|
|
|
|
RegServerCmd("sql_test_normal", Command_TestSql1)
|
|
|
|
RegServerCmd("sql_test_stmt", Command_TestSql2)
|
|
|
|
RegServerCmd("sql_test_thread1", Command_TestSql3)
|
|
|
|
RegServerCmd("sql_test_thread2", Command_TestSql4)
|
|
|
|
RegServerCmd("sql_test_thread3", Command_TestSql5)
|
2014-06-05 10:00:54 +02:00
|
|
|
RegServerCmd("sql_test_txn", Command_TestTxn)
|
|
|
|
|
|
|
|
new Handle:hibernate = FindConVar("sv_hibernate_when_empty");
|
|
|
|
if (hibernate != INVALID_HANDLE) {
|
|
|
|
ServerCommand("sv_hibernate_when_empty 0");
|
|
|
|
}
|
2008-03-30 09:00:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
PrintQueryData(Handle:query)
|
|
|
|
{
|
|
|
|
if (!SQL_HasResultSet(query))
|
|
|
|
{
|
|
|
|
PrintToServer("Query Handle %x has no results", query)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
new rows = SQL_GetRowCount(query)
|
|
|
|
new fields = SQL_GetFieldCount(query)
|
|
|
|
|
|
|
|
decl String:fieldNames[fields][32]
|
|
|
|
PrintToServer("Fields: %d", fields)
|
|
|
|
for (new i=0; i<fields; i++)
|
|
|
|
{
|
|
|
|
SQL_FieldNumToName(query, i, fieldNames[i], 32)
|
|
|
|
PrintToServer("-> Field %d: \"%s\"", i, fieldNames[i])
|
|
|
|
}
|
|
|
|
|
|
|
|
PrintToServer("Rows: %d", rows)
|
|
|
|
decl String:result[255]
|
|
|
|
new row
|
|
|
|
while (SQL_FetchRow(query))
|
|
|
|
{
|
|
|
|
row++
|
|
|
|
PrintToServer("Row %d:", row)
|
|
|
|
for (new i=0; i<fields; i++)
|
|
|
|
{
|
|
|
|
SQL_FetchString(query, i, result, sizeof(result))
|
|
|
|
PrintToServer(" [%s] %s", fieldNames[i], result)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Action:Command_TestSql1(args)
|
|
|
|
{
|
|
|
|
new String:error[255]
|
|
|
|
new Handle:db = SQL_DefConnect(error, sizeof(error))
|
|
|
|
if (db == INVALID_HANDLE)
|
|
|
|
{
|
|
|
|
PrintToServer("Failed to connect: %s", error)
|
|
|
|
return Plugin_Handled
|
|
|
|
}
|
|
|
|
|
2008-09-14 08:13:25 +02:00
|
|
|
new Handle:query = SQL_Query(db, "SELECT * FROM gab")
|
2008-03-30 09:00:22 +02:00
|
|
|
if (query == INVALID_HANDLE)
|
|
|
|
{
|
|
|
|
SQL_GetError(db, error, sizeof(error))
|
|
|
|
PrintToServer("Failed to query: %s", error)
|
|
|
|
} else {
|
|
|
|
PrintQueryData(query)
|
|
|
|
CloseHandle(query)
|
|
|
|
}
|
|
|
|
|
|
|
|
CloseHandle(db)
|
|
|
|
|
|
|
|
return Plugin_Handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Action:Command_TestSql2(args)
|
|
|
|
{
|
|
|
|
new String:error[255]
|
|
|
|
new Handle:db = SQL_DefConnect(error, sizeof(error))
|
|
|
|
if (db == INVALID_HANDLE)
|
|
|
|
{
|
|
|
|
PrintToServer("Failed to connect: %s", error)
|
|
|
|
return Plugin_Handled
|
|
|
|
}
|
|
|
|
|
2008-09-14 08:13:25 +02:00
|
|
|
new Handle:stmt = SQL_PrepareQuery(db, "SELECT * FROM gab WHERE gaben > ?", error, sizeof(error))
|
2008-03-30 09:00:22 +02:00
|
|
|
if (stmt == INVALID_HANDLE)
|
|
|
|
{
|
|
|
|
PrintToServer("Failed to prepare query: %s", error)
|
|
|
|
} else {
|
|
|
|
SQL_BindParamInt(stmt, 0, 1)
|
|
|
|
if (!SQL_Execute(stmt))
|
|
|
|
{
|
|
|
|
SQL_GetError(stmt, error, sizeof(error))
|
|
|
|
PrintToServer("Failed to execute query: %s", error)
|
|
|
|
} else {
|
|
|
|
PrintQueryData(stmt)
|
|
|
|
}
|
|
|
|
CloseHandle(stmt)
|
|
|
|
}
|
|
|
|
|
|
|
|
CloseHandle(db)
|
|
|
|
|
|
|
|
return Plugin_Handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
new Handle:g_ThreadedHandle = INVALID_HANDLE;
|
|
|
|
|
|
|
|
public CallbackTest3(Handle:owner, Handle:hndl, const String:error[], any:data)
|
|
|
|
{
|
|
|
|
PrintToServer("CallbackTest1() (owner %x) (hndl %x) (error \"%s\") (data %d)", owner, hndl, error, data);
|
|
|
|
if (g_ThreadedHandle != INVALID_HANDLE && hndl != INVALID_HANDLE)
|
|
|
|
{
|
|
|
|
CloseHandle(hndl);
|
|
|
|
} else {
|
|
|
|
g_ThreadedHandle = hndl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Action:Command_TestSql3(args)
|
|
|
|
{
|
|
|
|
if (g_ThreadedHandle != INVALID_HANDLE)
|
|
|
|
{
|
|
|
|
PrintToServer("A threaded connection already exists, run the next test");
|
|
|
|
return Plugin_Handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
new String:name[32];
|
|
|
|
GetCmdArg(1, name, sizeof(name));
|
|
|
|
|
|
|
|
SQL_TConnect(CallbackTest3, name);
|
|
|
|
|
|
|
|
return Plugin_Handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Action:Command_TestSql4(args)
|
|
|
|
{
|
|
|
|
SQL_LockDatabase(g_ThreadedHandle);
|
2008-09-14 08:13:25 +02:00
|
|
|
new Handle:query = SQL_Query(g_ThreadedHandle, "SELECT * FROM gab")
|
2008-03-30 09:00:22 +02:00
|
|
|
if (query == INVALID_HANDLE)
|
|
|
|
{
|
|
|
|
new String:error[255];
|
|
|
|
SQL_GetError(g_ThreadedHandle, error, sizeof(error))
|
|
|
|
PrintToServer("Failed to query: %s", error)
|
|
|
|
} else {
|
|
|
|
PrintQueryData(query)
|
|
|
|
CloseHandle(query)
|
|
|
|
}
|
|
|
|
SQL_UnlockDatabase(g_ThreadedHandle);
|
|
|
|
|
|
|
|
return Plugin_Handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
public CallbackTest5(Handle:owner, Handle:hndl, const String:error[], any:data)
|
|
|
|
{
|
|
|
|
if (hndl == INVALID_HANDLE)
|
|
|
|
{
|
|
|
|
PrintToServer("Failed to query: %s", error)
|
|
|
|
} else {
|
|
|
|
PrintQueryData(hndl)
|
2008-09-14 08:13:25 +02:00
|
|
|
SQL_TQuery(g_ThreadedHandle, CallbackTest6, "UPDATE gab SET `gaben` = `gaben` + 1 WHERE `gaben` >= 4", 52)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public CallbackTest6(Handle:owner, Handle:hndl, const String:error[], any:data)
|
|
|
|
{
|
|
|
|
if (hndl == INVALID_HANDLE)
|
|
|
|
{
|
|
|
|
PrintToServer("Failed to query: %s", error)
|
|
|
|
} else {
|
|
|
|
PrintToServer("Queried!");
|
|
|
|
SQL_TQuery(g_ThreadedHandle, CallbackTest7, "UPDATE gab SET `gaben` = `gaben` + 1 WHERE `gaben` >= 4", 52)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public CallbackTest7(Handle:owner, Handle:hndl, const String:error[], any:data)
|
|
|
|
{
|
|
|
|
if (hndl == INVALID_HANDLE)
|
|
|
|
{
|
|
|
|
PrintToServer("Failed to query: %s", error)
|
|
|
|
} else {
|
|
|
|
PrintToServer("Queried!");
|
2008-03-30 09:00:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Action:Command_TestSql5(args)
|
|
|
|
{
|
2008-09-14 08:13:25 +02:00
|
|
|
SQL_TQuery(g_ThreadedHandle, CallbackTest5, "SELECT * FROM gab", 52)
|
|
|
|
SQL_TQuery(g_ThreadedHandle, CallbackTest5, "SELECT * FROM gab", 52)
|
|
|
|
SQL_TQuery(g_ThreadedHandle, CallbackTest5, "SELECT * FROM gab", 52)
|
|
|
|
SQL_TQuery(g_ThreadedHandle, CallbackTest5, "SELECT * FROM gab", 52)
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
return Plugin_Handled;
|
|
|
|
}
|
|
|
|
|
2014-06-05 10:00:54 +02:00
|
|
|
FastQuery(Handle:db, const String:query[])
|
|
|
|
{
|
|
|
|
new String:error[256];
|
|
|
|
if (!SQL_FastQuery(db, query)) {
|
|
|
|
SQL_GetError(db, error, sizeof(error));
|
|
|
|
ThrowError("ERROR: %s", error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Txn_Test1_OnSuccess(Handle:db, any:data, numQueries, Handle:results[], any:queryData[])
|
|
|
|
{
|
|
|
|
SetTestContext("Transaction Test 1");
|
|
|
|
AssertEq("data", data, 1000);
|
|
|
|
AssertEq("numQueries", numQueries, 3);
|
|
|
|
AssertEq("queryData[0]", queryData[0], 50);
|
|
|
|
AssertEq("queryData[1]", queryData[1], 60);
|
|
|
|
AssertEq("queryData[2]", queryData[2], 70);
|
|
|
|
AssertFalse("HasResultSet(0)", SQL_HasResultSet(results[0]));
|
|
|
|
AssertFalse("HasResultSet(1)", SQL_HasResultSet(results[1]));
|
|
|
|
AssertTrue("HasResultSet(2)", SQL_HasResultSet(results[2]));
|
|
|
|
AssertTrue("FetchRow(2)", SQL_FetchRow(results[2]));
|
|
|
|
AssertEq("FetchInt(2, 0)", SQL_FetchInt(results[2], 0), 5);
|
|
|
|
AssertFalse("FetchRow(2)", SQL_FetchRow(results[2]));
|
|
|
|
}
|
|
|
|
|
|
|
|
public Txn_Test1_OnFailure(Handle:db, any:data, numQueries, const String:error[], failIndex, any:queryData[])
|
|
|
|
{
|
|
|
|
ThrowError("Transaction test 1 failed: %s (failIndex=%d)", error, failIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Txn_Test2_OnSuccess(Handle:db, any:data, numQueries, Handle:results[], any:queryData[])
|
|
|
|
{
|
|
|
|
ThrowError("Transaction test 2 failed: should have failed");
|
|
|
|
}
|
|
|
|
|
|
|
|
public Txn_Test2_OnFailure(Handle:db, any:data, numQueries, const String:error[], failIndex, any:queryData[])
|
|
|
|
{
|
|
|
|
SetTestContext("Transaction Test 2");
|
|
|
|
AssertEq("data", data, 1000);
|
|
|
|
AssertEq("numQueries", numQueries, 3);
|
|
|
|
AssertEq("queryData[0]", queryData[0], 50);
|
|
|
|
AssertEq("queryData[1]", queryData[1], 60);
|
|
|
|
AssertEq("queryData[2]", queryData[2], 70);
|
|
|
|
AssertEq("failIndex", failIndex, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Action:Command_TestTxn(args)
|
|
|
|
{
|
|
|
|
new String:error[256];
|
|
|
|
new Handle:db = SQL_Connect("storage-local", false, error, sizeof(error));
|
|
|
|
if (db == INVALID_HANDLE) {
|
|
|
|
ThrowError("ERROR: %s", error);
|
|
|
|
return Plugin_Handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
FastQuery(db, "DROP TABLE IF EXISTS egg");
|
|
|
|
FastQuery(db, "CREATE TABLE egg(id int primary key)");
|
|
|
|
FastQuery(db, "INSERT INTO egg (id) VALUES (1)");
|
|
|
|
FastQuery(db, "INSERT INTO egg (id) VALUES (2)");
|
|
|
|
FastQuery(db, "INSERT INTO egg (id) VALUES (3)");
|
|
|
|
|
|
|
|
SetTestContext("CreateTransaction");
|
|
|
|
|
|
|
|
new Handle:txn = SQL_CreateTransaction();
|
|
|
|
AssertEq("AddQuery", SQL_AddQuery(txn, "INSERT INTO egg (id) VALUES (4)", 50), 0);
|
|
|
|
AssertEq("AddQuery", SQL_AddQuery(txn, "INSERT INTO egg (id) VALUES (5)", 60), 1);
|
|
|
|
AssertEq("AddQuery", SQL_AddQuery(txn, "SELECT COUNT(id) FROM egg", 70), 2);
|
|
|
|
SQL_ExecuteTransaction(
|
|
|
|
db,
|
|
|
|
txn,
|
|
|
|
Txn_Test1_OnSuccess,
|
|
|
|
Txn_Test1_OnFailure,
|
|
|
|
1000
|
|
|
|
);
|
|
|
|
|
|
|
|
txn = SQL_CreateTransaction();
|
|
|
|
AssertEq("AddQuery", SQL_AddQuery(txn, "INSERT INTO egg (id) VALUES (6)", 50), 0);
|
|
|
|
AssertEq("AddQuery", SQL_AddQuery(txn, "INSERT INTO egg (id) VALUES (6)", 60), 1);
|
|
|
|
AssertEq("AddQuery", SQL_AddQuery(txn, "SELECT COUNT(id) FROM egg", 70), 2);
|
|
|
|
SQL_ExecuteTransaction(
|
|
|
|
db,
|
|
|
|
txn,
|
|
|
|
Txn_Test2_OnSuccess,
|
|
|
|
Txn_Test2_OnFailure,
|
|
|
|
1000
|
|
|
|
);
|
|
|
|
|
|
|
|
CloseHandle(db);
|
|
|
|
return Plugin_Handled;
|
|
|
|
}
|