aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-11-17 16:46:11 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-11-17 16:46:11 +0200
commite2f3b445828604945aa8ca8bfc2bf77ae7be8b81 (patch)
treee4854c3a6dd2ce5960f619e80e86c6dc8a4b4b64
parentbcbbad2716b09c0c70366825f5bdf2055c8d21b8 (diff)
Translate certain SQLSTATE codes to special exceptions
-rw-r--r--odb/mssql/database.cxx18
-rw-r--r--odb/mssql/database.hxx8
-rw-r--r--odb/mssql/error.cxx127
-rw-r--r--odb/mssql/error.hxx5
4 files changed, 128 insertions, 30 deletions
diff --git a/odb/mssql/database.cxx b/odb/mssql/database.cxx
index a22ae9b..0eb0ed9 100644
--- a/odb/mssql/database.cxx
+++ b/odb/mssql/database.cxx
@@ -47,6 +47,11 @@ namespace odb
if (!SQL_SUCCEEDED (r))
translate_error (environment_, SQL_HANDLE_ENV);
}
+
+ if (factory_.get () == 0)
+ factory_.reset (new connection_pool_factory ());
+
+ factory_->database (*this);
}
/*
@@ -113,21 +118,16 @@ namespace odb
}
*/
- /*
database::
database (int& argc,
char* argv[],
bool erase,
- ub2 charset,
- ub2 ncharset,
- OCIEnv* environment,
+ SQLHENV environment,
auto_ptr<connection_factory> factory)
- : port_ (0),
- charset_ (charset),
- ncharset_ (ncharset),
- environment_ (environment),
+ : environment_ (environment),
factory_ (factory)
{
+ /*
if (environment_ == 0)
{
sword s (OCIEnvNlsCreate (&environment_,
@@ -209,13 +209,13 @@ namespace odb
oss << e;
throw cli_exception (oss.str ());
}
+ */
if (factory_.get () == 0)
factory_.reset (new connection_pool_factory ());
factory_->database (*this);
}
- */
void database::
print_usage (std::ostream& os)
diff --git a/odb/mssql/database.hxx b/odb/mssql/database.hxx
index f82d7c9..d20d860 100644
--- a/odb/mssql/database.hxx
+++ b/odb/mssql/database.hxx
@@ -68,17 +68,15 @@ namespace odb
// argv array and the argc count is updated accordingly. This
// constructor may throw the cli_exception exception.
//
+ */
+
database (int& argc,
char* argv[],
bool erase = false,
- ub2 charset = 0,
- ub2 ncharset = 0,
- OCIEnv* environment = 0,
+ SQLHENV environment = 0,
std::auto_ptr<connection_factory> =
std::auto_ptr<connection_factory> (0));
- */
-
static void
print_usage (std::ostream&);
diff --git a/odb/mssql/error.cxx b/odb/mssql/error.cxx
index 4e79a4d..b405db7 100644
--- a/odb/mssql/error.cxx
+++ b/odb/mssql/error.cxx
@@ -3,6 +3,8 @@
// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
+#include <string>
+
#include <odb/mssql/mssql.hxx>
#include <odb/mssql/error.hxx>
#include <odb/mssql/connection.hxx>
@@ -24,6 +26,101 @@ namespace odb
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 = SQLGetDiagRec (htype,
+ h,
+ i,
+ (SQLCHAR*) sqlstate,
+ &native_code,
+ 0,
+ 0,
+ &msg_size);
+
+ string s (sqlstate);
+
+ if (r == SQL_NO_DATA)
+ break;
+ else if (SQL_SUCCEEDED (r))
+ {
+ code nc;
+
+ 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 (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)
@@ -41,7 +138,14 @@ namespace odb
break;
else if (SQL_SUCCEEDED (r))
{
- //@@ TODO: translate deadlock, timeout, connection_lost exceptions
+ if (conn != 0)
+ {
+ string s (sqlstate);
+
+ if (s == "08S01" || // Link failure.
+ s == "HYT01") // Connection timeout.
+ conn->mark_failed ();
+ }
e.append (native_code, sqlstate, msg);
}
@@ -53,21 +157,6 @@ namespace odb
if (e.size () == 0)
e.append (0, "?????", "no diagnostic record (using wrong handle?)");
- // Check if the connection has gone bad and mark it as failed if so.
- //
- if (conn != 0)
- {
- SQLUINTEGER dead (0);
- r = SQLGetConnectAttr (conn->handle (),
- SQL_ATTR_CONNECTION_DEAD,
- (SQLPOINTER) &dead,
- SQL_IS_UINTEGER,
- 0);
-
- if (!SQL_SUCCEEDED (r) || dead == SQL_CD_TRUE)
- conn->mark_failed ();
- }
-
throw e;
}
@@ -78,6 +167,12 @@ namespace odb
}
void
+ translate_error (connection& c, const auto_handle<SQL_HANDLE_STMT>& h)
+ {
+ translate_error (h, SQL_HANDLE_STMT, &c);
+ }
+
+ void
translate_error (SQLHANDLE h, SQLSMALLINT htype)
{
translate_error (h, htype, 0);
diff --git a/odb/mssql/error.hxx b/odb/mssql/error.hxx
index 35906b7..6208103 100644
--- a/odb/mssql/error.hxx
+++ b/odb/mssql/error.hxx
@@ -11,6 +11,8 @@
#include <odb/mssql/version.hxx>
#include <odb/mssql/forward.hxx> // connection
#include <odb/mssql/mssql-fwd.hxx>
+#include <odb/mssql/auto-handle.hxx>
+
#include <odb/mssql/details/export.hxx>
namespace odb
@@ -21,6 +23,9 @@ namespace odb
translate_error (connection&);
LIBODB_MSSQL_EXPORT void
+ translate_error (connection&, const auto_handle<SQL_HANDLE_STMT>&);
+
+ LIBODB_MSSQL_EXPORT void
translate_error (SQLHANDLE, SQLSMALLINT htype);
}
}