diff --git a/Data/ODBC/include/Poco/Data/ODBC/Binder.h b/Data/ODBC/include/Poco/Data/ODBC/Binder.h index 23b68c14f..a15747adc 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/Binder.h +++ b/Data/ODBC/include/Poco/Data/ODBC/Binder.h @@ -67,18 +67,15 @@ class ODBC_API Binder: public Poco::Data::AbstractBinder /// Binds placeholders in the sql query to the provided values. Performs data types mapping. { public: + typedef AbstractBinder::Direction Direction; + typedef std::map ParameterMap; + enum ParameterBinding { PB_IMMEDIATE, PB_AT_EXEC }; - enum Direction - { - PD_IN, - PD_OUT - }; - Binder(const StatementHandle& rStmt, ParameterBinding dataBinding = PB_IMMEDIATE, TypeInfo* pDataTypes = 0); @@ -87,49 +84,49 @@ public: ~Binder(); /// Destroys the Binder. - void bind(std::size_t pos, const Poco::Int8& val); + void bind(std::size_t pos, const Poco::Int8& val, Direction dir = PD_IN); /// Binds an Int8. - void bind(std::size_t pos, const Poco::UInt8& val); + void bind(std::size_t pos, const Poco::UInt8& val, Direction dir = PD_IN); /// Binds an UInt8. - void bind(std::size_t pos, const Poco::Int16& val); + void bind(std::size_t pos, const Poco::Int16& val, Direction dir = PD_IN); /// Binds an Int16. - void bind(std::size_t pos, const Poco::UInt16& val); + void bind(std::size_t pos, const Poco::UInt16& val, Direction dir = PD_IN); /// Binds an UInt16. - void bind(std::size_t pos, const Poco::Int32& val); + void bind(std::size_t pos, const Poco::Int32& val, Direction dir = PD_IN); /// Binds an Int32. - void bind(std::size_t pos, const Poco::UInt32& val); + void bind(std::size_t pos, const Poco::UInt32& val, Direction dir = PD_IN); /// Binds an UInt32. - void bind(std::size_t pos, const Poco::Int64& val); + void bind(std::size_t pos, const Poco::Int64& val, Direction dir = PD_IN); /// Binds an Int64. - void bind(std::size_t pos, const Poco::UInt64& val); + void bind(std::size_t pos, const Poco::UInt64& val, Direction dir = PD_IN); /// Binds an UInt64. - void bind(std::size_t pos, const bool& val); + void bind(std::size_t pos, const bool& val, Direction dir = PD_IN); /// Binds a boolean. - void bind(std::size_t pos, const float& val); + void bind(std::size_t pos, const float& val, Direction dir = PD_IN); /// Binds a float. - void bind(std::size_t pos, const double& val); + void bind(std::size_t pos, const double& val, Direction dir = PD_IN); /// Binds a double. - void bind(std::size_t pos, const char& val); + void bind(std::size_t pos, const char& val, Direction dir = PD_IN); /// Binds a single character. - void bind(std::size_t pos, const std::string& val); + void bind(std::size_t pos, const std::string& val, Direction dir = PD_IN); /// Binds a string. - void bind(std::size_t pos, const Poco::Data::BLOB& val); + void bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir = PD_IN); /// Binds a BLOB. - void bind(std::size_t pos, const Poco::DateTime& val); + void bind(std::size_t pos, const Poco::DateTime& val, Direction dir = PD_IN); /// Binds a DateTime. void setDataBinding(ParameterBinding binding); @@ -138,61 +135,54 @@ public: ParameterBinding getDataBinding() const; /// Return data binding type. - std::size_t dataSize(SQLPOINTER pAddr) const; + std::size_t parameterSize(SQLPOINTER pAddr) const; /// Returns bound data size for parameter at specified position. void sync(Direction direction); /// Synchronizes non-POD parameters. + ParameterMap& outParameters(); + /// Returns map of output parameter pointers and sizes. + private: typedef std::vector LengthVec; typedef std::map TimestampMap; - typedef std::map SizeMap; - void bind(std::size_t pos, const char* const &pVal); + void describeParameter(std::size_t pos); + /// Sets the description field for the parameter, if needed. + + void bind(std::size_t pos, const char* const &pVal, Direction dir = PD_IN); /// Binds a const char ptr. /// This is a private no-op in this implementation /// due to security risk. - SQLSMALLINT getParamType() const; + SQLSMALLINT getParamType(Direction dir) const; template - void bindImpl(std::size_t pos, T& val, SQLSMALLINT cDataType) + void bindImpl(std::size_t pos, T& val, SQLSMALLINT cDataType, Direction dir) { _lengthIndicator.push_back(0); - _dataSize.insert(SizeMap::value_type((SQLPOINTER) &val, sizeof(T))); int sqlDataType = Utility::sqlDataType(cDataType); - - SQLUINTEGER columnSize = 0; - SQLSMALLINT decimalDigits = 0; + SQLINTEGER colSize = 0; + SQLSMALLINT decDigits = 0; - // somewhat funky flow control, but not all - // ODBC drivers will cooperate here - try - { - Parameter p(_rStmt, pos); - columnSize = (SQLUINTEGER) p.columnSize(); - decimalDigits = (SQLSMALLINT) p.decimalDigits(); - } - catch (StatementException&) - { - try - { - ODBCColumn c(_rStmt, pos); - columnSize = (SQLUINTEGER) c.length(); - decimalDigits = (SQLSMALLINT) c.precision(); - } - catch (StatementException&) { } + if (_pTypeInfo) + { + try + { + colSize = _pTypeInfo->getInfo(cDataType, "COLUMN_SIZE"); + decDigits = _pTypeInfo->getInfo(cDataType, "MINIMUM_SCALE"); + }catch (NotFoundException&) { } } if (Utility::isError(SQLBindParameter(_rStmt, (SQLUSMALLINT) pos + 1, - getParamType(), + getParamType(dir), cDataType, sqlDataType, - columnSize, - decimalDigits, + colSize, + decDigits, (SQLPOINTER) &val, 0, _lengthIndicator.back()))) @@ -203,7 +193,8 @@ private: const StatementHandle& _rStmt; LengthVec _lengthIndicator; - SizeMap _dataSize; + ParameterMap _inParams; + ParameterMap _outParams; ParameterBinding _paramBinding; TimestampMap _timestamps; const TypeInfo* _pTypeInfo; @@ -213,75 +204,75 @@ private: // // inlines // -inline void Binder::bind(std::size_t pos, const Poco::Int8& val) +inline void Binder::bind(std::size_t pos, const Poco::Int8& val, Direction dir) { - bindImpl(pos, val, SQL_C_STINYINT); + bindImpl(pos, val, SQL_C_STINYINT, dir); } -inline void Binder::bind(std::size_t pos, const Poco::UInt8& val) +inline void Binder::bind(std::size_t pos, const Poco::UInt8& val, Direction dir) { - bindImpl(pos, val, SQL_C_UTINYINT); + bindImpl(pos, val, SQL_C_UTINYINT, dir); } -inline void Binder::bind(std::size_t pos, const Poco::Int16& val) +inline void Binder::bind(std::size_t pos, const Poco::Int16& val, Direction dir) { - bindImpl(pos, val, SQL_C_SSHORT); + bindImpl(pos, val, SQL_C_SSHORT, dir); } -inline void Binder::bind(std::size_t pos, const Poco::UInt16& val) +inline void Binder::bind(std::size_t pos, const Poco::UInt16& val, Direction dir) { - bindImpl(pos, val, SQL_C_USHORT); + bindImpl(pos, val, SQL_C_USHORT, dir); } -inline void Binder::bind(std::size_t pos, const Poco::UInt32& val) +inline void Binder::bind(std::size_t pos, const Poco::UInt32& val, Direction dir) { - bindImpl(pos, val, SQL_C_ULONG); + bindImpl(pos, val, SQL_C_ULONG, dir); } -inline void Binder::bind(std::size_t pos, const Poco::Int32& val) +inline void Binder::bind(std::size_t pos, const Poco::Int32& val, Direction dir) { - bindImpl(pos, val, SQL_C_SLONG); + bindImpl(pos, val, SQL_C_SLONG, dir); } -inline void Binder::bind(std::size_t pos, const Poco::UInt64& val) +inline void Binder::bind(std::size_t pos, const Poco::UInt64& val, Direction dir) { - bindImpl(pos, val, SQL_C_UBIGINT); + bindImpl(pos, val, SQL_C_UBIGINT, dir); } -inline void Binder::bind(std::size_t pos, const Poco::Int64& val) +inline void Binder::bind(std::size_t pos, const Poco::Int64& val, Direction dir) { - bindImpl(pos, val, SQL_C_SBIGINT); + bindImpl(pos, val, SQL_C_SBIGINT, dir); } -inline void Binder::bind(std::size_t pos, const float& val) +inline void Binder::bind(std::size_t pos, const float& val, Direction dir) { - bindImpl(pos, val, SQL_C_FLOAT); + bindImpl(pos, val, SQL_C_FLOAT, dir); } -inline void Binder::bind(std::size_t pos, const double& val) +inline void Binder::bind(std::size_t pos, const double& val, Direction dir) { - bindImpl(pos, val, SQL_C_DOUBLE); + bindImpl(pos, val, SQL_C_DOUBLE, dir); } -inline void Binder::bind(std::size_t pos, const bool& val) +inline void Binder::bind(std::size_t pos, const bool& val, Direction dir) { - bindImpl(pos, val, Utility::boolDataType); + bindImpl(pos, val, Utility::boolDataType, dir); } -inline void Binder::bind(std::size_t pos, const char& val) +inline void Binder::bind(std::size_t pos, const char& val, Direction dir) { - bindImpl(pos, val, SQL_C_STINYINT); + bindImpl(pos, val, SQL_C_STINYINT, dir); } @@ -297,6 +288,12 @@ inline Binder::ParameterBinding Binder::getDataBinding() const } +inline Binder::ParameterMap& Binder::outParameters() +{ + return _outParams; +} + + } } } // namespace Poco::Data::ODBC diff --git a/Data/ODBC/include/Poco/Data/ODBC/ODBCException.h b/Data/ODBC/include/Poco/Data/ODBC/ODBCException.h index 1a47f1365..00e89a003 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/ODBCException.h +++ b/Data/ODBC/include/Poco/Data/ODBC/ODBCException.h @@ -129,7 +129,7 @@ public: std::string toString() const { std::stringstream os; - os << "ODBC Error: " << _error.toString() << std::endl + os << "ODBC Error: " << what() << std::endl << "===================" << std::endl << _error.toString() << std::endl ; return os.str(); diff --git a/Data/ODBC/include/Poco/Data/ODBC/ODBCStatementImpl.h b/Data/ODBC/include/Poco/Data/ODBC/ODBCStatementImpl.h index f9b872948..bd24b9769 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/ODBCStatementImpl.h +++ b/Data/ODBC/include/Poco/Data/ODBC/ODBCStatementImpl.h @@ -95,7 +95,7 @@ protected: /// Compiles the statement, doesn't bind yet void bindImpl(); - /// Binds parameters + /// Binds all parameters and executes the statement. AbstractExtractor& extractor(); /// Returns the concrete extractor used by the statement. @@ -115,6 +115,9 @@ private: void clear(); /// Closes the cursor and resets indicator variables. + void doBind(bool clear = true, bool reset = false); + /// Binds parameters. + bool hasData() const; /// Returns true if statement returns data. diff --git a/Data/ODBC/include/Poco/Data/ODBC/Preparation.h b/Data/ODBC/include/Poco/Data/ODBC/Preparation.h index 08392922b..99b46d0b7 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/Preparation.h +++ b/Data/ODBC/include/Poco/Data/ODBC/Preparation.h @@ -233,8 +233,8 @@ private: } const StatementHandle& _rStmt; - std::vector _pValues; - std::vector _pLengths; + mutable std::vector _pValues; + mutable std::vector _pLengths; std::size_t _maxFieldSize; DataExtraction _dataExtraction; }; @@ -335,12 +335,6 @@ inline void Preparation::prepare(std::size_t pos, const Poco::DateTime&) } -inline std::size_t Preparation::columns() const -{ - return _pValues.size(); -} - - inline std::size_t Preparation::maxDataSize(std::size_t pos) const { poco_assert (pos >= 0 && pos < _pValues.size()); diff --git a/Data/ODBC/include/Poco/Data/ODBC/TypeInfo.h b/Data/ODBC/include/Poco/Data/ODBC/TypeInfo.h index 9df771dc8..ce400fba8 100644 --- a/Data/ODBC/include/Poco/Data/ODBC/TypeInfo.h +++ b/Data/ODBC/include/Poco/Data/ODBC/TypeInfo.h @@ -57,7 +57,16 @@ namespace ODBC { class ODBC_API TypeInfo - /// C <==> SQL datatypes mapping utility class. + /// Datatypes mapping utility class. + /// + /// This class provides mapping between C and SQL datatypes as well + /// as datatypes supported by the underlying database. In order for database + /// types to be available, a valid conection handle must be supplied at either + /// object construction time, or at a later point in time, through call to + /// fillTypeInfo member function. + /// + /// Class also provides a convenient debugging function that prints + /// tabulated data to an output stream. { public: typedef std::map DataTypeMap; @@ -99,7 +108,12 @@ public: /// Fills the data type info structure for the database. DynamicAny getInfo(SQLSMALLINT type, const std::string& param) const; - /// Returns information about specified data type. + /// Returns information about specified data type as specified by parameter 'type'. + /// The requested information is specified by parameter 'param'. + + void print(std::ostream& ostr); + /// Prints all the types (as reported by the underlying database) + /// to the supplied output stream. private: void fillCTypes(); diff --git a/Data/ODBC/src/Binder.cpp b/Data/ODBC/src/Binder.cpp index 0fed93c78..1a5dd548d 100644 --- a/Data/ODBC/src/Binder.cpp +++ b/Data/ODBC/src/Binder.cpp @@ -70,9 +70,9 @@ Binder::~Binder() } -void Binder::bind(std::size_t pos, const std::string& val) +void Binder::bind(std::size_t pos, const std::string& val, Direction dir) { - if (isOutBound()) + if (isOutBound(dir)) throw InvalidAccessException("std::string can only be in-bound"); SQLINTEGER size = (SQLINTEGER) val.size(); @@ -83,7 +83,11 @@ void Binder::bind(std::size_t pos, const std::string& val) *pLenIn = SQL_LEN_DATA_AT_EXEC(size); _lengthIndicator.push_back(pLenIn); - _dataSize.insert(SizeMap::value_type((SQLPOINTER) val.c_str(), size)); + if (isInBound(dir)) + _inParams.insert(ParameterMap::value_type((SQLPOINTER) val.c_str(), size)); + //TODO + //if (isOutBound(dir)) + // _outParams.insert(ParameterMap::value_type((SQLPOINTER) pTS, size)); if (Utility::isError(SQLBindParameter(_rStmt, (SQLUSMALLINT) pos + 1, @@ -101,9 +105,9 @@ void Binder::bind(std::size_t pos, const std::string& val) } -void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val) +void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir) { - if (isOutBound()) + if (isOutBound(dir)) throw InvalidAccessException("BLOB can only be in-bound"); SQLINTEGER size = (SQLINTEGER) val.size(); @@ -114,7 +118,11 @@ void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val) *pLenIn = SQL_LEN_DATA_AT_EXEC(size); _lengthIndicator.push_back(pLenIn); - _dataSize.insert(SizeMap::value_type((SQLPOINTER) val.rawContent(), size)); + if (isInBound(dir)) + _inParams.insert(ParameterMap::value_type((SQLPOINTER) val.rawContent(), size)); + //TODO + //if (isOutBound(dir)) + // _outParams.insert(ParameterMap::value_type((SQLPOINTER) pTS, size)); if (Utility::isError(SQLBindParameter(_rStmt, (SQLUSMALLINT) pos + 1, @@ -132,22 +140,18 @@ void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val) } -void Binder::bind(std::size_t pos, const Poco::DateTime& val) +void Binder::bind(std::size_t pos, const Poco::DateTime& val, Direction dir) { SQLINTEGER size = (SQLINTEGER) sizeof(SQL_TIMESTAMP_STRUCT); SQLLEN* pLenIn = new SQLLEN; *pLenIn = size; - if (PB_AT_EXEC == _paramBinding) - *pLenIn = SQL_LEN_DATA_AT_EXEC(size); - _lengthIndicator.push_back(pLenIn); SQL_TIMESTAMP_STRUCT* pTS = new SQL_TIMESTAMP_STRUCT; Utility::dateTimeSync(*pTS, val); _timestamps.insert(TimestampMap::value_type(pTS, const_cast(&val))); - _dataSize.insert(SizeMap::value_type((SQLPOINTER) pTS, size)); SQLINTEGER colSize = 0; SQLSMALLINT decDigits = 0; @@ -156,14 +160,14 @@ void Binder::bind(std::size_t pos, const Poco::DateTime& val) { try { - colSize = _pTypeInfo->getInfo(SQL_TIMESTAMP, "COLUMN_SIZE"); - decDigits = _pTypeInfo->getInfo(SQL_TIMESTAMP, "MINIMUM_SCALE"); + colSize = _pTypeInfo->getInfo(SQL_TYPE_TIMESTAMP, "COLUMN_SIZE"); + decDigits = _pTypeInfo->getInfo(SQL_TYPE_TIMESTAMP, "MINIMUM_SCALE"); }catch (NotFoundException&) { } } if (Utility::isError(SQLBindParameter(_rStmt, (SQLUSMALLINT) pos + 1, - getParamType(), + getParamType(dir), SQL_C_TIMESTAMP, SQL_TIMESTAMP, colSize, @@ -177,25 +181,25 @@ void Binder::bind(std::size_t pos, const Poco::DateTime& val) } -std::size_t Binder::dataSize(SQLPOINTER pAddr) const +std::size_t Binder::parameterSize(SQLPOINTER pAddr) const { - SizeMap::const_iterator it = _dataSize.find(pAddr); - if (it != _dataSize.end()) return it->second; + ParameterMap::const_iterator it = _inParams.find(pAddr); + if (it != _inParams.end()) return it->second; throw NotFoundException("Requested data size not found."); } -void Binder::bind(std::size_t pos, const char* const &pVal) +void Binder::bind(std::size_t pos, const char* const &pVal, Direction dir) { - //no-op + throw NotImplementedException("char* binding not implemented, Use std::string instead."); } -SQLSMALLINT Binder::getParamType() const +SQLSMALLINT Binder::getParamType(Direction dir) const { - bool in = isInBound(); - bool out = isOutBound(); + bool in = isInBound(dir); + bool out = isOutBound(dir); SQLSMALLINT ioType = SQL_PARAM_TYPE_UNKNOWN; if (in && out) ioType = SQL_PARAM_INPUT_OUTPUT; else if(in) ioType = SQL_PARAM_INPUT; @@ -206,7 +210,7 @@ SQLSMALLINT Binder::getParamType() const } -void Binder::sync(Binder::Direction direction) +void Binder::sync(Direction direction) { TimestampMap::iterator itTS = _timestamps.begin(); TimestampMap::iterator itTSEnd = _timestamps.end(); diff --git a/Data/ODBC/src/ODBCColumn.cpp b/Data/ODBC/src/ODBCColumn.cpp index 3252e4e90..757b14257 100644 --- a/Data/ODBC/src/ODBCColumn.cpp +++ b/Data/ODBC/src/ODBCColumn.cpp @@ -125,7 +125,7 @@ void ODBCColumn::init() case SQL_LONGVARBINARY: case -98:// IBM DB2 non-standard type setType(MetaColumn::FDT_BLOB); break; - case SQL_TIMESTAMP: + case SQL_TYPE_TIMESTAMP: setType(MetaColumn::FDT_TIMESTAMP); break; default: throw DataFormatException("Unsupported data type."); diff --git a/Data/ODBC/src/ODBCStatementImpl.cpp b/Data/ODBC/src/ODBCStatementImpl.cpp index 7c33fef78..7e90e2065 100644 --- a/Data/ODBC/src/ODBCStatementImpl.cpp +++ b/Data/ODBC/src/ODBCStatementImpl.cpp @@ -90,7 +90,7 @@ ODBCStatementImpl::~ODBCStatementImpl() void ODBCStatementImpl::compileImpl() { - _stepCalled = false; + _stepCalled = false; _nextResponse = 0; std::string statement(toString()); @@ -119,6 +119,17 @@ void ODBCStatementImpl::compileImpl() _pBinder = new Binder(_stmt, bind, pDT); _pExtractor = new Extractor(_stmt, *_pPreparation); + // This is a hack to conform to some ODBC drivers behavior (e.g. MS SQLServer) with + // stored procedure calls: driver refuses to report the number of columns, unless all + // parameters for the stored procedure are bound. Since number of columns is essential + // information for the internal extraction creation, in order to allow for querying it, + // these calls must occur before. + fixupBinding(); doBind(false, true); + + // Following code creates internal extraction storage in case when none is provided by user. + // Under normal circumstances, this is the responsibility of the Data framework. Due to some + // ODBC peculiarities, for ODBC it is implemented here. Data library detects this being already + // done and does not try to do it again. bool dataAvailable = hasData(); if (dataAvailable && !extractions().size()) { @@ -151,9 +162,9 @@ bool ODBCStatementImpl::canBind() const } -void ODBCStatementImpl::bindImpl() +void ODBCStatementImpl::doBind(bool clear, bool reset) { - clear(); + if (clear) this->clear(); Bindings& binds = bindings(); if (!binds.empty()) { @@ -164,7 +175,20 @@ void ODBCStatementImpl::bindImpl() (*it)->bind(pos); pos += (*it)->numOfColumnsHandled(); } + + if (reset) + { + it = binds.begin(); + for (; it != itEnd && (*it)->canBind(); ++it) + (*it)->reset(); + } } +} + + +void ODBCStatementImpl::bindImpl() +{ + doBind(); SQLRETURN rc = SQLExecute(_stmt); @@ -184,13 +208,29 @@ void ODBCStatementImpl::putData() { poco_assert_dbg (pParam); - SQLINTEGER dataSize = (SQLINTEGER) _pBinder->dataSize(pParam); + SQLINTEGER dataSize = (SQLINTEGER) _pBinder->parameterSize(pParam); if (Utility::isError(SQLPutData(_stmt, pParam, dataSize))) throw StatementException(_stmt, "SQLPutData()"); }while (SQL_NEED_DATA == (rc = SQLParamData(_stmt, &pParam))); checkError(rc, "SQLParamData()"); + +/* TODO: this is how manual extraction of parameters should work + in practice, for the time being, we only support automatic binding for output params + Binder::ParameterMap outParamMap = _pBinder->outParameters(); + Binder::ParameterMap::iterator it = outParamMap.begin(); + Binder::ParameterMap::iterator end = outParamMap.end(); + for (int i = 1; it != end; ++it, ++i) + { + SQLINTEGER retLen = 0; + while (SQL_NO_DATA != (rc = SQLGetData(_stmt, i, SQL_C_TYPE_TIMESTAMP, (SQLPOINTER) (it->first + retLen), it->second - retLen, &retLen))) + if (0 == retLen || SQL_NULL_DATA == retLen) break; + + StatementException se(_stmt); + std::cout << se.toString(); + } +*/ } diff --git a/Data/ODBC/src/Preparation.cpp b/Data/ODBC/src/Preparation.cpp index 4d98a3a69..e58b3bb26 100644 --- a/Data/ODBC/src/Preparation.cpp +++ b/Data/ODBC/src/Preparation.cpp @@ -54,16 +54,6 @@ Preparation::Preparation(const StatementHandle& rStmt, POCO_SQLCHAR* pStr = (POCO_SQLCHAR*) statement.c_str(); if (Utility::isError(SQLPrepare(_rStmt, pStr, (SQLINTEGER) statement.length()))) throw StatementException(_rStmt); - - SQLSMALLINT nCol; - if (Utility::isError(SQLNumResultCols(_rStmt, &nCol))) - throw StatementException(_rStmt); - - if (nCol) - { - _pValues.resize(nCol, 0); - _pLengths.resize(nCol, 0); - } } @@ -79,6 +69,25 @@ Preparation::~Preparation() } +std::size_t Preparation::columns() const +{ + if (_pValues.empty()) + { + SQLSMALLINT nCol = 0; + if (Utility::isError(SQLNumResultCols(_rStmt, &nCol))) + throw StatementException(_rStmt); + + if (nCol) + { + _pValues.resize(nCol, 0); + _pLengths.resize(nCol, 0); + } + } + + return _pValues.size(); +} + + Poco::Any& Preparation::operator [] (std::size_t pos) { poco_assert (pos >= 0 && pos < _pValues.size()); diff --git a/Data/ODBC/src/TypeInfo.cpp b/Data/ODBC/src/TypeInfo.cpp index c17b85e04..9dc1143c7 100644 --- a/Data/ODBC/src/TypeInfo.cpp +++ b/Data/ODBC/src/TypeInfo.cpp @@ -76,9 +76,9 @@ void TypeInfo::fillCTypes() _cDataTypes.insert(ValueType(SQL_BINARY, SQL_C_BINARY)); _cDataTypes.insert(ValueType(SQL_VARBINARY, SQL_C_BINARY)); _cDataTypes.insert(ValueType(SQL_LONGVARBINARY, SQL_C_BINARY)); - _cDataTypes.insert(ValueType(SQL_DATE, SQL_C_DATE)); - _cDataTypes.insert(ValueType(SQL_TIME, SQL_C_TIME)); - _cDataTypes.insert(ValueType(SQL_TIMESTAMP, SQL_C_TIMESTAMP)); + _cDataTypes.insert(ValueType(SQL_TYPE_DATE, SQL_C_DATE)); + _cDataTypes.insert(ValueType(SQL_TYPE_TIME, SQL_C_TIME)); + _cDataTypes.insert(ValueType(SQL_TYPE_TIMESTAMP, SQL_C_TIMESTAMP)); } @@ -100,9 +100,9 @@ void TypeInfo::fillSQLTypes() _sqlDataTypes.insert(ValueType(SQL_C_FLOAT, SQL_REAL)); _sqlDataTypes.insert(ValueType(SQL_C_DOUBLE, SQL_DOUBLE)); _sqlDataTypes.insert(ValueType(SQL_C_BINARY, SQL_LONGVARBINARY)); - _sqlDataTypes.insert(ValueType(SQL_C_DATE, SQL_DATE)); - _sqlDataTypes.insert(ValueType(SQL_C_TIME, SQL_TIME)); - _sqlDataTypes.insert(ValueType(SQL_C_TIMESTAMP, SQL_TIMESTAMP)); + _sqlDataTypes.insert(ValueType(SQL_C_DATE, SQL_TYPE_DATE)); + _sqlDataTypes.insert(ValueType(SQL_C_TIME, SQL_TYPE_TIME)); + _sqlDataTypes.insert(ValueType(SQL_C_TIMESTAMP, SQL_TYPE_TIMESTAMP)); } @@ -122,41 +122,37 @@ void TypeInfo::fillTypeInfo(SQLHDBC pHDBC) if (!SQL_SUCCEEDED(rc)) throw StatementException(hstmt, "SQLGetData()"); - DataTypeMap::const_iterator it = _cDataTypes.begin(); - DataTypeMap::const_iterator end = _cDataTypes.end(); - - for(; it != end; ++it) + rc = SQLGetTypeInfo(hstmt, SQL_ALL_TYPES); + if (SQL_SUCCEEDED(rc)) { - char typeName[stringSize] = { 0 }; - char literalPrefix[stringSize] = { 0 }; - char literalSuffix[stringSize] = { 0 }; - char createParams[stringSize] = { 0 }; - char localTypeName[stringSize] = { 0 }; - - TypeInfoTup ti("TYPE_NAME", "", - "DATA_TYPE", 0, - "COLUMN_SIZE", 0, - "LITERAL_PREFIX", "", - "LITERAL_SUFFIX", "", - "CREATE_PARAMS", "", - "NULLABLE", 0, - "CASE_SENSITIVE", 0, - "SEARCHABLE", 0, - "UNSIGNED_ATTRIBUTE", 0, - "FIXED_PREC_SCALE", 0, - "AUTO_UNIQUE_VALUE", 0, - "LOCAL_TYPE_NAME", "", - "MINIMUM_SCALE", 0, - "MAXIMUM_SCALE", 0, - "SQL_DATA_TYPE", 0, - "SQL_DATETIME_SUB", 0, - "NUM_PREC_RADIX", 0, - "INTERVAL_PRECISION", 0); - - rc = SQLGetTypeInfo(hstmt, it->first); - rc = SQLFetch(hstmt); - if (SQL_SUCCEEDED(rc)) + while (SQLFetch(hstmt) != SQL_NO_DATA_FOUND) { + char typeName[stringSize] = { 0 }; + char literalPrefix[stringSize] = { 0 }; + char literalSuffix[stringSize] = { 0 }; + char createParams[stringSize] = { 0 }; + char localTypeName[stringSize] = { 0 }; + + TypeInfoTup ti("TYPE_NAME", "", + "DATA_TYPE", 0, + "COLUMN_SIZE", 0, + "LITERAL_PREFIX", "", + "LITERAL_SUFFIX", "", + "CREATE_PARAMS", "", + "NULLABLE", 0, + "CASE_SENSITIVE", 0, + "SEARCHABLE", 0, + "UNSIGNED_ATTRIBUTE", 0, + "FIXED_PREC_SCALE", 0, + "AUTO_UNIQUE_VALUE", 0, + "LOCAL_TYPE_NAME", "", + "MINIMUM_SCALE", 0, + "MAXIMUM_SCALE", 0, + "SQL_DATA_TYPE", 0, + "SQL_DATETIME_SUB", 0, + "NUM_PREC_RADIX", 0, + "INTERVAL_PRECISION", 0); + rc = SQLGetData(hstmt, 1, SQL_C_CHAR, typeName, sizeof(typeName), 0); ti.set<0>(typeName); rc = SQLGetData(hstmt, 2, SQL_C_SSHORT, &ti.get<1>(), sizeof(SQLSMALLINT), 0); @@ -213,4 +209,47 @@ int TypeInfo::sqlDataType(int cDataType) const } +void TypeInfo::print(std::ostream& ostr) +{ + if (_typeInfo.empty()) + { + ostr << "No data found."; + return; + } + + TypeInfoTup::NameVec::const_iterator nIt = (*_typeInfo[0].names()).begin(); + TypeInfoTup::NameVec::const_iterator nItEnd = (*_typeInfo[0].names()).end(); + for (; nIt != nItEnd; ++nIt) + ostr << *nIt << "\t"; + + ostr << std::endl; + + TypeInfoVec::const_iterator it = _typeInfo.begin(); + TypeInfoVec::const_iterator end = _typeInfo.end(); + + for (; it != end; ++it) + { + ostr << it->get<0>() << "\t" + << it->get<1>() << "\t" + << it->get<2>() << "\t" + << it->get<3>() << "\t" + << it->get<4>() << "\t" + << it->get<5>() << "\t" + << it->get<6>() << "\t" + << it->get<7>() << "\t" + << it->get<8>() << "\t" + << it->get<9>() << "\t" + << it->get<10>() << "\t" + << it->get<11>() << "\t" + << it->get<12>() << "\t" + << it->get<13>() << "\t" + << it->get<14>() << "\t" + << it->get<15>() << "\t" + << it->get<16>() << "\t" + << it->get<17>() << "\t" + << it->get<18>() << std::endl; + } +} + + } } } // namespace Poco::Data::ODBC diff --git a/Data/ODBC/testsuite/TestSuite_VS80.vcproj b/Data/ODBC/testsuite/TestSuite_VS80.vcproj index e690047eb..35d18068a 100644 --- a/Data/ODBC/testsuite/TestSuite_VS80.vcproj +++ b/Data/ODBC/testsuite/TestSuite_VS80.vcproj @@ -4,6 +4,7 @@ Version="8.00" Name="TestSuite" ProjectGUID="{1B30A91B-375F-11DB-837B-00123FC423B5}" + RootNamespace="TestSuite" Keyword="Win32Proj" > diff --git a/Data/ODBC/testsuite/src/ODBCDB2Test.cpp b/Data/ODBC/testsuite/src/ODBCDB2Test.cpp index c9a741770..d06dad561 100644 --- a/Data/ODBC/testsuite/src/ODBCDB2Test.cpp +++ b/Data/ODBC/testsuite/src/ODBCDB2Test.cpp @@ -754,6 +754,21 @@ void ODBCDB2Test::testBLOBStmt() } +void ODBCDB2Test::testDateTime() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreatePersonDateTimeTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->dateTime(); + i += 2; + } +} + + void ODBCDB2Test::testFloat() { if (!_pSession) fail ("Test not available."); @@ -844,11 +859,11 @@ void ODBCDB2Test::testInternalStorageType() } -void ODBCDB2Test::dropTable(const std::string& tableName) +void ODBCDB2Test::dropObject(const std::string& type, const std::string& name) { try { - *_pSession << format("DROP TABLE %s", tableName), now; + *_pSession << format("DROP %s %s", type, name), now; } catch (StatementException& ex) { @@ -871,7 +886,7 @@ void ODBCDB2Test::dropTable(const std::string& tableName) void ODBCDB2Test::recreatePersonTable() { - dropTable("Person"); + dropObject("TABLE", "Person"); try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } @@ -880,16 +895,25 @@ void ODBCDB2Test::recreatePersonTable() void ODBCDB2Test::recreatePersonBLOBTable() { - dropTable("Person"); + dropObject("TABLE", "Person"); try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } } +void ODBCDB2Test::recreatePersonDateTimeTable() +{ + dropObject("TABLE", "Person"); + try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born TIMESTAMP)", now; } + catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } + catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } +} + + void ODBCDB2Test::recreateIntsTable() { - dropTable("Strings"); + dropObject("TABLE", "Strings"); try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } @@ -898,7 +922,7 @@ void ODBCDB2Test::recreateIntsTable() void ODBCDB2Test::recreateStringsTable() { - dropTable("Strings"); + dropObject("TABLE", "Strings"); try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); } @@ -907,7 +931,7 @@ void ODBCDB2Test::recreateStringsTable() void ODBCDB2Test::recreateFloatsTable() { - dropTable("Strings"); + dropObject("TABLE", "Strings"); try { *_pSession << "CREATE TABLE Strings (str FLOAT)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); } @@ -916,7 +940,7 @@ void ODBCDB2Test::recreateFloatsTable() void ODBCDB2Test::recreateTuplesTable() { - dropTable("Tuples"); + dropObject("TABLE", "Tuples"); try { *_pSession << "CREATE TABLE Tuples " "(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, " "int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER," @@ -928,7 +952,7 @@ void ODBCDB2Test::recreateTuplesTable() void ODBCDB2Test::recreateVectorsTable() { - dropTable("Vectors"); + dropObject("TABLE", "Vectors"); try { *_pSession << "CREATE TABLE Vectors (i0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); } @@ -988,9 +1012,9 @@ void ODBCDB2Test::setUp() void ODBCDB2Test::tearDown() { - dropTable("Person"); - dropTable("Strings"); - dropTable("Tuples"); + dropObject("TABLE", "Person"); + dropObject("TABLE", "Strings"); + dropObject("TABLE", "Tuples"); } @@ -1067,6 +1091,7 @@ CppUnit::Test* ODBCDB2Test::suite() CppUnit_addTest(pSuite, ODBCDB2Test, testEmptyDB); CppUnit_addTest(pSuite, ODBCDB2Test, testBLOB); CppUnit_addTest(pSuite, ODBCDB2Test, testBLOBStmt); + CppUnit_addTest(pSuite, ODBCDB2Test, testDateTime); CppUnit_addTest(pSuite, ODBCDB2Test, testFloat); CppUnit_addTest(pSuite, ODBCDB2Test, testDouble); CppUnit_addTest(pSuite, ODBCDB2Test, testTuple); diff --git a/Data/ODBC/testsuite/src/ODBCDB2Test.h b/Data/ODBC/testsuite/src/ODBCDB2Test.h index be3e0299a..a4fc8181c 100644 --- a/Data/ODBC/testsuite/src/ODBCDB2Test.h +++ b/Data/ODBC/testsuite/src/ODBCDB2Test.h @@ -108,6 +108,8 @@ public: void testBLOB(); void testBLOBStmt(); + void testDateTime(); + void testFloat(); void testDouble(); @@ -123,9 +125,10 @@ public: static CppUnit::Test* suite(); private: - void dropTable(const std::string& tableName); + void dropObject(const std::string& type, const std::string& tableName); void recreatePersonTable(); void recreatePersonBLOBTable(); + void recreatePersonDateTimeTable(); void recreateStringsTable(); void recreateIntsTable(); void recreateFloatsTable(); diff --git a/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp b/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp index 85e33781d..75d147150 100644 --- a/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCMySQLTest.cpp @@ -758,6 +758,21 @@ void ODBCMySQLTest::testBLOBStmt() } +void ODBCMySQLTest::testDateTime() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreatePersonDateTimeTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->dateTime(); + i += 2; + } +} + + void ODBCMySQLTest::testFloat() { if (!_pSession) fail ("Test not available."); @@ -888,6 +903,15 @@ void ODBCMySQLTest::recreatePersonBLOBTable() } +void ODBCMySQLTest::recreatePersonDateTimeTable() +{ + dropObject("TABLE", "Person"); + try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born DATETIME)", now; } + catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } + catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } +} + + void ODBCMySQLTest::recreateIntsTable() { dropObject("TABLE", "Strings"); @@ -1070,6 +1094,7 @@ CppUnit::Test* ODBCMySQLTest::suite() CppUnit_addTest(pSuite, ODBCMySQLTest, testEmptyDB); CppUnit_addTest(pSuite, ODBCMySQLTest, testBLOB); CppUnit_addTest(pSuite, ODBCMySQLTest, testBLOBStmt); + CppUnit_addTest(pSuite, ODBCMySQLTest, testDateTime); CppUnit_addTest(pSuite, ODBCMySQLTest, testFloat); CppUnit_addTest(pSuite, ODBCMySQLTest, testDouble); CppUnit_addTest(pSuite, ODBCMySQLTest, testTuple); diff --git a/Data/ODBC/testsuite/src/ODBCMySQLTest.h b/Data/ODBC/testsuite/src/ODBCMySQLTest.h index ca02261de..e189036de 100644 --- a/Data/ODBC/testsuite/src/ODBCMySQLTest.h +++ b/Data/ODBC/testsuite/src/ODBCMySQLTest.h @@ -111,6 +111,7 @@ public: void testBLOB(); void testBLOBStmt(); + void testDateTime(); void testFloat(); void testDouble(); @@ -132,6 +133,7 @@ private: void dropObject(const std::string& type, const std::string& name); void recreatePersonTable(); void recreatePersonBLOBTable(); + void recreatePersonDateTimeTable(); void recreateStringsTable(); void recreateIntsTable(); void recreateFloatsTable(); diff --git a/Data/ODBC/testsuite/src/ODBCOracleTest.cpp b/Data/ODBC/testsuite/src/ODBCOracleTest.cpp index ffd9300c1..151557d0e 100644 --- a/Data/ODBC/testsuite/src/ODBCOracleTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCOracleTest.cpp @@ -890,7 +890,7 @@ void ODBCOracleTest::testStoredProcedure() int i = 0; *_pSession << "{call storedProcedure(?)}", out(i), now; assert(-1 == i); - *_pSession << "DROP PROCEDURE storedProcedure;", now; + dropObject("PROCEDURE", "storedProcedure"); *_pSession << "CREATE OR REPLACE " "PROCEDURE storedProcedure(inParam IN NUMBER, outParam OUT NUMBER) IS " @@ -911,23 +911,20 @@ void ODBCOracleTest::testStoredProcedure() i = 2; *_pSession << "{call storedProcedure(?)}", io(i), now; assert(4 == i); - *_pSession << "DROP PROCEDURE storedProcedure;", now; + dropObject("PROCEDURE", "storedProcedure"); - k += 2; - } - - //DateTime io params only for autoBind for now - _pSession->setFeature("autoBind", true); - - *_pSession << "CREATE OR REPLACE " + *_pSession << "CREATE OR REPLACE " "PROCEDURE storedProcedure(ioParam IN OUT DATE) IS " " BEGIN ioParam := ioParam + 1; " " END storedProcedure;" , now; - DateTime dt(1965, 6, 18, 5, 35, 1); - *_pSession << "{call storedProcedure(?)}", io(dt), now; - assert(19 == dt.day()); - *_pSession << "DROP PROCEDURE storedProcedure;", now; + DateTime dt(1965, 6, 18, 5, 35, 1); + *_pSession << "{call storedProcedure(?)}", io(dt), now; + assert(19 == dt.day()); + dropObject("PROCEDURE", "storedProcedure"); + + k += 2; + } } @@ -937,6 +934,9 @@ void ODBCOracleTest::testStoredFunction() for (int k = 0; k < 8;) { + _pSession->setFeature("autoBind", bindValues[k]); + _pSession->setFeature("autoExtract", bindValues[k+1]); + *_pSession << "CREATE OR REPLACE " "FUNCTION storedFunction RETURN NUMBER IS " " BEGIN return(-1); " @@ -945,7 +945,7 @@ void ODBCOracleTest::testStoredFunction() int i = 0; *_pSession << "{? = call storedFunction()}", out(i), now; assert(-1 == i); - *_pSession << "DROP FUNCTION storedFunction;", now; + dropObject("FUNCTION", "storedFunction"); *_pSession << "CREATE OR REPLACE " "FUNCTION storedFunction(inParam IN NUMBER) RETURN NUMBER IS " @@ -956,7 +956,7 @@ void ODBCOracleTest::testStoredFunction() int result = 0; *_pSession << "{? = call storedFunction(?)}", out(result), in(i), now; assert(4 == result); - *_pSession << "DROP FUNCTION storedFunction;", now; + dropObject("FUNCTION", "storedFunction"); *_pSession << "CREATE OR REPLACE " "FUNCTION storedFunction(inParam IN NUMBER, outParam OUT NUMBER) RETURN NUMBER IS " @@ -969,7 +969,7 @@ void ODBCOracleTest::testStoredFunction() *_pSession << "{? = call storedFunction(?, ?)}", out(result), in(i), out(j), now; assert(4 == j); assert(j == result); - *_pSession << "DROP FUNCTION storedFunction;", now; + dropObject("FUNCTION", "storedFunction"); *_pSession << "CREATE OR REPLACE " "FUNCTION storedFunction(param1 IN OUT NUMBER, param2 IN OUT NUMBER) RETURN NUMBER IS " @@ -993,18 +993,18 @@ void ODBCOracleTest::testStoredFunction() assert(1 == params.get<1>()); assert(2 == params.get<0>()); assert(3 == result); - *_pSession << "DROP FUNCTION storedFunction;", now; + dropObject("FUNCTION", "storedFunction"); k += 2; } } -void ODBCOracleTest::dropTable(const std::string& tableName) +void ODBCOracleTest::dropObject(const std::string& type, const std::string& name) { try { - *_pSession << format("DROP TABLE %s", tableName), now; + *_pSession << format("DROP %s %s", type, name), now; } catch (StatementException& ex) { @@ -1027,7 +1027,7 @@ void ODBCOracleTest::dropTable(const std::string& tableName) void ODBCOracleTest::recreatePersonTable() { - dropTable("Person"); + dropObject("TABLE", "Person"); try { *_pSession << "CREATE TABLE Person (LastName VARCHAR2(30), FirstName VARCHAR2(30), Address VARCHAR2(30), Age INTEGER)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } @@ -1036,7 +1036,7 @@ void ODBCOracleTest::recreatePersonTable() void ODBCOracleTest::recreatePersonBLOBTable() { - dropTable("Person"); + dropObject("TABLE", "Person"); try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } @@ -1045,7 +1045,7 @@ void ODBCOracleTest::recreatePersonBLOBTable() void ODBCOracleTest::recreatePersonDateTimeTable() { - dropTable("Person"); + dropObject("TABLE", "Person"); try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born DATE)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } @@ -1054,7 +1054,7 @@ void ODBCOracleTest::recreatePersonDateTimeTable() void ODBCOracleTest::recreateIntsTable() { - dropTable("Strings"); + dropObject("TABLE", "Strings"); try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } @@ -1063,7 +1063,7 @@ void ODBCOracleTest::recreateIntsTable() void ODBCOracleTest::recreateStringsTable() { - dropTable("Strings"); + dropObject("TABLE", "Strings"); try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); } @@ -1072,7 +1072,7 @@ void ODBCOracleTest::recreateStringsTable() void ODBCOracleTest::recreateFloatsTable() { - dropTable("Strings"); + dropObject("TABLE", "Strings"); try { *_pSession << "CREATE TABLE Strings (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()"); } @@ -1081,7 +1081,7 @@ void ODBCOracleTest::recreateFloatsTable() void ODBCOracleTest::recreateTuplesTable() { - dropTable("Tuples"); + dropObject("TABLE", "Tuples"); try { *_pSession << "CREATE TABLE Tuples " "(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, " "int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER," @@ -1093,7 +1093,7 @@ void ODBCOracleTest::recreateTuplesTable() void ODBCOracleTest::recreateVectorsTable() { - dropTable("Vectors"); + dropObject("TABLE", "Vectors"); try { *_pSession << "CREATE TABLE Vectors (int0 INTEGER, flt0 NUMBER, str0 VARCHAR(30))", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); } @@ -1175,9 +1175,9 @@ void ODBCOracleTest::setUp() void ODBCOracleTest::tearDown() { - dropTable("Person"); - dropTable("Strings"); - dropTable("Tuples"); + dropObject("TABLE", "Person"); + dropObject("TABLE", "Strings"); + dropObject("TABLE", "Tuples"); } diff --git a/Data/ODBC/testsuite/src/ODBCOracleTest.h b/Data/ODBC/testsuite/src/ODBCOracleTest.h index 6a4fd311d..978eda6fc 100644 --- a/Data/ODBC/testsuite/src/ODBCOracleTest.h +++ b/Data/ODBC/testsuite/src/ODBCOracleTest.h @@ -128,7 +128,7 @@ public: static CppUnit::Test* suite(); private: - void dropTable(const std::string& tableName); + void dropObject(const std::string& type, const std::string& name); void recreatePersonTable(); void recreatePersonBLOBTable(); void recreatePersonDateTimeTable(); diff --git a/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp b/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp index 9cd843163..b9a6a44c4 100644 --- a/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp @@ -752,6 +752,21 @@ void ODBCPostgreSQLTest::testBLOBStmt() } +void ODBCPostgreSQLTest::testDateTime() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreatePersonDateTimeTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->dateTime(); + i += 2; + } +} + + void ODBCPostgreSQLTest::testFloat() { if (!_pSession) fail ("Test not available."); @@ -842,11 +857,11 @@ void ODBCPostgreSQLTest::testInternalStorageType() } -void ODBCPostgreSQLTest::dropTable(const std::string& tableName) +void ODBCPostgreSQLTest::dropObject(const std::string& type, const std::string& name) { try { - *_pSession << format("DROP TABLE %s", tableName), now; + *_pSession << format("DROP %s %s", type, name), now; } catch (StatementException& ex) { @@ -869,7 +884,7 @@ void ODBCPostgreSQLTest::dropTable(const std::string& tableName) void ODBCPostgreSQLTest::recreatePersonTable() { - dropTable("Person"); + dropObject("TABLE", "Person"); try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Age INTEGER)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } @@ -878,16 +893,26 @@ void ODBCPostgreSQLTest::recreatePersonTable() void ODBCPostgreSQLTest::recreatePersonBLOBTable() { - dropTable("Person"); + dropObject("TABLE", "Person"); try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BYTEA)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } } + +void ODBCPostgreSQLTest::recreatePersonDateTimeTable() +{ + dropObject("TABLE", "Person"); + try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born TIMESTAMP)", now; } + catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } + catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } +} + + void ODBCPostgreSQLTest::recreateIntsTable() { - dropTable("Strings"); + dropObject("TABLE", "Strings"); try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } @@ -896,7 +921,7 @@ void ODBCPostgreSQLTest::recreateIntsTable() void ODBCPostgreSQLTest::recreateStringsTable() { - dropTable("Strings"); + dropObject("TABLE", "Strings"); try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); } @@ -905,7 +930,7 @@ void ODBCPostgreSQLTest::recreateStringsTable() void ODBCPostgreSQLTest::recreateFloatsTable() { - dropTable("Strings"); + dropObject("TABLE", "Strings"); try { *_pSession << "CREATE TABLE Strings (str FLOAT)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); } @@ -914,7 +939,7 @@ void ODBCPostgreSQLTest::recreateFloatsTable() void ODBCPostgreSQLTest::recreateTuplesTable() { - dropTable("Tuples"); + dropObject("TABLE", "Tuples"); try { *_pSession << "CREATE TABLE Tuples " "(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, " "int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER," @@ -926,7 +951,7 @@ void ODBCPostgreSQLTest::recreateTuplesTable() void ODBCPostgreSQLTest::recreateVectorsTable() { - dropTable("Vectors"); + dropObject("TABLE", "Vectors"); try { *_pSession << "CREATE TABLE Vectors (int0 INTEGER, flt0 FLOAT, str0 VARCHAR(30))", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); } @@ -1015,9 +1040,9 @@ void ODBCPostgreSQLTest::setUp() void ODBCPostgreSQLTest::tearDown() { - dropTable("Person"); - dropTable("Strings"); - dropTable("Tuples"); + dropObject("TABLE", "Person"); + dropObject("TABLE", "Strings"); + dropObject("TABLE", "Tuples"); } @@ -1094,6 +1119,7 @@ CppUnit::Test* ODBCPostgreSQLTest::suite() CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testEmptyDB); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testBLOB); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testBLOBStmt); + CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testDateTime); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testFloat); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testDouble); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testTuple); diff --git a/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.h b/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.h index 66ec5677c..a5c3650d8 100644 --- a/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.h +++ b/Data/ODBC/testsuite/src/ODBCPostgreSQLTest.h @@ -111,6 +111,8 @@ public: void testBLOB(); void testBLOBStmt(); + void testDateTime(); + void testFloat(); void testDouble(); @@ -126,9 +128,10 @@ public: static CppUnit::Test* suite(); private: - void dropTable(const std::string& tableName); + void dropObject(const std::string& type, const std::string& name); void recreatePersonTable(); void recreatePersonBLOBTable(); + void recreatePersonDateTimeTable(); void recreateStringsTable(); void recreateIntsTable(); void recreateFloatsTable(); diff --git a/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp b/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp index e131237a2..a0dc35ae2 100644 --- a/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp @@ -864,123 +864,135 @@ void ODBCSQLServerTest::testInternalStorageType() void ODBCSQLServerTest::testStoredProcedure() { - dropObject("PROCEDURE", "storedProcedure"); - - *_pSession << "CREATE PROCEDURE storedProcedure " - "@outParam int = 0 OUTPUT " - "AS " - "SET @outParam = -1 " - , now; - - int i = 0; - *_pSession << "{call storedProcedure(?)}", out(i), now; - assert(-1 == i); - dropObject("PROCEDURE", "storedProcedure"); - - *_pSession << "CREATE PROCEDURE storedProcedure " - "@inParam int, " - "@outParam int = 0 OUTPUT " - "AS " - "SET @outParam = @inParam*@inParam " - , now; - - fail("TODO"); - i = 2; - int j = 0; - /*not working */ - try{ - *_pSession << "{call storedProcedure(2, ?)}", out(j), now; - }catch(StatementException& ex) + for (int k = 0; k < 8;) { - std::cout << ex.toString(); - } - //assert(4 == j); - dropObject("PROCEDURE", "storedProcedure"); + _pSession->setFeature("autoBind", bindValues[k]); + _pSession->setFeature("autoExtract", bindValues[k+1]); - *_pSession << "CREATE PROCEDURE storedProcedure " - "@ioParam int " - "AS " - "SET @ioParam = @ioParam*@ioParam " - , now; + dropObject("PROCEDURE", "storedProcedure"); - i = 2; - /*not working*/ - try{ + *_pSession << "CREATE PROCEDURE storedProcedure " + "@outParam int OUTPUT " + "AS " + "SET @outParam = -1 " + , now; + + int i = 0; + *_pSession << "{call storedProcedure(?)}", out(i), now; + assert(-1 == i); + dropObject("PROCEDURE", "storedProcedure"); + + *_pSession << "CREATE PROCEDURE storedProcedure " + "@inParam int, " + "@outParam int OUTPUT " + "AS " + "SET @outParam = @inParam*@inParam " + , now; + + i = 2; + int j = 0; + *_pSession << "{call storedProcedure(?, ?)}", in(i), out(j), now; + assert(4 == j); + dropObject("PROCEDURE", "storedProcedure"); + + *_pSession << "CREATE PROCEDURE storedProcedure " + "@ioParam int OUTPUT " + "AS " + "SET @ioParam = @ioParam*@ioParam " + , now; + + i = 2; *_pSession << "{call storedProcedure(?)}", io(i), now; - }catch(StatementException& ex) - { - std::cout << ex.toString(); + assert(4 == i); + dropObject("PROCEDURE", "storedProcedure"); + + k += 2; } - //assert(4 == i); - dropObject("PROCEDURE", "storedProcedure"); } void ODBCSQLServerTest::testStoredFunction() { - dropObject("PROCEDURE", "storedFunction"); - *_pSession << "CREATE PROCEDURE storedFunction " - "AS " - "DECLARE @retVal int " - "SET @retVal = -1 " - "RETURN @retVal" - , now; + for (int k = 0; k < 8;) + { + _pSession->setFeature("autoBind", bindValues[k]); + _pSession->setFeature("autoExtract", bindValues[k+1]); - int i = 0; - *_pSession << "{? = call storedFunction}", out(i), now; + dropObject("PROCEDURE", "storedFunction"); + *_pSession << "CREATE PROCEDURE storedFunction AS " + "BEGIN " + "DECLARE @retVal int;" + "SET @retVal = -1;" + "RETURN @retVal;" + "END;" + , now; - assert(-1 == i); - dropObject("PROCEDURE", "storedFunction"); + int i = 0; + *_pSession << "{? = call storedFunction}", out(i), now; + assert(-1 == i); + dropObject("PROCEDURE", "storedFunction"); - /*TODO - *_pSession << "CREATE OR REPLACE " - "FUNCTION storedFunction(inParam IN NUMBER) RETURN NUMBER IS " - " BEGIN RETURN(inParam*inParam); " - " END storedFunction;" , now; - i = 2; - int result = 0; - *_pSession << "{? = call storedFunction(?)}", out(result), in(i), now; - assert(4 == result); - *_pSession << "DROP FUNCTION storedFunction;", now; + *_pSession << "CREATE PROCEDURE storedFunction(@inParam int) AS " + "BEGIN " + "RETURN @inParam*@inParam;" + "END;" + , now; - *_pSession << "CREATE OR REPLACE " - "FUNCTION storedFunction(inParam IN NUMBER, outParam OUT NUMBER) RETURN NUMBER IS " - " BEGIN outParam := inParam*inParam; RETURN(outParam); " - " END storedFunction;" , now; + i = 2; + int result = 0; + *_pSession << "{? = call storedFunction(?)}", out(result), in(i), now; + assert(4 == result); + dropObject("PROCEDURE", "storedFunction"); - i = 2; - int j = 0; - result = 0; - *_pSession << "{? = call storedFunction(?, ?)}", out(result), in(i), out(j), now; - assert(4 == j); - assert(j == result); - *_pSession << "DROP FUNCTION storedFunction;", now; - *_pSession << "CREATE OR REPLACE " - "FUNCTION storedFunction(param1 IN OUT NUMBER, param2 IN OUT NUMBER) RETURN NUMBER IS " - " temp NUMBER := param1; " - " BEGIN param1 := param2; param2 := temp; RETURN(param1+param2); " - " END storedFunction;" , now; + *_pSession << "CREATE PROCEDURE storedFunction(@inParam int, @outParam int OUTPUT) AS " + "BEGIN " + "SET @outParam = @inParam*@inParam;" + "RETURN @outParam;" + "END" + , now; - i = 1; - j = 2; - result = 0; - *_pSession << "{? = call storedFunction(?, ?)}", out(result), io(i), io(j), now; - assert(1 == j); - assert(2 == i); - assert(3 == result); - - Tuple params(1, 2); - assert(1 == params.get<0>()); - assert(2 == params.get<1>()); - result = 0; - *_pSession << "{? = call storedFunction(?, ?)}", out(result), io(params), now; - assert(1 == params.get<1>()); - assert(2 == params.get<0>()); - assert(3 == result); - *_pSession << "DROP FUNCTION storedFunction;", now; - */ + i = 2; + int j = 0; + result = 0; + *_pSession << "{? = call storedFunction(?, ?)}", out(result), in(i), out(j), now; + assert(4 == j); + assert(j == result); + dropObject("PROCEDURE", "storedFunction"); + + + *_pSession << "CREATE PROCEDURE storedFunction(@param1 int OUTPUT,@param2 int OUTPUT) AS " + "BEGIN " + "DECLARE @temp int; " + "SET @temp = @param1;" + "SET @param1 = @param2;" + "SET @param2 = @temp;" + "RETURN @param1 + @param2; " + "END" + , now; + + i = 1; + j = 2; + result = 0; + *_pSession << "{? = call storedFunction(?, ?)}", out(result), io(i), io(j), now; + assert(1 == j); + assert(2 == i); + assert(3 == result); + + Tuple params(1, 2); + assert(1 == params.get<0>()); + assert(2 == params.get<1>()); + result = 0; + *_pSession << "{? = call storedFunction(?, ?)}", out(result), io(params), now; + assert(1 == params.get<1>()); + assert(2 == params.get<0>()); + assert(3 == result); + + dropObject("PROCEDURE", "storedFunction"); + + k += 2; + } } diff --git a/Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp b/Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp index 59ef7d3b4..a3d77892c 100644 --- a/Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp +++ b/Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp @@ -759,6 +759,21 @@ void ODBCSQLiteTest::testBLOBStmt() } +void ODBCSQLiteTest::testDateTime() +{ + if (!_pSession) fail ("Test not available."); + + for (int i = 0; i < 8;) + { + recreatePersonDateTimeTable(); + _pSession->setFeature("autoBind", bindValues[i]); + _pSession->setFeature("autoExtract", bindValues[i+1]); + _pExecutor->dateTime(); + i += 2; + } +} + + void ODBCSQLiteTest::testFloat() { if (!_pSession) fail ("Test not available."); @@ -849,11 +864,11 @@ void ODBCSQLiteTest::testInternalStorageType() } -void ODBCSQLiteTest::dropTable(const std::string& tableName) +void ODBCSQLiteTest::dropObject(const std::string& type, const std::string& name) { try { - *_pSession << format("DROP TABLE %s", tableName), now; + *_pSession << format("DROP %s %s", type, name), now; } catch (StatementException& ex) { @@ -876,7 +891,7 @@ void ODBCSQLiteTest::dropTable(const std::string& tableName) void ODBCSQLiteTest::recreatePersonTable() { - dropTable("Person"); + dropObject("TABLE", "Person"); try { *_pSession << "CREATE TABLE Person (LastName VARCHAR2(30), FirstName VARCHAR2(30), Address VARCHAR2(30), Age INTEGER)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonTable()"); } @@ -885,16 +900,25 @@ void ODBCSQLiteTest::recreatePersonTable() void ODBCSQLiteTest::recreatePersonBLOBTable() { - dropTable("Person"); + dropObject("TABLE", "Person"); try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Image BLOB)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonBLOBTable()"); } } +void ODBCSQLiteTest::recreatePersonDateTimeTable() +{ + dropObject("TABLE", "Person"); + try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Born TIMESTAMP)", now; } + catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } + catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreatePersonDateTimeTable()"); } +} + + void ODBCSQLiteTest::recreateIntsTable() { - dropTable("Strings"); + dropObject("TABLE", "Strings"); try { *_pSession << "CREATE TABLE Strings (str INTEGER)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateIntsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateIntsTable()"); } @@ -903,7 +927,7 @@ void ODBCSQLiteTest::recreateIntsTable() void ODBCSQLiteTest::recreateStringsTable() { - dropTable("Strings"); + dropObject("TABLE", "Strings"); try { *_pSession << "CREATE TABLE Strings (str VARCHAR(30))", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateStringsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateStringsTable()"); } @@ -912,7 +936,7 @@ void ODBCSQLiteTest::recreateStringsTable() void ODBCSQLiteTest::recreateFloatsTable() { - dropTable("Strings"); + dropObject("TABLE", "Strings"); try { *_pSession << "CREATE TABLE Strings (str REAL)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateFloatsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateFloatsTable()"); } @@ -921,7 +945,7 @@ void ODBCSQLiteTest::recreateFloatsTable() void ODBCSQLiteTest::recreateTuplesTable() { - dropTable("Tuples"); + dropObject("TABLE", "Tuples"); try { *_pSession << "CREATE TABLE Tuples " "(int0 INTEGER, int1 INTEGER, int2 INTEGER, int3 INTEGER, int4 INTEGER, int5 INTEGER, int6 INTEGER, " "int7 INTEGER, int8 INTEGER, int9 INTEGER, int10 INTEGER, int11 INTEGER, int12 INTEGER, int13 INTEGER," @@ -933,7 +957,7 @@ void ODBCSQLiteTest::recreateTuplesTable() void ODBCSQLiteTest::recreateVectorsTable() { - dropTable("Vectors"); + dropObject("TABLE", "Vectors"); try { *_pSession << "CREATE TABLE Vectors (int0 INTEGER, flt0 REAL, str0 VARCHAR)", now; } catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateVectorsTable()"); } catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateVectorsTable()"); } @@ -987,9 +1011,9 @@ void ODBCSQLiteTest::setUp() void ODBCSQLiteTest::tearDown() { - dropTable("Person"); - dropTable("Strings"); - dropTable("Tuples"); + dropObject("TABLE", "Person"); + dropObject("TABLE", "Strings"); + dropObject("TABLE", "Tuples"); } @@ -1066,6 +1090,7 @@ CppUnit::Test* ODBCSQLiteTest::suite() CppUnit_addTest(pSuite, ODBCSQLiteTest, testEmptyDB); CppUnit_addTest(pSuite, ODBCSQLiteTest, testBLOB); CppUnit_addTest(pSuite, ODBCSQLiteTest, testBLOBStmt); + CppUnit_addTest(pSuite, ODBCSQLiteTest, testDateTime); CppUnit_addTest(pSuite, ODBCSQLiteTest, testFloat); CppUnit_addTest(pSuite, ODBCSQLiteTest, testDouble); CppUnit_addTest(pSuite, ODBCSQLiteTest, testTuple); diff --git a/Data/ODBC/testsuite/src/ODBCSQLiteTest.h b/Data/ODBC/testsuite/src/ODBCSQLiteTest.h index 4222b2b97..fe5780b0a 100644 --- a/Data/ODBC/testsuite/src/ODBCSQLiteTest.h +++ b/Data/ODBC/testsuite/src/ODBCSQLiteTest.h @@ -108,6 +108,8 @@ public: void testBLOB(); void testBLOBStmt(); + void testDateTime(); + void testFloat(); void testDouble(); @@ -123,9 +125,10 @@ public: static CppUnit::Test* suite(); private: - void dropTable(const std::string& tableName); + void dropObject(const std::string& type, const std::string& name); void recreatePersonTable(); void recreatePersonBLOBTable(); + void recreatePersonDateTimeTable(); void recreateStringsTable(); void recreateIntsTable(); void recreateFloatsTable(); diff --git a/Data/ODBC/testsuite/src/SQLExecutor.cpp b/Data/ODBC/testsuite/src/SQLExecutor.cpp index 17e968135..10d66fd15 100644 --- a/Data/ODBC/testsuite/src/SQLExecutor.cpp +++ b/Data/ODBC/testsuite/src/SQLExecutor.cpp @@ -113,14 +113,17 @@ template <> class TypeHandler { public: - static void bind(std::size_t pos, const Person& obj, AbstractBinder* pBinder) + static void bind(std::size_t pos, + const Person& obj, + AbstractBinder* pBinder, + AbstractBinder::Direction dir = AbstractBinder::PD_IN) { // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3)) poco_assert_dbg (pBinder != 0); - pBinder->bind(pos++, obj.lastName); - pBinder->bind(pos++, obj.firstName); - pBinder->bind(pos++, obj.address); - pBinder->bind(pos++, obj.age); + pBinder->bind(pos++, obj.lastName, dir); + pBinder->bind(pos++, obj.firstName, dir); + pBinder->bind(pos++, obj.address, dir); + pBinder->bind(pos++, obj.age, dir); } static void prepare(std::size_t pos, const Person& obj, AbstractPreparation* pPrepare) @@ -217,11 +220,16 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString, SQLSMALLINT dateTimeDecDigits = 0; rc = SQLFetch(hstmt); - assert (SQL_SUCCEEDED(rc)); - rc = SQLGetData(hstmt, 3, SQL_C_SLONG, &dateTimeColSize, sizeof(SQLINTEGER), 0); - assert (SQL_SUCCEEDED(rc)); - rc = SQLGetData(hstmt, 14, SQL_C_SSHORT, &dateTimeDecDigits, sizeof(SQLSMALLINT), 0); - assert (SQL_SUCCEEDED(rc)); + assert (SQL_SUCCEEDED(rc) || SQL_NO_DATA == rc); + if (SQL_SUCCEEDED(rc)) + { + rc = SQLGetData(hstmt, 3, SQL_C_SLONG, &dateTimeColSize, sizeof(SQLINTEGER), 0); + assert (SQL_SUCCEEDED(rc)); + rc = SQLGetData(hstmt, 14, SQL_C_SSHORT, &dateTimeDecDigits, sizeof(SQLSMALLINT), 0); + assert (SQL_SUCCEEDED(rc)); + } + else if (SQL_NO_DATA == rc) + std::cerr << "Warning: no data type info returned by driver." << std::endl; rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); assert (SQL_SUCCEEDED(rc)); @@ -359,7 +367,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString, if (SQL_NEED_DATA == rc) { SQLPOINTER pParam = 0; - int i = 0; + int i = 1; rc = SQLParamData(hstmt, &pParam); do { @@ -368,12 +376,14 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString, // non-variable length fields, but SQLite ODBC // driver insists on it always being the actual // data length - if (i < 3) - dataSize = (SQLINTEGER) str[i++].size(); - else if (3 == i) dataSize = sizeof(int); - else if (4 == i) dataSize = sizeof(float); + if (i < 4) + dataSize = (SQLINTEGER) str[i-1].size(); + else if (4 == i) dataSize = sizeof(int); + else if (5 == i) dataSize = sizeof(float); + else if (6 == i) dataSize = sizeof(SQL_TIMESTAMP_STRUCT); rc = SQLPutData(hstmt, pParam, dataSize); + ++i; }while (SQL_NEED_DATA == (rc = SQLParamData(hstmt, &pParam))); } assert (SQL_SUCCEEDED(rc)); diff --git a/Data/include/Poco/Data/AbstractBinder.h b/Data/include/Poco/Data/AbstractBinder.h index 7c7804354..31ff28fe6 100644 --- a/Data/include/Poco/Data/AbstractBinder.h +++ b/Data/include/Poco/Data/AbstractBinder.h @@ -58,102 +58,85 @@ class Data_API AbstractBinder /// in the SQL query is ":name". { public: + enum Direction + /// Binding direction for a parameter. + { + PD_IN, + PD_OUT, + PD_IN_OUT + }; + AbstractBinder(); /// Creates the AbstractBinder. virtual ~AbstractBinder(); /// Destroys the AbstractBinder. - virtual void bind(std::size_t pos, const Poco::Int8& val) = 0; + virtual void bind(std::size_t pos, const Poco::Int8& val, Direction dir) = 0; /// Binds an Int8. - virtual void bind(std::size_t pos, const Poco::UInt8& val) = 0; + virtual void bind(std::size_t pos, const Poco::UInt8& val, Direction dir) = 0; /// Binds an UInt8. - virtual void bind(std::size_t pos, const Poco::Int16& val) = 0; + virtual void bind(std::size_t pos, const Poco::Int16& val, Direction dir) = 0; /// Binds an Int16. - virtual void bind(std::size_t pos, const Poco::UInt16& val) = 0; + virtual void bind(std::size_t pos, const Poco::UInt16& val, Direction dir) = 0; /// Binds an UInt16. - virtual void bind(std::size_t pos, const Poco::Int32& val) = 0; + virtual void bind(std::size_t pos, const Poco::Int32& val, Direction dir) = 0; /// Binds an Int32. - virtual void bind(std::size_t pos, const Poco::UInt32& val) = 0; + virtual void bind(std::size_t pos, const Poco::UInt32& val, Direction dir) = 0; /// Binds an UInt32. - virtual void bind(std::size_t pos, const Poco::Int64& val) = 0; + virtual void bind(std::size_t pos, const Poco::Int64& val, Direction dir) = 0; /// Binds an Int64. - virtual void bind(std::size_t pos, const Poco::UInt64& val) = 0; + virtual void bind(std::size_t pos, const Poco::UInt64& val, Direction dir) = 0; /// Binds an UInt64. - virtual void bind(std::size_t pos, const bool& val) = 0; + virtual void bind(std::size_t pos, const bool& val, Direction dir) = 0; /// Binds a boolean. - virtual void bind(std::size_t pos, const float& val) = 0; + virtual void bind(std::size_t pos, const float& val, Direction dir) = 0; /// Binds a float. - virtual void bind(std::size_t pos, const double& val) = 0; + virtual void bind(std::size_t pos, const double& val, Direction dir) = 0; /// Binds a double. - virtual void bind(std::size_t pos, const char& val) = 0; + virtual void bind(std::size_t pos, const char& val, Direction dir) = 0; /// Binds a single character. - virtual void bind(std::size_t pos, const char* const &pVal) = 0; + virtual void bind(std::size_t pos, const char* const &pVal, Direction dir) = 0; /// Binds a const char ptr. - virtual void bind(std::size_t pos, const std::string& val) = 0; + virtual void bind(std::size_t pos, const std::string& val, Direction dir) = 0; /// Binds a string. - virtual void bind(std::size_t pos, const BLOB& val) = 0; + virtual void bind(std::size_t pos, const BLOB& val, Direction dir) = 0; /// Binds a BLOB. - virtual void bind(std::size_t pos, const DateTime& val) = 0; + virtual void bind(std::size_t pos, const DateTime& val, Direction dir) = 0; /// Binds a DateTime. - bool isInBound() const; - /// Returns true if binder is in-bound. + static bool isOutBound(Direction dir); + /// Returns true if direction is out bound; - bool isOutBound() const; - /// Returns true if binder is out-bound. - - void setInBound(bool inBound = true); - /// If inBound is true, binder is set to be in-bound. - - void setOutBound(bool outBound = true); - /// If outBound is true, binder is set to be out-bound. - -protected: - bool _inBound; - bool _outBound; + static bool isInBound(Direction dir); + /// Returns true if direction is in bound; }; -/// -/// inlines -/// -inline bool AbstractBinder::isInBound() const +inline bool AbstractBinder::isOutBound(Direction dir) { - return _inBound; + return PD_OUT == dir || PD_IN_OUT == dir; } -inline bool AbstractBinder::isOutBound() const +inline bool AbstractBinder::isInBound(Direction dir) { - return _outBound; -} - - -inline void AbstractBinder::setInBound(bool inBound) -{ - _inBound = inBound; -} - - -inline void AbstractBinder::setOutBound(bool outBound) -{ - _outBound = outBound; + return PD_IN == dir || PD_IN_OUT == dir; } diff --git a/Data/include/Poco/Data/AbstractBinding.h b/Data/include/Poco/Data/AbstractBinding.h index 9f6d1c04e..6052549f2 100644 --- a/Data/include/Poco/Data/AbstractBinding.h +++ b/Data/include/Poco/Data/AbstractBinding.h @@ -57,7 +57,14 @@ class Data_API AbstractBinding: public Poco::RefCountedObject /// AbstractBinding connects a value with a placeholder via an AbstractBinder interface. { public: - AbstractBinding(); + enum Direction + { + PD_IN = AbstractBinder::PD_IN, + PD_OUT = AbstractBinder::PD_OUT, + PD_IN_OUT = AbstractBinder::PD_IN_OUT + }; + + AbstractBinding(const std::string& name = "", Direction direction = PD_IN); /// Creates the AbstractBinding. virtual ~AbstractBinding(); @@ -90,16 +97,16 @@ public: virtual void reset() = 0; /// Allows a binding to be reused. - void setInBound(bool inBound = true); - /// Sets the binder to be in-bound. + AbstractBinder::Direction getDirection() const; + /// Returns the binding direction. - void setOutBound(bool outBound = true); - /// Sets the binder to be out-bound. + const std::string& name() const; + /// Returns the name for this binding. private: AbstractBinder* _pBinder; - bool _inBound; - bool _outBound; + std::string _name; + Direction _direction; }; @@ -110,31 +117,21 @@ typedef std::vector AbstractBindingVec; // // inlines // -inline void AbstractBinding::setBinder(AbstractBinder* pBinder) -{ - poco_check_ptr (pBinder); - _pBinder = pBinder; - _pBinder->setInBound(_inBound); - _pBinder->setOutBound(_outBound); - poco_assert_dbg (_inBound || _outBound); -} - - inline AbstractBinder* AbstractBinding::getBinder() const { return _pBinder; } -inline void AbstractBinding::setInBound(bool inBound) +inline const std::string& AbstractBinding::name() const { - _inBound = inBound; + return _name; } -inline void AbstractBinding::setOutBound(bool outBound) +inline AbstractBinder::Direction AbstractBinding::getDirection() const { - _outBound = outBound; + return (AbstractBinder::Direction) _direction; } diff --git a/Data/include/Poco/Data/Binding.h b/Data/include/Poco/Data/Binding.h index 9af01e207..11fb80106 100644 --- a/Data/include/Poco/Data/Binding.h +++ b/Data/include/Poco/Data/Binding.h @@ -61,7 +61,10 @@ class Binding: public AbstractBinding /// A Binding maps a value to a column. { public: - explicit Binding(const T& val): _val(val), _bound(false) + explicit Binding(const T& val, const std::string& name = "", Direction direction = PD_IN): + AbstractBinding(name, direction), + _val(val), + _bound(false) /// Creates the Binding. { } @@ -89,7 +92,7 @@ public: void bind(std::size_t pos) { poco_assert_dbg(getBinder() != 0); - TypeHandler::bind(pos, _val, getBinder()); + TypeHandler::bind(pos, _val, getBinder(), getDirection()); _bound = true; } @@ -109,7 +112,11 @@ class Binding >: public AbstractBinding /// Specialization for std::vector. { public: - explicit Binding(const std::vector& val): _val(val), _begin(val.begin()), _end(val.end()) + explicit Binding(const std::vector& val, const std::string& name = "", Direction direction = PD_IN): + AbstractBinding(name, direction), + _val(val), + _begin(val.begin()), + _end(val.end()) /// Creates the Binding. { if (numOfRowsHandled() == 0) @@ -140,7 +147,7 @@ public: { poco_assert_dbg(getBinder() != 0); poco_assert_dbg(canBind()); - TypeHandler::bind(pos, *_begin, getBinder()); + TypeHandler::bind(pos, *_begin, getBinder(), getDirection()); ++_begin; } @@ -162,7 +169,11 @@ class Binding >: public AbstractBinding /// Specialization for std::list. { public: - explicit Binding(const std::list& val): _val(val), _begin(val.begin()), _end(val.end()) + explicit Binding(const std::list& val, const std::string& name = "", Direction direction = PD_IN): + AbstractBinding(name, direction), + _val(val), + _begin(val.begin()), + _end(val.end()) /// Creates the Binding. { if (numOfRowsHandled() == 0) @@ -193,7 +204,7 @@ public: { poco_assert_dbg(getBinder() != 0); poco_assert_dbg(canBind()); - TypeHandler::bind(pos, *_begin, getBinder()); + TypeHandler::bind(pos, *_begin, getBinder(), getDirection()); ++_begin; } @@ -215,7 +226,11 @@ class Binding >: public AbstractBinding /// Specialization for std::deque. { public: - explicit Binding(const std::deque& val): _val(val), _begin(val.begin()), _end(val.end()) + explicit Binding(const std::deque& val, const std::string& name = "", Direction direction = PD_IN): + AbstractBinding(name, direction), + _val(val), + _begin(val.begin()), + _end(val.end()) /// Creates the Binding. { if (numOfRowsHandled() == 0) @@ -246,7 +261,7 @@ public: { poco_assert_dbg(getBinder() != 0); poco_assert_dbg(canBind()); - TypeHandler::bind(pos, *_begin, getBinder()); + TypeHandler::bind(pos, *_begin, getBinder(), getDirection()); ++_begin; } @@ -268,7 +283,11 @@ class Binding >: public AbstractBinding /// Specialization for std::set. { public: - explicit Binding(const std::set& val): AbstractBinding(), _val(val), _begin(val.begin()), _end(val.end()) + explicit Binding(const std::set& val, const std::string& name = "", Direction direction = PD_IN): + AbstractBinding(name, direction), + _val(val), + _begin(val.begin()), + _end(val.end()) /// Creates the Binding. { if (numOfRowsHandled() == 0) @@ -299,7 +318,7 @@ public: { poco_assert_dbg(getBinder() != 0); poco_assert_dbg(canBind()); - TypeHandler::bind(pos, *_begin, getBinder()); + TypeHandler::bind(pos, *_begin, getBinder(), getDirection()); ++_begin; } @@ -321,7 +340,11 @@ class Binding >: public AbstractBinding /// Specialization for std::multiset. { public: - explicit Binding(const std::multiset& val): AbstractBinding(), _val(val), _begin(val.begin()), _end(val.end()) + explicit Binding(const std::multiset& val, const std::string& name = "", Direction direction = PD_IN): + AbstractBinding(name, direction), + _val(val), + _begin(val.begin()), + _end(val.end()) /// Creates the Binding. { if (numOfRowsHandled() == 0) @@ -352,7 +375,7 @@ public: { poco_assert_dbg(getBinder() != 0); poco_assert_dbg(canBind()); - TypeHandler::bind(pos, *_begin, getBinder()); + TypeHandler::bind(pos, *_begin, getBinder(), getDirection()); ++_begin; } @@ -374,7 +397,11 @@ class Binding >: public AbstractBinding /// Specialization for std::map. { public: - explicit Binding(const std::map& val): AbstractBinding(), _val(val), _begin(val.begin()), _end(val.end()) + explicit Binding(const std::map& val, const std::string& name = "", Direction direction = PD_IN): + AbstractBinding(name, direction), + _val(val), + _begin(val.begin()), + _end(val.end()) /// Creates the Binding. { if (numOfRowsHandled() == 0) @@ -405,7 +432,7 @@ public: { poco_assert_dbg(getBinder() != 0); poco_assert_dbg(canBind()); - TypeHandler::bind(pos, _begin->second, getBinder()); + TypeHandler::bind(pos, _begin->second, getBinder(), getDirection()); ++_begin; } @@ -427,7 +454,11 @@ class Binding >: public AbstractBinding /// Specialization for std::multimap. { public: - explicit Binding(const std::multimap& val): AbstractBinding(), _val(val), _begin(val.begin()), _end(val.end()) + explicit Binding(const std::multimap& val, const std::string& name = "", Direction direction = PD_IN): + AbstractBinding(name, direction), + _val(val), + _begin(val.begin()), + _end(val.end()) /// Creates the Binding. { if (numOfRowsHandled() == 0) @@ -458,7 +489,7 @@ public: { poco_assert_dbg(getBinder() != 0); poco_assert_dbg(canBind()); - TypeHandler::bind(pos, _begin->second, getBinder()); + TypeHandler::bind(pos, _begin->second, getBinder(), getDirection()); ++_begin; } @@ -475,38 +506,38 @@ private: }; -template Binding* use(const T& t) +template Binding* use(const T& t, const std::string& name = "") /// Convenience function for a more compact Binding creation. { - Binding* pB = new Binding(t); + Binding* pB = new Binding(t, name, AbstractBinding::PD_IN); poco_check_ptr (pB); return pB; } -template Binding* in(const T& t) +template Binding* in(const T& t, const std::string& name = "") /// Convenience function for a more compact Binding creation. { - return use(t); -} - - -template Binding* out(const T& t) - /// Convenience function for a more compact Binding creation. -{ - Binding* pB = use(t); - pB->setInBound(false); - pB->setOutBound(true); + Binding* pB = new Binding(t, name, AbstractBinding::PD_IN); + poco_check_ptr (pB); return pB; } -template Binding* io(const T& t) +template Binding* out(const T& t, const std::string& name = "") /// Convenience function for a more compact Binding creation. { - Binding* pB = use(t); - pB->setInBound(true); - pB->setOutBound(true); + Binding* pB = new Binding(t, name, AbstractBinding::PD_OUT); + poco_check_ptr (pB); + return pB; +} + + +template Binding* io(const T& t, const std::string& name = "") + /// Convenience function for a more compact Binding creation. +{ + Binding* pB = new Binding(t, name, AbstractBinding::PD_IN_OUT); + poco_check_ptr (pB); return pB; } diff --git a/Data/include/Poco/Data/StatementImpl.h b/Data/include/Poco/Data/StatementImpl.h index 8e0abb2d9..f26320c27 100644 --- a/Data/include/Poco/Data/StatementImpl.h +++ b/Data/include/Poco/Data/StatementImpl.h @@ -214,6 +214,12 @@ protected: SessionImpl& session(); /// Rteurns session associated with this statement. + void fixupBinding(); + /// Sets the AbstractBinder at the bindings. + + void resetBinding(); + /// Resets binding so it can be reused again. + private: void compile(); /// Compiles the statement, if not yet compiled. doesn't bind yet @@ -230,14 +236,8 @@ private: void fixupExtraction(); /// Sets the AbstractExtractor at the extractors. - void fixupBinding(); - /// Sets the AbstractBinder at the bindings - - void resetBinding(); - /// Resets binding so we can reuse it again. - void resetExtraction(); - /// Resets binding so we can reuse it again. + /// Resets binding so it can be reused again. template void addInternalExtract(const MetaColumn& mc) diff --git a/Data/include/Poco/Data/TypeHandler.h b/Data/include/Poco/Data/TypeHandler.h index 855f50aae..dfbc5a706 100644 --- a/Data/include/Poco/Data/TypeHandler.h +++ b/Data/include/Poco/Data/TypeHandler.h @@ -77,13 +77,13 @@ class TypeHandler /// return 3; // lastName + firstname + age occupy three columns /// } /// - /// static void bind(std::size_t pos, const Person& obj, AbstractBinder* pBinder) + /// static void bind(std::size_t pos, const Person& obj, AbstractBinder* pBinder, AbstractBinder::Direction dir) /// { /// // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Age INTEGER(3)) /// // Note that we advance pos by the number of columns the datatype uses! For string/int this is one. /// poco_assert_dbg (pBinder != 0); - /// TypeHandler::bind(pos++, obj.getLastName(), pBinder); - /// TypeHandler::bind(pos++, obj.getFirstName(), pBinder); + /// TypeHandler::bind(pos++, obj.getLastName(), pBinder, dir); + /// TypeHandler::bind(pos++, obj.getFirstName(), pBinder, dir); /// TypeHandler::bind(pos++, obj.getAge(), pBinder); /// } /// @@ -118,10 +118,10 @@ class TypeHandler /// Apart from that no further work is needed. One can now use Person with into and use clauses. { public: - static void bind(std::size_t pos, const T& obj, AbstractBinder* pBinder) + static void bind(std::size_t pos, const T& obj, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert_dbg (pBinder != 0); - pBinder->bind(pos, obj); + pBinder->bind(pos, obj, dir); } static std::size_t size() @@ -179,29 +179,29 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); - pBinder->bind(pos++, tuple.template get<7>()); - pBinder->bind(pos++, tuple.template get<8>()); - pBinder->bind(pos++, tuple.template get<9>()); - pBinder->bind(pos++, tuple.template get<10>()); - pBinder->bind(pos++, tuple.template get<11>()); - pBinder->bind(pos++, tuple.template get<12>()); - pBinder->bind(pos++, tuple.template get<13>()); - pBinder->bind(pos++, tuple.template get<14>()); - pBinder->bind(pos++, tuple.template get<15>()); - pBinder->bind(pos++, tuple.template get<16>()); - pBinder->bind(pos++, tuple.template get<17>()); - pBinder->bind(pos++, tuple.template get<18>()); - pBinder->bind(pos++, tuple.template get<19>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); + pBinder->bind(pos++, tuple.template get<7>(), dir); + pBinder->bind(pos++, tuple.template get<8>(), dir); + pBinder->bind(pos++, tuple.template get<9>(), dir); + pBinder->bind(pos++, tuple.template get<10>(), dir); + pBinder->bind(pos++, tuple.template get<11>(), dir); + pBinder->bind(pos++, tuple.template get<12>(), dir); + pBinder->bind(pos++, tuple.template get<13>(), dir); + pBinder->bind(pos++, tuple.template get<14>(), dir); + pBinder->bind(pos++, tuple.template get<15>(), dir); + pBinder->bind(pos++, tuple.template get<16>(), dir); + pBinder->bind(pos++, tuple.template get<17>(), dir); + pBinder->bind(pos++, tuple.template get<18>(), dir); + pBinder->bind(pos++, tuple.template get<19>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -312,28 +312,28 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); - pBinder->bind(pos++, tuple.template get<7>()); - pBinder->bind(pos++, tuple.template get<8>()); - pBinder->bind(pos++, tuple.template get<9>()); - pBinder->bind(pos++, tuple.template get<10>()); - pBinder->bind(pos++, tuple.template get<11>()); - pBinder->bind(pos++, tuple.template get<12>()); - pBinder->bind(pos++, tuple.template get<13>()); - pBinder->bind(pos++, tuple.template get<14>()); - pBinder->bind(pos++, tuple.template get<15>()); - pBinder->bind(pos++, tuple.template get<16>()); - pBinder->bind(pos++, tuple.template get<17>()); - pBinder->bind(pos++, tuple.template get<18>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); + pBinder->bind(pos++, tuple.template get<7>(), dir); + pBinder->bind(pos++, tuple.template get<8>(), dir); + pBinder->bind(pos++, tuple.template get<9>(), dir); + pBinder->bind(pos++, tuple.template get<10>(), dir); + pBinder->bind(pos++, tuple.template get<11>(), dir); + pBinder->bind(pos++, tuple.template get<12>(), dir); + pBinder->bind(pos++, tuple.template get<13>(), dir); + pBinder->bind(pos++, tuple.template get<14>(), dir); + pBinder->bind(pos++, tuple.template get<15>(), dir); + pBinder->bind(pos++, tuple.template get<16>(), dir); + pBinder->bind(pos++, tuple.template get<17>(), dir); + pBinder->bind(pos++, tuple.template get<18>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -440,27 +440,27 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); - pBinder->bind(pos++, tuple.template get<7>()); - pBinder->bind(pos++, tuple.template get<8>()); - pBinder->bind(pos++, tuple.template get<9>()); - pBinder->bind(pos++, tuple.template get<10>()); - pBinder->bind(pos++, tuple.template get<11>()); - pBinder->bind(pos++, tuple.template get<12>()); - pBinder->bind(pos++, tuple.template get<13>()); - pBinder->bind(pos++, tuple.template get<14>()); - pBinder->bind(pos++, tuple.template get<15>()); - pBinder->bind(pos++, tuple.template get<16>()); - pBinder->bind(pos++, tuple.template get<17>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); + pBinder->bind(pos++, tuple.template get<7>(), dir); + pBinder->bind(pos++, tuple.template get<8>(), dir); + pBinder->bind(pos++, tuple.template get<9>(), dir); + pBinder->bind(pos++, tuple.template get<10>(), dir); + pBinder->bind(pos++, tuple.template get<11>(), dir); + pBinder->bind(pos++, tuple.template get<12>(), dir); + pBinder->bind(pos++, tuple.template get<13>(), dir); + pBinder->bind(pos++, tuple.template get<14>(), dir); + pBinder->bind(pos++, tuple.template get<15>(), dir); + pBinder->bind(pos++, tuple.template get<16>(), dir); + pBinder->bind(pos++, tuple.template get<17>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -563,26 +563,26 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); - pBinder->bind(pos++, tuple.template get<7>()); - pBinder->bind(pos++, tuple.template get<8>()); - pBinder->bind(pos++, tuple.template get<9>()); - pBinder->bind(pos++, tuple.template get<10>()); - pBinder->bind(pos++, tuple.template get<11>()); - pBinder->bind(pos++, tuple.template get<12>()); - pBinder->bind(pos++, tuple.template get<13>()); - pBinder->bind(pos++, tuple.template get<14>()); - pBinder->bind(pos++, tuple.template get<15>()); - pBinder->bind(pos++, tuple.template get<16>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); + pBinder->bind(pos++, tuple.template get<7>(), dir); + pBinder->bind(pos++, tuple.template get<8>(), dir); + pBinder->bind(pos++, tuple.template get<9>(), dir); + pBinder->bind(pos++, tuple.template get<10>(), dir); + pBinder->bind(pos++, tuple.template get<11>(), dir); + pBinder->bind(pos++, tuple.template get<12>(), dir); + pBinder->bind(pos++, tuple.template get<13>(), dir); + pBinder->bind(pos++, tuple.template get<14>(), dir); + pBinder->bind(pos++, tuple.template get<15>(), dir); + pBinder->bind(pos++, tuple.template get<16>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -681,25 +681,25 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); - pBinder->bind(pos++, tuple.template get<7>()); - pBinder->bind(pos++, tuple.template get<8>()); - pBinder->bind(pos++, tuple.template get<9>()); - pBinder->bind(pos++, tuple.template get<10>()); - pBinder->bind(pos++, tuple.template get<11>()); - pBinder->bind(pos++, tuple.template get<12>()); - pBinder->bind(pos++, tuple.template get<13>()); - pBinder->bind(pos++, tuple.template get<14>()); - pBinder->bind(pos++, tuple.template get<15>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); + pBinder->bind(pos++, tuple.template get<7>(), dir); + pBinder->bind(pos++, tuple.template get<8>(), dir); + pBinder->bind(pos++, tuple.template get<9>(), dir); + pBinder->bind(pos++, tuple.template get<10>(), dir); + pBinder->bind(pos++, tuple.template get<11>(), dir); + pBinder->bind(pos++, tuple.template get<12>(), dir); + pBinder->bind(pos++, tuple.template get<13>(), dir); + pBinder->bind(pos++, tuple.template get<14>(), dir); + pBinder->bind(pos++, tuple.template get<15>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -794,24 +794,24 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); - pBinder->bind(pos++, tuple.template get<7>()); - pBinder->bind(pos++, tuple.template get<8>()); - pBinder->bind(pos++, tuple.template get<9>()); - pBinder->bind(pos++, tuple.template get<10>()); - pBinder->bind(pos++, tuple.template get<11>()); - pBinder->bind(pos++, tuple.template get<12>()); - pBinder->bind(pos++, tuple.template get<13>()); - pBinder->bind(pos++, tuple.template get<14>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); + pBinder->bind(pos++, tuple.template get<7>(), dir); + pBinder->bind(pos++, tuple.template get<8>(), dir); + pBinder->bind(pos++, tuple.template get<9>(), dir); + pBinder->bind(pos++, tuple.template get<10>(), dir); + pBinder->bind(pos++, tuple.template get<11>(), dir); + pBinder->bind(pos++, tuple.template get<12>(), dir); + pBinder->bind(pos++, tuple.template get<13>(), dir); + pBinder->bind(pos++, tuple.template get<14>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -902,23 +902,23 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); - pBinder->bind(pos++, tuple.template get<7>()); - pBinder->bind(pos++, tuple.template get<8>()); - pBinder->bind(pos++, tuple.template get<9>()); - pBinder->bind(pos++, tuple.template get<10>()); - pBinder->bind(pos++, tuple.template get<11>()); - pBinder->bind(pos++, tuple.template get<12>()); - pBinder->bind(pos++, tuple.template get<13>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); + pBinder->bind(pos++, tuple.template get<7>(), dir); + pBinder->bind(pos++, tuple.template get<8>(), dir); + pBinder->bind(pos++, tuple.template get<9>(), dir); + pBinder->bind(pos++, tuple.template get<10>(), dir); + pBinder->bind(pos++, tuple.template get<11>(), dir); + pBinder->bind(pos++, tuple.template get<12>(), dir); + pBinder->bind(pos++, tuple.template get<13>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -1005,22 +1005,22 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); - pBinder->bind(pos++, tuple.template get<7>()); - pBinder->bind(pos++, tuple.template get<8>()); - pBinder->bind(pos++, tuple.template get<9>()); - pBinder->bind(pos++, tuple.template get<10>()); - pBinder->bind(pos++, tuple.template get<11>()); - pBinder->bind(pos++, tuple.template get<12>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); + pBinder->bind(pos++, tuple.template get<7>(), dir); + pBinder->bind(pos++, tuple.template get<8>(), dir); + pBinder->bind(pos++, tuple.template get<9>(), dir); + pBinder->bind(pos++, tuple.template get<10>(), dir); + pBinder->bind(pos++, tuple.template get<11>(), dir); + pBinder->bind(pos++, tuple.template get<12>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -1103,21 +1103,21 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); - pBinder->bind(pos++, tuple.template get<7>()); - pBinder->bind(pos++, tuple.template get<8>()); - pBinder->bind(pos++, tuple.template get<9>()); - pBinder->bind(pos++, tuple.template get<10>()); - pBinder->bind(pos++, tuple.template get<11>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); + pBinder->bind(pos++, tuple.template get<7>(), dir); + pBinder->bind(pos++, tuple.template get<8>(), dir); + pBinder->bind(pos++, tuple.template get<9>(), dir); + pBinder->bind(pos++, tuple.template get<10>(), dir); + pBinder->bind(pos++, tuple.template get<11>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -1196,20 +1196,20 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); - pBinder->bind(pos++, tuple.template get<7>()); - pBinder->bind(pos++, tuple.template get<8>()); - pBinder->bind(pos++, tuple.template get<9>()); - pBinder->bind(pos++, tuple.template get<10>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); + pBinder->bind(pos++, tuple.template get<7>(), dir); + pBinder->bind(pos++, tuple.template get<8>(), dir); + pBinder->bind(pos++, tuple.template get<9>(), dir); + pBinder->bind(pos++, tuple.template get<10>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -1275,19 +1275,19 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); - pBinder->bind(pos++, tuple.template get<7>()); - pBinder->bind(pos++, tuple.template get<8>()); - pBinder->bind(pos++, tuple.template get<9>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); + pBinder->bind(pos++, tuple.template get<7>(), dir); + pBinder->bind(pos++, tuple.template get<8>(), dir); + pBinder->bind(pos++, tuple.template get<9>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -1350,18 +1350,18 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); - pBinder->bind(pos++, tuple.template get<7>()); - pBinder->bind(pos++, tuple.template get<8>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); + pBinder->bind(pos++, tuple.template get<7>(), dir); + pBinder->bind(pos++, tuple.template get<8>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -1421,17 +1421,17 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); - pBinder->bind(pos++, tuple.template get<7>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); + pBinder->bind(pos++, tuple.template get<7>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -1488,16 +1488,16 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); - pBinder->bind(pos++, tuple.template get<6>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); + pBinder->bind(pos++, tuple.template get<6>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -1551,15 +1551,15 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); - pBinder->bind(pos++, tuple.template get<5>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); + pBinder->bind(pos++, tuple.template get<5>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -1610,14 +1610,14 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); - pBinder->bind(pos++, tuple.template get<4>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); + pBinder->bind(pos++, tuple.template get<4>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -1665,13 +1665,13 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); - pBinder->bind(pos++, tuple.template get<3>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); + pBinder->bind(pos++, tuple.template get<3>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -1716,12 +1716,12 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); - pBinder->bind(pos++, tuple.template get<2>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); + pBinder->bind(pos++, tuple.template get<2>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -1763,11 +1763,11 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); - pBinder->bind(pos++, tuple.template get<1>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); + pBinder->bind(pos++, tuple.template get<1>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) @@ -1806,10 +1806,10 @@ public: typedef typename Poco::TypeWrapper >::CONSTREFTYPE TupleConstRef; typedef typename Poco::TypeWrapper >::REFTYPE TupleRef; - static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder) + static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder* pBinder, AbstractBinder::Direction dir) { poco_assert (pBinder != 0); - pBinder->bind(pos++, tuple.template get<0>()); + pBinder->bind(pos++, tuple.template get<0>(), dir); } static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) diff --git a/Data/src/AbstractBinder.cpp b/Data/src/AbstractBinder.cpp index 068e6e19c..41e5f42ab 100644 --- a/Data/src/AbstractBinder.cpp +++ b/Data/src/AbstractBinder.cpp @@ -41,9 +41,7 @@ namespace Poco { namespace Data { -AbstractBinder::AbstractBinder(): - _inBound(true), - _outBound(false) +AbstractBinder::AbstractBinder() { } diff --git a/Data/src/AbstractBinding.cpp b/Data/src/AbstractBinding.cpp index 14757f290..1e212179f 100644 --- a/Data/src/AbstractBinding.cpp +++ b/Data/src/AbstractBinding.cpp @@ -41,10 +41,10 @@ namespace Poco { namespace Data { -AbstractBinding::AbstractBinding(): +AbstractBinding::AbstractBinding(const std::string& name, Direction direction): _pBinder(0), - _inBound(true), - _outBound(false) + _name(name), + _direction(direction) { } @@ -54,4 +54,11 @@ AbstractBinding::~AbstractBinding() } +void AbstractBinding::setBinder(AbstractBinder* pBinder) +{ + poco_check_ptr (pBinder); + _pBinder = pBinder; +} + + } } // namespace Poco::Data diff --git a/Data/testsuite/src/Binder.cpp b/Data/testsuite/src/Binder.cpp index baf8225e9..8593ddb4d 100644 --- a/Data/testsuite/src/Binder.cpp +++ b/Data/testsuite/src/Binder.cpp @@ -50,77 +50,82 @@ Binder::~Binder() } -void Binder::bind(std::size_t pos, const Poco::Int8 &val) +void Binder::bind(std::size_t pos, const Poco::Int8 &val, Direction dir) { } -void Binder::bind(std::size_t pos, const Poco::UInt8 &val) +void Binder::bind(std::size_t pos, const Poco::UInt8 &val, Direction dir) { } -void Binder::bind(std::size_t pos, const Poco::Int16 &val) +void Binder::bind(std::size_t pos, const Poco::Int16 &val, Direction dir) { } -void Binder::bind(std::size_t pos, const Poco::UInt16 &val) +void Binder::bind(std::size_t pos, const Poco::UInt16 &val, Direction dir) { } -void Binder::bind(std::size_t pos, const Poco::Int32 &val) +void Binder::bind(std::size_t pos, const Poco::Int32 &val, Direction dir) { } -void Binder::bind(std::size_t pos, const Poco::UInt32 &val) +void Binder::bind(std::size_t pos, const Poco::UInt32 &val, Direction dir) { } -void Binder::bind(std::size_t pos, const Poco::Int64 &val) +void Binder::bind(std::size_t pos, const Poco::Int64 &val, Direction dir) { } -void Binder::bind(std::size_t pos, const Poco::UInt64 &val) +void Binder::bind(std::size_t pos, const Poco::UInt64 &val, Direction dir) { } -void Binder::bind(std::size_t pos, const bool &val) +void Binder::bind(std::size_t pos, const bool &val, Direction dir) { } -void Binder::bind(std::size_t pos, const float &val) +void Binder::bind(std::size_t pos, const float &val, Direction dir) { } -void Binder::bind(std::size_t pos, const double &val) +void Binder::bind(std::size_t pos, const double &val, Direction dir) { } -void Binder::bind(std::size_t pos, const char &val) +void Binder::bind(std::size_t pos, const char &val, Direction dir) { } -void Binder::bind(std::size_t pos, const char* const &pVal) +void Binder::bind(std::size_t pos, const char* const &pVal, Direction dir) { } -void Binder::bind(std::size_t pos, const std::string& val) +void Binder::bind(std::size_t pos, const std::string& val, Direction dir) { } -void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val) +void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir) +{ +} + + +void Binder::bind(std::size_t pos, const Poco::DateTime& val, Direction dir) { } diff --git a/Data/testsuite/src/Binder.h b/Data/testsuite/src/Binder.h index 4db36d879..80ba67603 100644 --- a/Data/testsuite/src/Binder.h +++ b/Data/testsuite/src/Binder.h @@ -54,51 +54,54 @@ public: ~Binder(); /// Destroys the Binder. - void bind(std::size_t pos, const Poco::Int8 &val); + void bind(std::size_t pos, const Poco::Int8 &val, Direction dir = PD_IN); /// Binds an Int8. - void bind(std::size_t pos, const Poco::UInt8 &val); + void bind(std::size_t pos, const Poco::UInt8 &val, Direction dir = PD_IN); /// Binds an UInt8. - void bind(std::size_t pos, const Poco::Int16 &val); + void bind(std::size_t pos, const Poco::Int16 &val, Direction dir = PD_IN); /// Binds an Int16. - void bind(std::size_t pos, const Poco::UInt16 &val); + void bind(std::size_t pos, const Poco::UInt16 &val, Direction dir = PD_IN); /// Binds an UInt16. - void bind(std::size_t pos, const Poco::Int32 &val); + void bind(std::size_t pos, const Poco::Int32 &val, Direction dir = PD_IN); /// Binds an Int32. - void bind(std::size_t pos, const Poco::UInt32 &val); + void bind(std::size_t pos, const Poco::UInt32 &val, Direction dir = PD_IN); /// Binds an UInt32. - void bind(std::size_t pos, const Poco::Int64 &val); + void bind(std::size_t pos, const Poco::Int64 &val, Direction dir = PD_IN); /// Binds an Int64. - void bind(std::size_t pos, const Poco::UInt64 &val); + void bind(std::size_t pos, const Poco::UInt64 &val, Direction dir = PD_IN); /// Binds an UInt64. - void bind(std::size_t pos, const bool &val); + void bind(std::size_t pos, const bool &val, Direction dir = PD_IN); /// Binds a boolean. - void bind(std::size_t pos, const float &val); + void bind(std::size_t pos, const float &val, Direction dir = PD_IN); /// Binds a float. - void bind(std::size_t pos, const double &val); + void bind(std::size_t pos, const double &val, Direction dir = PD_IN); /// Binds a double. - void bind(std::size_t pos, const char &val); + void bind(std::size_t pos, const char &val, Direction dir = PD_IN); /// Binds a single character. - void bind(std::size_t pos, const char* const &pVal); + void bind(std::size_t pos, const char* const &pVal, Direction dir = PD_IN); /// Binds a const char ptr. - void bind(std::size_t pos, const std::string& val); + void bind(std::size_t pos, const std::string& val, Direction dir = PD_IN); /// Binds a string. - void bind(std::size_t pos, const Poco::Data::BLOB& val); + void bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir = PD_IN); /// Binds a BLOB. + void bind(std::size_t pos, const Poco::DateTime& val, Direction dir = PD_IN); + /// Binds a DateTime. + void reset(); }; diff --git a/Data/testsuite/src/Extractor.cpp b/Data/testsuite/src/Extractor.cpp index 470842bfe..52efff3cf 100644 --- a/Data/testsuite/src/Extractor.cpp +++ b/Data/testsuite/src/Extractor.cpp @@ -146,5 +146,10 @@ bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val) return true; } +bool Extractor::extract(std::size_t pos, Poco::DateTime& val) +{ + return true; +} + } } } // namespace Poco::Data::Test diff --git a/Data/testsuite/src/Extractor.h b/Data/testsuite/src/Extractor.h index 94da80127..ba47b0240 100644 --- a/Data/testsuite/src/Extractor.h +++ b/Data/testsuite/src/Extractor.h @@ -96,6 +96,9 @@ public: bool extract(std::size_t pos, Poco::Data::BLOB& val); /// Extracts a BLOB. + bool extract(std::size_t pos, Poco::DateTime& val); + /// Extracts a DateTime. + void reset(); }; diff --git a/Data/testsuite/src/Preparation.cpp b/Data/testsuite/src/Preparation.cpp index bb8d58f97..d0fc0e0cc 100644 --- a/Data/testsuite/src/Preparation.cpp +++ b/Data/testsuite/src/Preparation.cpp @@ -120,6 +120,11 @@ void Preparation::prepare(std::size_t pos, const Poco::Data::BLOB&) } +void Preparation::prepare(std::size_t pos, const Poco::DateTime&) +{ +} + + void Preparation::prepare(std::size_t pos, const Poco::Any&) { } diff --git a/Data/testsuite/src/Preparation.h b/Data/testsuite/src/Preparation.h index 8ad85032b..de50d7c2d 100644 --- a/Data/testsuite/src/Preparation.h +++ b/Data/testsuite/src/Preparation.h @@ -97,6 +97,9 @@ public: void prepare(std::size_t pos, const Poco::Data::BLOB&); /// Extracts a BLOB. + void prepare(std::size_t pos, const Poco::DateTime&); + /// Extracts a DateTime. + void prepare(std::size_t pos, const Poco::Any&); /// Extracts an Any. };