diff --git a/src/BSQL/API.cpp b/src/BSQL/API.cpp index 0a7a257..189fe41 100644 --- a/src/BSQL/API.cpp +++ b/src/BSQL/API.cpp @@ -51,10 +51,7 @@ extern "C" { return nullptr; } - BYOND_FUNC GetError(const int argumentCount, const char* const* const args) noexcept { - if (argumentCount != 2) - return "Invalid arguments!"; - const auto& connectionIdentifier(args[0]), operationIdentifier(args[1]); + const char* GetErrorImpl(const char* const& connectionIdentifier, const char* const& operationIdentifier, bool code) { if (!library) return "Library not initialized!"; if (!connectionIdentifier) @@ -70,7 +67,7 @@ extern "C" { return "Operation identifier does not exist!"; if (!operation->IsComplete(true)) return "Operation is not complete!"; - returnValueHolder = operation->GetError(); + returnValueHolder = code ? operation->GetErrorCode() : operation->GetError(); return returnValueHolder.c_str(); } catch (std::bad_alloc&) { @@ -78,6 +75,20 @@ extern "C" { } } + BYOND_FUNC GetError(const int argumentCount, const char* const* const args) noexcept { + if (argumentCount != 2) + return "Invalid arguments!"; + const auto& connectionIdentifier(args[0]), operationIdentifier(args[1]); + return GetErrorImpl(connectionIdentifier, operationIdentifier, false); + } + + BYOND_FUNC GetErrorCode(const int argumentCount, const char* const* const args) noexcept { + if (argumentCount != 2) + return "Invalid arguments!"; + const auto& connectionIdentifier(args[0]), operationIdentifier(args[1]); + return GetErrorImpl(connectionIdentifier, operationIdentifier, true); + } + BYOND_FUNC CreateConnection(const int argumentCount, const char* const* const args) noexcept { if (argumentCount != 1) return "Invalid arguments!"; diff --git a/src/BSQL/Operation.cpp b/src/BSQL/Operation.cpp index c885302..42b3889 100644 --- a/src/BSQL/Operation.cpp +++ b/src/BSQL/Operation.cpp @@ -6,6 +6,12 @@ std::string Operation::GetError() { return error; } +std::string Operation::GetErrorCode() { + if (!IsComplete(true)) + return std::string(); + return std::to_string(errnum); +} + int Operation::GetErrno() { if (!IsComplete(true)) return -1; diff --git a/src/BSQL/Operation.h b/src/BSQL/Operation.h index 0c9ef78..4f0b21d 100644 --- a/src/BSQL/Operation.h +++ b/src/BSQL/Operation.h @@ -14,6 +14,7 @@ class Operation { virtual ~Operation() = default; std::string GetError(); + std::string GetErrorCode(); int GetErrno(); virtual bool IsComplete(bool noSkip) = 0; diff --git a/src/DMAPI/BSQL.dm b/src/DMAPI/BSQL.dm index d07d52d..d893e3a 100644 --- a/src/DMAPI/BSQL.dm +++ b/src/DMAPI/BSQL.dm @@ -1,4 +1,4 @@ -//BSQL - DMAPI v1.1.0.0 +//BSQL - DMAPI v1.1.1.0 //types of connections #define BSQL_CONNECTION_TYPE_MARIADB "MySql" @@ -51,7 +51,7 @@ Starts an operation for a query */ /datum/BSQL_Connection/proc/BeginQuery(query) return - + /* Checks if the operation is complete. This, in some cases must be called multiple times with false return before a result is present regardless of timespan. For best performance check it once per tick @@ -74,6 +74,14 @@ Get the error message associated with an operation. Should not be used while IsC /datum/BSQL_Operation/proc/GetError() return +/* +Get the error code associated with an operation. Should not be used while IsComplete() returns FALSE + + Returns: The error code, if any. null otherwise +*/ +/datum/BSQL_Operation/proc/GetErrorCode() + return + /* Gets an associated list of column name -> value representation of the most recent row in the query. Only valid if IsComplete() returns TRUE. If this returns null and no errors are present there are no more results in the query. Important to note that once IsComplete() returns TRUE it must not be called again without checking this or the row values may be lost diff --git a/src/DMAPI/BSQL/core/operation.dm b/src/DMAPI/BSQL/core/operation.dm index 2c820ee..c56867d 100644 --- a/src/DMAPI/BSQL/core/operation.dm +++ b/src/DMAPI/BSQL/core/operation.dm @@ -30,6 +30,11 @@ BSQL_DEL_PROC(/datum/BSQL_Operation) return "Connection deleted!" return world._BSQL_Internal_Call("GetError", connection.id, id) +/datum/BSQL_Operation/GetErrorCode() + if(BSQL_IS_DELETED(connection)) + return -2 + return text2num(world._BSQL_Internal_Call("GetErrorCode", connection.id, id)) + /datum/BSQL_Operation/WaitForCompletion() if(BSQL_IS_DELETED(connection)) return diff --git a/tests/Test.dm b/tests/Test.dm index 99b8e63..a19daf7 100644 --- a/tests/Test.dm +++ b/tests/Test.dm @@ -64,7 +64,18 @@ CRASH("Failed to quote \"[other_quote_test]\"! Got: \"[quote_test]\"") world.log << "Quoted \"[other_quote_test]\" to \"[quote_test]\"" - var/datum/BSQL_Operation/Query/q = conn.BeginQuery("DROP DATABASE IF EXISTS [quoted_db]"); + var/datum/BSQL_Operation/Query/q = conn.BeginQuery("This is not a real query") + world.log << "Nonsense op id: [q.id]" + WaitOp(q) + error = q.GetError() + if(!error) + CRASH("Nonsense query returned no error!") + var/errorCode = q.GetErrorCode() + if(errorCode == null) + CRASH("Nonsense query returned no error code!") + world.log << "Nonsense error ([errorCode]): [error]" + + q = conn.BeginQuery("DROP DATABASE IF EXISTS [quoted_db]") world.log << "Drop db op id: [q.id]" WaitOp(q) error = q.GetError()