mirror of
https://github.com/pocoproject/poco.git
synced 2025-03-04 07:27:23 +01:00
DateTime binding (work in progress)
This commit is contained in:
parent
b55004813d
commit
0bde32efac
@ -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
|
||||
|
||||
|
@ -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">
|
||||
|
@ -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"
|
||||
>
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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;
|
||||
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;
|
||||
|
||||
DataTypes();
|
||||
/// Creates the DataTypes.
|
||||
explicit TypeInfo(SQLHDBC* pHDBC=0);
|
||||
/// Creates the TypeInfo.
|
||||
|
||||
~DataTypes();
|
||||
/// Destroys the DataTypes.
|
||||
~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
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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)");
|
||||
|
@ -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
|
@ -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();
|
||||
|
@ -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
Data/ODBC/src/TypeInfo.cpp
Normal file
216
Data/ODBC/src/TypeInfo.cpp
Normal file
@ -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
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user