aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-11-21 12:31:17 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-11-21 12:31:17 +0200
commitc0fa8c535ddb136f5488dd1028a02e8d1f1d4465 (patch)
tree0814df490a46f89487146867fcb9013ecd45282b
parenta8a2cd61bb9f3657c65acf3a1d9dfaaa68271f4e (diff)
Implement connection::execute()
-rw-r--r--odb/mssql/connection.cxx116
-rw-r--r--odb/mssql/connection.hxx5
2 files changed, 114 insertions, 7 deletions
diff --git a/odb/mssql/connection.cxx b/odb/mssql/connection.cxx
index 0d09461..3ba10ba 100644
--- a/odb/mssql/connection.cxx
+++ b/odb/mssql/connection.cxx
@@ -5,7 +5,7 @@
//@@ disabled functionality
-//#include <string>
+#include <string>
#include <odb/mssql/mssql.hxx>
#include <odb/mssql/database.hxx>
@@ -47,7 +47,7 @@ namespace odb
r = SQLSetConnectAttr (handle_,
SQL_ATTR_AUTOCOMMIT,
SQL_AUTOCOMMIT_OFF,
- SQL_IS_UINTEGER);
+ 0);
if (!SQL_SUCCEEDED (r))
// Still use the handle version of translate_error since there
@@ -107,12 +107,114 @@ namespace odb
}
unsigned long long connection::
- execute (const char* /*s*/, std::size_t /*n*/)
+ execute (const char* s, std::size_t n)
{
- //@@
- //generic_statement st (*this, string (s, n));
- //return st.execute ();
- return 0;
+ /*
+ @@
+ {
+ odb::tracer* t;
+ if ((t = transaction_tracer ()) ||
+ (t = tracer ()) ||
+ (t = database ().tracer ()))
+ {
+ string str (s, n);
+ t->execute (*this, str.c_str ());
+ }
+ }
+ */
+
+ SQLRETURN r;
+
+ // Allocate the statement if necessary.
+ //
+ if (direct_stmt_ == 0)
+ {
+ SQLHANDLE h;
+ r = SQLAllocHandle (SQL_HANDLE_STMT, handle_, &h);
+
+ if (!SQL_SUCCEEDED (r))
+ translate_error (r, *this);
+
+ direct_stmt_.reset (h);
+
+ // Disable escape sequences.
+ //
+ r = SQLSetStmtAttr (direct_stmt_,
+ SQL_ATTR_NOSCAN,
+ (SQLPOINTER) SQL_NOSCAN_OFF,
+ 0);
+
+ if (!SQL_SUCCEEDED (r))
+ translate_error (r, *this, direct_stmt_);
+
+ // Disable data retrieval for SELECT statements.
+ //
+ r = SQLSetStmtAttr (direct_stmt_,
+ SQL_ATTR_RETRIEVE_DATA,
+ (SQLPOINTER) SQL_RD_OFF,
+ 0);
+
+ if (!SQL_SUCCEEDED (r))
+ translate_error (r, *this, direct_stmt_);
+ }
+
+ // Execute.
+ //
+ r = SQLExecDirect (direct_stmt_, (SQLCHAR*) s, (SQLINTEGER) n);
+
+ // SQL_NO_DATA indicates that a DML statement hasn't affected
+ // any rows.
+ //
+ if (r == SQL_NO_DATA)
+ return 0;
+
+ if (!SQL_SUCCEEDED (r))
+ translate_error (r, *this, direct_stmt_);
+
+ // Get the number of affected/returned rows.
+ //
+ SQLLEN rows;
+
+ // See if this is a select statement.
+ //
+ SQLSMALLINT cols;
+ r = SQLNumResultCols (direct_stmt_, &cols);
+
+ if (!SQL_SUCCEEDED (r))
+ translate_error (r, *this, direct_stmt_);
+
+ if (cols != 0)
+ {
+ for (rows = 0;; ++rows)
+ {
+ r = SQLFetch (direct_stmt_);
+
+ if (r == SQL_NO_DATA)
+ break;
+ else if (!SQL_SUCCEEDED (r))
+ translate_error (r, *this, direct_stmt_);
+ }
+
+ r = SQLCloseCursor (direct_stmt_);
+
+ if (!SQL_SUCCEEDED (r))
+ translate_error (r, *this, direct_stmt_);
+ }
+ else
+ {
+ r = SQLRowCount (direct_stmt_, &rows);
+
+ if (!SQL_SUCCEEDED (r))
+ translate_error (r, *this, direct_stmt_);
+
+ // -1 means the row count is not available. In particular, the
+ // Native Client ODBC driver returns this value for DDL statements.
+ //
+ if (rows == -1)
+ rows = 0;
+ }
+
+ return static_cast<unsigned long long> (rows);
}
}
}
diff --git a/odb/mssql/connection.hxx b/odb/mssql/connection.hxx
index fea9035..1a6cd24 100644
--- a/odb/mssql/connection.hxx
+++ b/odb/mssql/connection.hxx
@@ -127,6 +127,11 @@ namespace odb
state_failed
} state_;
+ // Statement handle for direct execution. It should be after the
+ // connection handle to be destroyed in the correct order.
+ //
+ auto_handle<SQL_HANDLE_STMT> direct_stmt_;
+
//std::auto_ptr<statement_cache_type> statement_cache_;
};
}