Skip to content

Commit

Permalink
fix(Poco::Data): fixes and improvements #4198
Browse files Browse the repository at this point in the history
  • Loading branch information
aleks-f committed Oct 18, 2023
1 parent 69fd22c commit 821ae70
Show file tree
Hide file tree
Showing 43 changed files with 2,085 additions and 703 deletions.
75 changes: 39 additions & 36 deletions Data/ODBC/include/Poco/Data/ODBC/Binder.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
decDigits,
(SQLPOINTER) &val, 0, 0)))
{
throw StatementException(_rStmt, "SQLBindParameter()");
throw StatementException(_rStmt, "ODBC::Binder::SQLBindParameter()");
}
}

Expand Down Expand Up @@ -436,14 +436,14 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
(SQLUSMALLINT) pos + 1,
SQL_PARAM_INPUT,
SQL_C_BINARY,
SQL_LONGVARBINARY,
Utility::sqlDataType(SQL_C_BINARY),
columnSize,
0,
pVal,
(SQLINTEGER) size,
_lengthIndicator.back())))
{
throw StatementException(_rStmt, "SQLBindParameter(LOB)");
throw StatementException(_rStmt, "ODBC::Binder::SQLBindParameter(LOB)");
}
}

Expand Down Expand Up @@ -476,7 +476,7 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
0,
&(*_vecLengthIndicator[pos])[0])))
{
throw StatementException(_rStmt, "SQLBindParameter()");
throw StatementException(_rStmt, "ODBC::Binder::SQLBindParameter()");
}
}

Expand Down Expand Up @@ -537,7 +537,7 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
0,
&(*_vecLengthIndicator[pos])[0])))
{
throw StatementException(_rStmt, "SQLBindParameter()");
throw StatementException(_rStmt, "ODBC::Binder::SQLBindParameter()");
}
}

Expand Down Expand Up @@ -577,7 +577,7 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
if (size == _maxFieldSize)
{
getMinValueSize(*pVal, size);
// accomodate for terminating zero
// accommodate for terminating zero
if (size != _maxFieldSize) ++size;
}

Expand Down Expand Up @@ -614,14 +614,14 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
(SQLUSMALLINT) pos + 1,
toODBCDirection(dir),
SQL_C_CHAR,
SQL_LONGVARCHAR,
Utility::sqlDataType(SQL_C_CHAR),
(SQLUINTEGER) size - 1,
0,
_charPtrs[pos],
(SQLINTEGER) size,
&(*_vecLengthIndicator[pos])[0])))
{
throw StatementException(_rStmt, Poco::format("SQLBindParameter(%s)", typeID));
throw StatementException(_rStmt, "SQLBindParameter(std::vector<std::string>)");
}
}

Expand Down Expand Up @@ -672,7 +672,7 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
{
strSize = it->size() * sizeof(UTF16Char);
if (strSize > size)
throw LengthExceededException("SQLBindParameter(std::vector<UTF16String>)");
throw LengthExceededException("ODBC::Binder::bindImplContainerUTF16String:SQLBindParameter(std::vector<UTF16String>)");
std::memcpy(pBuf + offset, it->data(), strSize);
offset += size;
}
Expand All @@ -681,14 +681,14 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
(SQLUSMALLINT)pos + 1,
toODBCDirection(dir),
SQL_C_WCHAR,
SQL_WLONGVARCHAR,
Utility::sqlDataType(SQL_C_WCHAR),
(SQLUINTEGER)size - 1,
0,
_utf16CharPtrs[pos],
(SQLINTEGER)size,
&(*_vecLengthIndicator[pos])[0])))
{
throw StatementException(_rStmt, "SQLBindParameter(std::vector<UTF16String>)");
throw StatementException(_rStmt, "ODBC::Binder::bindImplContainerUTF16String:SQLBindParameter(std::vector<UTF16String>)");
}
}

Expand All @@ -699,14 +699,14 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
typedef typename LOBType::ValueType CharType;

if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("BLOB container parameter type can only be inbound.");
throw NotImplementedException("ODBC::Binder::bindImplContainerLOB():BLOB container parameter type can only be inbound.");

if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("Containers can only be bound immediately.");
throw InvalidAccessException("ODBC::Binder::bindImplContainerLOB():Containers can only be bound immediately.");

std::size_t length = val.size();
if (0 == length)
throw InvalidArgumentException("Empty container not allowed.");
throw InvalidArgumentException("ODBC::Binder::bindImplContainerLOB():Empty container not allowed.");

setParamSetSize(length);

Expand Down Expand Up @@ -742,7 +742,7 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
{
blobSize = cIt->size();
if (blobSize > size)
throw LengthExceededException("SQLBindParameter(std::vector<BLOB>)");
throw LengthExceededException("ODBC::Binder::bindImplContainerLOB():SQLBindParameter(std::vector<BLOB>)");
std::memcpy(_charPtrs[pos] + offset, cIt->rawContent(), blobSize * sizeof(CharType));
offset += size;
}
Expand All @@ -751,30 +751,30 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
(SQLUSMALLINT) pos + 1,
SQL_PARAM_INPUT,
SQL_C_BINARY,
SQL_LONGVARBINARY,
Utility::sqlDataType(SQL_C_BINARY),
(SQLUINTEGER) size,
0,
_charPtrs[pos],
(SQLINTEGER) size,
&(*_vecLengthIndicator[pos])[0])))
{
throw StatementException(_rStmt, "SQLBindParameter(std::vector<BLOB>)");
throw StatementException(_rStmt, "ODBC::Binder::bindImplContainerLOB():SQLBindParameter(std::vector<BLOB>)");
}
}

template<typename C>
void bindImplContainerDate(std::size_t pos, const C& val, Direction dir)
{
if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("Date vector parameter type can only be inbound.");
throw NotImplementedException("ODBC::Binder::bindImplContainerDate():Date vector parameter type can only be inbound.");

if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("std::vector can only be bound immediately.");
throw InvalidAccessException("ODBC::Binder::bindImplContainerDate():std::vector can only be bound immediately.");

std::size_t length = val.size();

if (0 == length)
throw InvalidArgumentException("Empty vector not allowed.");
throw InvalidArgumentException("ODBC::Binder::bindImplContainerDate():Empty vector not allowed.");

setParamSetSize(length);

Expand All @@ -800,29 +800,29 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
(SQLUSMALLINT) pos + 1,
toODBCDirection(dir),
SQL_C_TYPE_DATE,
SQL_TYPE_DATE,
Utility::sqlDataType(SQL_C_TYPE_DATE),
colSize,
decDigits,
(SQLPOINTER) &(*_dateVecVec[pos])[0],
0,
&(*_vecLengthIndicator[pos])[0])))
{
throw StatementException(_rStmt, "SQLBindParameter(Date[])");
throw StatementException(_rStmt, "ODBC::Binder::bindImplContainerDate():SQLBindParameter(Date[])");
}
}

template<typename C>
void bindImplContainerTime(std::size_t pos, const C& val, Direction dir)
{
if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("Time container parameter type can only be inbound.");
throw NotImplementedException("ODBC::Binder::bindImplContainerTime():Time container parameter type can only be inbound.");

if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("Containers can only be bound immediately.");
throw InvalidAccessException("ODBC::Binder::bindImplContainerTime():Containers can only be bound immediately.");

std::size_t length = val.size();
if (0 == length)
throw InvalidArgumentException("Empty container not allowed.");
throw InvalidArgumentException("ODBC::Binder::bindImplContainerTime():Empty container not allowed.");

setParamSetSize(val.size());

Expand All @@ -848,30 +848,30 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
(SQLUSMALLINT) pos + 1,
toODBCDirection(dir),
SQL_C_TYPE_TIME,
SQL_TYPE_TIME,
Utility::sqlDataType(SQL_C_TYPE_TIME),
colSize,
decDigits,
(SQLPOINTER) &(*_timeVecVec[pos])[0],
0,
&(*_vecLengthIndicator[pos])[0])))
{
throw StatementException(_rStmt, "SQLBindParameter(Time[])");
throw StatementException(_rStmt, "ODBC::Binder::bindImplContainerTime():SQLBindParameter(Time[])");
}
}

template<typename C>
void bindImplContainerDateTime(std::size_t pos, const C& val, Direction dir)
{
if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("DateTime container parameter type can only be inbound.");
throw NotImplementedException("ODBC::Binder::bindImplContainerDateTime():DateTime container parameter type can only be inbound.");

if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("Containers can only be bound immediately.");
throw InvalidAccessException("ODBC::Binder::bindImplContainerDateTime():Containers can only be bound immediately.");

std::size_t length = val.size();

if (0 == length)
throw InvalidArgumentException("Empty Containers not allowed.");
throw InvalidArgumentException("ODBC::Binder::bindImplContainerDateTime():Empty Containers not allowed.");

setParamSetSize(length);

Expand All @@ -897,30 +897,30 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
(SQLUSMALLINT) pos + 1,
toODBCDirection(dir),
SQL_C_TYPE_TIMESTAMP,
SQL_TYPE_TIMESTAMP,
Utility::sqlDataType(SQL_C_TYPE_TIMESTAMP),
colSize,
decDigits,
(SQLPOINTER) &(*_dateTimeVecVec[pos])[0],
0,
&(*_vecLengthIndicator[pos])[0])))
{
throw StatementException(_rStmt, "SQLBindParameter(Time[])");
throw StatementException(_rStmt, "ODBC::Binder::bindImplContainerDateTime():SQLBindParameter(Time[])");
}
}

template<typename C>
void bindImplNullContainer(std::size_t pos, const C& val, Direction dir)
{
if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("Null container parameter type can only be inbound.");
throw NotImplementedException("ODBC::Binder::bindImplNullContainer():Null container parameter type can only be inbound.");

if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("Container can only be bound immediately.");
throw InvalidAccessException("ODBC::Binder::bindImplNullContainer():Container can only be bound immediately.");

std::size_t length = val.size();

if (0 == length)
throw InvalidArgumentException("Empty container not allowed.");
throw InvalidArgumentException("ODBC::Binder::bindImplNullContainer():Empty container not allowed.");

setParamSetSize(length);

Expand All @@ -945,7 +945,7 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
0,
&(*_vecLengthIndicator[pos])[0])))
{
throw StatementException(_rStmt, "SQLBindParameter()");
throw StatementException(_rStmt, "ODBC::Binder::bindImplNullContainer():SQLBindParameter()");
}
}

Expand Down Expand Up @@ -973,6 +973,9 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder
/// size should be set to some default value prior to calling this
/// function in order to avoid undefined size value.

std::size_t getParamSizeDirect(std::size_t pos, SQLINTEGER& size);
/// A "last ditch" attempt" to obtain parameter size directly from the driver.

void freeMemory();
/// Frees all dynamically allocated memory resources.

Expand Down
37 changes: 35 additions & 2 deletions Data/ODBC/include/Poco/Data/ODBC/ConnectionHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,36 +36,63 @@ class ODBC_API ConnectionHandle
/// ODBC connection handle class
{
public:
ConnectionHandle(EnvironmentHandle* pEnvironment = 0);
ConnectionHandle(const std::string& connectString = "", SQLULEN timeout = 5);
/// Creates the ConnectionHandle.

~ConnectionHandle();
/// Creates the ConnectionHandle.

bool connect(const std::string& connectString = "", SQLULEN timeout = 5);
/// Connects the handle to the database.

bool disconnect();
/// Disconnects the handle from database.

bool isConnected() const;
/// Returns true if connected.

void setTimeout(SQLULEN timeout);
/// Sets the connection timeout in seconds.

int getTimeout() const;
/// Returns the connection timeout in seconds.

operator const SQLHDBC& () const;
/// Const conversion operator into reference to native type.

const SQLHDBC& handle() const;
/// Returns const reference to handle;

const SQLHDBC* pHandle() const;
/// Returns const pointer to handle;

private:
operator SQLHDBC& ();
/// Conversion operator into reference to native type.

SQLHDBC& handle();
/// Returns reference to handle;

void alloc();
/// Allocates the connection handle.

void free();
/// Frees the connection handle.

ConnectionHandle(const ConnectionHandle&);
const ConnectionHandle& operator=(const ConnectionHandle&);

const EnvironmentHandle* _pEnvironment;
SQLHDBC _hdbc;
bool _ownsEnvironment;
std::string _connectString;

friend class Poco::Data::ODBC::SessionImpl;
};


using Connection = ConnectionHandle;


//
// inlines
//
Expand All @@ -81,6 +108,12 @@ inline const SQLHDBC& ConnectionHandle::handle() const
}


inline const SQLHDBC* ConnectionHandle::pHandle() const
{
return &_hdbc;
}


inline ConnectionHandle::operator SQLHDBC& ()
{
return handle();
Expand Down
2 changes: 2 additions & 0 deletions Data/ODBC/include/Poco/Data/ODBC/Diagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ class Diagnostics

const Diagnostics& diagnostics()
{
if (SQL_NULL_HANDLE == _handle) return *this;

DiagnosticFields df;
SQLSMALLINT count = 1;
SQLSMALLINT messageLength = 0;
Expand Down
1 change: 0 additions & 1 deletion Data/ODBC/include/Poco/Data/ODBC/EnvironmentHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ class ODBC_API EnvironmentHandle
const EnvironmentHandle& operator=(const EnvironmentHandle&);

SQLHENV _henv;
bool _isOwner;
};


Expand Down
Loading

0 comments on commit 821ae70

Please sign in to comment.