summaryrefslogtreecommitdiff
path: root/odb/mssql/error.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2024-02-01 18:10:29 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2024-02-01 18:10:29 +0300
commit2895ad78dbdb43e57fc34558b4530b4e105fc72d (patch)
tree9a176c9a1a34cfa9df60fcf482bc6c360ae11214 /odb/mssql/error.cxx
parent8ac5c705c360b9ccde527eea24ddc90b2f6ed7ec (diff)
Turn libodb-mssql repository into package for muti-package repositorylibodb-mssql
Diffstat (limited to 'odb/mssql/error.cxx')
-rw-r--r--odb/mssql/error.cxx273
1 files changed, 0 insertions, 273 deletions
diff --git a/odb/mssql/error.cxx b/odb/mssql/error.cxx
deleted file mode 100644
index 897d415..0000000
--- a/odb/mssql/error.cxx
+++ /dev/null
@@ -1,273 +0,0 @@
-// file : odb/mssql/error.cxx
-// license : ODB NCUEL; see accompanying LICENSE file
-
-#include <string>
-#include <cstring> // std::strlen
-
-#include <odb/mssql/mssql.hxx>
-#include <odb/mssql/error.hxx>
-#include <odb/mssql/connection.hxx>
-#include <odb/mssql/exceptions.hxx>
-
-using namespace std;
-
-namespace odb
-{
- namespace mssql
- {
- static void
- translate_error (SQLRETURN r,
- SQLHANDLE h,
- SQLSMALLINT htype,
- connection* conn,
- bool end_tran,
- size_t pos,
- multiple_exceptions* mex)
- {
- // First see if we have one of the errors indicated via the
- // return error code.
- //
- switch (r)
- {
- case SQL_STILL_EXECUTING:
- {
- throw database_exception (0, "?????", "statement still executing");
- break;
- }
- case SQL_NEED_DATA:
- case SQL_NO_DATA:
-#if ODBCVER >= 0x0380
- case SQL_PARAM_DATA_AVAILABLE:
-#endif
- {
- throw database_exception (
- 0, "?????", "unhandled SQL_*_DATA condition");
- break;
- }
- case SQL_INVALID_HANDLE:
- {
- throw database_exception (0, "?????", "invalid handle");
- break;
- }
- }
-
- // Otherwise the diagnostics is stored in the handle.
- //
- char sqlstate[SQL_SQLSTATE_SIZE + 1];
- SQLINTEGER native_code; // Will be 0 if no natve code.
- char msg[512]; // Will be truncated if doesn't fit.
- SQLSMALLINT msg_size;
-
- // We need to translate certain sqlstate codes to special exceptions,
- // such as deadlock, timeout, etc. The problem is we can have multiple
- // records potentially with different sqlstate codes. If we have both,
- // say, a deadlock code and some other code, then we should probably
- // throw database_exception, which is more severe. To implement this
- // we are going to pre-scan the records looking for the codes we are
- // interested in. If in the process we see any other code, then we
- // stop and go ahead to prepare and throw database_exception.
- //
- enum code
- {
- code_none,
- code_deadlock,
- code_timeout,
- code_connection_lost
- };
-
- code c (code_none);
-
- for (SQLSMALLINT i (1);; ++i)
- {
- r = SQLGetDiagRecA (htype,
- h,
- i,
- (SQLCHAR*) sqlstate,
- &native_code,
- 0,
- 0,
- &msg_size);
-
- if (r == SQL_NO_DATA)
- break;
- else if (SQL_SUCCEEDED (r))
- {
- code nc;
- string s (sqlstate);
-
- if (s == "40001") // Serialization failure (native code 1205).
- nc = code_deadlock;
- else if (s == "HYT00") // Timeout expired.
- nc = code_timeout;
- else if (s == "HYT01") // Connection timeout expired.
- {
- nc = code_timeout;
-
- if (conn != 0)
- conn->mark_failed ();
- }
- else if (s == "08S01") // Link failure.
- {
- nc = code_connection_lost;
-
- if (conn != 0)
- conn->mark_failed ();
- }
- else if (s == "01000") // General warning.
- continue;
- else
- {
- c = code_none;
- break;
- }
-
- // If a call to SQLEndTran() fails, then the connection is
- // put into the so called "suspended state" and should be
- // disconnected unless we know the transaction was rolled
- // back. See SQLEndTran() documentation for details.
- //
- if (end_tran &&
- s != "25S03" && // Transaction is rolled back.
- s != "40001" && // Serialization failure.
- s != "40002" && // Integrity constraint.
- s != "HYC00") // Optional feature not implemented.
- conn->mark_failed ();
-
- if (c != code_none && c != nc)
- {
- // Several different codes.
- //
- c = code_none;
- break;
- }
-
- c = nc;
- }
- else
- {
- c = code_none;
- break;
- }
- }
-
- switch (c)
- {
- case code_deadlock:
- throw deadlock ();
- case code_timeout:
- throw timeout ();
- case code_connection_lost:
- throw connection_lost ();
- case code_none:
- break;
- }
-
- // Some other error code. Prepare database_exception.
- //
- database_exception e;
-
- for (SQLSMALLINT i (1);; ++i)
- {
- // If this is for a batch, filter out based on row association.
- // Here we only ignore records that have the associated row
- // number and this number doesn't match ours. In particular,
- // this means that all the un-associated records which will be
- // duplicated for all the failed rows, which seems like the
- // correct thing to do.
- //
- if (mex != 0)
- {
- SQLLEN n;
- r = SQLGetDiagField (htype,
- h,
- i,
- SQL_DIAG_ROW_NUMBER,
- &n,
- 0,
- 0);
-
- if (r == SQL_NO_DATA)
- break;
- else if (SQL_SUCCEEDED (r) &&
- n != SQL_NO_ROW_NUMBER &&
- n != SQL_ROW_NUMBER_UNKNOWN &&
- n != static_cast<SQLLEN> (pos + 1)) // 1-based
- continue;
- }
-
- r = SQLGetDiagRecA (htype,
- h,
- i,
- (SQLCHAR*) sqlstate,
- &native_code,
- (SQLCHAR*) msg,
- sizeof (msg),
- &msg_size);
-
- if (r == SQL_NO_DATA)
- break;
- else if (SQL_SUCCEEDED (r))
- {
- if (conn != 0)
- {
- string s (sqlstate);
-
- if (s == "08S01" || // Link failure.
- s == "HYT01" || // Connection timeout.
- (end_tran &&
- s != "25S03" &&
- s != "40001" &&
- s != "40002" &&
- s != "HYC00"))
- conn->mark_failed ();
- }
-
- // Get rid of a trailing newline if there is one.
- //
- size_t n (strlen (msg));
- if (n != 0 && msg[n - 1] == '\n')
- msg[n - 1] = '\0';
-
- e.append (native_code, sqlstate, msg);
- }
- else
- e.append (0, "?????", "unable to extract information for this "
- "diagnostic record");
- }
-
- if (e.size () == 0)
- e.append (0, "?????", "no diagnostic record (using wrong handle?)");
-
- if (mex == 0)
- throw e;
- else
- // It could be that some of these errors are fatal. I guess we
- // will just have to learn from experience which ones are. The
- // client code can always treat specific error codes as fatal.
- //
- mex->insert (pos, e);
- }
-
- void
- translate_error (SQLRETURN r, connection& c, bool end_tran)
- {
- translate_error (r, c.handle (), SQL_HANDLE_DBC, &c, end_tran, 0, 0);
- }
-
- void
- translate_error (SQLRETURN r,
- connection& c,
- const auto_handle<SQL_HANDLE_STMT>& h,
- size_t pos,
- multiple_exceptions* mex)
- {
- translate_error (r, h, SQL_HANDLE_STMT, &c, false, pos, mex);
- }
-
- void
- translate_error (SQLRETURN r, SQLHANDLE h, SQLSMALLINT htype)
- {
- translate_error (r, h, htype, 0, false, 0, 0);
- }
- }
-}