Преглед на файлове

DateTime binding (work in progress)

Aleksandar Fabijanic преди 19 години
родител
ревизия
0bde32efac

+ 1 - 1
Data/ODBC/Makefile

@@ -16,7 +16,7 @@ else
 $(error No ODBC library found. Please install unixODBC or iODBC and try again)
 endif
 
-objects = Binder ConnectionHandle DataTypes EnvironmentHandle \
+objects = Binder ConnectionHandle TypeInfo EnvironmentHandle \
 	Extractor ODBCColumn ODBCException ODBCStatementImpl Parameter Preparation \
 	SessionImpl Connector Utility 
 

+ 2 - 2
Data/ODBC/ODBC_VS71.vcproj

@@ -158,7 +158,7 @@
 					RelativePath=".\include\Poco\Data\Odbc\Connector.h">
 				</File>
 				<File
-					RelativePath=".\include\Poco\Data\Odbc\DataTypes.h">
+					RelativePath=".\include\Poco\Data\Odbc\TypeInfo.h">
 				</File>
 				<File
 					RelativePath=".\include\Poco\Data\Odbc\Diagnostics.h">
@@ -213,7 +213,7 @@
 					RelativePath=".\src\Connector.cpp">
 				</File>
 				<File
-					RelativePath=".\src\DataTypes.cpp">
+					RelativePath=".\src\TypeInfo.cpp">
 				</File>
 				<File
 					RelativePath=".\src\EnvironmentHandle.cpp">

+ 8 - 8
Data/ODBC/ODBC_VS80.vcproj

@@ -221,10 +221,6 @@
 					RelativePath=".\include\Poco\Data\ODBC\Connector.h"
 					>
 				</File>
-				<File
-					RelativePath=".\include\Poco\Data\ODBC\DataTypes.h"
-					>
-				</File>
 				<File
 					RelativePath=".\include\Poco\Data\ODBC\Diagnostics.h"
 					>
@@ -273,6 +269,10 @@
 					RelativePath=".\include\Poco\Data\ODBC\SessionImpl.h"
 					>
 				</File>
+				<File
+					RelativePath=".\include\Poco\Data\ODBC\TypeInfo.h"
+					>
+				</File>
 				<File
 					RelativePath=".\include\Poco\Data\ODBC\Utility.h"
 					>
@@ -293,10 +293,6 @@
 					RelativePath=".\src\Connector.cpp"
 					>
 				</File>
-				<File
-					RelativePath=".\src\DataTypes.cpp"
-					>
-				</File>
 				<File
 					RelativePath=".\src\EnvironmentHandle.cpp"
 					>
@@ -329,6 +325,10 @@
 					RelativePath=".\src\SessionImpl.cpp"
 					>
 				</File>
+				<File
+					RelativePath=".\src\TypeInfo.cpp"
+					>
+				</File>
 				<File
 					RelativePath=".\src\Utility.cpp"
 					>

+ 4 - 1
Data/ODBC/include/Poco/Data/ODBC/Binder.h

@@ -47,6 +47,7 @@
 #include "Poco/Data/ODBC/Parameter.h"
 #include "Poco/Data/ODBC/ODBCColumn.h"
 #include "Poco/Data/ODBC/Utility.h"
+#include "Poco/Data/ODBC/TypeInfo.h"
 #include "Poco/DateTime.h"
 #include "Poco/Exception.h"
 #include <vector>
@@ -79,7 +80,8 @@ public:
 	};
 
 	Binder(const StatementHandle& rStmt,
-		ParameterBinding dataBinding = PB_IMMEDIATE);
+		ParameterBinding dataBinding = PB_IMMEDIATE,
+		TypeInfo* pDataTypes = 0);
 		/// Creates the Binder.
 
 	~Binder();
@@ -204,6 +206,7 @@ private:
 	SizeMap _dataSize;
 	ParameterBinding _paramBinding;
 	TimestampMap _timestamps;
+	const TypeInfo* _pTypeInfo;
 };
 
 

+ 23 - 2
Data/ODBC/include/Poco/Data/ODBC/SessionImpl.h

@@ -41,6 +41,7 @@
 
 
 #include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/ODBC/TypeInfo.h"
 #include "Poco/Data/ODBC/Binder.h"
 #include "Poco/Data/ODBC/Handle.h"
 #include "Poco/Data/ODBC/ODBCException.h"
@@ -133,14 +134,21 @@ public:
 	const ConnectionHandle& dbc() const;
 		/// Returns the connection handle.
 
+	Poco::Any dataTypeInfo(const std::string& rName="");
+		/// Returns the data types information.
+
 private:
+	void setDataTypeInfo(const std::string& rName, const Poco::Any& rValue);
+		/// No-op. Throws InvalidAccessException.
+
 	static const int FUNCTIONS = SQL_API_ODBC3_ALL_FUNCTIONS_SIZE;
 
 	void open();
 		/// Opens a connection to the Database
 
-	bool isCapable();
-		/// Returns true if driver supports all required functions.
+	bool isCapable(int function = 0);
+		/// Returns true if driver supports specified function, or if
+		/// specified function is zero, all required functions.
 		/// Called upon succesful connection if _enforceCapability is true.
 		/// This function code should be updated whenever a new 
 		/// ODBC API call is introduced anywhere in ODBC data connector.
@@ -153,6 +161,7 @@ private:
 	bool _enforceCapability;
 	bool _autoBind;
 	bool _autoExtract;
+	TypeInfo _dataTypes;
 };
 
 
@@ -198,6 +207,18 @@ inline Poco::Any SessionImpl::getMaxFieldSize(const std::string& rName)
 }
 
 
+inline void SessionImpl::setDataTypeInfo(const std::string& rName, const Poco::Any& rValue)
+{
+	throw InvalidAccessException();
+}
+
+		
+inline Poco::Any SessionImpl::dataTypeInfo(const std::string& rName)
+{
+	return &_dataTypes;
+}
+
+
 } } } // namespace Poco::Data::ODBC
 
 

+ 59 - 11
Data/ODBC/include/Poco/Data/ODBC/DataTypes.h → Data/ODBC/include/Poco/Data/ODBC/TypeInfo.h

@@ -1,13 +1,13 @@
 //
-// DataTypes.h
+// TypeInfo.h
 //
-// $Id: //poco/Main/Data/ODBC/include/Poco/Data/ODBC/DataTypes.h#3 $
+// $Id: //poco/Main/Data/ODBC/include/Poco/Data/ODBC/TypeInfo.h#3 $
 //
 // Library: ODBC
 // Package: ODBC
-// Module:  DataTypes
+// Module:  TypeInfo
 //
-// Definition of DataTypes.
+// Definition of TypeInfo.
 //
 // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
 // and Contributors.
@@ -41,6 +41,9 @@
 
 
 #include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/NamedTuple.h"
+#include "Poco/DynamicAny.h"
+#include <vector>
 #include <map>
 #ifdef POCO_OS_FAMILY_WINDOWS
 #include <windows.h>
@@ -53,18 +56,38 @@ namespace Data {
 namespace ODBC {
 
 
-class ODBC_API DataTypes
+class ODBC_API TypeInfo
 	/// C <==> SQL datatypes mapping utility class.
 {
 public:
 	typedef std::map<int, int> DataTypeMap;
 	typedef DataTypeMap::value_type ValueType;
-
-	DataTypes();
-		/// Creates the DataTypes.
-
-	~DataTypes();
-		/// Destroys the DataTypes.
+	typedef Poco::NamedTuple<std::string,
+		SQLSMALLINT,
+		SQLINTEGER,
+		std::string,
+		std::string,
+		std::string,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		std::string,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLINTEGER,
+		SQLSMALLINT> TypeInfoTup;
+	typedef std::vector<TypeInfoTup> TypeInfoVec;
+
+	explicit TypeInfo(SQLHDBC* pHDBC=0);
+		/// Creates the TypeInfo.
+
+	~TypeInfo();
+		/// Destroys the TypeInfo.
 
 	int cDataType(int sqlDataType) const;
 		/// Returns C data type corresponding to supplied SQL data type.
@@ -72,12 +95,37 @@ public:
 	int sqlDataType(int cDataType) const;
 		/// Returns SQL data type corresponding to supplied C data type.
 
+	void fillTypeInfo(SQLHDBC pHDBC);
+		/// Fills the data type info structure for the database.
+
+	DynamicAny getInfo(SQLSMALLINT type, const std::string& param) const;
+		/// Returns information about specified data type.
+
 private:
+	void fillCTypes();
+	void fillSQLTypes();
+
 	DataTypeMap _cDataTypes; 
 	DataTypeMap _sqlDataTypes; 
+	TypeInfoVec _typeInfo;
+	SQLHDBC*    _pHDBC;
 };
 
 
+inline DynamicAny TypeInfo::getInfo(SQLSMALLINT type, const std::string& param) const
+{
+	TypeInfoVec::const_iterator it = _typeInfo.begin();
+	TypeInfoVec::const_iterator end = _typeInfo.end();
+	for (; it != end; ++it)
+	{
+		if (type == it->get<1>())
+			return (*it)[param];
+	}
+
+	throw NotFoundException(param);
+}
+
+
 } } } // namespace Poco::Data::ODBC
 
 

+ 3 - 2
Data/ODBC/include/Poco/Data/ODBC/Utility.h

@@ -41,9 +41,10 @@
 
 
 #include "Poco/Data/ODBC/ODBC.h"
-#include "Poco/Data/ODBC/DataTypes.h"
+#include "Poco/Data/ODBC/TypeInfo.h"
 #include "Poco/DateTime.h"
 #include <sstream>
+#include <map>
 #ifdef POCO_OS_FAMILY_WINDOWS
 #include <windows.h>
 #endif
@@ -104,7 +105,7 @@ public:
 		/// ODBC size for bool data type.
 
 private:
-	static const DataTypes _dataTypes;
+	static const TypeInfo _dataTypes;
 		/// C <==> SQL data type mapping
 };
 

+ 20 - 5
Data/ODBC/src/Binder.cpp

@@ -48,9 +48,12 @@ namespace Data {
 namespace ODBC {
 
 
-Binder::Binder(const StatementHandle& rStmt, Binder::ParameterBinding dataBinding):
+Binder::Binder(const StatementHandle& rStmt, 
+	Binder::ParameterBinding dataBinding,
+	TypeInfo* pDataTypes):
 	_rStmt(rStmt),
-	_paramBinding(dataBinding)
+	_paramBinding(dataBinding),
+	_pTypeInfo(pDataTypes)
 {
 }
 
@@ -146,15 +149,27 @@ void Binder::bind(std::size_t pos, const Poco::DateTime& val)
 	_timestamps.insert(TimestampMap::value_type(pTS, const_cast<DateTime*>(&val)));
 	_dataSize.insert(SizeMap::value_type((SQLPOINTER) pTS, size));
 
+	SQLINTEGER colSize = 0;
+	SQLSMALLINT decDigits = 0;
+
+	if (_pTypeInfo)
+	{
+		try
+		{
+			colSize = _pTypeInfo->getInfo(SQL_TIMESTAMP, "COLUMN_SIZE");
+			decDigits = _pTypeInfo->getInfo(SQL_TIMESTAMP, "MINIMUM_SCALE");
+		}catch (NotFoundException&) { }
+	}
+
 	if (Utility::isError(SQLBindParameter(_rStmt, 
 		(SQLUSMALLINT) pos + 1, 
 		getParamType(), 
 		SQL_C_TIMESTAMP, 
 		SQL_TIMESTAMP, 
-		(SQLUINTEGER) size,
-		0,
+		colSize,
+		decDigits,
 		(SQLPOINTER) pTS, 
-		(SQLINTEGER) size, 
+		0, 
 		_lengthIndicator.back())))
 	{
 		throw StatementException(_rStmt, "SQLBindParameter(BLOB)");

+ 0 - 118
Data/ODBC/src/DataTypes.cpp

@@ -1,118 +0,0 @@
-//
-// DataTypes.cpp
-//
-// $Id: //poco/Main/Data/ODBC/src/DataTypes.cpp#3 $
-//
-// Library: ODBC
-// Package: ODBC
-// Module:  DataTypes
-//
-// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
-// and Contributors.
-//
-// Permission is hereby granted, free of charge, to any person or organization
-// obtaining a copy of the software and accompanying documentation covered by
-// this license (the "Software") to use, reproduce, display, distribute,
-// execute, and transmit the Software, and to prepare derivative works of the
-// Software, and to permit third-parties to whom the Software is furnished to
-// do so, all subject to the following:
-// 
-// The copyright notices in the Software and this entire statement, including
-// the above license grant, this restriction and the following disclaimer,
-// must be included in all copies of the Software, in whole or in part, and
-// all derivative works of the Software, unless such copies or derivative
-// works are solely in the form of machine-executable object code generated by
-// a source language processor.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
-// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
-// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
-// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-//
-
-
-#include "Poco/Data/ODBC/DataTypes.h"
-#include "Poco/Format.h"
-#include "Poco/Exception.h"
-
-
-namespace Poco {
-namespace Data {
-namespace ODBC {
-
-
-DataTypes::DataTypes()
-{
-	_cDataTypes.insert(ValueType(SQL_CHAR, SQL_C_CHAR));
-	_cDataTypes.insert(ValueType(SQL_VARCHAR, SQL_C_CHAR));
-	_cDataTypes.insert(ValueType(SQL_LONGVARCHAR, SQL_C_CHAR));
-	_cDataTypes.insert(ValueType(SQL_DECIMAL, SQL_C_SLONG));
-	_cDataTypes.insert(ValueType(SQL_NUMERIC, SQL_C_DOUBLE));
-	_cDataTypes.insert(ValueType(SQL_BIT, SQL_C_BIT));
-	_cDataTypes.insert(ValueType(SQL_TINYINT, SQL_C_STINYINT));
-	_cDataTypes.insert(ValueType(SQL_SMALLINT, SQL_C_SSHORT));
-	_cDataTypes.insert(ValueType(SQL_INTEGER, SQL_C_SLONG));
-	_cDataTypes.insert(ValueType(SQL_BIGINT, SQL_C_SBIGINT));
-	_cDataTypes.insert(ValueType(SQL_REAL, SQL_C_FLOAT));
-	_cDataTypes.insert(ValueType(SQL_FLOAT, SQL_C_DOUBLE));
-	_cDataTypes.insert(ValueType(SQL_DOUBLE, SQL_C_DOUBLE));
-	_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_TYPE_DATE, SQL_C_TYPE_DATE));
-	_cDataTypes.insert(ValueType(SQL_TYPE_TIME, SQL_C_TYPE_TIME));
-	_cDataTypes.insert(ValueType(SQL_TYPE_TIMESTAMP, SQL_C_TYPE_TIMESTAMP));
-
-	_sqlDataTypes.insert(ValueType(SQL_C_CHAR, SQL_LONGVARCHAR));
-	_sqlDataTypes.insert(ValueType(SQL_C_BIT, SQL_BIT));
-	_sqlDataTypes.insert(ValueType(SQL_C_TINYINT, SQL_TINYINT));
-	_sqlDataTypes.insert(ValueType(SQL_C_STINYINT, SQL_TINYINT));
-	_sqlDataTypes.insert(ValueType(SQL_C_UTINYINT, SQL_TINYINT));
-	_sqlDataTypes.insert(ValueType(SQL_C_SHORT, SQL_SMALLINT));
-	_sqlDataTypes.insert(ValueType(SQL_C_SSHORT, SQL_SMALLINT));
-	_sqlDataTypes.insert(ValueType(SQL_C_USHORT, SQL_SMALLINT));
-	_sqlDataTypes.insert(ValueType(SQL_C_LONG, SQL_INTEGER));
-	_sqlDataTypes.insert(ValueType(SQL_C_SLONG, SQL_INTEGER));
-	_sqlDataTypes.insert(ValueType(SQL_C_ULONG, SQL_INTEGER));
-	_sqlDataTypes.insert(ValueType(SQL_C_SBIGINT, SQL_BIGINT));
-	_sqlDataTypes.insert(ValueType(SQL_C_UBIGINT, SQL_BIGINT));
-	_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_TYPE_DATE, SQL_TYPE_DATE));
-	_sqlDataTypes.insert(ValueType(SQL_C_TYPE_TIME, SQL_TYPE_TIME));
-	_sqlDataTypes.insert(ValueType(SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP));
-}
-
-
-DataTypes::~DataTypes()
-{
-}
-
-
-int DataTypes::cDataType(int sqlDataType) const
-{
-	DataTypeMap::const_iterator it = _cDataTypes.find(sqlDataType);
-
-	if (_cDataTypes.end() == it)
-		throw NotFoundException(format("C data type not found for SQL data type: %d", sqlDataType));
-
-	return it->second;
-}
-
-
-int DataTypes::sqlDataType(int cDataType) const
-{
-	DataTypeMap::const_iterator it = _sqlDataTypes.find(cDataType);
-
-	if (_sqlDataTypes.end() == it)
-		throw NotFoundException(format("SQL data type not found for C data type: %d", cDataType));
-
-	return it->second;
-}
-
-
-} } } // namespace Poco::Data::ODBC

+ 8 - 1
Data/ODBC/src/ODBCStatementImpl.cpp

@@ -109,7 +109,14 @@ void ODBCStatementImpl::compileImpl()
 	Binder::ParameterBinding bind = session().getFeature("autoBind") ? 
 		Binder::PB_IMMEDIATE : Binder::PB_AT_EXEC;
 
-	_pBinder = new Binder(_stmt, bind);
+	TypeInfo* pDT = 0;
+	try
+	{
+		Poco::Any dti = session().getProperty("dataTypeInfo");
+		pDT = AnyCast<TypeInfo*>(dti);
+	}catch (NotSupportedException&) { }
+
+	_pBinder = new Binder(_stmt, bind, pDT);
 	_pExtractor = new Extractor(_stmt, *_pPreparation);
 
 	bool dataAvailable = hasData();

+ 9 - 2
Data/ODBC/src/SessionImpl.cpp

@@ -98,6 +98,11 @@ void SessionImpl::open()
 		throw exc;
 	}
 
+	_dataTypes.fillTypeInfo(_db);
+		addProperty("dataTypeInfo", 
+		&SessionImpl::setDataTypeInfo, 
+		&SessionImpl::dataTypeInfo);
+
 	addFeature("enforceCapability", 
 		&SessionImpl::setEnforceCapability, 
 		&SessionImpl::getEnforceCapability);
@@ -189,7 +194,7 @@ void SessionImpl::close()
 }
 
 
-bool SessionImpl::isCapable()
+bool SessionImpl::isCapable(int function)
 {
 	SQLUSMALLINT exists[FUNCTIONS] = {0};
 
@@ -199,7 +204,8 @@ bool SessionImpl::isCapable()
 			"SQLGetFunctions(SQL_API_ODBC3_ALL_FUNCTIONS)");
 	}
 
-	return 
+	if (0 != function) return 0 != exists[function];
+	else return 
 		exists[SQL_API_SQLBINDPARAMETER]  &&
 		exists[SQL_API_SQLBINDCOL]        &&
 		exists[SQL_API_SQLGETDATA]        &&
@@ -208,6 +214,7 @@ bool SessionImpl::isCapable()
 		exists[SQL_API_SQLDESCRIBECOL]    &&
 		exists[SQL_API_SQLDESCRIBEPARAM]  &&
 		exists[SQL_API_SQLGETINFO]        &&
+		exists[SQL_API_SQLGETTYPEINFO]    &&
 		exists[SQL_API_SQLGETDIAGREC]     &&
 		exists[SQL_API_SQLGETDIAGFIELD]   &&
 		exists[SQL_API_SQLPREPARE]        &&

+ 216 - 0
Data/ODBC/src/TypeInfo.cpp

@@ -0,0 +1,216 @@
+//
+// TypeInfo.cpp
+//
+// $Id: //poco/Main/Data/ODBC/src/TypeInfo.cpp#3 $
+//
+// Library: ODBC
+// Package: ODBC
+// Module:  TypeInfo
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+// 
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#include "Poco/Data/ODBC/TypeInfo.h"
+#include "Poco/Data/ODBC/ODBCException.h"
+#include "Poco/Format.h"
+#include "Poco/Exception.h"
+#include <iostream>
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+TypeInfo::TypeInfo(SQLHDBC* pHDBC): _pHDBC(pHDBC)
+{
+	fillCTypes();
+	fillSQLTypes();
+	if (_pHDBC) fillTypeInfo(*_pHDBC);
+}
+
+
+TypeInfo::~TypeInfo()
+{
+}
+
+
+void TypeInfo::fillCTypes()
+{
+	_cDataTypes.insert(ValueType(SQL_CHAR, SQL_C_CHAR));
+	_cDataTypes.insert(ValueType(SQL_VARCHAR, SQL_C_CHAR));
+	_cDataTypes.insert(ValueType(SQL_LONGVARCHAR, SQL_C_CHAR));
+	_cDataTypes.insert(ValueType(SQL_DECIMAL, SQL_C_SLONG));
+	_cDataTypes.insert(ValueType(SQL_NUMERIC, SQL_C_DOUBLE));
+	_cDataTypes.insert(ValueType(SQL_BIT, SQL_C_BIT));
+	_cDataTypes.insert(ValueType(SQL_TINYINT, SQL_C_STINYINT));
+	_cDataTypes.insert(ValueType(SQL_SMALLINT, SQL_C_SSHORT));
+	_cDataTypes.insert(ValueType(SQL_INTEGER, SQL_C_SLONG));
+	_cDataTypes.insert(ValueType(SQL_BIGINT, SQL_C_SBIGINT));
+	_cDataTypes.insert(ValueType(SQL_REAL, SQL_C_FLOAT));
+	_cDataTypes.insert(ValueType(SQL_FLOAT, SQL_C_DOUBLE));
+	_cDataTypes.insert(ValueType(SQL_DOUBLE, SQL_C_DOUBLE));
+	_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));
+}
+
+
+void TypeInfo::fillSQLTypes()
+{
+	_sqlDataTypes.insert(ValueType(SQL_C_CHAR, SQL_LONGVARCHAR));
+	_sqlDataTypes.insert(ValueType(SQL_C_BIT, SQL_BIT));
+	_sqlDataTypes.insert(ValueType(SQL_C_TINYINT, SQL_TINYINT));
+	_sqlDataTypes.insert(ValueType(SQL_C_STINYINT, SQL_TINYINT));
+	_sqlDataTypes.insert(ValueType(SQL_C_UTINYINT, SQL_TINYINT));
+	_sqlDataTypes.insert(ValueType(SQL_C_SHORT, SQL_SMALLINT));
+	_sqlDataTypes.insert(ValueType(SQL_C_SSHORT, SQL_SMALLINT));
+	_sqlDataTypes.insert(ValueType(SQL_C_USHORT, SQL_SMALLINT));
+	_sqlDataTypes.insert(ValueType(SQL_C_LONG, SQL_INTEGER));
+	_sqlDataTypes.insert(ValueType(SQL_C_SLONG, SQL_INTEGER));
+	_sqlDataTypes.insert(ValueType(SQL_C_ULONG, SQL_INTEGER));
+	_sqlDataTypes.insert(ValueType(SQL_C_SBIGINT, SQL_BIGINT));
+	_sqlDataTypes.insert(ValueType(SQL_C_UBIGINT, SQL_BIGINT));
+	_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));
+}
+
+
+void TypeInfo::fillTypeInfo(SQLHDBC pHDBC)
+{
+	_pHDBC = &pHDBC;
+
+	if (_typeInfo.empty() && _pHDBC)
+	{
+		const static int stringSize = 512;
+		TypeInfoVec().swap(_typeInfo);
+
+		SQLRETURN rc;
+		SQLHSTMT hstmt = SQL_NULL_HSTMT;
+
+		rc = SQLAllocHandle(SQL_HANDLE_STMT, *_pHDBC, &hstmt);
+		if (!SQL_SUCCEEDED(rc))
+			throw StatementException(hstmt, "SQLGetData()");
+
+		DataTypeMap::const_iterator it = _cDataTypes.begin();
+		DataTypeMap::const_iterator end = _cDataTypes.end();
+
+		for(; it != end; ++it)
+		{
+			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))
+			{
+				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);
+				rc = SQLGetData(hstmt, 3, SQL_C_SLONG, &ti.get<2>(), sizeof(SQLINTEGER), 0);
+				rc = SQLGetData(hstmt, 4, SQL_C_CHAR, literalPrefix, sizeof(literalPrefix), 0);
+				ti.set<3>(literalPrefix);
+				rc = SQLGetData(hstmt, 5, SQL_C_CHAR, literalSuffix, sizeof(literalSuffix), 0);
+				ti.set<4>(literalSuffix);
+				rc = SQLGetData(hstmt, 6, SQL_C_CHAR, createParams, sizeof(createParams), 0);
+				ti.set<5>(createParams);
+				rc = SQLGetData(hstmt, 7, SQL_C_SSHORT, &ti.get<6>(), sizeof(SQLSMALLINT), 0); 
+				rc = SQLGetData(hstmt, 8, SQL_C_SSHORT, &ti.get<7>(), sizeof(SQLSMALLINT), 0); 
+				rc = SQLGetData(hstmt, 9, SQL_C_SSHORT, &ti.get<8>(), sizeof(SQLSMALLINT), 0); 
+				rc = SQLGetData(hstmt, 10, SQL_C_SSHORT, &ti.get<9>(), sizeof(SQLSMALLINT), 0); 
+				rc = SQLGetData(hstmt, 11, SQL_C_SSHORT, &ti.get<10>(), sizeof(SQLSMALLINT), 0);
+				rc = SQLGetData(hstmt, 12, SQL_C_SSHORT, &ti.get<11>(), sizeof(SQLSMALLINT), 0);
+				rc = SQLGetData(hstmt, 13, SQL_C_CHAR, localTypeName, sizeof(localTypeName), 0);
+				ti.set<12>(localTypeName);
+				rc = SQLGetData(hstmt, 14, SQL_C_SSHORT, &ti.get<13>(), sizeof(SQLSMALLINT), 0);
+				rc = SQLGetData(hstmt, 15, SQL_C_SSHORT, &ti.get<14>(), sizeof(SQLSMALLINT), 0);
+				rc = SQLGetData(hstmt, 16, SQL_C_SSHORT, &ti.get<15>(), sizeof(SQLSMALLINT), 0);
+				rc = SQLGetData(hstmt, 17, SQL_C_SSHORT, &ti.get<16>(), sizeof(SQLSMALLINT), 0);
+				rc = SQLGetData(hstmt, 18, SQL_C_SLONG, &ti.get<17>(), sizeof(SQLINTEGER), 0);
+				rc = SQLGetData(hstmt, 19, SQL_C_SSHORT, &ti.get<18>(), sizeof(SQLSMALLINT), 0);
+
+				_typeInfo.push_back(ti);
+			}
+		}
+
+		SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
+	}
+}
+
+
+int TypeInfo::cDataType(int sqlDataType) const
+{
+	DataTypeMap::const_iterator it = _cDataTypes.find(sqlDataType);
+
+	if (_cDataTypes.end() == it)
+		throw NotFoundException(format("C data type not found for SQL data type: %d", sqlDataType));
+
+	return it->second;
+}
+
+
+int TypeInfo::sqlDataType(int cDataType) const
+{
+	DataTypeMap::const_iterator it = _sqlDataTypes.find(cDataType);
+
+	if (_sqlDataTypes.end() == it)
+		throw NotFoundException(format("SQL data type not found for C data type: %d", cDataType));
+
+	return it->second;
+}
+
+
+} } } // namespace Poco::Data::ODBC

+ 1 - 1
Data/ODBC/src/Utility.cpp

@@ -47,7 +47,7 @@ namespace Data {
 namespace ODBC {
 
 
-const DataTypes Utility::_dataTypes;
+const TypeInfo Utility::_dataTypes;
 const SQLSMALLINT Utility::boolDataType = (sizeof(bool) <= sizeof(char)) ? SQL_C_TINYINT :
 	(sizeof(bool) == sizeof(short)) ? SQL_C_SHORT : SQL_C_LONG;
 

+ 2 - 1
Data/ODBC/testsuite/src/ODBCDB2Test.cpp

@@ -84,7 +84,8 @@ void ODBCDB2Test::testBareboneODBC()
 		"Second VARCHAR(30),"
 		"Third BLOB,"
 		"Fourth INTEGER,"
-		"Fifth FLOAT)";
+		"Fifth FLOAT,"
+		"Sixth TIMESTAMP)";
 
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL);
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);

+ 15 - 1
Data/ODBC/testsuite/src/ODBCMySQLTest.cpp

@@ -86,12 +86,26 @@ void ODBCMySQLTest::testBareboneODBC()
 		"Second VARCHAR(30),"
 		"Third VARBINARY(30),"
 		"Fourth INTEGER,"
-		"Fifth FLOAT)";
+		"Fifth FLOAT,"
+		"Sixth DATETIME)";
 
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL);
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
+
+	tableCreateString = "CREATE TABLE Test "
+		"(First VARCHAR(30),"
+		"Second VARCHAR(30),"
+		"Third VARBINARY(30),"
+		"Fourth INTEGER,"
+		"Fifth FLOAT,"
+		"Sixth DATE)";
+
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL, false);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND, false);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL, false);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND, false);
 }
 
 

+ 15 - 1
Data/ODBC/testsuite/src/ODBCOracleTest.cpp

@@ -88,7 +88,21 @@ void ODBCOracleTest::testBareboneODBC()
 		"Second VARCHAR(30),"
 		"Third BLOB,"
 		"Fourth INTEGER,"
-		"Fifth NUMBER)";
+		"Fifth NUMBER,"
+		"Sixth TIMESTAMP)";
+
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
+
+	tableCreateString = "CREATE TABLE Test "
+		"(First VARCHAR(30),"
+		"Second VARCHAR(30),"
+		"Third BLOB,"
+		"Fourth INTEGER,"
+		"Fifth NUMBER,"
+		"Sixth DATE)";
 
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL);
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);

+ 15 - 1
Data/ODBC/testsuite/src/ODBCPostgreSQLTest.cpp

@@ -86,12 +86,26 @@ void ODBCPostgreSQLTest::testBareboneODBC()
 		"Second VARCHAR(30),"
 		"Third BYTEA,"
 		"Fourth INTEGER,"
-		"Fifth FLOAT)";
+		"Fifth FLOAT,"
+		"Sixth TIMESTAMP)";
 
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL);
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
+
+	tableCreateString = "CREATE TABLE Test "
+		"(First VARCHAR(30),"
+		"Second VARCHAR(30),"
+		"Third BYTEA,"
+		"Fourth INTEGER,"
+		"Fifth FLOAT,"
+		"Sixth DATE)";
+
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL, false);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND, false);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL, false);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND, false);
 }
 
 

+ 2 - 1
Data/ODBC/testsuite/src/ODBCSQLServerTest.cpp

@@ -87,7 +87,8 @@ void ODBCSQLServerTest::testBareboneODBC()
 		"Second VARCHAR(30),"
 		"Third VARBINARY(30),"
 		"Fourth INTEGER,"
-		"Fifth FLOAT)";
+		"Fifth FLOAT,"
+		"Sixth DATETIME)";
 
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL);
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);

+ 28 - 1
Data/ODBC/testsuite/src/ODBCSQLiteTest.cpp

@@ -84,7 +84,34 @@ void ODBCSQLiteTest::testBareboneODBC()
 		"Second VARCHAR(30),"
 		"Third BLOB,"
 		"Fourth INTEGER,"
-		"Fifth REAL)";
+		"Fifth REAL,"
+		"Sixth TIMESTAMP)";
+
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
+
+	tableCreateString = "CREATE TABLE Test "
+		"(First VARCHAR(30),"
+		"Second VARCHAR(30),"
+		"Third BLOB,"
+		"Fourth INTEGER,"
+		"Fifth REAL,"
+		"Sixth DATETIME)";
+
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
+	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
+
+	tableCreateString = "CREATE TABLE Test "
+		"(First VARCHAR(30),"
+		"Second VARCHAR(30),"
+		"Third BLOB,"
+		"Fourth INTEGER,"
+		"Fifth REAL,"
+		"Sixth DATE)";
 
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL);
 	_pExecutor->bareboneODBCTest(_dbConnString, tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);

+ 74 - 5
Data/ODBC/testsuite/src/SQLExecutor.cpp

@@ -177,7 +177,8 @@ SQLExecutor::~SQLExecutor()
 void SQLExecutor::bareboneODBCTest(const std::string& dbConnString, 
 	const std::string& tableCreateString, 
 	SQLExecutor::DataBinding bindMode, 
-	SQLExecutor::DataExtraction extractMode)
+	SQLExecutor::DataExtraction extractMode,
+	bool doTime)
 {
 	SQLRETURN rc;
 	SQLHENV henv = SQL_NULL_HENV;
@@ -206,6 +207,25 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
 			, SQL_DRIVER_NOPROMPT);
 		assert (SQL_SUCCEEDED(rc));
 
+		// retrieve datetime type information for this DBMS
+		rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
+		assert (SQL_SUCCEEDED(rc));
+
+		rc = SQLGetTypeInfo(hstmt, SQL_TIMESTAMP);
+		assert (SQL_SUCCEEDED(rc));
+		SQLINTEGER dateTimeColSize = 0;
+		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));
+
+		rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
+		assert (SQL_SUCCEEDED(rc));
+
 			// Statement begin
 			rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
 			assert (SQL_SUCCEEDED(rc));
@@ -215,6 +235,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
 			SQLExecDirect(hstmt, pStr, (SQLINTEGER) sql.length());
 			//no return code check - ignore drop errors
 
+			// create table and go
 			sql = tableCreateString;
 			pStr = (POCO_SQLCHAR*) sql.c_str();
 			rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length());
@@ -223,7 +244,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
 			rc = SQLExecute(hstmt);
 			assert (SQL_SUCCEEDED(rc));
 
-			sql = "INSERT INTO Test VALUES (?,?,?,?,?)";
+			sql = "INSERT INTO Test VALUES (?,?,?,?,?,?)";
 			pStr = (POCO_SQLCHAR*) sql.c_str();
 			rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length());
 			assert (SQL_SUCCEEDED(rc));
@@ -231,6 +252,16 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
 			std::string str[3] = { "111", "222", "333" };
 			int fourth = 4;
 			float fifth = 1.5;
+			SQL_TIMESTAMP_STRUCT sixth;
+			sixth.year = 1965;
+			sixth.month = 6;
+			sixth.day = 18;
+			sixth.hour = 5;
+			sixth.minute = 34;
+			sixth.second = 59;
+			//some DBMS do not support this (e.g. MS SQL Server), hence 0
+			sixth.fraction = 0;
+
 			SQLLEN li = SQL_NTS;
 			SQLINTEGER size = (SQLINTEGER) str[0].size();
 	
@@ -306,6 +337,18 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
 				0);
 			assert (SQL_SUCCEEDED(rc));
 
+			rc = SQLBindParameter(hstmt, 
+				(SQLUSMALLINT) 6, 
+				SQL_PARAM_INPUT, 
+				SQL_C_TIMESTAMP, 
+				SQL_TIMESTAMP, 
+				dateTimeColSize,
+				dateTimeDecDigits,
+				(SQLPOINTER) &sixth, 
+				0, 
+				0);
+			assert (SQL_SUCCEEDED(rc));
+
 			size = 0;
 			if (SQLExecutor::PB_AT_EXEC == bindMode)
 				li = SQL_LEN_DATA_AT_EXEC((int) sizeof(int));
@@ -341,9 +384,10 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
 			assert (SQL_SUCCEEDED(rc));
 
 			char chr[3][5] = {{ 0 }};
-			SQLLEN lengths[5] = { 0 };
+			SQLLEN lengths[6] = { 0 };
 			fourth = 0;
 			fifth = 0.0f;
+			memset(&sixth, 0, sizeof(sixth));
 
 			if (SQLExecutor::DE_BOUND == extractMode)
 			{
@@ -386,6 +430,14 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
 					(SQLINTEGER) 0, 
 					&lengths[4]);
 				assert (SQL_SUCCEEDED(rc));
+
+				rc = SQLBindCol(hstmt, 
+					(SQLUSMALLINT) 6, 
+					SQL_C_TIMESTAMP, 
+					(SQLPOINTER) &sixth, 
+					(SQLINTEGER) 0, 
+					&lengths[5]);
+				assert (SQL_SUCCEEDED(rc));
 			}
 			
 			rc = SQLExecute(hstmt);
@@ -423,7 +475,7 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
 					(SQLUSMALLINT) 4, 
 					SQL_C_SLONG, 
 					&fourth, 
-					4,
+					0,
 					&lengths[3]);
 				assert (SQL_SUCCEEDED(rc));
 
@@ -431,9 +483,17 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
 					(SQLUSMALLINT) 5, 
 					SQL_C_FLOAT, 
 					&fifth, 
-					5,
+					0,
 					&lengths[4]);
 				assert (SQL_SUCCEEDED(rc));
+
+				rc = SQLGetData(hstmt, 
+					(SQLUSMALLINT) 6, 
+					SQL_C_TIMESTAMP, 
+					&sixth, 
+					0,
+					&lengths[5]);
+				assert (SQL_SUCCEEDED(rc));
 			}
 
 			assert (0 == strncmp("111", chr[0], 3));
@@ -441,6 +501,15 @@ void SQLExecutor::bareboneODBCTest(const std::string& dbConnString,
 			assert (0 == strncmp("333", chr[2], 3));
 			assert (4 == fourth);
 			assert (1.5 == fifth);
+			assert (1965 == sixth.year);
+			assert (6 == sixth.month);
+			assert (18 == sixth.day);
+			if (doTime)
+			{
+				assert (5 == sixth.hour);
+				assert (34 == sixth.minute);
+				assert (59 == sixth.second);
+			}
 
 			rc = SQLCloseCursor(hstmt);
 			assert (SQL_SUCCEEDED(rc));

+ 2 - 1
Data/ODBC/testsuite/src/SQLExecutor.h

@@ -62,7 +62,8 @@ public:
 	void bareboneODBCTest(const std::string& dbConnString,
 		const std::string& tableCreateString,
 		DataBinding bindMode, 
-		DataExtraction extractMode);
+		DataExtraction extractMode,
+		bool doTime=true);
 		/// This function uses "bare bone" ODBC API calls (i.e. calls are not 
 		/// "wrapped" in PocoData framework structures).
 		/// The purpose of the function is to verify that driver behaves