From c0fa8c535ddb136f5488dd1028a02e8d1f1d4465 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 21 Nov 2011 12:31:17 +0200 Subject: Implement connection::execute() --- odb/mssql/connection.cxx | 116 ++++++++++++++++++++++++++++++++++++++++++++--- odb/mssql/connection.hxx | 5 ++ 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 +#include #include #include @@ -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 (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 direct_stmt_; + //std::auto_ptr statement_cache_; }; } -- cgit v1.1