From 494579542f57ff339bb34146a4cf04df7b94686c Mon Sep 17 00:00:00 2001 From: Alex Fabijanic Date: Thu, 26 Oct 2017 12:54:04 -0500 Subject: [PATCH] Oracle ODBC fixes --- .../Poco/Data/ODBC/ODBCStatementImpl.h | 1 - Data/ODBC/include/Poco/Data/ODBC/Preparator.h | 4 +--- Data/ODBC/src/ODBCMetaColumn.cpp | 17 +++++--------- Data/ODBC/src/ODBCStatementImpl.cpp | 11 ++++------ Data/ODBC/src/Preparator.cpp | 8 +++---- Data/ODBC/testsuite/src/ODBCOracleTest.cpp | 22 ++++++++++++++----- Data/ODBC/testsuite/src/ODBCOracleTest.h | 1 + Data/ODBC/testsuite/src/SQLExecutor.cpp | 3 ++- 8 files changed, 33 insertions(+), 34 deletions(-) diff --git a/Data/ODBC/include/Poco/Data/ODBC/ODBCStatementImpl.h b/Data/ODBC/include/Poco/Data/ODBC/ODBCStatementImpl.h index 08026af60..0ed7dd6c8 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/ODBCStatementImpl.h +++ b/Data/ODBC/include/Poco/Data/ODBC/ODBCStatementImpl.h @@ -158,7 +158,6 @@ private: bool _prepared; mutable std::size_t _affectedRowCount; bool _canCompile; - bool _isPostgres; bool _insertHint; }; diff --git a/Data/ODBC/include/Poco/Data/ODBC/Preparator.h b/Data/ODBC/include/Poco/Data/ODBC/Preparator.h index 50b41b647..00af7988e 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/Preparator.h +++ b/Data/ODBC/include/Poco/Data/ODBC/Preparator.h @@ -99,9 +99,7 @@ public: Preparator(const StatementHandle& rStmt, const std::string& statement, std::size_t maxFieldSize, - DataExtraction dataExtraction, - bool isPostgres - ); + DataExtraction dataExtraction); /// Creates the Preparator. Preparator(const Preparator& other); diff --git a/Data/ODBC/src/ODBCMetaColumn.cpp b/Data/ODBC/src/ODBCMetaColumn.cpp index ff90818f6..401770219 100644 --- a/Data/ODBC/src/ODBCMetaColumn.cpp +++ b/Data/ODBC/src/ODBCMetaColumn.cpp @@ -135,18 +135,11 @@ void ODBCMetaColumn::init() case SQL_NUMERIC: case SQL_DECIMAL: - if (0 == _columnDesc.decimalDigits) - { -#ifdef POCO_64_BIT - setType(MetaColumn::FDT_INT64); -#else - setType(MetaColumn::FDT_INT32); -#endif - } - else - { - setType(MetaColumn::FDT_DOUBLE); - } + // Oracle has no INTEGER type - it's essentially NUMBER with 38 whole and + // 0 fractional digits. It also does not recognize SQL_BIGINT type, + // so the workaround here is to hardcode it to 32 bit integer + if (0 == _columnDesc.decimalDigits) setType(MetaColumn::FDT_INT32); + else setType(MetaColumn::FDT_DOUBLE); break; case SQL_REAL: diff --git a/Data/ODBC/src/ODBCStatementImpl.cpp b/Data/ODBC/src/ODBCStatementImpl.cpp index 3eb5a4029..168035fd4 100644 --- a/Data/ODBC/src/ODBCStatementImpl.cpp +++ b/Data/ODBC/src/ODBCStatementImpl.cpp @@ -45,7 +45,6 @@ ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession): _prepared(false), _affectedRowCount(0), _canCompile(true), - _isPostgres(false), _insertHint(false) { int queryTimeout = rSession.queryTimeout(); @@ -64,7 +63,6 @@ ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession): std::string serverString; serverString.resize(static_cast(t) + 2); r = Poco::Data::ODBC::SQLGetInfo(_rConnection, SQL_DRIVER_NAME, &serverString[0], SQLSMALLINT((serverString.length() - 1) * sizeof(serverString[0])), &t); - _isPostgres = (!Utility::isError(r) && Poco::toUpperInPlace(serverString).find("PSQLODBC") == 0); } } @@ -152,7 +150,7 @@ bool ODBCStatementImpl::addPreparator(bool addAlways) std::size_t maxFieldSize = AnyCast(session().getProperty("maxFieldSize")); - prep = new Preparator(_stmt, statement, maxFieldSize, ext, _isPostgres); + prep = new Preparator(_stmt, statement, maxFieldSize, ext); } else prep = new Preparator(*_preparations[0]); @@ -307,14 +305,13 @@ bool ODBCStatementImpl::nextResultSet() if (SQL_NO_DATA == ret) return false; - if (Utility::isError(ret)) { + if (Utility::isError(ret)) throw StatementException(_stmt, "SQLMoreResults()"); - } // need to remove old bindings, as Sybase doesn't like old ones - if (Utility::isError(SQLFreeStmt(_stmt, SQL_UNBIND))) { + if (Utility::isError(SQLFreeStmt(_stmt, SQL_UNBIND))) throw StatementException(_stmt, "SQLFreeStmt(SQL_UNBIND)"); - } + return true; } diff --git a/Data/ODBC/src/Preparator.cpp b/Data/ODBC/src/Preparator.cpp index fa1ae33eb..9347b94c5 100644 --- a/Data/ODBC/src/Preparator.cpp +++ b/Data/ODBC/src/Preparator.cpp @@ -28,8 +28,7 @@ namespace ODBC { Preparator::Preparator(const StatementHandle& rStmt, const std::string& statement, std::size_t maxFieldSize, - DataExtraction dataExtraction, - bool isPostgres) : + DataExtraction dataExtraction) : _rStmt(rStmt), _maxFieldSize(maxFieldSize), _dataExtraction(dataExtraction) @@ -38,9 +37,8 @@ Preparator::Preparator(const StatementHandle& rStmt, if (Utility::isError(Poco::Data::ODBC::SQLPrepare(_rStmt, pStr, (SQLINTEGER) statement.length()))) throw StatementException(_rStmt); // PostgreSQL error swallowing workaround: - // Postgres may execute a statement with sintax error fine, - // but would return error once num of columns requested! - if (isPostgres) + // Postgres may execute a statement with syntax error fine, + // but will return error later { SQLSMALLINT t = 0; SQLRETURN r = SQLNumResultCols(rStmt, &t); diff --git a/Data/ODBC/testsuite/src/ODBCOracleTest.cpp b/Data/ODBC/testsuite/src/ODBCOracleTest.cpp index c632dec61..cc39f34aa 100644 --- a/Data/ODBC/testsuite/src/ODBCOracleTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCOracleTest.cpp @@ -41,7 +41,7 @@ using Poco::DynamicAny; using Poco::DateTime; -#define ORACLE_ODBC_DRIVER "Oracle in OraClient12Home1_32bit"//XE" +#define ORACLE_ODBC_DRIVER "Oracle in OraDB12Home1"//XE" #define ORACLE_DSN "PocoDataOracleTest" #define ORACLE_SERVER POCO_ODBC_TEST_DATABASE_SERVER #define ORACLE_PORT "1521" @@ -775,13 +775,22 @@ void ODBCOracleTest::recreateStringsTable() void ODBCOracleTest::recreateFloatsTable() { - dropObject("TABLE", ExecUtil::strings()); - try { *_pSession << "CREATE TABLE " << ExecUtil::strings() <<" (str NUMBER)", now; } + dropObject("TABLE", ExecUtil::floats()); + try { *_pSession << "CREATE TABLE " << ExecUtil::floats() <<" (str NUMBER)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); } } +void ODBCOracleTest::recreateDoublesTable() +{ + dropObject("TABLE", ExecUtil::doubles()); + try { *_pSession << "CREATE TABLE " << ExecUtil::doubles() << " (str NUMBER)", now; } + catch (ConnectionException& ce) { std::cout << ce.toString() << std::endl; fail("recreateFloatsTable()"); } + catch (StatementException& se) { std::cout << se.toString() << std::endl; fail("recreateFloatsTable()"); } +} + + void ODBCOracleTest::recreateTuplesTable() { dropObject("TABLE", ExecUtil::tuples()); @@ -815,10 +824,13 @@ void ODBCOracleTest::recreateAnysTable() void ODBCOracleTest::recreateNullsTable(const std::string& notNull) { dropObject("TABLE", ExecUtil::nulltest()); - try { *_pSession << format("CREATE TABLE %s (i INTEGER %s, r NUMBER %s, v VARCHAR(30) %s)",ExecUtil::nulltest(), + try + { + *_pSession << format("CREATE TABLE %s (i INTEGER %s, r NUMBER %s, v VARCHAR(30) %s)", ExecUtil::nulltest(), notNull, notNull, - notNull), now; } + notNull), now; + } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateNullsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateNullsTable()"); } } diff --git a/Data/ODBC/testsuite/src/ODBCOracleTest.h b/Data/ODBC/testsuite/src/ODBCOracleTest.h index 227efc739..babcb52c2 100644 --- a/Data/ODBC/testsuite/src/ODBCOracleTest.h +++ b/Data/ODBC/testsuite/src/ODBCOracleTest.h @@ -65,6 +65,7 @@ private: void recreateStringsTable(); void recreateIntsTable(); void recreateFloatsTable(); + void recreateDoublesTable(); void recreateTuplesTable(); void recreateVectorsTable(); void recreateAnysTable(); diff --git a/Data/ODBC/testsuite/src/SQLExecutor.cpp b/Data/ODBC/testsuite/src/SQLExecutor.cpp index 98a317268..bf534365e 100644 --- a/Data/ODBC/testsuite/src/SQLExecutor.cpp +++ b/Data/ODBC/testsuite/src/SQLExecutor.cpp @@ -3015,7 +3015,8 @@ void SQLExecutor::notNulls(const std::string& sqlState) { session() << "INSERT INTO "<< ExecUtil::nulltest() << " (i,r,v) VALUES (?,?,?)", use(null), use(null), use(null), now; fail ("must fail"); - }catch (StatementException& se) + } + catch (StatementException& se) { //double check if we're failing for the right reason //default sqlState value is "23502"; some drivers report "HY???" codes