#include #include 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) RegServerCmd("sql_test_txn", Command_TestTxn) new Handle:hibernate = FindConVar("sv_hibernate_when_empty"); if (hibernate != null) { ServerCommand("sv_hibernate_when_empty 0"); } } 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 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 ?", error, sizeof(error)) if (stmt == null) { 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) } delete stmt } delete db return Plugin_Handled; } new Handle:g_ThreadedHandle = null; 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 != null && hndl != null) { delete hndl; } else { g_ThreadedHandle = hndl; } } public Action:Command_TestSql3(args) { if (g_ThreadedHandle != null) { 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); new Handle:query = SQL_Query(g_ThreadedHandle, "SELECT * FROM gab") if (query == null) { new String:error[255]; SQL_GetError(g_ThreadedHandle, error, sizeof(error)) PrintToServer("Failed to query: %s", error) } else { PrintQueryData(query) delete query } SQL_UnlockDatabase(g_ThreadedHandle); return Plugin_Handled; } public CallbackTest5(Handle:owner, Handle:hndl, const String:error[], any:data) { if (hndl == null) { PrintToServer("Failed to query: %s", error) } else { PrintQueryData(hndl) 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 == null) { 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 == null) { PrintToServer("Failed to query: %s", error) } else { PrintToServer("Queried!"); } } public Action:Command_TestSql5(args) { 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) return Plugin_Handled; } 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 Txn_Test3_OnSuccess(Handle:db, any:data, numQueries, Handle:results[], any:queryData[]) { SetTestContext("Transaction Test 3"); AssertEq("data", data, 0); AssertEq("numQueries", numQueries, 1); AssertEq("queryData[0]", queryData[0], 0); AssertTrue("HasResultSet(0)", SQL_HasResultSet(results[0])); AssertTrue("FetchRow(0)", SQL_FetchRow(results[0])); AssertEq("FetchInt(0, 0)", SQL_FetchInt(results[0], 0), 5); } public Action:Command_TestTxn(args) { new String:error[256]; new Handle:db = SQL_Connect("storage-local", false, error, sizeof(error)); if (db == null) { 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 Transaction:txn = SQL_CreateTransaction(); AssertEq("AddQuery", txn.AddQuery("INSERT INTO egg (id) VALUES (4)", 50), 0); AssertEq("AddQuery", txn.AddQuery("INSERT INTO egg (id) VALUES (5)", 60), 1); AssertEq("AddQuery", txn.AddQuery("SELECT COUNT(id) FROM egg", 70), 2); SQL_ExecuteTransaction( db, txn, Txn_Test1_OnSuccess, Txn_Test1_OnFailure, 1000 ); txn = SQL_CreateTransaction(); AssertEq("AddQuery", txn.AddQuery("INSERT INTO egg (id) VALUES (6)", 50), 0); AssertEq("AddQuery", txn.AddQuery("INSERT INTO egg (id) VALUES (6)", 60), 1); AssertEq("AddQuery", txn.AddQuery("SELECT COUNT(id) FROM egg", 70), 2); SQL_ExecuteTransaction( db, txn, Txn_Test2_OnSuccess, Txn_Test2_OnFailure, 1000 ); // Make sure the transaction was rolled back - COUNT should be 5. txn = SQL_CreateTransaction(); AssertEq("CloneHandle", _:CloneHandle(txn), _:null); txn.AddQuery("SELECT COUNT(id) FROM egg"); SQL_ExecuteTransaction( db, txn, Txn_Test3_OnSuccess ); db.Close(); return Plugin_Handled; }