Skip to content

Commit

Permalink
fix(ODBC): detect backend at runtime for string size; add Session::db…
Browse files Browse the repository at this point in the history
…msName() #4324
  • Loading branch information
aleks-f committed Oct 19, 2024
1 parent a120310 commit 6a148ed
Show file tree
Hide file tree
Showing 21 changed files with 145 additions and 30 deletions.
2 changes: 2 additions & 0 deletions Data/MySQL/include/Poco/Data/MySQL/SessionImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ class MySQL_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
return getValue<T>(pResult, val);
}

void setName();

std::string _connector;
mutable SessionHandle _handle;
bool _reset;
Expand Down
8 changes: 7 additions & 1 deletion Data/MySQL/src/SessionImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ SessionImpl::SessionImpl(const std::string& connectionString, std::size_t loginT
}


void SessionImpl::setName()
{
setDBMSName("MySQL"s);
}


void SessionImpl::open(const std::string& connect)
{
if (connect != connectionString())
Expand Down Expand Up @@ -175,7 +181,7 @@ void SessionImpl::open(const std::string& connect)

// autocommit is initially on when a session is opened
AbstractSessionImpl::setAutoCommit("", true);

setName();
_connected = true;
}

Expand Down
17 changes: 7 additions & 10 deletions Data/ODBC/include/Poco/Data/ODBC/Binder.h
Original file line number Diff line number Diff line change
Expand Up @@ -616,11 +616,7 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
toODBCDirection(dir),
SQL_C_CHAR,
Utility::sqlDataType(SQL_C_CHAR),
#if defined(POCO_DATA_ODBC_HAVE_SQL_SERVER_EXT) && POCO_DATA_SQL_SERVER_BIG_STRINGS
SQL_SS_LENGTH_UNLIMITED,
#else
(SQLUINTEGER)size - 1,
#endif
getStringColSize(size),
0,
_charPtrs[pos],
(SQLINTEGER) size,
Expand Down Expand Up @@ -687,11 +683,7 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
toODBCDirection(dir),
SQL_C_WCHAR,
Utility::sqlDataType(SQL_C_WCHAR),
#if defined(POCO_DATA_ODBC_HAVE_SQL_SERVER_EXT) && POCO_DATA_SQL_SERVER_BIG_STRINGS
SQL_SS_LENGTH_UNLIMITED,
#else
(SQLUINTEGER)size - 1,
#endif
getStringColSize(size),
0,
_utf16CharPtrs[pos],
(SQLINTEGER)size,
Expand Down Expand Up @@ -958,6 +950,11 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
}
}

SQLUINTEGER getStringColSize(SQLUINTEGER columnSize);
/// Returns the string column size.
/// If the back end is not SQL Server, it returns
/// the `columnSize` passed in.

void getColSizeAndPrecision(std::size_t pos,
SQLSMALLINT cDataType,
SQLINTEGER& colSize,
Expand Down
6 changes: 6 additions & 0 deletions Data/ODBC/include/Poco/Data/ODBC/Handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ class Handle
return _handle;
}

const ConnectionHandle& connection() const
/// Returns the connection handle.
{
return _rConnection;
}

private:
Handle(const Handle&);
const Handle& operator=(const Handle&);
Expand Down
2 changes: 1 addition & 1 deletion Data/ODBC/include/Poco/Data/ODBC/ODBC.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
// - increasing the "maxFieldSize" property may
// affect performance (more memory preallocated
// for prepared statements in order to safely
// accomodate data returned at execution)
// accommodate data returned at execution)
#if !defined(POCO_DATA_SQL_SERVER_BIG_STRINGS)
#define POCO_DATA_SQL_SERVER_BIG_STRINGS 1
#endif
Expand Down
3 changes: 3 additions & 0 deletions Data/ODBC/include/Poco/Data/ODBC/SessionImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ class ODBC_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
/// Sets the transaction isolation level.
/// Called internally from getTransactionIsolation()

void setName();
/// Sets the back end DBMS name.

std::string _connector;
mutable ConnectionHandle _db;
Poco::Any _maxFieldSize;
Expand Down
7 changes: 7 additions & 0 deletions Data/ODBC/include/Poco/Data/ODBC/Utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ namespace Data {
namespace ODBC {


class ConnectionHandle;


class ODBC_API Utility
/// Various utility functions
{
Expand Down Expand Up @@ -162,6 +165,10 @@ class ODBC_API Utility
for (; it != end; ++it, ++tIt) dateTimeSync(*tIt, *it);
}

static std::string dbmsName(const ConnectionHandle& db);
/// Returns the back end DBMS name.
/// On error, returns "unknown".

private:
static const TypeInfo _dataTypes;
/// C <==> SQL data type mapping
Expand Down
26 changes: 14 additions & 12 deletions Data/ODBC/src/Binder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,7 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
toODBCDirection(dir),
SQL_C_CHAR,
Utility::sqlDataType(SQL_C_CHAR),
#if defined(POCO_DATA_ODBC_HAVE_SQL_SERVER_EXT) && POCO_DATA_SQL_SERVER_BIG_STRINGS
SQL_SS_LENGTH_UNLIMITED,
#else
(SQLUINTEGER)colSize,
#endif
getStringColSize(colSize),
0,
pVal,
(SQLINTEGER)size,
Expand Down Expand Up @@ -223,11 +219,7 @@ void Binder::bind(std::size_t pos, const UTF16String& val, Direction dir)
toODBCDirection(dir),
SQL_C_WCHAR,
Utility::sqlDataType(SQL_C_WCHAR),
#if defined(POCO_DATA_ODBC_HAVE_SQL_SERVER_EXT) && POCO_DATA_SQL_SERVER_BIG_STRINGS
SQL_SS_LENGTH_UNLIMITED,
#else
(SQLUINTEGER)colSize,
#endif
getStringColSize(colSize),
0,
pVal,
(SQLINTEGER)size,
Expand Down Expand Up @@ -514,6 +506,16 @@ void Binder::reset()
}


SQLUINTEGER Binder::getStringColSize(SQLUINTEGER columnSize)
{
#if defined(POCO_DATA_ODBC_HAVE_SQL_SERVER_EXT) && POCO_DATA_SQL_SERVER_BIG_STRINGS
if (Utility::dbmsName(_rStmt.connection()) == "SQLServer"s)
return SQL_SS_LENGTH_UNLIMITED;
#endif
return columnSize;
}


void Binder::getColSizeAndPrecision(std::size_t pos,
SQLSMALLINT cDataType,
SQLINTEGER& colSize,
Expand Down Expand Up @@ -634,14 +636,14 @@ void Binder::getColumnOrParameterSize(std::size_t pos, SQLINTEGER& size)
ODBCMetaColumn col(_rStmt, pos);
colSize = col.length();
}
catch (StatementException&) { }
catch (StatementException&){}

try
{
Parameter p(_rStmt, pos);
paramSize = p.columnSize();
}
catch (StatementException&) {}
catch (StatementException&){}

if (colSize == 0 && paramSize == 0)
paramSize = getParamSizeDirect(pos, size);
Expand Down
8 changes: 8 additions & 0 deletions Data/ODBC/src/SessionImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ SessionImpl::~SessionImpl()
}


void SessionImpl::setName()
{
setDBMSName(Utility::dbmsName(_db));
}


Poco::Data::StatementImpl::Ptr SessionImpl::createStatementImpl()
{
return new ODBCStatementImpl(*this);
Expand Down Expand Up @@ -173,6 +179,8 @@ void SessionImpl::open(const std::string& connect)
else
throw ConnectionException(SQL_NULL_HDBC,
Poco::format("Connection to '%s' failed.", connectionString()));

setName();
}


Expand Down
12 changes: 12 additions & 0 deletions Data/ODBC/src/Utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "Poco/Data/ODBC/Utility.h"
#include "Poco/Data/ODBC/Handle.h"
#include "Poco/Data/ODBC/ConnectionHandle.h"
#include "Poco/Data/ODBC/ODBCException.h"
#include "Poco/NumberFormatter.h"
#include "Poco/DateTime.h"
Expand Down Expand Up @@ -156,4 +157,15 @@ void Utility::dateTimeSync(SQL_TIMESTAMP_STRUCT& ts, const Poco::DateTime& dt)
}


std::string Utility::dbmsName(const ConnectionHandle& db)
{
const SQLSMALLINT bufSize = 1024;
SQLCHAR dbmsName[bufSize] = {0};
SQLSMALLINT retSize = 0;
SQLRETURN rc = Poco::Data::ODBC::SQLGetInfo(const_cast<SQLHDBC>(db.handle()), SQL_DBMS_NAME, dbmsName, bufSize, &retSize);
if (!isError(rc)) return std::string(dbmsName[0], retSize);
return "unknown"s;
}


} } } // namespace Poco::Data::ODBC
3 changes: 1 addition & 2 deletions Data/ODBC/testsuite/src/ODBCTestSuite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ CppUnit::Test* ODBCTestSuite::suite()
//
// For the time being, the workaround is to connect to DB2 after connecting to PostgreSQL and Oracle.


addTest(pSuite, ODBCSQLServerTest::suite());
addTest(pSuite, ODBCOracleTest::suite());
addTest(pSuite, ODBCSQLServerTest::suite());
addTest(pSuite, ODBCMySQLTest::suite());
addTest(pSuite, ODBCPostgreSQLTest::suite());
addTest(pSuite, ODBCSQLiteTest::suite());
Expand Down
2 changes: 2 additions & 0 deletions Data/PostgreSQL/include/Poco/Data/PostgreSQL/SessionImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ class PostgreSQL_API SessionImpl: public Poco::Data::AbstractSessionImpl<Session
const std::string& connectorName() const;
/// Returns the name of the connector.

void setName();

private:
std::string _connectorName;
mutable SessionHandle _sessionHandle;
Expand Down
8 changes: 8 additions & 0 deletions Data/PostgreSQL/src/SessionImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ SessionImpl::~SessionImpl()
}


void SessionImpl::setName()
{
setDBMSName("PostgreSQL"s);
}


void SessionImpl::setConnectionTimeout(std::size_t aTimeout)
{
_timeout = aTimeout;
Expand Down Expand Up @@ -145,6 +151,8 @@ void SessionImpl::open(const std::string& aConnectionString)
addFeature("binaryExtraction",
&SessionImpl::setBinaryExtraction,
&SessionImpl::isBinaryExtraction);

setName();
}


Expand Down
3 changes: 3 additions & 0 deletions Data/SQLite/include/Poco/Data/SQLite/SessionImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ class SQLite_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl

void setTransactionType(const std::string &prop, const Poco::Any& value);
Poco::Any getTransactionType(const std::string& prop) const;

private:
void setName();

std::string _connector;
sqlite3* _pDB;
bool _connected;
Expand Down
12 changes: 9 additions & 3 deletions Data/SQLite/src/SessionImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ SessionImpl::~SessionImpl()
}


void SessionImpl::setName()
{
setDBMSName("SQLite"s);
}


Poco::Data::StatementImpl::Ptr SessionImpl::createStatementImpl()
{
poco_check_ptr (_pDB);
Expand Down Expand Up @@ -273,17 +279,17 @@ Poco::Any SessionImpl::getConnectionTimeout(const std::string& prop) const
return Poco::Any(_timeout/1000);
}

void SessionImpl::setTransactionType(TransactionType transactionType)
void SessionImpl::setTransactionType(TransactionType transactionType)
{
_transactionType = transactionType;
}

void SessionImpl::setTransactionType(const std::string &prop, const Poco::Any& value)
void SessionImpl::setTransactionType(const std::string &prop, const Poco::Any& value)
{
setTransactionType(Poco::RefAnyCast<TransactionType>(value));
}

Poco::Any SessionImpl::getTransactionType(const std::string& prop) const
Poco::Any SessionImpl::getTransactionType(const std::string& prop) const
{
return Poco::Any(_transactionType);
}
Expand Down
11 changes: 11 additions & 0 deletions Data/include/Poco/Data/Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@ class Data_API Session
return (_statementCreator << t);
}

const std::string& dbmsName() const;
/// Returns the DBMS name. The name must be set by the
/// implementation.
/// Defaults to "unknown".

SharedPtr<StatementImpl> createStatementImpl();
/// Creates a StatementImpl.

Expand Down Expand Up @@ -351,6 +356,12 @@ class Data_API Session
// inlines
//

inline const std::string& Session::dbmsName() const
{
return _pImpl->dbmsName();
}


inline bool Session::isAutocommit() const
{
return _pImpl->isAutocommit();
Expand Down
22 changes: 22 additions & 0 deletions Data/include/Poco/Data/SessionImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ class Data_API SessionImpl: public Poco::RefCountedObject
virtual ~SessionImpl();
/// Destroys the SessionImpl.

const std::string& dbmsName() const;
/// Returns the DBMS name. The name must be set by the
/// implementation.
/// Defaults to "unknown".

virtual Poco::SharedPtr<StatementImpl> createStatementImpl() = 0;
/// Creates a StatementImpl.

Expand Down Expand Up @@ -195,6 +200,9 @@ class Data_API SessionImpl: public Poco::RefCountedObject
/// not supported by the underlying implementation.

protected:
void setDBMSName(const std::string& name);
/// Sets the DBMS name.

void setConnectionString(const std::string& connectionString);
/// Sets the connection string. Should only be called on
/// disconnected sessions. Throws InvalidAccessException when called on
Expand All @@ -205,6 +213,7 @@ class Data_API SessionImpl: public Poco::RefCountedObject
SessionImpl(const SessionImpl&);
SessionImpl& operator = (const SessionImpl&);

std::string _dbmsName;
std::string _connectionString;
std::size_t _loginTimeout;
};
Expand All @@ -213,6 +222,19 @@ class Data_API SessionImpl: public Poco::RefCountedObject
//
// inlines
//

inline void SessionImpl::setDBMSName(const std::string& name)
{
_dbmsName = name;
}


inline const std::string& SessionImpl::dbmsName() const
{
return _dbmsName;
}


inline const std::string& SessionImpl::connectionString() const
{
return _connectionString;
Expand Down
1 change: 1 addition & 0 deletions Data/src/SessionImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace Data {


SessionImpl::SessionImpl(const std::string& connectionString, std::size_t timeout):
_dbmsName("unknown"s),
_connectionString(connectionString),
_loginTimeout(timeout)
{
Expand Down
Loading

0 comments on commit 6a148ed

Please sign in to comment.