added bulk, removed step

This commit is contained in:
Aleksandar Fabijanic
2007-12-16 17:44:46 +00:00
parent 33ed26b48b
commit c26de87394
62 changed files with 4399 additions and 1285 deletions

View File

@@ -249,6 +249,18 @@
RelativePath=".\include\Poco\Data\BLOBStream.h" RelativePath=".\include\Poco\Data\BLOBStream.h"
> >
</File> </File>
<File
RelativePath=".\include\Poco\Data\Bulk.h"
>
</File>
<File
RelativePath=".\include\Poco\Data\BulkBinding.h"
>
</File>
<File
RelativePath=".\include\Poco\Data\BulkExtraction.h"
>
</File>
<File <File
RelativePath=".\include\Poco\Data\Column.h" RelativePath=".\include\Poco\Data\Column.h"
> >
@@ -281,6 +293,10 @@
RelativePath=".\include\Poco\Data\MetaColumn.h" RelativePath=".\include\Poco\Data\MetaColumn.h"
> >
</File> </File>
<File
RelativePath=".\include\Poco\Data\Position.h"
>
</File>
<File <File
RelativePath=".\include\Poco\Data\Prepare.h" RelativePath=".\include\Poco\Data\Prepare.h"
> >
@@ -329,10 +345,6 @@
RelativePath=".\include\Poco\Data\StatementImpl.h" RelativePath=".\include\Poco\Data\StatementImpl.h"
> >
</File> </File>
<File
RelativePath=".\include\Poco\Data\Step.h"
>
</File>
<File <File
RelativePath=".\include\Poco\Data\Time.h" RelativePath=".\include\Poco\Data\Time.h"
> >
@@ -377,6 +389,10 @@
RelativePath=".\src\BLOBStream.cpp" RelativePath=".\src\BLOBStream.cpp"
> >
</File> </File>
<File
RelativePath=".\src\Bulk.cpp"
>
</File>
<File <File
RelativePath=".\src\Connector.cpp" RelativePath=".\src\Connector.cpp"
> >
@@ -397,6 +413,10 @@
RelativePath=".\src\MetaColumn.cpp" RelativePath=".\src\MetaColumn.cpp"
> >
</File> </File>
<File
RelativePath=".\src\Position.cpp"
>
</File>
<File <File
RelativePath=".\src\Range.cpp" RelativePath=".\src\Range.cpp"
> >
@@ -441,10 +461,6 @@
RelativePath=".\src\StatementImpl.cpp" RelativePath=".\src\StatementImpl.cpp"
> >
</File> </File>
<File
RelativePath=".\src\Step.cpp"
>
</File>
<File <File
RelativePath=".\src\Time.cpp" RelativePath=".\src\Time.cpp"
> >

View File

@@ -9,13 +9,12 @@
include $(POCO_BASE)/build/rules/global include $(POCO_BASE)/build/rules/global
objects = AbstractBinder AbstractBinding AbstractExtraction \ objects = AbstractBinder AbstractBinding AbstractExtraction \
AbstractExtractor AbstractPreparation AbstractPrepare \ AbstractExtractor AbstractPreparation AbstractPrepare Bulk \
Connector BLOB BLOBStream DataException Date Limit MetaColumn \ Connector BLOB BLOBStream DataException Date Limit MetaColumn \
PooledSessionHolder PooledSessionImpl \ PooledSessionHolder PooledSessionImpl Position \
Range RecordSet Row RowFormatter RowIterator \ Range RecordSet Row RowFormatter RowIterator \
Session SessionFactory SessionImpl \ Session SessionFactory SessionImpl \
SessionPool Statement StatementCreator StatementImpl \ SessionPool Statement StatementCreator StatementImpl Time
Step Time
target = PocoData target = PocoData
target_version = $(LIBVERSION) target_version = $(LIBVERSION)

View File

@@ -17,8 +17,8 @@ $(error No ODBC library found. Please install unixODBC or iODBC and try again)
endif endif
objects = Binder ConnectionHandle Connector EnvironmentHandle \ objects = Binder ConnectionHandle Connector EnvironmentHandle \
Extractor ODBCColumn ODBCException ODBCStatementImpl Parameter Preparation \ Extractor ODBCColumn ODBCException ODBCStatementImpl \
SessionImpl TypeInfo Unicode Utility Parameter Preparation SessionImpl TypeInfo Unicode Utility
target = PocoODBC target = PocoODBC
target_version = $(LIBVERSION) target_version = $(LIBVERSION)

View File

@@ -81,6 +81,7 @@ public:
}; };
Binder(const StatementHandle& rStmt, Binder(const StatementHandle& rStmt,
std::size_t maxFieldSize,
ParameterBinding dataBinding = PB_IMMEDIATE, ParameterBinding dataBinding = PB_IMMEDIATE,
TypeInfo* pDataTypes = 0); TypeInfo* pDataTypes = 0);
/// Creates the Binder. /// Creates the Binder.
@@ -91,62 +92,119 @@ public:
void bind(std::size_t pos, const Poco::Int8& val, Direction dir); void bind(std::size_t pos, const Poco::Int8& val, Direction dir);
/// Binds an Int8. /// Binds an Int8.
void bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir);
/// Binds an Int8 vector.
void bind(std::size_t pos, const Poco::UInt8& val, Direction dir); void bind(std::size_t pos, const Poco::UInt8& val, Direction dir);
/// Binds an UInt8. /// Binds an UInt8.
void bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir);
/// Binds an UInt8 vector.
void bind(std::size_t pos, const Poco::Int16& val, Direction dir); void bind(std::size_t pos, const Poco::Int16& val, Direction dir);
/// Binds an Int16. /// Binds an Int16.
void bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir);
/// Binds an Int16 vector.
void bind(std::size_t pos, const Poco::UInt16& val, Direction dir); void bind(std::size_t pos, const Poco::UInt16& val, Direction dir);
/// Binds an UInt16. /// Binds an UInt16.
void bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir);
/// Binds an UInt16 vector.
void bind(std::size_t pos, const Poco::Int32& val, Direction dir); void bind(std::size_t pos, const Poco::Int32& val, Direction dir);
/// Binds an Int32. /// Binds an Int32.
void bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir);
/// Binds an Int32 vector.
void bind(std::size_t pos, const Poco::UInt32& val, Direction dir); void bind(std::size_t pos, const Poco::UInt32& val, Direction dir);
/// Binds an UInt32. /// Binds an UInt32.
void bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir);
/// Binds an UInt32 vector.
void bind(std::size_t pos, const Poco::Int64& val, Direction dir); void bind(std::size_t pos, const Poco::Int64& val, Direction dir);
/// Binds an Int64. /// Binds an Int64.
void bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir);
/// Binds an Int64 vector.
void bind(std::size_t pos, const Poco::UInt64& val, Direction dir); void bind(std::size_t pos, const Poco::UInt64& val, Direction dir);
/// Binds an UInt64. /// Binds an UInt64.
void bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir);
/// Binds an UInt64 vector.
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
void bind(std::size_t pos, const long& val, Direction dir); void bind(std::size_t pos, const long& val, Direction dir);
/// Binds a long. /// Binds a long.
void bind(std::size_t pos, const std::vector<long>& val, Direction dir);
/// Binds a long vector.
#endif #endif
void bind(std::size_t pos, const bool& val, Direction dir); void bind(std::size_t pos, const bool& val, Direction dir);
/// Binds a boolean. /// Binds a boolean.
void bind(std::size_t pos, const std::vector<bool>& val, Direction dir);
/// Binds a boolean vector.
void bind(std::size_t pos, const float& val, Direction dir); void bind(std::size_t pos, const float& val, Direction dir);
/// Binds a float. /// Binds a float.
void bind(std::size_t pos, const std::vector<float>& val, Direction dir);
/// Binds a float vector.
void bind(std::size_t pos, const double& val, Direction dir); void bind(std::size_t pos, const double& val, Direction dir);
/// Binds a double. /// Binds a double.
void bind(std::size_t pos, const std::vector<double>& val, Direction dir);
/// Binds a double vector.
void bind(std::size_t pos, const char& val, Direction dir); void bind(std::size_t pos, const char& val, Direction dir);
/// Binds a single character. /// Binds a single character.
void bind(std::size_t pos, const std::vector<char>& val, Direction dir);
/// Binds a character vector.
void bind(std::size_t pos, const std::string& val, Direction dir); void bind(std::size_t pos, const std::string& val, Direction dir);
/// Binds a string. /// Binds a string.
void bind(std::size_t pos, const std::vector<std::string>& val, Direction dir);
/// Binds a string vector.
void bind(std::size_t pos, const BLOB& val, Direction dir); void bind(std::size_t pos, const BLOB& val, Direction dir);
/// Binds a BLOB. In-bound only. /// Binds a BLOB. In-bound only.
void bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir);
/// Binds a BLOB vector. In-bound only.
void bind(std::size_t pos, const Date& val, Direction dir); void bind(std::size_t pos, const Date& val, Direction dir);
/// Binds a Date. /// Binds a Date.
void bind(std::size_t pos, const std::vector<Date>& val, Direction dir);
/// Binds a Date vector.
void bind(std::size_t pos, const Time& val, Direction dir); void bind(std::size_t pos, const Time& val, Direction dir);
/// Binds a Time. /// Binds a Time.
void bind(std::size_t pos, const std::vector<Time>& val, Direction dir);
/// Binds a Time vector.
void bind(std::size_t pos, const DateTime& val, Direction dir); void bind(std::size_t pos, const DateTime& val, Direction dir);
/// Binds a DateTime. /// Binds a DateTime.
void bind(std::size_t pos, const std::vector<DateTime>& val, Direction dir);
/// Binds a DateTime vector.
void bind(std::size_t pos, const NullData& val, Direction dir); void bind(std::size_t pos, const NullData& val, Direction dir);
/// Binds a null. In-bound only. /// Binds a null. In-bound only.
void bind(std::size_t pos, const std::vector<NullData>& val, Direction dir);
/// Binds a null vector. In-bound only.
void setDataBinding(ParameterBinding binding); void setDataBinding(ParameterBinding binding);
/// Set data binding type. /// Set data binding type.
@@ -164,16 +222,22 @@ public:
/// Clears the cached storage. /// Clears the cached storage.
private: private:
typedef std::vector<SQLLEN*> LengthVec; typedef std::vector<SQLLEN*> LengthVec;
typedef std::map<char*, std::string*> StringMap; typedef std::vector<std::vector<SQLLEN> > LengthVecVec;
typedef std::map<SQL_DATE_STRUCT*, Date*> DateMap; typedef std::vector<char*> CharPtrVec;
typedef std::map<SQL_TIME_STRUCT*, Time*> TimeMap; typedef std::vector<bool*> BoolPtrVec;
typedef std::map<SQL_TIMESTAMP_STRUCT*, DateTime*> TimestampMap; typedef std::vector<std::vector<SQL_DATE_STRUCT> > DateVec;
typedef std::vector<std::vector<SQL_TIME_STRUCT> > TimeVec;
typedef std::vector<std::vector<SQL_TIMESTAMP_STRUCT> > DateTimeVec;
typedef std::map<char*, std::string*> StringMap;
typedef std::map<SQL_DATE_STRUCT*, Date*> DateMap;
typedef std::map<SQL_TIME_STRUCT*, Time*> TimeMap;
typedef std::map<SQL_TIMESTAMP_STRUCT*, DateTime*> TimestampMap;
void describeParameter(std::size_t pos); void describeParameter(std::size_t pos);
/// Sets the description field for the parameter, if needed. /// Sets the description field for the parameter, if needed.
void bind(std::size_t pos, const char* const &pVal, Direction dir); void bind(std::size_t pos, const char* const& pVal, Direction dir);
/// Binds a const char ptr. /// Binds a const char ptr.
/// This is a private no-op in this implementation /// This is a private no-op in this implementation
/// due to security risk. /// due to security risk.
@@ -185,12 +249,12 @@ private:
template <typename T> template <typename T>
void bindImpl(std::size_t pos, T& val, SQLSMALLINT cDataType, Direction dir) void bindImpl(std::size_t pos, T& val, SQLSMALLINT cDataType, Direction dir)
{ {
_lengthIndicator.push_back(0);
SQLINTEGER colSize = 0; SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0; SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, cDataType, colSize, decDigits); getColSizeAndPrecision(pos, cDataType, colSize, decDigits);
_lengthIndicator.push_back(0);
if (Utility::isError(SQLBindParameter(_rStmt, if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1, (SQLUSMALLINT) pos + 1,
toODBCDirection(dir), toODBCDirection(dir),
@@ -198,14 +262,50 @@ private:
Utility::sqlDataType(cDataType), Utility::sqlDataType(cDataType),
colSize, colSize,
decDigits, decDigits,
(SQLPOINTER) &val, (SQLPOINTER) &val, 0, 0)))
0,
0)))
{ {
throw StatementException(_rStmt, "SQLBindParameter()"); throw StatementException(_rStmt, "SQLBindParameter()");
} }
} }
template <typename T>
void bindImplVec(std::size_t pos, const std::vector<T>& val, SQLSMALLINT cDataType, Direction dir)
{
if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("std::vector can only be bound immediately.");
std::size_t length = val.size();
SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, cDataType, colSize, decDigits);
setParamSetSize(pos, length);
if (_vecLengthIndicator.size() <= pos)
{
_vecLengthIndicator.resize(pos + 1);
_vecLengthIndicator[pos].resize(length, sizeof(T));
}
if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1,
toODBCDirection(dir),
cDataType,
Utility::sqlDataType(cDataType),
colSize,
decDigits,
(SQLPOINTER) &val[0],
0,
&_vecLengthIndicator[pos][0])))
{
throw StatementException(_rStmt, "SQLBindParameter()");
}
}
void bindImplVecBool(std::size_t pos,
const std::vector<bool>& val,
SQLSMALLINT cDataType,
Direction dir);
void getColSizeAndPrecision(std::size_t pos, void getColSizeAndPrecision(std::size_t pos,
SQLSMALLINT cDataType, SQLSMALLINT cDataType,
SQLINTEGER& colSize, SQLINTEGER& colSize,
@@ -218,20 +318,40 @@ private:
/// to discover the required values are unsuccesfully exhausted, the values /// to discover the required values are unsuccesfully exhausted, the values
/// are both set to zero and no exception is thrown. /// are both set to zero and no exception is thrown.
void bindNull(std::size_t pos, SQLSMALLINT cDataType); void setParamSetSize(std::size_t pos, std::size_t length);
/// Utility function for binding null values. /// Sets the parameter set size. Used for column-wise binding.
/// For in-bound purposes only.
void getColumnOrParameterSize(std::size_t pos, SQLINTEGER& size);
/// Fills the column or parameter size into the 'size' argument.
/// Does nothing if neither can be obtained from the driver, so
/// size should be set to some default value prior to calling this
/// function in order to avoid undefined size value.
void freeMemory();
/// Frees all dynamically allocated memory resources.
const StatementHandle& _rStmt; const StatementHandle& _rStmt;
LengthVec _lengthIndicator;
ParamMap _inParams; LengthVec _lengthIndicator;
ParamMap _outParams; LengthVecVec _vecLengthIndicator;
ParameterBinding _paramBinding;
DateMap _dates; ParamMap _inParams;
TimeMap _times; ParamMap _outParams;
TimestampMap _timestamps; ParameterBinding _paramBinding;
StringMap _strings;
const TypeInfo* _pTypeInfo; DateMap _dates;
TimeMap _times;
TimestampMap _timestamps;
StringMap _strings;
DateVec _dateVec;
TimeVec _timeVec;
DateTimeVec _dateTimeVec;
CharPtrVec _charPtrs;
BoolPtrVec _boolPtrs;
const TypeInfo* _pTypeInfo;
SQLINTEGER _paramSetSize;
std::size_t _maxFieldSize;
}; };
@@ -244,53 +364,107 @@ inline void Binder::bind(std::size_t pos, const Poco::Int8& val, Direction dir)
} }
inline void Binder::bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir)
{
bindImplVec(pos, val, SQL_C_STINYINT, dir);
}
inline void Binder::bind(std::size_t pos, const Poco::UInt8& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::UInt8& val, Direction dir)
{ {
bindImpl(pos, val, SQL_C_UTINYINT, dir); bindImpl(pos, val, SQL_C_UTINYINT, dir);
} }
inline void Binder::bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir)
{
bindImplVec(pos, val, SQL_C_UTINYINT, dir);
}
inline void Binder::bind(std::size_t pos, const Poco::Int16& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::Int16& val, Direction dir)
{ {
bindImpl(pos, val, SQL_C_SSHORT, dir); bindImpl(pos, val, SQL_C_SSHORT, dir);
} }
inline void Binder::bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir)
{
bindImplVec(pos, val, SQL_C_SSHORT, dir);
}
inline void Binder::bind(std::size_t pos, const Poco::UInt16& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::UInt16& val, Direction dir)
{ {
bindImpl(pos, val, SQL_C_USHORT, dir); bindImpl(pos, val, SQL_C_USHORT, dir);
} }
inline void Binder::bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir)
{
bindImplVec(pos, val, SQL_C_USHORT, dir);
}
inline void Binder::bind(std::size_t pos, const Poco::Int32& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::Int32& val, Direction dir)
{ {
bindImpl(pos, val, SQL_C_SLONG, dir); bindImpl(pos, val, SQL_C_SLONG, dir);
} }
inline void Binder::bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir)
{
bindImplVec(pos, val, SQL_C_SLONG, dir);
}
inline void Binder::bind(std::size_t pos, const Poco::UInt32& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::UInt32& val, Direction dir)
{ {
bindImpl(pos, val, SQL_C_ULONG, dir); bindImpl(pos, val, SQL_C_ULONG, dir);
} }
inline void Binder::bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir)
{
bindImplVec(pos, val, SQL_C_ULONG, dir);
}
inline void Binder::bind(std::size_t pos, const Poco::Int64& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::Int64& val, Direction dir)
{ {
bindImpl(pos, val, SQL_C_SBIGINT, dir); bindImpl(pos, val, SQL_C_SBIGINT, dir);
} }
inline void Binder::bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir)
{
bindImplVec(pos, val, SQL_C_SBIGINT, dir);
}
inline void Binder::bind(std::size_t pos, const Poco::UInt64& val, Direction dir) inline void Binder::bind(std::size_t pos, const Poco::UInt64& val, Direction dir)
{ {
bindImpl(pos, val, SQL_C_UBIGINT, dir); bindImpl(pos, val, SQL_C_UBIGINT, dir);
} }
inline void Binder::bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir)
{
bindImplVec(pos, val, SQL_C_UBIGINT, dir);
}
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
inline void Binder::bind(std::size_t pos, const long& val, Direction dir) inline void Binder::bind(std::size_t pos, const long& val, Direction dir)
{ {
bindImpl(pos, val, SQL_C_SLONG, dir); bindImpl(pos, val, SQL_C_SLONG, dir);
} }
inline void Binder::bind(std::size_t pos, const std::vector<long>& val, Direction dir)
{
bindImplVec(pos, val, SQL_C_SLONG, dir);
}
#endif #endif
@@ -300,24 +474,48 @@ inline void Binder::bind(std::size_t pos, const float& val, Direction dir)
} }
inline void Binder::bind(std::size_t pos, const std::vector<float>& val, Direction dir)
{
bindImplVec(pos, val, SQL_C_FLOAT, dir);
}
inline void Binder::bind(std::size_t pos, const double& val, Direction dir) inline void Binder::bind(std::size_t pos, const double& val, Direction dir)
{ {
bindImpl(pos, val, SQL_C_DOUBLE, dir); bindImpl(pos, val, SQL_C_DOUBLE, dir);
} }
inline void Binder::bind(std::size_t pos, const std::vector<double>& val, Direction dir)
{
bindImplVec(pos, val, SQL_C_DOUBLE, dir);
}
inline void Binder::bind(std::size_t pos, const bool& val, Direction dir) inline void Binder::bind(std::size_t pos, const bool& val, Direction dir)
{ {
bindImpl(pos, val, SQL_C_BIT, dir); bindImpl(pos, val, SQL_C_BIT, dir);
} }
inline void Binder::bind(std::size_t pos, const std::vector<bool>& val, Direction dir)
{
bindImplVecBool(pos, val, SQL_C_BIT, dir);
}
inline void Binder::bind(std::size_t pos, const char& val, Direction dir) inline void Binder::bind(std::size_t pos, const char& val, Direction dir)
{ {
bindImpl(pos, val, SQL_C_STINYINT, dir); bindImpl(pos, val, SQL_C_STINYINT, dir);
} }
inline void Binder::bind(std::size_t pos, const std::vector<char>& val, Direction dir)
{
bindImplVec(pos, val, SQL_C_STINYINT, dir);
}
inline void Binder::setDataBinding(Binder::ParameterBinding binding) inline void Binder::setDataBinding(Binder::ParameterBinding binding)
{ {
_paramBinding = binding; _paramBinding = binding;

View File

@@ -77,73 +77,133 @@ public:
bool extract(std::size_t pos, Poco::Int8& val); bool extract(std::size_t pos, Poco::Int8& val);
/// Extracts an Int8. /// Extracts an Int8.
bool extract(std::size_t pos, std::vector<Poco::Int8>& val);
/// Extracts an Int8 vector.
bool extract(std::size_t pos, Poco::UInt8& val); bool extract(std::size_t pos, Poco::UInt8& val);
/// Extracts an UInt8. /// Extracts an UInt8.
bool extract(std::size_t pos, std::vector<Poco::UInt8>& val);
/// Extracts an UInt8 vector.
bool extract(std::size_t pos, Poco::Int16& val); bool extract(std::size_t pos, Poco::Int16& val);
/// Extracts an Int16. /// Extracts an Int16.
bool extract(std::size_t pos, std::vector<Poco::Int16>& val);
/// Extracts an Int16 vector.
bool extract(std::size_t pos, Poco::UInt16& val); bool extract(std::size_t pos, Poco::UInt16& val);
/// Extracts an UInt16. /// Extracts an UInt16.
bool extract(std::size_t pos, std::vector<Poco::UInt16>& val);
/// Extracts an UInt16 vector.
bool extract(std::size_t pos, Poco::Int32& val); bool extract(std::size_t pos, Poco::Int32& val);
/// Extracts an Int32. /// Extracts an Int32.
bool extract(std::size_t pos, std::vector<Poco::Int32>& val);
/// Extracts an Int32 vector.
bool extract(std::size_t pos, Poco::UInt32& val); bool extract(std::size_t pos, Poco::UInt32& val);
/// Extracts an UInt32. /// Extracts an UInt32.
bool extract(std::size_t pos, std::vector<Poco::UInt32>& val);
/// Extracts an UInt32 vector.
bool extract(std::size_t pos, Poco::Int64& val); bool extract(std::size_t pos, Poco::Int64& val);
/// Extracts an Int64. /// Extracts an Int64.
bool extract(std::size_t pos, std::vector<Poco::Int64>& val);
/// Extracts an Int64 vector.
bool extract(std::size_t pos, Poco::UInt64& val); bool extract(std::size_t pos, Poco::UInt64& val);
/// Extracts an UInt64. /// Extracts an UInt64.
bool extract(std::size_t pos, std::vector<Poco::UInt64>& val);
/// Extracts an UInt64 vector.
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
bool extract(std::size_t pos, long& val); bool extract(std::size_t pos, long& val);
/// Extracts a long. /// Extracts a long.
bool extract(std::size_t pos, std::vector<long>& val);
/// Extracts a long vector.
#endif #endif
bool extract(std::size_t pos, bool& val); bool extract(std::size_t pos, bool& val);
/// Extracts a boolean. /// Extracts a boolean.
bool extract(std::size_t pos, std::vector<bool>& val);
/// Extracts a boolean vector.
bool extract(std::size_t pos, float& val); bool extract(std::size_t pos, float& val);
/// Extracts a float. /// Extracts a float.
bool extract(std::size_t pos, std::vector<float>& val);
/// Extracts a float vector.
bool extract(std::size_t pos, double& val); bool extract(std::size_t pos, double& val);
/// Extracts a double. /// Extracts a double.
bool extract(std::size_t pos, std::vector<double>& val);
/// Extracts a double vector.
bool extract(std::size_t pos, char& val); bool extract(std::size_t pos, char& val);
/// Extracts a single character. /// Extracts a single character.
bool extract(std::size_t pos, std::vector<char>& val);
/// Extracts a single character vector.
bool extract(std::size_t pos, std::string& val); bool extract(std::size_t pos, std::string& val);
/// Extracts a string. /// Extracts a string.
bool extract(std::size_t pos, std::vector<std::string>& val);
/// Extracts a string vector.
bool extract(std::size_t pos, Poco::Data::BLOB& val); bool extract(std::size_t pos, Poco::Data::BLOB& val);
/// Extracts a BLOB. /// Extracts a BLOB.
bool extract(std::size_t pos, std::vector<Poco::Data::BLOB>& val);
/// Extracts a BLOB vector.
bool extract(std::size_t pos, Poco::Data::Date& val); bool extract(std::size_t pos, Poco::Data::Date& val);
/// Extracts a Date. /// Extracts a Date.
bool extract(std::size_t pos, std::vector<Poco::Data::Date>& val);
/// Extracts a Date vector.
bool extract(std::size_t pos, Poco::Data::Time& val); bool extract(std::size_t pos, Poco::Data::Time& val);
/// Extracts a Time. /// Extracts a Time.
bool extract(std::size_t pos, std::vector<Poco::Data::Time>& val);
/// Extracts a Time vector.
bool extract(std::size_t pos, Poco::DateTime& val); bool extract(std::size_t pos, Poco::DateTime& val);
/// Extracts a DateTime. /// Extracts a DateTime.
bool extract(std::size_t pos, std::vector<Poco::DateTime>& val);
/// Extracts a DateTime vector.
bool extract(std::size_t pos, Poco::Any& val); bool extract(std::size_t pos, Poco::Any& val);
/// Extracts an Any. /// Extracts an Any.
bool extract(std::size_t pos, std::vector<Poco::Any>& val);
/// Extracts an Any vector.
bool extract(std::size_t pos, Poco::DynamicAny& val); bool extract(std::size_t pos, Poco::DynamicAny& val);
/// Extracts a DynamicAny. /// Extracts a DynamicAny.
bool extract(std::size_t pos, std::vector<Poco::DynamicAny>& val);
/// Extracts a DynamicAny vector.
void setDataExtraction(Preparation::DataExtraction ext); void setDataExtraction(Preparation::DataExtraction ext);
/// Set data extraction mode. /// Set data extraction mode.
Preparation::DataExtraction getDataExtraction() const; Preparation::DataExtraction getDataExtraction() const;
/// Returns data extraction mode. /// Returns data extraction mode.
bool isNull(std::size_t pos); bool isNull(std::size_t col, std::size_t row = Preparation::INVALID_ROW);
/// Returns true if the current row value at pos column is null. /// Returns true if the value at [col,row] is null.
void reset(); void reset();
/// Resets the internally cached length indicators. /// Resets the internally cached length indicators.
@@ -171,13 +231,20 @@ private:
bool extractBoundImpl(std::size_t pos, T& val) bool extractBoundImpl(std::size_t pos, T& val)
{ {
if (isNull(pos)) return false; if (isNull(pos)) return false;
poco_assert_dbg (typeid(T) == _rPreparation[pos].type());
poco_assert (typeid(T) == _rPreparation[pos].type());
val = *AnyCast<T>(&_rPreparation[pos]); val = *AnyCast<T>(&_rPreparation[pos]);
return true; return true;
} }
template<typename T>
bool extractBoundImplVec(std::size_t pos, std::vector<T>& val)
{
poco_assert_dbg (typeid(std::vector<T>) == _rPreparation[pos].type());
std::vector<T>& v = RefAnyCast<std::vector<T> >(_rPreparation[pos]);
val.assign(v.begin(), v.end());
return true;
}
template<typename T> template<typename T>
bool extractManualImpl(std::size_t pos, T& val, SQLSMALLINT cType) bool extractManualImpl(std::size_t pos, T& val, SQLSMALLINT cType)
{ {
@@ -271,6 +338,8 @@ private:
/// SQLLEN macro (a.k.a. SQLINTEGER) yields 64-bit value, /// SQLLEN macro (a.k.a. SQLINTEGER) yields 64-bit value,
/// while SQL_NULL_DATA (#define'd as -1 literal) remains 32-bit. /// while SQL_NULL_DATA (#define'd as -1 literal) remains 32-bit.
SQLINTEGER columnSize(std::size_t pos) const;
const StatementHandle& _rStmt; const StatementHandle& _rStmt;
Preparation& _rPreparation; Preparation& _rPreparation;
Preparation::DataExtraction _dataExtraction; Preparation::DataExtraction _dataExtraction;
@@ -281,8 +350,6 @@ private:
/// ///
/// inlines /// inlines
/// ///
inline void Extractor::setDataExtraction(Preparation::DataExtraction ext) inline void Extractor::setDataExtraction(Preparation::DataExtraction ext)
{ {
_rPreparation.setDataExtraction(_dataExtraction = ext); _rPreparation.setDataExtraction(_dataExtraction = ext);
@@ -314,6 +381,12 @@ inline bool Extractor::isNullLengthIndicator(SQLLEN val) const
} }
inline SQLINTEGER Extractor::columnSize(std::size_t pos) const
{
return (SQLINTEGER) ODBCColumn(_rStmt, pos).length();
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@@ -206,17 +206,6 @@ inline bool ODBCStatementImpl::nextRowReady() const
} }
inline const MetaColumn& ODBCStatementImpl::metaColumn(Poco::UInt32 pos) const
{
std::size_t sz = _columnPtrs.size();
if (0 == sz || pos > sz - 1)
throw InvalidAccessException(format("Invalid column number: %u", pos));
return *_columnPtrs[pos];
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@@ -82,8 +82,6 @@ public:
private: private:
Parameter(); Parameter();
static const int BUFFER_LENGTH = 2048;
void init(); void init();
SQLSMALLINT _dataType; SQLSMALLINT _dataType;

View File

@@ -76,8 +76,9 @@ class ODBC_API Preparation : public AbstractPreparation
/// with respective memory output locations before extracting data. /// with respective memory output locations before extracting data.
/// Extraction works in two-phases: first prepare is called once, then extract n-times. /// Extraction works in two-phases: first prepare is called once, then extract n-times.
/// In ODBC, SQLBindCol/SQLFetch is the preferred method of data retrieval (SQLGetData is available, /// In ODBC, SQLBindCol/SQLFetch is the preferred method of data retrieval (SQLGetData is available,
/// however with numerous driver implementation dependent limitations). In order to fit this functionality /// however with numerous driver implementation dependent limitations and inferior performance).
/// into Poco DataConnectors framework, every ODBC SQL statement instantiates its own Preparation object. /// In order to fit this functionality into Poco DataConnectors framework, every ODBC SQL statement
/// instantiates its own Preparation object.
/// This is done once per statement execution (from StatementImpl::bindImpl()). /// This is done once per statement execution (from StatementImpl::bindImpl()).
/// ///
/// Preparation object is used to : /// Preparation object is used to :
@@ -94,12 +95,26 @@ class ODBC_API Preparation : public AbstractPreparation
/// ///
{ {
public: public:
typedef std::vector<char*> CharArray;
enum DataExtraction enum DataExtraction
{ {
DE_MANUAL, DE_MANUAL,
DE_BOUND DE_BOUND
}; };
static const std::size_t INVALID_ROW;
enum DataType
{
DT_BOOL,
DT_CHAR,
DT_CHAR_ARRAY,
DT_DATE,
DT_TIME,
DT_DATETIME
};
Preparation(const StatementHandle& rStmt, Preparation(const StatementHandle& rStmt,
const std::string& statement, const std::string& statement,
std::size_t maxFieldSize, std::size_t maxFieldSize,
@@ -112,68 +127,128 @@ public:
~Preparation(); ~Preparation();
/// Destroys the Preparation. /// Destroys the Preparation.
void prepare(std::size_t pos, Poco::Int8); void prepare(std::size_t pos, Poco::Int8& val);
/// Prepares an Int8. /// Prepares an Int8.
void prepare(std::size_t pos, Poco::UInt8); void prepare(std::size_t pos, std::vector<Poco::Int8>& val);
/// Prepares an Int8 vector.
void prepare(std::size_t pos, Poco::UInt8& val);
/// Prepares an UInt8. /// Prepares an UInt8.
void prepare(std::size_t pos, Poco::Int16); void prepare(std::size_t pos, std::vector<Poco::UInt8>& val);
/// Prepares an UInt8 vector.
void prepare(std::size_t pos, Poco::Int16& val);
/// Prepares an Int16. /// Prepares an Int16.
void prepare(std::size_t pos, Poco::UInt16); void prepare(std::size_t pos, std::vector<Poco::Int16>& val);
/// Prepares an Int16 vector.
void prepare(std::size_t pos, Poco::UInt16& val);
/// Prepares an UInt16. /// Prepares an UInt16.
void prepare(std::size_t pos, Poco::Int32); void prepare(std::size_t pos, std::vector<Poco::UInt16>& val);
/// Prepares an UInt16 vector.
void prepare(std::size_t pos, Poco::Int32& val);
/// Prepares an Int32. /// Prepares an Int32.
void prepare(std::size_t pos, Poco::UInt32); void prepare(std::size_t pos, std::vector<Poco::Int32>& val);
/// Prepares an Int32 vector.
void prepare(std::size_t pos, Poco::UInt32& val);
/// Prepares an UInt32. /// Prepares an UInt32.
void prepare(std::size_t pos, Poco::Int64); void prepare(std::size_t pos, std::vector<Poco::UInt32>& val);
/// Prepares an UInt32 vector.
void prepare(std::size_t pos, Poco::Int64& val);
/// Prepares an Int64. /// Prepares an Int64.
void prepare(std::size_t pos, Poco::UInt64); void prepare(std::size_t pos, std::vector<Poco::Int64>& val);
/// Prepares an Int64 vector.
void prepare(std::size_t pos, Poco::UInt64& val);
/// Prepares an UInt64. /// Prepares an UInt64.
void prepare(std::size_t pos, std::vector<Poco::UInt64>& val);
/// Prepares an UInt64 vector.
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
void prepare(std::size_t pos, long); void prepare(std::size_t pos, long& val);
/// Prepares a long. /// Prepares a long.
void prepare(std::size_t pos, std::vector<long>& val);
/// Prepares a long vector.
#endif #endif
void prepare(std::size_t pos, bool); void prepare(std::size_t pos, bool& val);
/// Prepares a boolean. /// Prepares a boolean.
void prepare(std::size_t pos, float); void prepare(std::size_t pos, std::vector<bool>& val);
/// Prepares a boolean vector.
void prepare(std::size_t pos, float& val);
/// Prepares a float. /// Prepares a float.
void prepare(std::size_t pos, double); void prepare(std::size_t pos, std::vector<float>& val);
/// Prepares a float vector.
void prepare(std::size_t pos, double& val);
/// Prepares a double. /// Prepares a double.
void prepare(std::size_t pos, char); void prepare(std::size_t pos, std::vector<double>& val);
/// Prepares a double vector.
void prepare(std::size_t pos, char& val);
/// Prepares a single character. /// Prepares a single character.
void prepare(std::size_t pos, const std::string&); void prepare(std::size_t pos, std::vector<char>& val);
/// Prepares a single character vector.
void prepare(std::size_t pos, const std::string& val);
/// Prepares a string. /// Prepares a string.
void prepare(std::size_t pos, const Poco::Data::BLOB&); void prepare(std::size_t pos, const std::vector<std::string>& val);
/// Prepares a string vector.
void prepare(std::size_t pos, const Poco::Data::BLOB& val);
/// Prepares a BLOB. /// Prepares a BLOB.
void prepare(std::size_t pos, const Poco::Data::Date&); void prepare(std::size_t pos, const std::vector<Poco::Data::BLOB>& val);
/// Prepares a BLOB vector.
void prepare(std::size_t pos, const Poco::Data::Date& val);
/// Prepares a Date. /// Prepares a Date.
void prepare(std::size_t pos, const Poco::Data::Time&); void prepare(std::size_t pos, const std::vector<Poco::Data::Date>& val);
/// Prepares a Date vector.
void prepare(std::size_t pos, const Poco::Data::Time& val);
/// Prepares a Time. /// Prepares a Time.
void prepare(std::size_t pos, const Poco::DateTime&); void prepare(std::size_t pos, const std::vector<Poco::Data::Time>& val);
/// Prepares a Time vector.
void prepare(std::size_t pos, const Poco::DateTime& val);
/// Prepares a DateTime. /// Prepares a DateTime.
void prepare(std::size_t pos, const Poco::Any&); void prepare(std::size_t pos, const std::vector<Poco::DateTime>& val);
/// Prepares a DateTime vector.
void prepare(std::size_t pos, const Poco::Any& val);
/// Prepares an Any. /// Prepares an Any.
void prepare(std::size_t pos, const Poco::DynamicAny&); void prepare(std::size_t pos, const std::vector<Poco::Any>& val);
/// Prepares an Any vector.
void prepare(std::size_t pos, const Poco::DynamicAny& val);
/// Prepares a DynamicAny. /// Prepares a DynamicAny.
void prepare(std::size_t pos, const std::vector<Poco::DynamicAny>& val);
/// Prepares a DynamicAny vector.
std::size_t columns() const; std::size_t columns() const;
/// Returns the number of columns. /// Returns the number of columns.
/// Resizes the internal storage iff the size is zero. /// Resizes the internal storage iff the size is zero.
@@ -192,12 +267,16 @@ public:
/// Returned length for variable length fields is the one /// Returned length for variable length fields is the one
/// supported by this implementation, not the underlying DB. /// supported by this implementation, not the underlying DB.
int actualDataSize(std::size_t pos) const; std::size_t actualDataSize(std::size_t col, std::size_t row = INVALID_ROW) const;
/// Returns the returned length. This is usually /// Returns the returned length for the column and row specified.
/// equal to the column size, except for variable length fields /// This is usually equal to the column size, except for
/// (BLOB and variable length strings). /// variable length fields (BLOB and variable length strings).
/// For null values, the return value is -1 (SQL_NO_DATA) /// For null values, the return value is -1 (SQL_NO_DATA)
std::size_t bulkSize(std::size_t col = 0) const;
/// Returns bulk size. Column argument is optional
/// since all columns must be the same size.
void setDataExtraction(DataExtraction ext); void setDataExtraction(DataExtraction ext);
/// Set data extraction mode. /// Set data extraction mode.
@@ -205,201 +284,486 @@ public:
/// Returns data extraction mode. /// Returns data extraction mode.
private: private:
typedef std::vector<Poco::Any> ValueVec;
typedef std::vector<SQLLEN> LengthVec;
typedef std::vector<LengthVec> LengthLengthVec;
typedef std::map<std::size_t, DataType> IndexMap;
Preparation(); Preparation();
Preparation& operator = (const Preparation&); Preparation& operator = (const Preparation&);
void prepareImpl(std::size_t pos); template <typename T>
/// Utility function to prepare Any and DynamicAny void prepareImpl(std::size_t pos, const std::vector<T>* pVal = 0)
/// Utility function to prepare Any and DynamicAny.
{
ODBCColumn col(_rStmt, pos);
switch (col.type())
{
case MetaColumn::FDT_INT8:
if (pVal)
return prepareFixedSize<Poco::Int8>(pos, SQL_C_STINYINT, pVal->size());
else
return prepareFixedSize<Poco::Int8>(pos, SQL_C_STINYINT);
case MetaColumn::FDT_UINT8:
if (pVal)
return prepareFixedSize<Poco::UInt8>(pos, SQL_C_UTINYINT, pVal->size());
else
return prepareFixedSize<Poco::UInt8>(pos, SQL_C_UTINYINT);
case MetaColumn::FDT_INT16:
if (pVal)
return prepareFixedSize<Poco::Int16>(pos, SQL_C_SSHORT, pVal->size());
else
return prepareFixedSize<Poco::Int16>(pos, SQL_C_SSHORT);
case MetaColumn::FDT_UINT16:
if (pVal)
return prepareFixedSize<Poco::UInt16>(pos, SQL_C_USHORT, pVal->size());
else
return prepareFixedSize<Poco::UInt16>(pos, SQL_C_USHORT);
case MetaColumn::FDT_INT32:
if (pVal)
return prepareFixedSize<Poco::Int32>(pos, SQL_C_SLONG, pVal->size());
else
return prepareFixedSize<Poco::Int32>(pos, SQL_C_SLONG);
case MetaColumn::FDT_UINT32:
if (pVal)
return prepareFixedSize<Poco::UInt32>(pos, SQL_C_ULONG, pVal->size());
else
return prepareFixedSize<Poco::UInt32>(pos, SQL_C_ULONG);
case MetaColumn::FDT_INT64:
if (pVal)
return prepareFixedSize<Poco::Int64>(pos, SQL_C_SBIGINT, pVal->size());
else
return prepareFixedSize<Poco::Int64>(pos, SQL_C_SBIGINT);
case MetaColumn::FDT_UINT64:
if (pVal)
return prepareFixedSize<Poco::UInt64>(pos, SQL_C_UBIGINT, pVal->size());
else
return prepareFixedSize<Poco::UInt64>(pos, SQL_C_UBIGINT);
case MetaColumn::FDT_BOOL:
if (pVal)
return prepareVariableLen<bool>(pos, SQL_C_BIT, pVal->size(), DT_BOOL);
else
return prepareFixedSize<bool>(pos, SQL_C_BIT);
case MetaColumn::FDT_FLOAT:
if (pVal)
return prepareFixedSize<float>(pos, SQL_C_FLOAT, pVal->size());
else
return prepareFixedSize<float>(pos, SQL_C_FLOAT);
case MetaColumn::FDT_DOUBLE:
if (pVal)
return prepareFixedSize<double>(pos, SQL_C_DOUBLE, pVal->size());
else
return prepareFixedSize<double>(pos, SQL_C_DOUBLE);
case MetaColumn::FDT_STRING:
if (pVal)
return prepareVariableLenArray(pos, SQL_C_CHAR, maxDataSize(pos), pVal->size(), DT_CHAR_ARRAY);
else
return prepareVariableLen<char>(pos, SQL_C_CHAR, maxDataSize(pos), DT_CHAR);
case MetaColumn::FDT_BLOB:
if (pVal)
return prepareVariableLenArray(pos, SQL_C_BINARY, maxDataSize(pos), pVal->size(), DT_CHAR_ARRAY);
else
return prepareVariableLen<char>(pos, SQL_C_BINARY, maxDataSize(pos), DT_CHAR);
case MetaColumn::FDT_DATE:
if (pVal)
return prepareFixedSize<Date>(pos, SQL_C_TYPE_DATE, pVal->size());
else
return prepareFixedSize<Date>(pos, SQL_C_TYPE_DATE);
case MetaColumn::FDT_TIME:
if (pVal)
return prepareFixedSize<Time>(pos, SQL_C_TYPE_TIME, pVal->size());
else
return prepareFixedSize<Time>(pos, SQL_C_TYPE_TIME);
case MetaColumn::FDT_TIMESTAMP:
if (pVal)
return prepareFixedSize<DateTime>(pos, SQL_C_TYPE_TIMESTAMP, pVal->size());
else
return prepareFixedSize<DateTime>(pos, SQL_C_TYPE_TIMESTAMP);
default:
throw DataFormatException("Unsupported data type.");
}
}
void resize() const; void resize() const;
/// Resize the values and lengths vectors. /// Resize the values and lengths vectors.
template <typename T> template <typename T>
void preparePOD(std::size_t pos, SQLSMALLINT valueType) void prepareFixedSize(std::size_t pos, SQLSMALLINT valueType)
/// Utility function for preparation of fixed length columns.
{ {
poco_assert (DE_BOUND == _dataExtraction); poco_assert (DE_BOUND == _dataExtraction);
poco_assert (pos >= 0 && pos < _pValues.size());
std::size_t dataSize = sizeof(T); std::size_t dataSize = sizeof(T);
_pValues[pos] = new Poco::Any(T()); poco_assert (pos < _values.size());
_pLengths[pos] = new SQLLEN; _values[pos] = Poco::Any(T());
*_pLengths[pos] = 0;
T* pVal = AnyCast<T>(_pValues[pos]);
poco_assert_dbg (pVal);
T* pVal = AnyCast<T>(&_values[pos]);
if (Utility::isError(SQLBindCol(_rStmt, if (Utility::isError(SQLBindCol(_rStmt,
(SQLUSMALLINT) pos + 1, (SQLUSMALLINT) pos + 1,
valueType, valueType,
(SQLPOINTER) pVal, (SQLPOINTER) pVal,
(SQLINTEGER) dataSize, (SQLINTEGER) dataSize,
_pLengths[pos]))) &_lengths[pos])))
{ {
throw StatementException(_rStmt, "SQLBindCol()"); throw StatementException(_rStmt, "SQLBindCol()");
} }
} }
template <typename T> template <typename T>
void prepareRaw(std::size_t pos, SQLSMALLINT valueType, std::size_t size) void prepareFixedSize(std::size_t pos, SQLSMALLINT valueType, std::size_t length)
/// Utility function for preparation of fixed length columns that are
/// bound to a std::vector.
{ {
poco_assert (DE_BOUND == _dataExtraction); poco_assert (DE_BOUND == _dataExtraction);
poco_assert (pos >= 0 && pos < _pValues.size()); std::size_t dataSize = sizeof(T);
T* pChr = new T[size]; poco_assert (pos < _values.size());
poco_assert_dbg (pChr); poco_assert (length);
memset(pChr, 0, size); _values[pos] = Poco::Any(std::vector<T>(length));
_lengths[pos] = 0;
SharedPtr<T> sp = pChr; poco_assert (0 == _lenLengths[pos].size());
_pValues[pos] = new Any(sp); _lenLengths[pos].resize(length);
_pLengths[pos] = new SQLLEN;
*_pLengths[pos] = (SQLLEN) size;
std::vector<T>& cache = RefAnyCast<std::vector<T> >(_values[pos]);
if (Utility::isError(SQLBindCol(_rStmt, if (Utility::isError(SQLBindCol(_rStmt,
(SQLUSMALLINT) pos + 1, (SQLUSMALLINT) pos + 1,
valueType, valueType,
(SQLPOINTER) pChr, (SQLPOINTER) &cache[0],
(SQLINTEGER) size, (SQLINTEGER) dataSize,
_pLengths[pos]))) &_lenLengths[pos][0])))
{ {
throw StatementException(_rStmt, "SQLBindCol()"); throw StatementException(_rStmt, "SQLBindCol()");
} }
} }
const StatementHandle& _rStmt; template <typename T>
mutable std::vector<Poco::Any*> _pValues; void prepareVariableLen(std::size_t pos, SQLSMALLINT valueType, std::size_t size, DataType dt)
mutable std::vector<SQLLEN*> _pLengths; /// Utility function for preparation of variable length columns and bool vectors.
std::size_t _maxFieldSize; {
DataExtraction _dataExtraction; poco_assert (DE_BOUND == _dataExtraction);
poco_assert (pos < _values.size());
T* pCache = new T[size];
poco_assert_dbg (pCache);
std::memset(pCache, 0, size);
_values[pos] = Any(pCache);
_lengths[pos] = (SQLLEN) size;
_varLengthArrays.insert(IndexMap::value_type(pos, dt));
if (Utility::isError(SQLBindCol(_rStmt,
(SQLUSMALLINT) pos + 1,
valueType,
(SQLPOINTER) pCache,
(SQLINTEGER) size,
&_lengths[pos])))
{
throw StatementException(_rStmt, "SQLBindCol()");
}
}
void prepareVariableLenArray(std::size_t pos, SQLSMALLINT valueType, std::size_t size, std::size_t length, DataType dt);
/// Utility function for preparation of variable length character and BLOB columns.
void freeMemory() const;
/// Utility function. Releases memory allocated for variable length columns.
template <typename T>
void deleteCachedArray(std::size_t pos) const
{
T* p = Poco::AnyCast<T>(&_values[pos]);
delete [] p;
}
const StatementHandle& _rStmt;
mutable ValueVec _values;
mutable LengthVec _lengths;
mutable LengthLengthVec _lenLengths;
mutable IndexMap _varLengthArrays;
std::size_t _maxFieldSize;
DataExtraction _dataExtraction;
}; };
// //
// inlines // inlines
// //
inline void Preparation::prepare(std::size_t pos, Poco::Int8) inline void Preparation::prepare(std::size_t pos, Poco::Int8&)
{ {
preparePOD<Poco::Int8>(pos, SQL_C_STINYINT); prepareFixedSize<Poco::Int8>(pos, SQL_C_STINYINT);
} }
inline void Preparation::prepare(std::size_t pos, Poco::UInt8) inline void Preparation::prepare(std::size_t pos, std::vector<Poco::Int8>& val)
{ {
preparePOD<Poco::UInt8>(pos, SQL_C_UTINYINT); prepareFixedSize<Poco::Int8>(pos, SQL_C_STINYINT, val.size());
} }
inline void Preparation::prepare(std::size_t pos, Poco::Int16) inline void Preparation::prepare(std::size_t pos, Poco::UInt8&)
{ {
preparePOD<Poco::Int16>(pos, SQL_C_SSHORT); prepareFixedSize<Poco::UInt8>(pos, SQL_C_UTINYINT);
} }
inline void Preparation::prepare(std::size_t pos, Poco::UInt16) inline void Preparation::prepare(std::size_t pos, std::vector<Poco::UInt8>& val)
{ {
preparePOD<Poco::UInt16>(pos, SQL_C_USHORT); prepareFixedSize<Poco::UInt8>(pos, SQL_C_UTINYINT, val.size());
} }
inline void Preparation::prepare(std::size_t pos, Poco::Int32) inline void Preparation::prepare(std::size_t pos, Poco::Int16&)
{ {
preparePOD<Poco::Int32>(pos, SQL_C_SLONG); prepareFixedSize<Poco::Int16>(pos, SQL_C_SSHORT);
} }
inline void Preparation::prepare(std::size_t pos, Poco::UInt32) inline void Preparation::prepare(std::size_t pos, std::vector<Poco::Int16>& val)
{ {
preparePOD<Poco::UInt32>(pos, SQL_C_ULONG); prepareFixedSize<Poco::Int16>(pos, SQL_C_SSHORT, val.size());
} }
inline void Preparation::prepare(std::size_t pos, Poco::Int64) inline void Preparation::prepare(std::size_t pos, Poco::UInt16&)
{ {
preparePOD<Poco::Int64>(pos, SQL_C_SBIGINT); prepareFixedSize<Poco::UInt16>(pos, SQL_C_USHORT);
} }
inline void Preparation::prepare(std::size_t pos, Poco::UInt64) inline void Preparation::prepare(std::size_t pos, std::vector<Poco::UInt16>& val)
{ {
preparePOD<Poco::UInt64>(pos, SQL_C_UBIGINT); prepareFixedSize<Poco::UInt16>(pos, SQL_C_USHORT, val.size());
}
inline void Preparation::prepare(std::size_t pos, Poco::Int32&)
{
prepareFixedSize<Poco::Int32>(pos, SQL_C_SLONG);
}
inline void Preparation::prepare(std::size_t pos, std::vector<Poco::Int32>& val)
{
prepareFixedSize<Poco::Int32>(pos, SQL_C_SLONG, val.size());
}
inline void Preparation::prepare(std::size_t pos, Poco::UInt32&)
{
prepareFixedSize<Poco::UInt32>(pos, SQL_C_ULONG);
}
inline void Preparation::prepare(std::size_t pos, std::vector<Poco::UInt32>& val)
{
prepareFixedSize<Poco::UInt32>(pos, SQL_C_ULONG, val.size());
}
inline void Preparation::prepare(std::size_t pos, Poco::Int64&)
{
prepareFixedSize<Poco::Int64>(pos, SQL_C_SBIGINT);
}
inline void Preparation::prepare(std::size_t pos, std::vector<Poco::Int64>& val)
{
prepareFixedSize<Poco::Int64>(pos, SQL_C_SBIGINT, val.size());
}
inline void Preparation::prepare(std::size_t pos, Poco::UInt64&)
{
prepareFixedSize<Poco::UInt64>(pos, SQL_C_UBIGINT);
}
inline void Preparation::prepare(std::size_t pos, std::vector<Poco::UInt64>& val)
{
prepareFixedSize<Poco::UInt64>(pos, SQL_C_UBIGINT, val.size());
} }
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
inline void Preparation::prepare(std::size_t pos, long) inline void Preparation::prepare(std::size_t pos, long&)
{ {
preparePOD<long>(pos, SQL_C_SLONG); prepareFixedSize<long>(pos, SQL_C_SLONG);
}
inline void Preparation::prepare(std::size_t pos, std::vector<long>& val)
{
prepareFixedSize<long>(pos, SQL_C_SLONG, val.size());
} }
#endif #endif
inline void Preparation::prepare(std::size_t pos, bool) inline void Preparation::prepare(std::size_t pos, bool&)
{ {
preparePOD<bool>(pos, SQL_C_BIT); prepareFixedSize<bool>(pos, SQL_C_BIT);
} }
inline void Preparation::prepare(std::size_t pos, float) inline void Preparation::prepare(std::size_t pos, std::vector<bool>& val)
{ {
preparePOD<float>(pos, SQL_C_FLOAT); prepareVariableLen<bool>(pos, SQL_C_BIT, val.size(), DT_BOOL);
} }
inline void Preparation::prepare(std::size_t pos, double) inline void Preparation::prepare(std::size_t pos, float&)
{ {
preparePOD<double>(pos, SQL_C_DOUBLE); prepareFixedSize<float>(pos, SQL_C_FLOAT);
} }
inline void Preparation::prepare(std::size_t pos, char) inline void Preparation::prepare(std::size_t pos, std::vector<float>& val)
{ {
preparePOD<char>(pos, SQL_C_STINYINT); prepareFixedSize<float>(pos, SQL_C_FLOAT, val.size());
}
inline void Preparation::prepare(std::size_t pos, double&)
{
prepareFixedSize<double>(pos, SQL_C_DOUBLE);
}
inline void Preparation::prepare(std::size_t pos, std::vector<double>& val)
{
prepareFixedSize<double>(pos, SQL_C_DOUBLE, val.size());
}
inline void Preparation::prepare(std::size_t pos, char&)
{
prepareFixedSize<char>(pos, SQL_C_STINYINT);
}
inline void Preparation::prepare(std::size_t pos, std::vector<char>& val)
{
prepareFixedSize<char>(pos, SQL_C_STINYINT, val.size());
} }
inline void Preparation::prepare(std::size_t pos, const std::string&) inline void Preparation::prepare(std::size_t pos, const std::string&)
{ {
prepareRaw<char>(pos, SQL_C_CHAR, maxDataSize(pos)); prepareVariableLen<char>(pos, SQL_C_CHAR, maxDataSize(pos), DT_CHAR);
}
inline void Preparation::prepare(std::size_t pos, const std::vector<std::string>& val)
{
prepareVariableLenArray(pos, SQL_C_CHAR, maxDataSize(pos), val.size(), DT_CHAR_ARRAY);
} }
inline void Preparation::prepare(std::size_t pos, const Poco::Data::BLOB&) inline void Preparation::prepare(std::size_t pos, const Poco::Data::BLOB&)
{ {
prepareRaw<char>(pos, SQL_C_BINARY, maxDataSize(pos)); prepareVariableLen<char>(pos, SQL_C_BINARY, maxDataSize(pos), DT_CHAR);
}
inline void Preparation::prepare(std::size_t pos, const std::vector<Poco::Data::BLOB>& val)
{
prepareVariableLenArray(pos, SQL_C_BINARY, maxDataSize(pos), val.size(), DT_CHAR_ARRAY);
} }
inline void Preparation::prepare(std::size_t pos, const Poco::Data::Date&) inline void Preparation::prepare(std::size_t pos, const Poco::Data::Date&)
{ {
prepareRaw<SQL_DATE_STRUCT>(pos, prepareFixedSize<SQL_DATE_STRUCT>(pos, SQL_C_TYPE_DATE);
SQL_C_TYPE_DATE, }
sizeof(SQL_DATE_STRUCT));
inline void Preparation::prepare(std::size_t pos, const std::vector<Poco::Data::Date>& val)
{
prepareFixedSize<SQL_DATE_STRUCT>(pos, SQL_C_TYPE_DATE, val.size());
} }
inline void Preparation::prepare(std::size_t pos, const Poco::Data::Time&) inline void Preparation::prepare(std::size_t pos, const Poco::Data::Time&)
{ {
prepareRaw<SQL_TIME_STRUCT>(pos, prepareFixedSize<SQL_TIME_STRUCT>(pos, SQL_C_TYPE_TIME);
SQL_C_TYPE_TIME, }
sizeof(SQL_TIME_STRUCT));
inline void Preparation::prepare(std::size_t pos, const std::vector<Poco::Data::Time>& val)
{
prepareFixedSize<SQL_TIME_STRUCT>(pos, SQL_C_TYPE_TIME, val.size());
} }
inline void Preparation::prepare(std::size_t pos, const Poco::DateTime&) inline void Preparation::prepare(std::size_t pos, const Poco::DateTime&)
{ {
prepareRaw<SQL_TIMESTAMP_STRUCT>(pos, prepareFixedSize<SQL_TIMESTAMP_STRUCT>(pos, SQL_C_TYPE_TIMESTAMP);
SQL_C_TYPE_TIMESTAMP,
sizeof(SQL_TIMESTAMP_STRUCT));
} }
inline int Preparation::actualDataSize(std::size_t pos) const inline void Preparation::prepare(std::size_t pos, const std::vector<Poco::DateTime>& val)
{ {
poco_assert (pos >= 0 && pos < _pValues.size()); prepareFixedSize<SQL_TIMESTAMP_STRUCT>(pos, SQL_C_TYPE_TIMESTAMP, val.size());
poco_assert (_pLengths[pos]); }
return *_pLengths[pos];
inline void Preparation::prepare(std::size_t pos, const Poco::Any& val)
{
prepareImpl<Poco::Any>(pos);
}
inline void Preparation::prepare(std::size_t pos, const std::vector<Poco::Any>& val)
{
prepareImpl<Poco::Any>(pos, &val);
}
inline void Preparation::prepare(std::size_t pos, const Poco::DynamicAny& val)
{
prepareImpl<Poco::DynamicAny>(pos);
}
inline void Preparation::prepare(std::size_t pos, const std::vector<Poco::DynamicAny>& val)
{
prepareImpl<Poco::DynamicAny>(pos, &val);
}
inline std::size_t Preparation::actualDataSize(std::size_t col, std::size_t row) const
{
poco_assert (col < _values.size());
if (INVALID_ROW == row) return _lengths[col];
else return _lenLengths[col].at(row);
}
inline std::size_t Preparation::bulkSize(std::size_t col) const
{
poco_assert (col < _lenLengths.size());
return _lenLengths[col].size();
} }
@@ -427,6 +791,14 @@ inline Preparation::DataExtraction Preparation::getDataExtraction() const
} }
inline Poco::Any& Preparation::operator [] (std::size_t pos)
{
poco_assert (pos < _values.size());
return _values[pos];
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@@ -97,21 +97,39 @@ public:
static void dateSync(Date& dt, const SQL_DATE_STRUCT& ts); static void dateSync(Date& dt, const SQL_DATE_STRUCT& ts);
/// Transfers data from ODBC SQL_DATE_STRUCT to Poco::DateTime. /// Transfers data from ODBC SQL_DATE_STRUCT to Poco::DateTime.
static void dateSync(std::vector<Date>& d, const std::vector<SQL_DATE_STRUCT>& ds);
/// Transfers data from ODBC SQL_DATE_STRUCT vector to Poco::DateTime vector.
static void timeSync(Time& dt, const SQL_TIME_STRUCT& ts); static void timeSync(Time& dt, const SQL_TIME_STRUCT& ts);
/// Transfers data from ODBC SQL_TIME_STRUCT to Poco::DateTime. /// Transfers data from ODBC SQL_TIME_STRUCT to Poco::DateTime.
static void timeSync(std::vector<Time>& t, const std::vector<SQL_TIME_STRUCT>& ts);
/// Transfers data from ODBC SQL_TIME_STRUCT vector to Poco::DateTime vector.
static void dateTimeSync(Poco::DateTime& dt, const SQL_TIMESTAMP_STRUCT& ts); static void dateTimeSync(Poco::DateTime& dt, const SQL_TIMESTAMP_STRUCT& ts);
/// Transfers data from ODBC SQL_TIMESTAMP_STRUCT to Poco::DateTime. /// Transfers data from ODBC SQL_TIMESTAMP_STRUCT to Poco::DateTime.
static void dateTimeSync(std::vector<Poco::DateTime>& dt, const std::vector<SQL_TIMESTAMP_STRUCT>& ts);
/// Transfers data from ODBC SQL_TIMESTAMP_STRUCT vector to Poco::DateTime vector.
static void dateSync(SQL_DATE_STRUCT& ts, const Date& dt); static void dateSync(SQL_DATE_STRUCT& ts, const Date& dt);
/// Transfers data from Poco::Data::Date to ODBC SQL_DATE_STRUCT. /// Transfers data from Poco::Data::Date to ODBC SQL_DATE_STRUCT.
static void dateSync(std::vector<SQL_DATE_STRUCT>& ds, const std::vector<Date>& d);
/// Transfers data from Poco::Data::Date vector to ODBC SQL_DATE_STRUCT vector.
static void timeSync(SQL_TIME_STRUCT& ts, const Time& dt); static void timeSync(SQL_TIME_STRUCT& ts, const Time& dt);
/// Transfers data from Poco::Data::Time to ODBC SQL_TIME_STRUCT. /// Transfers data from Poco::Data::Time to ODBC SQL_TIME_STRUCT.
static void timeSync(std::vector<SQL_TIME_STRUCT>& ts, const std::vector<Time>& t);
/// Transfers data from Poco::Data::Time vector to ODBC SQL_TIME_STRUCT vector.
static void dateTimeSync(SQL_TIMESTAMP_STRUCT& ts, const Poco::DateTime& dt); static void dateTimeSync(SQL_TIMESTAMP_STRUCT& ts, const Poco::DateTime& dt);
/// Transfers data from Poco::DateTime to ODBC SQL_TIMESTAMP_STRUCT. /// Transfers data from Poco::DateTime to ODBC SQL_TIMESTAMP_STRUCT.
static void dateTimeSync(std::vector<SQL_TIMESTAMP_STRUCT>& ts, const std::vector<Poco::DateTime>& dt);
/// Transfers data from Poco::DateTime to ODBC SQL_TIMESTAMP_STRUCT.
private: private:
static const TypeInfo _dataTypes; static const TypeInfo _dataTypes;
/// C <==> SQL data type mapping /// C <==> SQL data type mapping
@@ -139,15 +157,15 @@ inline int Utility::sqlDataType(int cDataType)
} }
inline void Utility::dateSync(Date& dt, const SQL_DATE_STRUCT& ts) inline void Utility::dateSync(Date& d, const SQL_DATE_STRUCT& ts)
{ {
dt.assign(ts.year, ts.month, ts.day); d.assign(ts.year, ts.month, ts.day);
} }
inline void Utility::timeSync(Time& dt, const SQL_TIME_STRUCT& ts) inline void Utility::timeSync(Time& t, const SQL_TIME_STRUCT& ts)
{ {
dt.assign(ts.hour, ts.minute, ts.second); t.assign(ts.hour, ts.minute, ts.second);
} }

View File

@@ -48,12 +48,15 @@ namespace Data {
namespace ODBC { namespace ODBC {
Binder::Binder(const StatementHandle& rStmt, Binder::Binder(const StatementHandle& rStmt,
std::size_t maxFieldSize,
Binder::ParameterBinding dataBinding, Binder::ParameterBinding dataBinding,
TypeInfo* pDataTypes): TypeInfo* pDataTypes):
_rStmt(rStmt), _rStmt(rStmt),
_paramBinding(dataBinding), _paramBinding(dataBinding),
_pTypeInfo(pDataTypes) _pTypeInfo(pDataTypes),
_paramSetSize(0),
_maxFieldSize(maxFieldSize)
{ {
} }
@@ -71,6 +74,42 @@ Binder::~Binder()
StringMap::iterator itStr = _strings.begin(); StringMap::iterator itStr = _strings.begin();
StringMap::iterator itStrEnd = _strings.end(); StringMap::iterator itStrEnd = _strings.end();
for(; itStr != itStrEnd; ++itStr) std::free(itStr->first); for(; itStr != itStrEnd; ++itStr) std::free(itStr->first);
CharPtrVec::iterator itChr = _charPtrs.begin();
CharPtrVec::iterator endChr = _charPtrs.end();
for (; itChr != endChr; ++itChr) delete [] *itChr;
}
void Binder::freeMemory()
{
LengthVec::iterator itLen = _lengthIndicator.begin();
LengthVec::iterator itLenEnd = _lengthIndicator.end();
for(; itLen != itLenEnd; ++itLen) delete *itLen;
TimeMap::iterator itT = _times.begin();
TimeMap::iterator itTEnd = _times.end();
for(; itT != itTEnd; ++itT) delete itT->first;
DateMap::iterator itD = _dates.begin();
DateMap::iterator itDEnd = _dates.end();
for(; itD != itDEnd; ++itD) delete itD->first;
TimestampMap::iterator itTS = _timestamps.begin();
TimestampMap::iterator itTSEnd = _timestamps.end();
for(; itTS != itTSEnd; ++itTS) delete itTS->first;
StringMap::iterator itStr = _strings.begin();
StringMap::iterator itStrEnd = _strings.end();
for(; itStr != itStrEnd; ++itStr) std::free(itStr->first);
CharPtrVec::iterator itChr = _charPtrs.begin();
CharPtrVec::iterator endChr = _charPtrs.end();
for (; itChr != endChr; ++itChr) std::free(*itChr);
BoolPtrVec::iterator itBool = _boolPtrs.begin();
BoolPtrVec::iterator endBool = _boolPtrs.end();
for (; itBool != endBool; ++itBool) delete [] *itBool;
} }
@@ -81,29 +120,7 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
if (isOutBound(dir)) if (isOutBound(dir))
{ {
try getColumnOrParameterSize(pos, size);
{
Parameter p(_rStmt, pos);
size = (SQLUINTEGER) p.columnSize();
}
catch (StatementException&)
{
size = DEFAULT_PARAM_SIZE;
//On Linux, PostgreSQL driver segfaults on SQLGetDescField, so this is disabled for now
#ifdef POCO_OS_FAMILY_WINDOWS
SQLHDESC hIPD = 0;
if (!Utility::isError(SQLGetStmtAttr(_rStmt, SQL_ATTR_IMP_PARAM_DESC, &hIPD, SQL_IS_POINTER, 0)))
{
SQLUINTEGER sz = 0;
if (!Utility::isError(SQLGetDescField(hIPD, (SQLSMALLINT) pos + 1, SQL_DESC_LENGTH, &sz, SQL_IS_UINTEGER, 0)) &&
sz > 0)
{
size = sz;
}
}
#endif
}
char* pChar = (char*) std::calloc(size, sizeof(char)); char* pChar = (char*) std::calloc(size, sizeof(char));
pVal = (SQLPOINTER) pChar; pVal = (SQLPOINTER) pChar;
_outParams.insert(ParamMap::value_type(pVal, size)); _outParams.insert(ParamMap::value_type(pVal, size));
@@ -115,7 +132,7 @@ void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
_inParams.insert(ParamMap::value_type(pVal, size)); _inParams.insert(ParamMap::value_type(pVal, size));
} }
else else
throw IllegalStateException("Parameter must be [in] OR [out] bound."); throw InvalidArgumentException("Parameter must be [in] OR [out] bound.");
SQLLEN* pLenIn = new SQLLEN; SQLLEN* pLenIn = new SQLLEN;
*pLenIn = SQL_NTS; *pLenIn = SQL_NTS;
@@ -141,7 +158,64 @@ 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, Direction dir) void Binder::bind(std::size_t pos, const std::vector<std::string>& val, Direction dir)
{
if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("String vector parameter type can only be inbound.");
if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("std::vector can only be bound immediately.");
if (0 == val.size())
throw InvalidArgumentException("Empty vector not allowed.");
setParamSetSize(pos, val.size());
SQLINTEGER size = 0;
getColumnOrParameterSize(pos, size);
poco_assert (size > 0);
if (_vecLengthIndicator.size() <= pos)
{
_vecLengthIndicator.resize(pos + 1);
_vecLengthIndicator[pos].resize(val.size(), SQL_NTS);
}
if (_charPtrs.size() <= pos)
_charPtrs.resize(pos + 1, 0);
_charPtrs[pos] = (char*) std::calloc(val.size() * size, sizeof(char));
std::size_t strSize;
std::size_t offset = 0;
std::vector<std::string>::const_iterator it = val.begin();
std::vector<std::string>::const_iterator end = val.end();
for (; it != end; ++it)
{
strSize = it->size();
if (strSize > size)
throw LengthExceededException("SQLBindParameter(std::vector<std::string>)");
std::memcpy(_charPtrs[pos] + offset, it->c_str(), strSize);
offset += size;
}
if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1,
toODBCDirection(dir),
SQL_C_CHAR,
SQL_LONGVARCHAR,
(SQLUINTEGER) size - 1,
0,
_charPtrs[pos],
(SQLINTEGER) size,
&_vecLengthIndicator[pos][0])))
{
throw StatementException(_rStmt, "SQLBindParameter(std::vector<std::string>)");
}
}
void Binder::bind(std::size_t pos, const BLOB& val, Direction dir)
{ {
if (isOutBound(dir) || !isInBound(dir)) if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("BLOB parameter type can only be inbound."); throw NotImplementedException("BLOB parameter type can only be inbound.");
@@ -175,6 +249,78 @@ void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir)
} }
void Binder::bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir)
{
if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("BLOB vector parameter type can only be inbound.");
if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("std::vector can only be bound immediately.");
if (0 == val.size())
throw InvalidArgumentException("Empty vector not allowed.");
setParamSetSize(pos, val.size());
SQLINTEGER size = 0;
getColumnOrParameterSize(pos, size);
poco_assert (size > 0);
if (size == _maxFieldSize)
{
std::size_t maxSize = 0;
std::vector<BLOB>::const_iterator it = val.begin();
std::vector<BLOB>::const_iterator end = val.end();
for (; it != end; ++it)
{
std::size_t sz = it->size();
if (sz < _maxFieldSize && sz > maxSize)
maxSize = sz;
}
if (maxSize) size = maxSize;
}
if (_vecLengthIndicator.size() <= pos)
{
_vecLengthIndicator.resize(pos + 1);
_vecLengthIndicator[pos].resize(val.size(), SQL_NTS);
}
if (_charPtrs.size() <= pos)
_charPtrs.resize(pos + 1, 0);
_charPtrs[pos] = (char*) std::calloc(val.size() * size, sizeof(char));
poco_check_ptr (_charPtrs[pos]);
std::size_t blobSize;
std::size_t offset = 0;
std::vector<BLOB>::const_iterator it = val.begin();
std::vector<BLOB>::const_iterator end = val.end();
for (; it != end; ++it)
{
blobSize = it->size();
if (blobSize > size)
throw LengthExceededException("SQLBindParameter(std::vector<BLOB>)");
std::memcpy(_charPtrs[pos] + offset, it->rawContent(), blobSize);
offset += size;
}
if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1,
SQL_PARAM_INPUT,
SQL_C_BINARY,
SQL_LONGVARBINARY,
(SQLUINTEGER) size,
0,
_charPtrs[pos],
(SQLINTEGER) size,
&_vecLengthIndicator[pos][0])))
{
throw StatementException(_rStmt, "SQLBindParameter(std::vector<BLOB>)");
}
}
void Binder::bind(std::size_t pos, const Date& val, Direction dir) void Binder::bind(std::size_t pos, const Date& val, Direction dir)
{ {
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_DATE_STRUCT); SQLINTEGER size = (SQLINTEGER) sizeof(SQL_DATE_STRUCT);
@@ -203,7 +349,51 @@ void Binder::bind(std::size_t pos, const Date& val, Direction dir)
0, 0,
_lengthIndicator.back()))) _lengthIndicator.back())))
{ {
throw StatementException(_rStmt, "SQLBindParameter(BLOB)"); throw StatementException(_rStmt, "SQLBindParameter(Date)");
}
}
void Binder::bind(std::size_t pos, const std::vector<Date>& val, Direction dir)
{
if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("Date vector parameter type can only be inbound.");
if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("std::vector can only be bound immediately.");
if (0 == val.size())
throw InvalidArgumentException("Empty vector not allowed.");
setParamSetSize(pos, val.size());
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_DATE_STRUCT);
if (_vecLengthIndicator.size() <= pos)
{
_vecLengthIndicator.resize(pos + 1);
_vecLengthIndicator[pos].resize(val.size(), size);
}
if (_dateVec.size() <= pos) _dateVec.resize(pos + 1);
Utility::dateSync(_dateVec[pos], val);
SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, SQL_TYPE_DATE, colSize, decDigits);
if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1,
toODBCDirection(dir),
SQL_C_DATE,
SQL_DATE,
colSize,
decDigits,
(SQLPOINTER) &_dateVec[pos][0],
0,
&_vecLengthIndicator[pos][0])))
{
throw StatementException(_rStmt, "SQLBindParameter(Date[])");
} }
} }
@@ -236,7 +426,51 @@ void Binder::bind(std::size_t pos, const Time& val, Direction dir)
0, 0,
_lengthIndicator.back()))) _lengthIndicator.back())))
{ {
throw StatementException(_rStmt, "SQLBindParameter(BLOB)"); throw StatementException(_rStmt, "SQLBindParameter(Time)");
}
}
void Binder::bind(std::size_t pos, const std::vector<Time>& val, Direction dir)
{
if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("Time vector parameter type can only be inbound.");
if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("std::vector can only be bound immediately.");
if (0 == val.size())
throw InvalidArgumentException("Empty vector not allowed.");
setParamSetSize(pos, val.size());
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_TIME_STRUCT);
if (_vecLengthIndicator.size() <= pos)
{
_vecLengthIndicator.resize(pos + 1);
_vecLengthIndicator[pos].resize(val.size(), size);
}
if (_timeVec.size() <= pos) _timeVec.resize(pos + 1);
Utility::timeSync(_timeVec[pos], val);
SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, SQL_TYPE_TIME, colSize, decDigits);
if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1,
toODBCDirection(dir),
SQL_C_TIME,
SQL_TIME,
colSize,
decDigits,
(SQLPOINTER) &_timeVec[pos][0],
0,
&_vecLengthIndicator[pos][0])))
{
throw StatementException(_rStmt, "SQLBindParameter(Time[])");
} }
} }
@@ -251,7 +485,7 @@ void Binder::bind(std::size_t pos, const Poco::DateTime& val, Direction dir)
SQL_TIMESTAMP_STRUCT* pTS = new SQL_TIMESTAMP_STRUCT; SQL_TIMESTAMP_STRUCT* pTS = new SQL_TIMESTAMP_STRUCT;
Utility::dateTimeSync(*pTS, val); Utility::dateTimeSync(*pTS, val);
_timestamps.insert(TimestampMap::value_type(pTS, const_cast<DateTime*>(&val))); _timestamps.insert(TimestampMap::value_type(pTS, const_cast<DateTime*>(&val)));
SQLINTEGER colSize = 0; SQLINTEGER colSize = 0;
@@ -269,7 +503,51 @@ void Binder::bind(std::size_t pos, const Poco::DateTime& val, Direction dir)
0, 0,
_lengthIndicator.back()))) _lengthIndicator.back())))
{ {
throw StatementException(_rStmt, "SQLBindParameter(BLOB)"); throw StatementException(_rStmt, "SQLBindParameter(DateTime)");
}
}
void Binder::bind(std::size_t pos, const std::vector<DateTime>& val, Direction dir)
{
if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("DateTime vector parameter type can only be inbound.");
if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("std::vector can only be bound immediately.");
if (0 == val.size())
throw InvalidArgumentException("Empty vector not allowed.");
setParamSetSize(pos, val.size());
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_TIMESTAMP_STRUCT);
if (_vecLengthIndicator.size() <= pos)
{
_vecLengthIndicator.resize(pos + 1);
_vecLengthIndicator[pos].resize(val.size(), size);
}
if (_dateTimeVec.size() <= pos) _dateTimeVec.resize(pos + 1);
Utility::dateTimeSync(_dateTimeVec[pos], val);
SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, SQL_TYPE_TIME, colSize, decDigits);
if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1,
toODBCDirection(dir),
SQL_C_TIMESTAMP,
SQL_TIMESTAMP,
colSize,
decDigits,
(SQLPOINTER) &_dateTimeVec[pos][0],
0,
&_vecLengthIndicator[pos][0])))
{
throw StatementException(_rStmt, "SQLBindParameter(Time[])");
} }
} }
@@ -279,34 +557,6 @@ void Binder::bind(std::size_t pos, const NullData& val, Direction dir)
if (isOutBound(dir) || !isInBound(dir)) if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("NULL parameter type can only be inbound."); throw NotImplementedException("NULL parameter type can only be inbound.");
switch (val)
{
case NULL_GENERIC:
case NULL_INT8: bindNull(pos, SQL_C_STINYINT); break;
case NULL_UINT8: bindNull(pos, SQL_C_UTINYINT); break;
case NULL_INT16: bindNull(pos, SQL_C_SSHORT); break;
case NULL_UINT16: bindNull(pos, SQL_C_USHORT); break;
case NULL_INT32: bindNull(pos, SQL_C_SLONG); break;
case NULL_UINT32: bindNull(pos, SQL_C_ULONG); break;
case NULL_INT64: bindNull(pos, SQL_C_SBIGINT); break;
case NULL_UINT64: bindNull(pos, SQL_C_UBIGINT); break;
case NULL_BOOL: bindNull(pos, SQL_C_BIT); break;
case NULL_FLOAT: bindNull(pos, SQL_C_FLOAT); break;
case NULL_DOUBLE: bindNull(pos, SQL_C_DOUBLE); break;
case NULL_STRING: bindNull(pos, SQL_C_CHAR); break;
case NULL_BLOB: bindNull(pos, SQL_C_BINARY); break;
case NULL_DATE: bindNull(pos, SQL_C_DATE); break;
case NULL_TIME: bindNull(pos, SQL_C_TIME); break;
case NULL_TIMESTAMP: bindNull(pos, SQL_C_TIMESTAMP); break;
default:
throw DataFormatException("Unsupported data type.");
}
}
void Binder::bindNull(std::size_t pos, SQLSMALLINT cDataType)
{
_inParams.insert(ParamMap::value_type(0, 0)); _inParams.insert(ParamMap::value_type(0, 0));
SQLLEN* pLenIn = new SQLLEN; SQLLEN* pLenIn = new SQLLEN;
@@ -316,13 +566,13 @@ void Binder::bindNull(std::size_t pos, SQLSMALLINT cDataType)
SQLINTEGER colSize = 0; SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0; SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, cDataType, colSize, decDigits); getColSizeAndPrecision(pos, SQL_C_STINYINT, colSize, decDigits);
if (Utility::isError(SQLBindParameter(_rStmt, if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1, (SQLUSMALLINT) pos + 1,
SQL_PARAM_INPUT, SQL_PARAM_INPUT,
cDataType, SQL_C_STINYINT,
Utility::sqlDataType(cDataType), Utility::sqlDataType(SQL_C_STINYINT),
colSize, colSize,
decDigits, decDigits,
0, 0,
@@ -334,6 +584,90 @@ void Binder::bindNull(std::size_t pos, SQLSMALLINT cDataType)
} }
void Binder::bind(std::size_t pos, const std::vector<NullData>& val, Direction dir)
{
if (isOutBound(dir) || !isInBound(dir))
throw NotImplementedException("DateTime vector parameter type can only be inbound.");
if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("std::vector can only be bound immediately.");
if (0 == val.size())
throw InvalidArgumentException("Empty vector not allowed.");
setParamSetSize(pos, val.size());
SQLINTEGER size = SQL_NULL_DATA;
if (_vecLengthIndicator.size() <= pos)
{
_vecLengthIndicator.resize(pos + 1);
_vecLengthIndicator[pos].resize(val.size(), size);
}
SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, SQL_TYPE_TIME, colSize, decDigits);
if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1,
SQL_PARAM_INPUT,
SQL_C_STINYINT,
Utility::sqlDataType(SQL_C_STINYINT),
colSize,
decDigits,
0,
0,
&_vecLengthIndicator[pos][0])))
{
throw StatementException(_rStmt, "SQLBindParameter()");
}
}
void Binder::bindImplVecBool(std::size_t pos, const std::vector<bool>& val, SQLSMALLINT cDataType, Direction dir)
{
if (PB_IMMEDIATE != _paramBinding)
throw InvalidAccessException("std::vector can only be bound immediately.");
std::size_t length = val.size();
SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, cDataType, colSize, decDigits);
setParamSetSize(pos, val.size());
if (_vecLengthIndicator.size() <= pos)
{
_vecLengthIndicator.resize(pos + 1);
_vecLengthIndicator[pos].resize(length, sizeof(bool));
}
if (_boolPtrs.size() <= pos)
_boolPtrs.resize(pos + 1);
_boolPtrs[pos] = new bool[val.size()];
std::vector<bool>::const_iterator it = val.begin();
std::vector<bool>::const_iterator end = val.end();
for (int i = 0; it != end; ++it, ++i) _boolPtrs[pos][i] = *it;
if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1,
toODBCDirection(dir),
cDataType,
Utility::sqlDataType(cDataType),
colSize,
decDigits,
(SQLPOINTER) &_boolPtrs[pos][0],
0,
&_vecLengthIndicator[pos][0])))
{
throw StatementException(_rStmt, "SQLBindParameter()");
}
}
std::size_t Binder::parameterSize(SQLPOINTER pAddr) const std::size_t Binder::parameterSize(SQLPOINTER pAddr) const
{ {
ParamMap::const_iterator it = _inParams.find(pAddr); ParamMap::const_iterator it = _inParams.find(pAddr);
@@ -370,40 +704,41 @@ void Binder::synchronize()
{ {
if (_dates.size()) if (_dates.size())
{ {
DateMap::iterator itTS = _dates.begin(); DateMap::iterator it = _dates.begin();
DateMap::iterator itTSEnd = _dates.end(); DateMap::iterator end = _dates.end();
for(; itTS != itTSEnd; ++itTS) for(; it != end; ++it)
Utility::dateSync(*itTS->second, *itTS->first); Utility::dateSync(*it->second, *it->first);
} }
if (_times.size()) if (_times.size())
{ {
TimeMap::iterator itTS = _times.begin(); TimeMap::iterator it = _times.begin();
TimeMap::iterator itTSEnd = _times.end(); TimeMap::iterator end = _times.end();
for(; itTS != itTSEnd; ++itTS) for(; it != end; ++it)
Utility::timeSync(*itTS->second, *itTS->first); Utility::timeSync(*it->second, *it->first);
} }
if (_timestamps.size()) if (_timestamps.size())
{ {
TimestampMap::iterator itTS = _timestamps.begin(); TimestampMap::iterator it = _timestamps.begin();
TimestampMap::iterator itTSEnd = _timestamps.end(); TimestampMap::iterator end = _timestamps.end();
for(; itTS != itTSEnd; ++itTS) for(; it != end; ++it)
Utility::dateTimeSync(*itTS->second, *itTS->first); Utility::dateTimeSync(*it->second, *it->first);
} }
if (_strings.size()) if (_strings.size())
{ {
StringMap::iterator itStr = _strings.begin(); StringMap::iterator it = _strings.begin();
StringMap::iterator itStrEnd = _strings.end(); StringMap::iterator end = _strings.end();
for(; itStr != itStrEnd; ++itStr) for(; it != end; ++it)
itStr->second->assign(itStr->first, strlen(itStr->first)); it->second->assign(it->first, strlen(it->first));
} }
} }
void Binder::reset() void Binder::reset()
{ {
freeMemory();
LengthVec().swap(_lengthIndicator); LengthVec().swap(_lengthIndicator);
_inParams.clear(); _inParams.clear();
_outParams.clear(); _outParams.clear();
@@ -411,6 +746,11 @@ void Binder::reset()
_times.clear(); _times.clear();
_timestamps.clear(); _timestamps.clear();
_strings.clear(); _strings.clear();
_dateVec.clear();
_timeVec.clear();
_dateTimeVec.clear();
_charPtrs.clear();
_boolPtrs.clear();
} }
@@ -429,27 +769,23 @@ void Binder::getColSizeAndPrecision(std::size_t pos,
decDigits = _pTypeInfo->getInfo(cDataType, "MINIMUM_SCALE"); decDigits = _pTypeInfo->getInfo(cDataType, "MINIMUM_SCALE");
return; return;
} }
else } catch (NotFoundException&) { }
throw NotFoundException();
}catch (NotFoundException&) try
{ {
try Parameter p(_rStmt, pos);
{ colSize = (SQLINTEGER) p.columnSize();
Parameter p(_rStmt, pos); decDigits = (SQLSMALLINT) p.decimalDigits();
colSize = (SQLINTEGER) p.columnSize(); return;
decDigits = (SQLSMALLINT) p.decimalDigits(); } catch (StatementException&) { }
return;
}catch (StatementException&) try
{ {
try ODBCColumn c(_rStmt, pos);
{ colSize = (SQLINTEGER) c.length();
ODBCColumn c(_rStmt, pos); decDigits = (SQLSMALLINT) c.precision();
colSize = (SQLINTEGER) c.length(); return;
decDigits = (SQLSMALLINT) c.precision(); } catch (StatementException&) { }
return;
}catch (StatementException&) { }
}
}
// no success, set to zero and hope for the best // no success, set to zero and hope for the best
// (most drivers do not require these most of the times anyway) // (most drivers do not require these most of the times anyway)
@@ -459,4 +795,67 @@ void Binder::getColSizeAndPrecision(std::size_t pos,
} }
void Binder::getColumnOrParameterSize(std::size_t pos, SQLINTEGER& size)
{
std::size_t colSize = 0;
std::size_t paramSize = 0;
try
{
ODBCColumn col(_rStmt, pos);
colSize = col.length();
}
catch (StatementException&) { }
try
{
Parameter p(_rStmt, pos);
paramSize = p.columnSize();
}
catch (StatementException&)
{
size = DEFAULT_PARAM_SIZE;
//On Linux, PostgreSQL driver segfaults on SQLGetDescField, so this is disabled for now
#ifdef POCO_OS_FAMILY_WINDOWS
SQLHDESC hIPD = 0;
if (!Utility::isError(SQLGetStmtAttr(_rStmt, SQL_ATTR_IMP_PARAM_DESC, &hIPD, SQL_IS_POINTER, 0)))
{
SQLUINTEGER sz = 0;
if (!Utility::isError(SQLGetDescField(hIPD, (SQLSMALLINT) pos + 1, SQL_DESC_LENGTH, &sz, SQL_IS_UINTEGER, 0)) &&
sz > 0)
{
size = sz;
}
}
#endif
}
if (colSize > 0 && paramSize > 0)
size = colSize < paramSize ? colSize : paramSize;
else if (colSize > 0)
size = colSize;
else if (paramSize > 0)
size = paramSize;
if (size > _maxFieldSize) size = _maxFieldSize;
}
void Binder::setParamSetSize(std::size_t pos, std::size_t length)
{
if (0 == _paramSetSize)
{
if (Utility::isError(SQLSetStmtAttr(_rStmt, SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, SQL_IS_UINTEGER)) ||
Utility::isError(SQLSetStmtAttr(_rStmt, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER) length, SQL_IS_UINTEGER)))
throw StatementException(_rStmt, "SQLSetStmtAttr()");
if (Utility::isError(SQLGetStmtAttr(_rStmt, SQL_ATTR_PARAMSET_SIZE, &_paramSetSize, 0, 0)))
throw StatementException(_rStmt, "SQLGetStmtAttr()");
}
if (_paramSetSize != length)
throw InvalidArgumentException("Invalid parameter array length.");
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@@ -73,11 +73,29 @@ bool Extractor::extractBoundImpl<std::string>(std::size_t pos, std::string& val)
if (isNull(pos)) return false; if (isNull(pos)) return false;
std::size_t dataSize = _rPreparation.actualDataSize(pos); std::size_t dataSize = _rPreparation.actualDataSize(pos);
SharedPtr<char>& sp = RefAnyCast<SharedPtr<char> >(_rPreparation[pos]); char* sp = AnyCast<char*>(_rPreparation[pos]);
std::size_t len = strlen(sp); std::size_t len = strlen(sp);
if (len < dataSize) dataSize = len; if (len < dataSize) dataSize = len;
checkDataSize(dataSize); checkDataSize(dataSize);
val.assign(sp, dataSize); val.assign(sp, dataSize);
return true;
}
template<>
bool Extractor::extractBoundImpl<std::vector<std::string> >(std::size_t pos,
std::vector<std::string>& values)
{
char** pc = AnyCast<char*>(&_rPreparation[pos]);
poco_assert_dbg (pc);
poco_assert_dbg (_rPreparation.bulkSize() == values.size());
std::size_t colWidth = columnSize(pos);
std::vector<std::string>::iterator it = values.begin();
std::vector<std::string>::iterator end = values.end();
for (int row = 0; it != end; ++it, ++row)
it->assign(*pc + row * colWidth, _rPreparation.actualDataSize(pos, row));
return true; return true;
} }
@@ -89,8 +107,26 @@ bool Extractor::extractBoundImpl<Poco::Data::BLOB>(std::size_t pos, Poco::Data::
std::size_t dataSize = _rPreparation.actualDataSize(pos); std::size_t dataSize = _rPreparation.actualDataSize(pos);
checkDataSize(dataSize); checkDataSize(dataSize);
SharedPtr<char>& sp = RefAnyCast<SharedPtr<char> >(_rPreparation[pos]); char* sp = AnyCast<char*>(_rPreparation[pos]);
val.assignRaw(sp, dataSize); val.assignRaw(sp, dataSize);
return true;
}
template<>
bool Extractor::extractBoundImpl<std::vector<Poco::Data::BLOB> >(std::size_t pos,
std::vector<Poco::Data::BLOB>& values)
{
char** pc = AnyCast<char*>(&_rPreparation[pos]);
poco_assert_dbg (pc);
poco_assert_dbg (_rPreparation.bulkSize() == values.size());
std::size_t colWidth = columnSize(pos);
std::vector<Poco::Data::BLOB>::iterator it = values.begin();
std::vector<Poco::Data::BLOB>::iterator end = values.end();
for (int row = 0; it != end; ++it, ++row)
it->assignRaw(*pc + row * colWidth, _rPreparation.actualDataSize(pos, row));
return true; return true;
} }
@@ -99,12 +135,18 @@ template<>
bool Extractor::extractBoundImpl<Poco::Data::Date>(std::size_t pos, Poco::Data::Date& val) bool Extractor::extractBoundImpl<Poco::Data::Date>(std::size_t pos, Poco::Data::Date& val)
{ {
if (isNull(pos)) return false; if (isNull(pos)) return false;
SQL_DATE_STRUCT& ds = *AnyCast<SQL_DATE_STRUCT>(&_rPreparation[pos]);
Utility::dateSync(val, ds);
return true;
}
std::size_t dataSize = _rPreparation.actualDataSize(pos);
checkDataSize(dataSize); template<>
SharedPtr<SQL_DATE_STRUCT>& sp = RefAnyCast<SharedPtr<SQL_DATE_STRUCT> >(_rPreparation[pos]); bool Extractor::extractBoundImpl<std::vector<Poco::Data::Date> >(std::size_t pos,
std::vector<Poco::Data::Date>& val)
Utility::dateSync(val, *sp); {
std::vector<SQL_DATE_STRUCT>& ds = RefAnyCast<std::vector<SQL_DATE_STRUCT> >(_rPreparation[pos]);
Utility::dateSync(val, ds);
return true; return true;
} }
@@ -116,9 +158,19 @@ bool Extractor::extractBoundImpl<Poco::Data::Time>(std::size_t pos, Poco::Data::
std::size_t dataSize = _rPreparation.actualDataSize(pos); std::size_t dataSize = _rPreparation.actualDataSize(pos);
checkDataSize(dataSize); checkDataSize(dataSize);
SharedPtr<SQL_TIME_STRUCT>& sp = RefAnyCast<SharedPtr<SQL_TIME_STRUCT> >(_rPreparation[pos]); SQL_TIME_STRUCT& ts = *AnyCast<SQL_TIME_STRUCT>(&_rPreparation[pos]);
Utility::timeSync(val, ts);
Utility::timeSync(val, *sp);
return true;
}
template<>
bool Extractor::extractBoundImpl<std::vector<Poco::Data::Time> >(std::size_t pos,
std::vector<Poco::Data::Time>& val)
{
std::vector<SQL_TIME_STRUCT>& ds = RefAnyCast<std::vector<SQL_TIME_STRUCT> >(_rPreparation[pos]);
Utility::timeSync(val, ds);
return true; return true;
} }
@@ -130,9 +182,31 @@ bool Extractor::extractBoundImpl<Poco::DateTime>(std::size_t pos, Poco::DateTime
std::size_t dataSize = _rPreparation.actualDataSize(pos); std::size_t dataSize = _rPreparation.actualDataSize(pos);
checkDataSize(dataSize); checkDataSize(dataSize);
SharedPtr<SQL_TIMESTAMP_STRUCT>& sp = RefAnyCast<SharedPtr<SQL_TIMESTAMP_STRUCT> >(_rPreparation[pos]); SQL_TIMESTAMP_STRUCT& tss = *AnyCast<SQL_TIMESTAMP_STRUCT>(&_rPreparation[pos]);
Utility::dateTimeSync(val, tss);
Utility::dateTimeSync(val, *sp);
return true;
}
template<>
bool Extractor::extractBoundImpl<std::vector<Poco::DateTime> >(std::size_t pos,
std::vector<Poco::DateTime>& val)
{
std::vector<SQL_TIMESTAMP_STRUCT>& ds = RefAnyCast<std::vector<SQL_TIMESTAMP_STRUCT> >(_rPreparation[pos]);
Utility::dateTimeSync(val, ds);
return true;
}
template<>
bool Extractor::extractBoundImpl<std::vector<bool> >(std::size_t pos, std::vector<bool>& val)
{
std::size_t length = _rPreparation.getLength();
bool* p = AnyCast<bool>(&_rPreparation[pos]);
for (int i = 0; i < length; ++i)
val.push_back(p[i]);
return true; return true;
} }
@@ -162,8 +236,6 @@ bool Extractor::extractManualImpl<std::string>(std::size_t pos, std::string& val
pChar, //returned value pChar, //returned value
CHUNK_SIZE, //buffer length CHUNK_SIZE, //buffer length
&len); //length indicator &len); //length indicator
_lengths[pos] += len;
if (SQL_NO_DATA != rc && Utility::isError(rc)) if (SQL_NO_DATA != rc && Utility::isError(rc))
throw StatementException(_rStmt, "SQLGetData()"); throw StatementException(_rStmt, "SQLGetData()");
@@ -172,18 +244,21 @@ bool Extractor::extractManualImpl<std::string>(std::size_t pos, std::string& val
throw UnknownDataLengthException("Could not determine returned data length."); throw UnknownDataLengthException("Could not determine returned data length.");
if (isNullLengthIndicator(len)) if (isNullLengthIndicator(len))
{
_lengths[pos] = len;
return false; return false;
}
if (SQL_NO_DATA == rc || !len) if (SQL_NO_DATA == rc || !len)
break; break;
_lengths[pos] += len;
fetchedSize = _lengths[pos] > CHUNK_SIZE ? CHUNK_SIZE : _lengths[pos]; fetchedSize = _lengths[pos] > CHUNK_SIZE ? CHUNK_SIZE : _lengths[pos];
totalSize += fetchedSize; totalSize += fetchedSize;
if (totalSize <= maxSize) val.append(pChar, fetchedSize); if (totalSize <= maxSize)
else throw DataException(format(FLD_SIZE_EXCEEDED_FMT, val.append(pChar, fetchedSize);
fetchedSize, else
maxSize)); throw DataException(format(FLD_SIZE_EXCEEDED_FMT, fetchedSize, maxSize));
}while (true); }while (true);
return true; return true;
@@ -237,9 +312,7 @@ bool Extractor::extractManualImpl<Poco::Data::BLOB>(std::size_t pos,
if (totalSize <= maxSize) if (totalSize <= maxSize)
val.appendRaw(pChar, fetchedSize); val.appendRaw(pChar, fetchedSize);
else else
throw DataException(format(FLD_SIZE_EXCEEDED_FMT, throw DataException(format(FLD_SIZE_EXCEEDED_FMT, fetchedSize, maxSize));
fetchedSize,
maxSize));
}while (true); }while (true);
@@ -334,6 +407,16 @@ bool Extractor::extract(std::size_t pos, Poco::Int32& val)
return extractManualImpl(pos, val, SQL_C_SLONG); return extractManualImpl(pos, val, SQL_C_SLONG);
else else
return extractBoundImpl(pos, val); return extractBoundImpl(pos, val);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::Int32>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImplVec(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
} }
@@ -347,6 +430,17 @@ bool Extractor::extract(std::size_t pos, Poco::Int64& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<Poco::Int64>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImplVec(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
bool Extractor::extract(std::size_t pos, long& val) bool Extractor::extract(std::size_t pos, long& val)
{ {
@@ -355,6 +449,17 @@ bool Extractor::extract(std::size_t pos, long& val)
else else
return extractBoundImpl(pos, val); return extractBoundImpl(pos, val);
} }
bool Extractor::extract(std::size_t pos, std::vector<long>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImplVec(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
#endif #endif
@@ -367,6 +472,17 @@ bool Extractor::extract(std::size_t pos, double& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<double>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImplVec(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, std::string& val) bool Extractor::extract(std::size_t pos, std::string& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -376,6 +492,17 @@ bool Extractor::extract(std::size_t pos, std::string& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<std::string>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImpl(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val) bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -385,6 +512,17 @@ bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<Poco::Data::BLOB>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImpl(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, Poco::Data::Date& val) bool Extractor::extract(std::size_t pos, Poco::Data::Date& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -394,6 +532,17 @@ bool Extractor::extract(std::size_t pos, Poco::Data::Date& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<Poco::Data::Date>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImpl(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, Poco::Data::Time& val) bool Extractor::extract(std::size_t pos, Poco::Data::Time& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -403,6 +552,17 @@ bool Extractor::extract(std::size_t pos, Poco::Data::Time& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<Poco::Data::Time>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImpl(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, Poco::DateTime& val) bool Extractor::extract(std::size_t pos, Poco::DateTime& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -412,6 +572,17 @@ bool Extractor::extract(std::size_t pos, Poco::DateTime& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<Poco::DateTime>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImpl(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, Poco::Int8& val) bool Extractor::extract(std::size_t pos, Poco::Int8& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -421,6 +592,17 @@ bool Extractor::extract(std::size_t pos, Poco::Int8& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<Poco::Int8>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImplVec(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, Poco::UInt8& val) bool Extractor::extract(std::size_t pos, Poco::UInt8& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -430,6 +612,15 @@ bool Extractor::extract(std::size_t pos, Poco::UInt8& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<Poco::UInt8>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImplVec(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, Poco::Int16& val) bool Extractor::extract(std::size_t pos, Poco::Int16& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -439,6 +630,17 @@ bool Extractor::extract(std::size_t pos, Poco::Int16& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<Poco::Int16>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImplVec(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, Poco::UInt16& val) bool Extractor::extract(std::size_t pos, Poco::UInt16& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -448,6 +650,17 @@ bool Extractor::extract(std::size_t pos, Poco::UInt16& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<Poco::UInt16>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImplVec(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, Poco::UInt32& val) bool Extractor::extract(std::size_t pos, Poco::UInt32& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -457,6 +670,17 @@ bool Extractor::extract(std::size_t pos, Poco::UInt32& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<Poco::UInt32>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImplVec(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, Poco::UInt64& val) bool Extractor::extract(std::size_t pos, Poco::UInt64& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -466,6 +690,17 @@ bool Extractor::extract(std::size_t pos, Poco::UInt64& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<Poco::UInt64>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImplVec(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, bool& val) bool Extractor::extract(std::size_t pos, bool& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -475,6 +710,17 @@ bool Extractor::extract(std::size_t pos, bool& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<bool>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImplVec(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, float& val) bool Extractor::extract(std::size_t pos, float& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -484,6 +730,17 @@ bool Extractor::extract(std::size_t pos, float& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<float>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImplVec(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, char& val) bool Extractor::extract(std::size_t pos, char& val)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
@@ -493,32 +750,65 @@ bool Extractor::extract(std::size_t pos, char& val)
} }
bool Extractor::extract(std::size_t pos, std::vector<char>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImplVec(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, Poco::Any& val) bool Extractor::extract(std::size_t pos, Poco::Any& val)
{ {
return extractImpl(pos, val); return extractImpl(pos, val);
} }
bool Extractor::extract(std::size_t pos, std::vector<Poco::Any>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImpl(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::extract(std::size_t pos, Poco::DynamicAny& val) bool Extractor::extract(std::size_t pos, Poco::DynamicAny& val)
{ {
return extractImpl(pos, val); return extractImpl(pos, val);
} }
bool Extractor::isNull(std::size_t pos) bool Extractor::extract(std::size_t pos, std::vector<Poco::DynamicAny>& val)
{
if (Preparation::DE_BOUND == _dataExtraction)
return extractBoundImpl(pos, val);
else
throw InvalidAccessException("Direct vector extraction only allowed for bound mode.");
}
bool Extractor::isNull(std::size_t col, std::size_t row)
{ {
if (Preparation::DE_MANUAL == _dataExtraction) if (Preparation::DE_MANUAL == _dataExtraction)
{ {
try try
{ {
return isNullLengthIndicator(_lengths.at(pos)); return isNullLengthIndicator(_lengths.at(col));
}catch (std::out_of_range& ex) }catch (std::out_of_range& ex)
{ {
throw RangeException(ex.what()); throw RangeException(ex.what());
} }
} }
else else
return SQL_NULL_DATA == _rPreparation.actualDataSize(pos); return SQL_NULL_DATA == _rPreparation.actualDataSize(col, row);
} }
@@ -526,11 +816,7 @@ void Extractor::checkDataSize(std::size_t size)
{ {
std::size_t maxSize = _rPreparation.getMaxFieldSize(); std::size_t maxSize = _rPreparation.getMaxFieldSize();
if (size > maxSize) if (size > maxSize)
{ throw DataException(format(FLD_SIZE_EXCEEDED_FMT, size, maxSize));
throw DataException(format(FLD_SIZE_EXCEEDED_FMT,
size,
maxSize));
}
} }

View File

@@ -40,11 +40,9 @@
#include "Poco/Data/ODBC/ODBCException.h" #include "Poco/Data/ODBC/ODBCException.h"
#include "Poco/Data/AbstractPrepare.h" #include "Poco/Data/AbstractPrepare.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include <limits>
#ifdef POCO_OS_FAMILY_WINDOWS #ifdef POCO_OS_FAMILY_WINDOWS
#undef max
#pragma warning(disable:4312)// 'type cast' : conversion from 'Poco::UInt32' to 'SQLPOINTER' of greater size #pragma warning(disable:4312)// 'type cast' : conversion from 'Poco::UInt32' to 'SQLPOINTER' of greater size
#endif #endif
@@ -68,11 +66,6 @@ ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession):
_nextResponse(0), _nextResponse(0),
_prepared(false) _prepared(false)
{ {
if (session().getFeature("autoBind"))
SQLSetStmtAttr(_stmt, SQL_ATTR_PARAM_BIND_TYPE, (SQLPOINTER) SQL_PARAM_BIND_BY_COLUMN, 0);
Poco::UInt32 step = getStep();
SQLSetStmtAttr(_stmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) step, 0);
} }
@@ -104,7 +97,9 @@ void ODBCStatementImpl::compileImpl()
pDT = AnyCast<TypeInfo*>(dti); pDT = AnyCast<TypeInfo*>(dti);
}catch (NotSupportedException&) { } }catch (NotSupportedException&) { }
_pBinder = new Binder(_stmt, bind, pDT); std::size_t maxFieldSize = AnyCast<std::size_t>(session().getProperty("maxFieldSize"));
_pBinder = new Binder(_stmt, maxFieldSize, bind, pDT);
// This is a hack to conform to some ODBC drivers behavior (e.g. MS SQLServer) with // 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 // stored procedure calls: driver refuses to report the number of columns, unless all
@@ -169,6 +164,16 @@ void ODBCStatementImpl::doPrepare()
Extractions& extracts = extractions(); Extractions& extracts = extractions();
Extractions::iterator it = extracts.begin(); Extractions::iterator it = extracts.begin();
Extractions::iterator itEnd = extracts.end(); Extractions::iterator itEnd = extracts.end();
if (it != itEnd && (*it)->isBulk())
{
Poco::UInt32 limit = getExtractionLimit();
if (limit == Limit::LIMIT_UNLIMITED)
throw InvalidArgumentException("Bulk operation not allowed without limit.");
checkError(SQLSetStmtAttr(_stmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) limit, 0),
"SQLSetStmtAttr(SQL_ATTR_ROW_ARRAY_SIZE)");
}
for (std::size_t pos = 0; it != itEnd; ++it) for (std::size_t pos = 0; it != itEnd; ++it)
{ {
AbstractPrepare* pAP = (*it)->createPrepareObject(_preparations[curDataSet], pos); AbstractPrepare* pAP = (*it)->createPrepareObject(_preparations[curDataSet], pos);
@@ -199,17 +204,17 @@ void ODBCStatementImpl::doBind(bool clear, bool reset)
{ {
Bindings::iterator it = binds.begin(); Bindings::iterator it = binds.begin();
Bindings::iterator itEnd = binds.end(); Bindings::iterator itEnd = binds.end();
for (std::size_t pos = 0; it != itEnd && (*it)->canBind(); ++it)
{
(*it)->bind(pos);
pos += (*it)->numOfColumnsHandled();
}
if (reset) if (reset)
{ {
it = binds.begin(); it = binds.begin();
for (; it != itEnd && (*it)->canBind(); ++it) for (; it != itEnd; ++it) (*it)->reset();
(*it)->reset(); }
for (std::size_t pos = 0; it != itEnd && (*it)->canBind(); ++it)
{
(*it)->bind(pos);
pos += (*it)->numOfColumnsHandled();
} }
} }
} }
@@ -292,12 +297,11 @@ bool ODBCStatementImpl::hasNext()
if (!nextRowReady()) if (!nextRowReady())
{ {
try { activateNextDataSet(); } try { activateNextDataSet(); }
catch (InvalidAccessException&) catch (NoDataException&)
{ return false; } { return false; }
try { checkError(SQLMoreResults(_stmt)); } if (SQL_NO_DATA == SQLMoreResults(_stmt))
catch (NoDataException&) return false;
{ return false; }
addPreparation(); addPreparation();
doPrepare(); doPrepare();
@@ -324,14 +328,20 @@ void ODBCStatementImpl::makeStep()
Poco::UInt32 ODBCStatementImpl::next() Poco::UInt32 ODBCStatementImpl::next()
{ {
std::size_t count = 0;
if (nextRowReady()) if (nextRowReady())
{ {
Extractions& extracts = extractions(); Extractions& extracts = extractions();
Extractions::iterator it = extracts.begin(); Extractions::iterator it = extracts.begin();
Extractions::iterator itEnd = extracts.end(); Extractions::iterator itEnd = extracts.end();
std::size_t prevCount = 0;
for (std::size_t pos = 0; it != itEnd; ++it) for (std::size_t pos = 0; it != itEnd; ++it)
{ {
(*it)->extract(pos); count = (*it)->extract(pos);
if (prevCount && count != prevCount)
throw IllegalStateException("Different extraction counts");
prevCount = count;
pos += (*it)->numOfColumnsHandled(); pos += (*it)->numOfColumnsHandled();
} }
_stepCalled = false; _stepCalled = false;
@@ -342,7 +352,9 @@ Poco::UInt32 ODBCStatementImpl::next()
std::string("Iterator Error: trying to access the next value")); std::string("Iterator Error: trying to access the next value"));
} }
return 1u; return static_cast<Poco::UInt32>(count);
return 0;
} }
@@ -415,4 +427,15 @@ bool ODBCStatementImpl::isStoredProcedure() const
} }
const MetaColumn& ODBCStatementImpl::metaColumn(Poco::UInt32 pos) const
{
std::size_t sz = _columnPtrs.size();
if (0 == sz || pos > sz - 1)
throw InvalidAccessException(format("Invalid column number: %u", pos));
return *_columnPtrs[pos];
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@@ -43,6 +43,9 @@ namespace Data {
namespace ODBC { namespace ODBC {
const std::size_t Preparation::INVALID_ROW = std::numeric_limits<std::size_t>::max();
Preparation::Preparation(const StatementHandle& rStmt, Preparation::Preparation(const StatementHandle& rStmt,
const std::string& statement, const std::string& statement,
std::size_t maxFieldSize, std::size_t maxFieldSize,
@@ -68,118 +71,73 @@ Preparation::Preparation(const Preparation& other):
Preparation::~Preparation() Preparation::~Preparation()
{ {
std::vector<SQLLEN*>::iterator itLen = _pLengths.begin(); freeMemory();
std::vector<SQLLEN*>::iterator itLenEnd = _pLengths.end(); }
for (; itLen != itLenEnd; ++itLen) delete *itLen;
std::vector<Poco::Any*>::iterator itVal = _pValues.begin();
std::vector<Poco::Any*>::iterator itValEnd = _pValues.end(); void Preparation::freeMemory() const
for (; itVal != itValEnd; ++itVal) delete *itVal; {
IndexMap::iterator it = _varLengthArrays.begin();
IndexMap::iterator end = _varLengthArrays.end();
for (; it != end; ++it)
{
switch (it->second)
{
case DT_BOOL:
deleteCachedArray<bool>(it->first);
break;
case DT_CHAR:
deleteCachedArray<char>(it->first);
break;
case DT_CHAR_ARRAY:
std::free(AnyCast<char>(&_values[it->first]));
break;
case DT_DATE:
deleteCachedArray<SQL_DATE_STRUCT>(it->first);
break;
case DT_TIME:
deleteCachedArray<SQL_TIME_STRUCT>(it->first);
break;
case DT_DATETIME:
deleteCachedArray<SQL_TIMESTAMP_STRUCT>(it->first);
break;
}
}
} }
std::size_t Preparation::columns() const std::size_t Preparation::columns() const
{ {
if (_pValues.empty()) resize(); if (_values.empty()) resize();
return _pValues.size(); return _values.size();
} }
void Preparation::resize() const void Preparation::resize() const
{ {
SQLSMALLINT nCol = 0; SQLSMALLINT nCol = 0;
if (!Utility::isError(SQLNumResultCols(_rStmt, &nCol)) && if (!Utility::isError(SQLNumResultCols(_rStmt, &nCol)) && 0 != nCol)
0 != nCol)
{ {
_pValues.resize(nCol, 0); _values.resize(nCol, 0);
_pLengths.resize(nCol, 0); _lengths.resize(nCol, 0);
} _lenLengths.resize(nCol);
} if(_varLengthArrays.size())
{
freeMemory();
Poco::Any& Preparation::operator [] (std::size_t pos) _varLengthArrays.clear();
{ }
poco_assert (pos >= 0 && pos < _pValues.size());
return *_pValues[pos];
}
void Preparation::prepare(std::size_t pos, const Poco::Any&)
{
prepareImpl(pos);
}
void Preparation::prepare(std::size_t pos, const Poco::DynamicAny&)
{
prepareImpl(pos);
}
void Preparation::prepareImpl(std::size_t pos)
{
ODBCColumn col(_rStmt, pos);
switch (col.type())
{
case MetaColumn::FDT_INT8:
return preparePOD<Poco::Int8>(pos, SQL_C_STINYINT);
case MetaColumn::FDT_UINT8:
return preparePOD<Poco::UInt8>(pos, SQL_C_UTINYINT);
case MetaColumn::FDT_INT16:
return preparePOD<Poco::Int16>(pos, SQL_C_SSHORT);
case MetaColumn::FDT_UINT16:
return preparePOD<Poco::UInt16>(pos, SQL_C_USHORT);
case MetaColumn::FDT_INT32:
return preparePOD<Poco::Int32>(pos, SQL_C_SLONG);
case MetaColumn::FDT_UINT32:
return preparePOD<Poco::UInt32>(pos, SQL_C_ULONG);
case MetaColumn::FDT_INT64:
return preparePOD<Poco::Int64>(pos, SQL_C_SBIGINT);
case MetaColumn::FDT_UINT64:
return preparePOD<Poco::UInt64>(pos, SQL_C_UBIGINT);
case MetaColumn::FDT_BOOL:
return preparePOD<bool>(pos, SQL_C_BIT);
case MetaColumn::FDT_FLOAT:
return preparePOD<float>(pos, SQL_C_FLOAT);
case MetaColumn::FDT_DOUBLE:
return preparePOD<double>(pos, SQL_C_DOUBLE);
case MetaColumn::FDT_STRING:
return prepareRaw<char>(pos, SQL_C_CHAR, maxDataSize(pos));
case MetaColumn::FDT_BLOB:
return prepareRaw<char>(pos, SQL_C_BINARY, maxDataSize(pos));
case MetaColumn::FDT_DATE:
return prepareRaw<Date>(pos, SQL_C_TYPE_DATE, sizeof(SQL_DATE_STRUCT));
case MetaColumn::FDT_TIME:
return prepareRaw<Time>(pos, SQL_C_TYPE_TIME, sizeof(SQL_TIME_STRUCT));
case MetaColumn::FDT_TIMESTAMP:
return prepareRaw<Time>(pos, SQL_C_TYPE_TIMESTAMP, sizeof(SQL_TIMESTAMP_STRUCT));
default:
throw DataFormatException("Unsupported data type.");
} }
} }
std::size_t Preparation::maxDataSize(std::size_t pos) const std::size_t Preparation::maxDataSize(std::size_t pos) const
{ {
poco_assert (pos >= 0 && pos < _pValues.size()); poco_assert_dbg (pos < _values.size());
std::size_t sz = 0; std::size_t sz = 0;
std::size_t maxsz = getMaxFieldSize(); std::size_t maxsz = getMaxFieldSize();
@@ -195,4 +153,30 @@ std::size_t Preparation::maxDataSize(std::size_t pos) const
} }
void Preparation::prepareVariableLenArray(std::size_t pos, SQLSMALLINT valueType, std::size_t size, std::size_t length, DataType dt)
{
poco_assert_dbg (DE_BOUND == _dataExtraction);
poco_assert_dbg (pos < _values.size());
poco_assert_dbg (pos < _lengths.size());
poco_assert_dbg (pos < _lenLengths.size());
char* pArray = (char*) std::calloc(length * size, sizeof(char));
_values[pos] = Any(pArray);
_lengths[pos] = 0;
_lenLengths[pos].resize(length);
_varLengthArrays.insert(IndexMap::value_type(pos, dt));
if (Utility::isError(SQLBindCol(_rStmt,
(SQLUSMALLINT) pos + 1,
valueType,
(SQLPOINTER) pArray,
(SQLINTEGER) size,
&_lenLengths[pos][0])))
{
throw StatementException(_rStmt, "SQLBindCol()");
}
}
} } } // namespace Poco::Data::ODBC } } } // namespace Poco::Data::ODBC

View File

@@ -138,6 +138,17 @@ void Utility::dateTimeSync(Poco::DateTime& dt, const SQL_TIMESTAMP_STRUCT& ts)
} }
void Utility::dateTimeSync(std::vector<Poco::DateTime>& dt, const std::vector<SQL_TIMESTAMP_STRUCT>& ts)
{
std::size_t size = ts.size();
if (dt.size() != size) dt.resize(size);
std::vector<Poco::DateTime>::iterator dIt = dt.begin();
std::vector<SQL_TIMESTAMP_STRUCT>::const_iterator it = ts.begin();
std::vector<SQL_TIMESTAMP_STRUCT>::const_iterator end = ts.end();
for (; it != end; ++it, ++dIt) dateTimeSync(*dIt, *it);
}
void Utility::dateSync(SQL_DATE_STRUCT& ds, const Date& d) void Utility::dateSync(SQL_DATE_STRUCT& ds, const Date& d)
{ {
ds.year = d.year(); ds.year = d.year();
@@ -146,6 +157,17 @@ void Utility::dateSync(SQL_DATE_STRUCT& ds, const Date& d)
} }
void Utility::dateSync(std::vector<SQL_DATE_STRUCT>& ds, const std::vector<Date>& d)
{
std::size_t size = d.size();
if (ds.size() != size) ds.resize(size);
std::vector<SQL_DATE_STRUCT>::iterator dIt = ds.begin();
std::vector<Date>::const_iterator it = d.begin();
std::vector<Date>::const_iterator end = d.end();
for (; it != end; ++it, ++dIt) dateSync(*dIt, *it);
}
void Utility::timeSync(SQL_TIME_STRUCT& ts, const Time& t) void Utility::timeSync(SQL_TIME_STRUCT& ts, const Time& t)
{ {
ts.hour = t.hour(); ts.hour = t.hour();
@@ -154,6 +176,17 @@ void Utility::timeSync(SQL_TIME_STRUCT& ts, const Time& t)
} }
void Utility::timeSync(std::vector<SQL_TIME_STRUCT>& ts, const std::vector<Time>& t)
{
std::size_t size = t.size();
if (ts.size() != size) ts.resize(size);
std::vector<SQL_TIME_STRUCT>::iterator tIt = ts.begin();
std::vector<Time>::const_iterator it = t.begin();
std::vector<Time>::const_iterator end = t.end();
for (; it != end; ++it, ++tIt) timeSync(*tIt, *it);
}
void Utility::dateTimeSync(SQL_TIMESTAMP_STRUCT& ts, const Poco::DateTime& dt) void Utility::dateTimeSync(SQL_TIMESTAMP_STRUCT& ts, const Poco::DateTime& dt)
{ {
ts.year = dt.year(); ts.year = dt.year();
@@ -162,7 +195,42 @@ void Utility::dateTimeSync(SQL_TIMESTAMP_STRUCT& ts, const Poco::DateTime& dt)
ts.hour = dt.hour(); ts.hour = dt.hour();
ts.minute = dt.minute(); ts.minute = dt.minute();
ts.second = dt.second(); ts.second = dt.second();
ts.fraction = (dt.millisecond() * 1000000) + (dt.microsecond() * 1000); // Fraction support is limited to milliseconds due to MS SQL Server limitation
// see http://support.microsoft.com/kb/263872
ts.fraction = (dt.millisecond() * 1000000);// + (dt.microsecond() * 1000);
}
void Utility::dateTimeSync(std::vector<SQL_TIMESTAMP_STRUCT>& ts, const std::vector<Poco::DateTime>& dt)
{
std::size_t size = dt.size();
if (ts.size() != size) ts.resize(size);
std::vector<SQL_TIMESTAMP_STRUCT>::iterator tIt = ts.begin();
std::vector<Poco::DateTime>::const_iterator it = dt.begin();
std::vector<Poco::DateTime>::const_iterator end = dt.end();
for (; it != end; ++it, ++tIt) dateTimeSync(*tIt, *it);
}
void Utility::dateSync(std::vector<Date>& d, const std::vector<SQL_DATE_STRUCT>& ds)
{
std::size_t size = ds.size();
if (d.size() != size) d.resize(size);
std::vector<Date>::iterator dIt = d.begin();
std::vector<SQL_DATE_STRUCT>::const_iterator it = ds.begin();
std::vector<SQL_DATE_STRUCT>::const_iterator end = ds.end();
for (; it != end; ++it, ++dIt) dateSync(*dIt, *it);
}
void Utility::timeSync(std::vector<Time>& t, const std::vector<SQL_TIME_STRUCT>& ts)
{
std::size_t size = ts.size();
if (t.size() != size) t.resize(size);
std::vector<Time>::iterator dIt = t.begin();
std::vector<SQL_TIME_STRUCT>::const_iterator it = ts.begin();
std::vector<SQL_TIME_STRUCT>::const_iterator end = ts.end();
for (; it != end; ++it, ++dIt) timeSync(*dIt, *it);
} }

View File

@@ -571,7 +571,7 @@ CppUnit::Test* ODBCDB2Test::suite()
CppUnit_addTest(pSuite, ODBCDB2Test, testLimitPrepare); CppUnit_addTest(pSuite, ODBCDB2Test, testLimitPrepare);
CppUnit_addTest(pSuite, ODBCDB2Test, testLimitZero); CppUnit_addTest(pSuite, ODBCDB2Test, testLimitZero);
CppUnit_addTest(pSuite, ODBCDB2Test, testPrepare); CppUnit_addTest(pSuite, ODBCDB2Test, testPrepare);
CppUnit_addTest(pSuite, ODBCDB2Test, testStep); CppUnit_addTest(pSuite, ODBCDB2Test, testBulk);
CppUnit_addTest(pSuite, ODBCDB2Test, testSetSimple); CppUnit_addTest(pSuite, ODBCDB2Test, testSetSimple);
CppUnit_addTest(pSuite, ODBCDB2Test, testSetComplex); CppUnit_addTest(pSuite, ODBCDB2Test, testSetComplex);
CppUnit_addTest(pSuite, ODBCDB2Test, testSetComplexUnique); CppUnit_addTest(pSuite, ODBCDB2Test, testSetComplexUnique);

View File

@@ -391,7 +391,7 @@ CppUnit::Test* ODBCMySQLTest::suite()
CppUnit_addTest(pSuite, ODBCMySQLTest, testLimitPrepare); CppUnit_addTest(pSuite, ODBCMySQLTest, testLimitPrepare);
CppUnit_addTest(pSuite, ODBCMySQLTest, testLimitZero); CppUnit_addTest(pSuite, ODBCMySQLTest, testLimitZero);
CppUnit_addTest(pSuite, ODBCMySQLTest, testPrepare); CppUnit_addTest(pSuite, ODBCMySQLTest, testPrepare);
CppUnit_addTest(pSuite, ODBCMySQLTest, testStep); CppUnit_addTest(pSuite, ODBCMySQLTest, testBulk);
CppUnit_addTest(pSuite, ODBCMySQLTest, testSetSimple); CppUnit_addTest(pSuite, ODBCMySQLTest, testSetSimple);
CppUnit_addTest(pSuite, ODBCMySQLTest, testSetComplex); CppUnit_addTest(pSuite, ODBCMySQLTest, testSetComplex);
CppUnit_addTest(pSuite, ODBCMySQLTest, testSetComplexUnique); CppUnit_addTest(pSuite, ODBCMySQLTest, testSetComplexUnique);

View File

@@ -146,7 +146,7 @@ void ODBCOracleTest::testBarebone()
"(First VARCHAR(30)," "(First VARCHAR(30),"
"Second INTEGER," "Second INTEGER,"
"Third NUMBER)"; "Third NUMBER)";
/*
*_pSession << "CREATE OR REPLACE " *_pSession << "CREATE OR REPLACE "
"PROCEDURE multiResultsProcedure(ret1 OUT SYS_REFCURSOR, " "PROCEDURE multiResultsProcedure(ret1 OUT SYS_REFCURSOR, "
"ret2 OUT SYS_REFCURSOR," "ret2 OUT SYS_REFCURSOR,"
@@ -185,7 +185,7 @@ void ODBCOracleTest::testBarebone()
SQLExecutor::DE_BOUND, SQLExecutor::DE_BOUND,
MULTI_INSERT, MULTI_INSERT,
MULTI_SELECT); MULTI_SELECT);
*/
} }
@@ -224,6 +224,19 @@ void ODBCOracleTest::testBLOB()
} }
void ODBCOracleTest::testBulk()
{
if (!_pSession) fail ("Test not available.");
_pSession->setFeature("autoBind", true);
_pSession->setFeature("autoExtract", true);
recreateMiscTable();
_pExecutor->doBulkNoBool(100);
recreateMiscTable();
_pExecutor->doBulkPerformance(1000);
}
void ODBCOracleTest::testNull() void ODBCOracleTest::testNull()
{ {
// test for NOT NULL violation exception // test for NOT NULL violation exception
@@ -739,6 +752,22 @@ void ODBCOracleTest::recreateNullsTable(const std::string& notNull)
} }
void ODBCOracleTest::recreateMiscTable()
{
dropObject("TABLE", "MiscTest");
try
{
session() << "CREATE TABLE MiscTest "
"(First VARCHAR(30),"
"Second BLOB,"
"Third INTEGER,"
"Fourth NUMBER,"
"Fifth TIMESTAMP)", now;
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateMiscTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateMiscTable()"); }
}
CppUnit::Test* ODBCOracleTest::suite() CppUnit::Test* ODBCOracleTest::suite()
{ {
if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString)) if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString))
@@ -771,7 +800,7 @@ CppUnit::Test* ODBCOracleTest::suite()
CppUnit_addTest(pSuite, ODBCOracleTest, testLimitPrepare); CppUnit_addTest(pSuite, ODBCOracleTest, testLimitPrepare);
CppUnit_addTest(pSuite, ODBCOracleTest, testLimitZero); CppUnit_addTest(pSuite, ODBCOracleTest, testLimitZero);
CppUnit_addTest(pSuite, ODBCOracleTest, testPrepare); CppUnit_addTest(pSuite, ODBCOracleTest, testPrepare);
CppUnit_addTest(pSuite, ODBCOracleTest, testStep); CppUnit_addTest(pSuite, ODBCOracleTest, testBulk);
CppUnit_addTest(pSuite, ODBCOracleTest, testSetSimple); CppUnit_addTest(pSuite, ODBCOracleTest, testSetSimple);
CppUnit_addTest(pSuite, ODBCOracleTest, testSetComplex); CppUnit_addTest(pSuite, ODBCOracleTest, testSetComplex);
CppUnit_addTest(pSuite, ODBCOracleTest, testSetComplexUnique); CppUnit_addTest(pSuite, ODBCOracleTest, testSetComplexUnique);

View File

@@ -56,7 +56,8 @@ public:
void testBareboneODBC(); void testBareboneODBC();
void testBLOB(); void testBLOB();
void testBulk();
void testMultipleResults(); void testMultipleResults();
void testStoredProcedure(); void testStoredProcedure();
@@ -84,6 +85,7 @@ private:
void recreateVectorsTable(); void recreateVectorsTable();
void recreateAnysTable(); void recreateAnysTable();
void recreateNullsTable(const std::string& notNull = ""); void recreateNullsTable(const std::string& notNull = "");
void recreateMiscTable();
static ODBCTest::SessionPtr _pSession; static ODBCTest::SessionPtr _pSession;
static ODBCTest::ExecPtr _pExecutor; static ODBCTest::ExecPtr _pExecutor;

View File

@@ -346,6 +346,19 @@ void ODBCPostgreSQLTest::testStoredFunctionDynamicAny()
} }
void ODBCPostgreSQLTest::testBulk()
{
if (!_pSession) fail ("Test not available.");
_pSession->setFeature("autoBind", true);
_pSession->setFeature("autoExtract", true);
recreateMiscTable();
_pExecutor->doBulkStringIntFloat(100);
recreateMiscTable();
_pExecutor->doBulkPerformance(1000);
}
void ODBCPostgreSQLTest::configurePLPgSQL() void ODBCPostgreSQLTest::configurePLPgSQL()
{ {
try try
@@ -518,6 +531,24 @@ void ODBCPostgreSQLTest::recreateBoolTable()
} }
void ODBCPostgreSQLTest::recreateMiscTable()
{
dropObject("TABLE", "MiscTest");
try
{
// pgSQL fails with BLOB bulk operations
// Mammoth does not bind columns properly
session() << "CREATE TABLE MiscTest "
"(First VARCHAR(30),"
//"Second BYTEA,"
"Third INTEGER,"
"Fourth FLOAT,"
"Fifth TIMESTAMP)", now;
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateMiscTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateMiscTable()"); }
}
CppUnit::Test* ODBCPostgreSQLTest::suite() CppUnit::Test* ODBCPostgreSQLTest::suite()
{ {
if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString)) if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString))
@@ -550,7 +581,7 @@ CppUnit::Test* ODBCPostgreSQLTest::suite()
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testLimitPrepare); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testLimitPrepare);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testLimitZero); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testLimitZero);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testPrepare); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testPrepare);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testStep); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testBulk);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSetSimple); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSetSimple);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSetComplex); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSetComplex);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSetComplexUnique); CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSetComplexUnique);

View File

@@ -64,6 +64,7 @@ public:
void testBareboneODBC(); void testBareboneODBC();
void testBLOB(); void testBLOB();
void testBulk();
void testStoredFunction(); void testStoredFunction();
void testStoredFunctionAny(); void testStoredFunctionAny();
@@ -86,7 +87,8 @@ private:
void recreateAnysTable(); void recreateAnysTable();
void recreateNullsTable(const std::string& notNull=""); void recreateNullsTable(const std::string& notNull="");
void recreateBoolTable(); void recreateBoolTable();
void recreateMiscTable();
void configurePLPgSQL(); void configurePLPgSQL();
/// Configures PL/pgSQL in the database. A reasonable defaults /// Configures PL/pgSQL in the database. A reasonable defaults
/// for the interpreter location on WIN32 and POSIX platforms are /// for the interpreter location on WIN32 and POSIX platforms are

View File

@@ -112,9 +112,8 @@ void ODBCSQLServerTest::testBareboneODBC()
"Fifth FLOAT," "Fifth FLOAT,"
"Sixth DATETIME)"; "Sixth DATETIME)";
//TODO: auto binding fails at SQLExecute() ("String data, right truncated") executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL);
//executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_MANUAL); executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);
//executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_IMMEDIATE, SQLExecutor::DE_BOUND);
executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL); executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_MANUAL);
executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND); executor().bareboneODBCTest(dbConnString(), tableCreateString, SQLExecutor::PB_AT_EXEC, SQLExecutor::DE_BOUND);
@@ -611,6 +610,23 @@ void ODBCSQLServerTest::recreateBoolTable()
} }
void ODBCSQLServerTest::recreateMiscTable()
{
dropObject("TABLE", "MiscTest");
try
{
session() << "CREATE TABLE MiscTest "
"(First VARCHAR(30),"
"Second VARBINARY(30),"
"Third INTEGER,"
"Fourth FLOAT,"
"Fifth DATETIME,"
"Sixth BIT)", now;
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateMiscTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateMiscTable()"); }
}
CppUnit::Test* ODBCSQLServerTest::suite() CppUnit::Test* ODBCSQLServerTest::suite()
{ {
if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString, _db)) if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString, _db))
@@ -643,7 +659,7 @@ CppUnit::Test* ODBCSQLServerTest::suite()
CppUnit_addTest(pSuite, ODBCSQLServerTest, testLimitPrepare); CppUnit_addTest(pSuite, ODBCSQLServerTest, testLimitPrepare);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testLimitZero); CppUnit_addTest(pSuite, ODBCSQLServerTest, testLimitZero);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testPrepare); CppUnit_addTest(pSuite, ODBCSQLServerTest, testPrepare);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStep); CppUnit_addTest(pSuite, ODBCSQLServerTest, testBulk);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSetSimple); CppUnit_addTest(pSuite, ODBCSQLServerTest, testSetSimple);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSetComplex); CppUnit_addTest(pSuite, ODBCSQLServerTest, testSetComplex);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSetComplexUnique); CppUnit_addTest(pSuite, ODBCSQLServerTest, testSetComplexUnique);

View File

@@ -89,6 +89,7 @@ private:
void recreateAnysTable(); void recreateAnysTable();
void recreateNullsTable(const std::string& notNull = ""); void recreateNullsTable(const std::string& notNull = "");
void recreateBoolTable(); void recreateBoolTable();
void recreateMiscTable();
static SessionPtr _pSession; static SessionPtr _pSession;
static ExecPtr _pExecutor; static ExecPtr _pExecutor;

View File

@@ -141,6 +141,19 @@ void ODBCSQLiteTest::testNull()
} }
void ODBCSQLiteTest::testBulk()
{
if (!_pSession) fail ("Test not available.");
_pSession->setFeature("autoBind", true);
_pSession->setFeature("autoExtract", true);
recreateMiscTable();
_pExecutor->doBulkStringIntFloat(100);
recreateMiscTable();
_pExecutor->doBulkPerformance(1000);
}
void ODBCSQLiteTest::dropObject(const std::string& type, const std::string& name) void ODBCSQLiteTest::dropObject(const std::string& type, const std::string& name)
{ {
try try
@@ -262,6 +275,23 @@ void ODBCSQLiteTest::recreateNullsTable(const std::string& notNull)
} }
void ODBCSQLiteTest::recreateMiscTable()
{
dropObject("TABLE", "MiscTest");
try
{
// SQLite fails with BLOB bulk operations
session() << "CREATE TABLE MiscTest "
"(First VARCHAR(30),"
//"Second BLOB,"
"Third INTEGER,"
"Fourth REAL,"
"Fifth DATETIME)", now;
} catch(ConnectionException& ce){ std::cout << ce.toString() << std::endl; fail ("recreateMiscTable()"); }
catch(StatementException& se){ std::cout << se.toString() << std::endl; fail ("recreateMiscTable()"); }
}
CppUnit::Test* ODBCSQLiteTest::suite() CppUnit::Test* ODBCSQLiteTest::suite()
{ {
if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString)) if (_pSession = init(_driver, _dsn, _uid, _pwd, _connectString))
@@ -294,7 +324,7 @@ CppUnit::Test* ODBCSQLiteTest::suite()
CppUnit_addTest(pSuite, ODBCSQLiteTest, testLimitPrepare); CppUnit_addTest(pSuite, ODBCSQLiteTest, testLimitPrepare);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testLimitZero); CppUnit_addTest(pSuite, ODBCSQLiteTest, testLimitZero);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testPrepare); CppUnit_addTest(pSuite, ODBCSQLiteTest, testPrepare);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testStep); CppUnit_addTest(pSuite, ODBCSQLiteTest, testBulk);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSetSimple); CppUnit_addTest(pSuite, ODBCSQLiteTest, testSetSimple);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSetComplex); CppUnit_addTest(pSuite, ODBCSQLiteTest, testSetComplex);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSetComplexUnique); CppUnit_addTest(pSuite, ODBCSQLiteTest, testSetComplexUnique);

View File

@@ -54,6 +54,7 @@ public:
void testBareboneODBC(); void testBareboneODBC();
void testNull(); void testNull();
void testBulk();
static CppUnit::Test* suite(); static CppUnit::Test* suite();
@@ -69,14 +70,15 @@ private:
void recreateVectorsTable(); void recreateVectorsTable();
void recreateAnysTable(); void recreateAnysTable();
void recreateNullsTable(const std::string& notNull = ""); void recreateNullsTable(const std::string& notNull = "");
void recreateMiscTable();
static ODBCTest::SessionPtr _pSession; static ODBCTest::SessionPtr _pSession;
static ODBCTest::ExecPtr _pExecutor; static ODBCTest::ExecPtr _pExecutor;
static std::string _driver; static std::string _driver;
static std::string _dsn; static std::string _dsn;
static std::string _uid; static std::string _uid;
static std::string _pwd; static std::string _pwd;
static std::string _connectString; static std::string _connectString;
}; };

View File

@@ -407,27 +407,16 @@ void ODBCTest::testPrepare()
} }
void ODBCTest::testStep() void ODBCTest::testBulk()
{ {
if (!_pSession) fail ("Test not available."); if (!_pSession) fail ("Test not available.");
for (int i = 0; i < 8;) _pSession->setFeature("autoBind", true);
{ _pSession->setFeature("autoExtract", true);
recreateIntsTable(); recreateMiscTable();
_pSession->setFeature("autoBind", bindValue(i)); _pExecutor->doBulk(100);
_pSession->setFeature("autoExtract", bindValue(i+1)); recreateMiscTable();
std::string mode = bindValue(i+1) ? "auto" : "manual"; _pExecutor->doBulkPerformance(1000);
std::cout << "Extraction: " << mode << std::endl;
_pExecutor->doStep(1000, 1);
recreateIntsTable();
_pExecutor->doStep(1000, 10);
recreateIntsTable();
_pExecutor->doStep(1000, 100);
recreateIntsTable();
_pExecutor->doStep(1000, 1000);
i += 2;
}
} }

View File

@@ -91,7 +91,7 @@ public:
virtual void testLimitPrepare(); virtual void testLimitPrepare();
virtual void testLimitZero(); virtual void testLimitZero();
virtual void testPrepare(); virtual void testPrepare();
virtual void testStep(); virtual void testBulk();
virtual void testSetSimple(); virtual void testSetSimple();
virtual void testSetComplex(); virtual void testSetComplex();
@@ -165,6 +165,7 @@ protected:
virtual void recreateAnysTable() { /* no-op */ }; virtual void recreateAnysTable() { /* no-op */ };
virtual void recreateNullsTable(const std::string& notNull="") { /* no-op */ }; virtual void recreateNullsTable(const std::string& notNull="") { /* no-op */ };
virtual void recreateBoolTable() { /* no-op */ }; virtual void recreateBoolTable() { /* no-op */ };
virtual void recreateMiscTable() { /* no-op */ };
static SessionPtr init(const std::string& driver, static SessionPtr init(const std::string& driver,
std::string& dsn, std::string& dsn,
@@ -182,8 +183,8 @@ protected:
bool bindValue(int i); bool bindValue(int i);
Poco::Data::Session& session(); Poco::Data::Session& session();
SQLExecutor& executor(); SQLExecutor& executor();
const std::string& dsn(); const std::string& dsn();
const std::string& uid(); const std::string& uid();

File diff suppressed because it is too large Load Diff

View File

@@ -140,7 +140,10 @@ public:
void limitPrepare(); void limitPrepare();
void limitZero(); void limitZero();
void prepare(); void prepare();
void doStep(Poco::UInt32 dataSize, Poco::UInt32 stepSize); void doBulk(Poco::UInt32 size);
void doBulkPerformance(Poco::UInt32 size);
void doBulkNoBool(Poco::UInt32 size);
void doBulkStringIntFloat(Poco::UInt32 size);
void setSimple(); void setSimple();
void setComplex(); void setComplex();
@@ -194,8 +197,17 @@ private:
static const std::string MULTI_INSERT; static const std::string MULTI_INSERT;
static const std::string MULTI_SELECT; static const std::string MULTI_SELECT;
Poco::Data::Session& session();
Poco::Data::Session* _pSession; Poco::Data::Session* _pSession;
}; };
inline Poco::Data::Session& SQLExecutor::session()
{
poco_check_ptr (_pSession);
return *_pSession;
}
#endif // SQLExecutor_INCLUDED #endif // SQLExecutor_INCLUDED

View File

@@ -135,7 +135,7 @@ public:
bool extract(std::size_t pos, Poco::DynamicAny& val); bool extract(std::size_t pos, Poco::DynamicAny& val);
/// Extracts a DynamicAny. /// Extracts a DynamicAny.
bool isNull(std::size_t pos); bool isNull(std::size_t pos, std::size_t row = -1);
/// Returns true if the current row value at pos column is null. /// Returns true if the current row value at pos column is null.
/// Because of the loss of information about null-ness of the /// Because of the loss of information about null-ness of the
/// underlying database values due to the nature of SQLite engine, /// underlying database values due to the nature of SQLite engine,
@@ -148,6 +148,8 @@ public:
/// bool value in the pair is true if the null indicator has /// bool value in the pair is true if the null indicator has
/// been set and the second bool value in the pair is true if /// been set and the second bool value in the pair is true if
/// the column is actually null. /// the column is actually null.
/// The row argument, needed for connectors with bulk capabilities,
/// is ignored in this implementation.
void reset(); void reset();
/// Clears the cached nulls indicator vector. /// Clears the cached nulls indicator vector.

View File

@@ -251,7 +251,7 @@ bool Extractor::extract(std::size_t pos, Poco::DynamicAny& val)
} }
bool Extractor::isNull(std::size_t pos) bool Extractor::isNull(std::size_t pos, std::size_t)
{ {
if (pos >= _nulls.size()) if (pos >= _nulls.size())
_nulls.resize(pos + 1); _nulls.resize(pos + 1);

View File

@@ -33,12 +33,12 @@
#include "SQLiteTest.h" #include "SQLiteTest.h"
#include "CppUnit/TestCaller.h" #include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h" #include "CppUnit/TestSuite.h"
#include "Poco/Data/Common.h"
#include "Poco/Data/Date.h" #include "Poco/Data/Date.h"
#include "Poco/Data/Time.h" #include "Poco/Data/Time.h"
#include "Poco/Data/BLOB.h" #include "Poco/Data/BLOB.h"
#include "Poco/Data/Statement.h" #include "Poco/Data/Statement.h"
#include "Poco/Data/RecordSet.h" #include "Poco/Data/RecordSet.h"
#include "Poco/Data/SessionFactory.h"
#include "Poco/Data/SQLite/Connector.h" #include "Poco/Data/SQLite/Connector.h"
#include "Poco/Data/SQLite/SQLiteException.h" #include "Poco/Data/SQLite/SQLiteException.h"
#include "Poco/Data/TypeHandler.h" #include "Poco/Data/TypeHandler.h"
@@ -117,7 +117,7 @@ public:
pBinder->bind(pos++, obj.age, dir); pBinder->bind(pos++, obj.age, dir);
} }
static void prepare(std::size_t pos, const Person& obj, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, Person& obj, AbstractPreparation* pPrepare)
{ {
// the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3)) // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))
poco_assert_dbg (pPrepare != 0); poco_assert_dbg (pPrepare != 0);

View File

@@ -41,40 +41,29 @@
#include "Poco/Data/Data.h" #include "Poco/Data/Data.h"
#include <vector>
#include <cstddef> #include <cstddef>
namespace Poco { namespace Poco {
class DateTime; class DateTime;
class Any; class Any;
class DynamicAny; class DynamicAny;
namespace Data { namespace Data {
class Date; class Date;
class Time; class Time;
class BLOB; class BLOB;
enum NullData enum NullData
{ {
NULL_GENERIC = 0, NULL_GENERIC = 0
NULL_INT8,
NULL_UINT8,
NULL_INT16,
NULL_UINT16,
NULL_INT32,
NULL_UINT32,
NULL_INT64,
NULL_UINT64,
NULL_BOOL,
NULL_FLOAT,
NULL_DOUBLE,
NULL_STRING,
NULL_BLOB,
NULL_DATE,
NULL_TIME,
NULL_TIMESTAMP
}; };
@@ -82,8 +71,7 @@ static const NullData null = NULL_GENERIC;
class Data_API AbstractBinder class Data_API AbstractBinder
/// Interface for Binding data types to placeholders. The default placeholder format /// Interface for Binding data types to placeholders.
/// in the SQL query is ":name".
{ {
public: public:
enum Direction enum Direction
@@ -103,65 +91,122 @@ public:
virtual void bind(std::size_t pos, const Poco::Int8& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::Int8& val, Direction dir = PD_IN) = 0;
/// Binds an Int8. /// Binds an Int8.
virtual void bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir = PD_IN);
/// Binds an Int8 vector.
virtual void bind(std::size_t pos, const Poco::UInt8& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::UInt8& val, Direction dir = PD_IN) = 0;
/// Binds an UInt8. /// Binds an UInt8.
virtual void bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir = PD_IN);
/// Binds an UInt8 vector.
virtual void bind(std::size_t pos, const Poco::Int16& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::Int16& val, Direction dir = PD_IN) = 0;
/// Binds an Int16. /// Binds an Int16.
virtual void bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir = PD_IN);
/// Binds an Int16 vector.
virtual void bind(std::size_t pos, const Poco::UInt16& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::UInt16& val, Direction dir = PD_IN) = 0;
/// Binds an UInt16. /// Binds an UInt16.
virtual void bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir = PD_IN);
/// Binds an UInt16 vector.
virtual void bind(std::size_t pos, const Poco::Int32& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::Int32& val, Direction dir = PD_IN) = 0;
/// Binds an Int32. /// Binds an Int32.
virtual void bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir = PD_IN);
/// Binds an Int32 vector.
virtual void bind(std::size_t pos, const Poco::UInt32& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::UInt32& val, Direction dir = PD_IN) = 0;
/// Binds an UInt32. /// Binds an UInt32.
virtual void bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir = PD_IN);
/// Binds an UInt32 vector.
virtual void bind(std::size_t pos, const Poco::Int64& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::Int64& val, Direction dir = PD_IN) = 0;
/// Binds an Int64. /// Binds an Int64.
virtual void bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir = PD_IN);
/// Binds an Int64 vector.
virtual void bind(std::size_t pos, const Poco::UInt64& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Poco::UInt64& val, Direction dir = PD_IN) = 0;
/// Binds an UInt64. /// Binds an UInt64.
virtual void bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir = PD_IN);
/// Binds an UInt64 vector.
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
virtual void bind(std::size_t pos, const long& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const long& val, Direction dir = PD_IN) = 0;
/// Binds a long. /// Binds a long.
virtual void bind(std::size_t pos, const std::vector<long>& val, Direction dir = PD_IN);
/// Binds a long vector.
#endif #endif
virtual void bind(std::size_t pos, const bool& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const bool& val, Direction dir = PD_IN) = 0;
/// Binds a boolean. /// Binds a boolean.
virtual void bind(std::size_t pos, const std::vector<bool>& val, Direction dir = PD_IN);
/// Binds a boolean vector.
virtual void bind(std::size_t pos, const float& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const float& val, Direction dir = PD_IN) = 0;
/// Binds a float. /// Binds a float.
virtual void bind(std::size_t pos, const std::vector<float>& val, Direction dir = PD_IN);
/// Binds a float vector.
virtual void bind(std::size_t pos, const double& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const double& val, Direction dir = PD_IN) = 0;
/// Binds a double. /// Binds a double.
virtual void bind(std::size_t pos, const std::vector<double>& val, Direction dir = PD_IN);
/// Binds a double vector.
virtual void bind(std::size_t pos, const char& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const char& val, Direction dir = PD_IN) = 0;
/// Binds a single character. /// Binds a single character.
virtual void bind(std::size_t pos, const char* const &pVal, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const std::vector<char>& val, Direction dir = PD_IN);
/// Binds a character vector.
virtual void bind(std::size_t pos, const char* const& pVal, Direction dir = PD_IN) = 0;
/// Binds a const char ptr. /// Binds a const char ptr.
virtual void bind(std::size_t pos, const std::string& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const std::string& val, Direction dir = PD_IN) = 0;
/// Binds a string. /// Binds a string.
virtual void bind(std::size_t pos, const std::vector<std::string>& val, Direction dir = PD_IN);
/// Binds a string vector.
virtual void bind(std::size_t pos, const BLOB& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const BLOB& val, Direction dir = PD_IN) = 0;
/// Binds a BLOB. /// Binds a BLOB.
virtual void bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir = PD_IN);
/// Binds a BLOB vector.
virtual void bind(std::size_t pos, const DateTime& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const DateTime& val, Direction dir = PD_IN) = 0;
/// Binds a DateTime. /// Binds a DateTime.
virtual void bind(std::size_t pos, const std::vector<DateTime>& val, Direction dir = PD_IN);
/// Binds a DateTime vector.
virtual void bind(std::size_t pos, const Date& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Date& val, Direction dir = PD_IN) = 0;
/// Binds a Date. /// Binds a Date.
virtual void bind(std::size_t pos, const std::vector<Date>& val, Direction dir = PD_IN);
/// Binds a Date vector.
virtual void bind(std::size_t pos, const Time& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const Time& val, Direction dir = PD_IN) = 0;
/// Binds a Time. /// Binds a Time.
virtual void bind(std::size_t pos, const std::vector<Time>& val, Direction dir = PD_IN);
/// Binds a Time vector.
virtual void bind(std::size_t pos, const NullData& val, Direction dir = PD_IN) = 0; virtual void bind(std::size_t pos, const NullData& val, Direction dir = PD_IN) = 0;
/// Binds a null. /// Binds a null.
virtual void bind(std::size_t pos, const std::vector<NullData>& val, Direction dir = PD_IN);
/// Binds a null vector.
void bind(std::size_t pos, const Any& val, Direction dir = PD_IN); void bind(std::size_t pos, const Any& val, Direction dir = PD_IN);
/// Binds an Any. /// Binds an Any.

View File

@@ -64,7 +64,7 @@ public:
PD_IN_OUT = AbstractBinder::PD_IN_OUT PD_IN_OUT = AbstractBinder::PD_IN_OUT
}; };
AbstractBinding(const std::string& name = "", Direction direction = PD_IN); AbstractBinding(const std::string& name = "", Direction direction = PD_IN, Poco::UInt32 bulkSize = 0);
/// Creates the AbstractBinding. /// Creates the AbstractBinding.
virtual ~AbstractBinding(); virtual ~AbstractBinding();
@@ -86,7 +86,7 @@ public:
/// Returns the number of rows that the binding handles. /// Returns the number of rows that the binding handles.
/// ///
/// The trivial case will be one single row but /// The trivial case will be one single row but
/// for collection data types (ie vector) it can be larger. /// for collection data types it can be larger.
virtual bool canBind() const = 0; virtual bool canBind() const = 0;
/// Returns true if we have enough data to bind /// Returns true if we have enough data to bind
@@ -103,10 +103,17 @@ public:
const std::string& name() const; const std::string& name() const;
/// Returns the name for this binding. /// Returns the name for this binding.
bool isBulk() const;
/// Returns true if extraction is bulk.
Poco::UInt32 bulkSize() const;
/// Returns the size of the bulk binding.
private: private:
AbstractBinder* _pBinder; AbstractBinder* _pBinder;
std::string _name; std::string _name;
Direction _direction; Direction _direction;
Poco::UInt32 _bulkSize;
}; };
@@ -135,6 +142,18 @@ inline AbstractBinder::Direction AbstractBinding::getDirection() const
} }
inline bool AbstractBinding::isBulk() const
{
return _bulkSize > 0;
}
inline Poco::UInt32 AbstractBinding::bulkSize() const
{
return _bulkSize;
}
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@@ -63,7 +63,7 @@ class Data_API AbstractExtraction: public Poco::RefCountedObject
{ {
public: public:
AbstractExtraction(Poco::UInt32 limit = Limit::LIMIT_UNLIMITED, AbstractExtraction(Poco::UInt32 limit = Limit::LIMIT_UNLIMITED,
Poco::UInt32 position = 0); Poco::UInt32 position = 0, bool bulk = false);
/// Creates the AbstractExtraction. A limit value equal to EXTRACT_UNLIMITED (0xffffffffu) /// Creates the AbstractExtraction. A limit value equal to EXTRACT_UNLIMITED (0xffffffffu)
/// means that we extract as much data as possible during one execute. /// means that we extract as much data as possible during one execute.
/// Otherwise the limit value is used to partition data extracting to a limited amount of rows. /// Otherwise the limit value is used to partition data extracting to a limited amount of rows.
@@ -95,13 +95,14 @@ public:
virtual std::size_t numOfRowsAllowed() const = 0; virtual std::size_t numOfRowsAllowed() const = 0;
/// Returns the upper limit on number of rows that the extraction will handle. /// Returns the upper limit on number of rows that the extraction will handle.
virtual void extract(std::size_t pos) = 0; virtual std::size_t extract(std::size_t pos) = 0;
/// Extracts a value from the param, starting at the given column position. /// Extracts a value from the param, starting at the given column position.
/// Returns the number of rows extracted.
virtual void reset() = 0; virtual void reset() = 0;
/// Resets the extractor so that it can be re-used. /// Resets the extractor so that it can be re-used.
virtual AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos) const = 0; virtual AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos) = 0;
/// Creates a Prepare object for the extracting object /// Creates a Prepare object for the extracting object
void setLimit(Poco::UInt32 limit); void setLimit(Poco::UInt32 limit);
@@ -118,10 +119,14 @@ public:
/// null values and be able to later provide information about them. /// null values and be able to later provide information about them.
/// Here, this function throws NotImplementedException. /// Here, this function throws NotImplementedException.
bool isBulk() const;
/// Returns true if this is bulk extraction.
private: private:
AbstractExtractor* _pExtractor; AbstractExtractor* _pExtractor;
Poco::UInt32 _limit; Poco::UInt32 _limit;
Poco::UInt32 _position; Poco::UInt32 _position;
bool _bulk;
}; };
@@ -169,6 +174,12 @@ inline Poco::UInt32 AbstractExtraction::position() const
} }
inline bool AbstractExtraction::isBulk() const
{
return _bulk;
}
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@@ -41,6 +41,7 @@
#include "Poco/Data/Data.h" #include "Poco/Data/Data.h"
#include <vector>
#include <cstddef> #include <cstddef>
@@ -74,67 +75,127 @@ public:
virtual bool extract(std::size_t pos, Poco::Int8& val) = 0; virtual bool extract(std::size_t pos, Poco::Int8& val) = 0;
/// Extracts an Int8. Returns false if null was received. /// Extracts an Int8. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::Int8>& val);
/// Extracts an Int8 vector.
virtual bool extract(std::size_t pos, Poco::UInt8& val) = 0; virtual bool extract(std::size_t pos, Poco::UInt8& val) = 0;
/// Extracts an UInt8. Returns false if null was received. /// Extracts an UInt8. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt8>& val);
/// Extracts an UInt8vector .
virtual bool extract(std::size_t pos, Poco::Int16& val) = 0; virtual bool extract(std::size_t pos, Poco::Int16& val) = 0;
/// Extracts an Int16. Returns false if null was received. /// Extracts an Int16. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::Int16>& val);
/// Extracts an Int16 vector.
virtual bool extract(std::size_t pos, Poco::UInt16& val) = 0; virtual bool extract(std::size_t pos, Poco::UInt16& val) = 0;
/// Extracts an UInt16. Returns false if null was received. /// Extracts an UInt16. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt16>& val);
/// Extracts an UInt16 vector.
virtual bool extract(std::size_t pos, Poco::Int32& val) = 0; virtual bool extract(std::size_t pos, Poco::Int32& val) = 0;
/// Extracts an Int32. Returns false if null was received. /// Extracts an Int32. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::Int32>& val);
/// Extracts an Int32 vector.
virtual bool extract(std::size_t pos, Poco::UInt32& val) = 0; virtual bool extract(std::size_t pos, Poco::UInt32& val) = 0;
/// Extracts an UInt32. Returns false if null was received. /// Extracts an UInt32. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt32>& val);
/// Extracts an UInt32 vector.
virtual bool extract(std::size_t pos, Poco::Int64& val) = 0; virtual bool extract(std::size_t pos, Poco::Int64& val) = 0;
/// Extracts an Int64. Returns false if null was received. /// Extracts an Int64. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::Int64>& val);
/// Extracts an Int64 vector.
virtual bool extract(std::size_t pos, Poco::UInt64& val) = 0; virtual bool extract(std::size_t pos, Poco::UInt64& val) = 0;
/// Extracts an UInt64. Returns false if null was received. /// Extracts an UInt64. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Poco::UInt64>& val);
/// Extracts an UInt64 vector.
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
virtual bool extract(std::size_t pos, long& val) = 0; virtual bool extract(std::size_t pos, long& val) = 0;
/// Extracts a long. Returns false if null was received. /// Extracts a long. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<long>& val);
/// Extracts a long vector.
#endif #endif
virtual bool extract(std::size_t pos, bool& val) = 0; virtual bool extract(std::size_t pos, bool& val) = 0;
/// Extracts a boolean. Returns false if null was received. /// Extracts a boolean. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<bool>& val);
/// Extracts a boolean vector.
virtual bool extract(std::size_t pos, float& val) = 0; virtual bool extract(std::size_t pos, float& val) = 0;
/// Extracts a float. Returns false if null was received. /// Extracts a float. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<float>& val);
/// Extracts a float vector.
virtual bool extract(std::size_t pos, double& val) = 0; virtual bool extract(std::size_t pos, double& val) = 0;
/// Extracts a double. Returns false if null was received. /// Extracts a double. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<double>& val);
/// Extracts a double vector.
virtual bool extract(std::size_t pos, char& val) = 0; virtual bool extract(std::size_t pos, char& val) = 0;
/// Extracts a single character. Returns false if null was received. /// Extracts a single character. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<char>& val);
/// Extracts a character vector.
virtual bool extract(std::size_t pos, std::string& val) = 0; virtual bool extract(std::size_t pos, std::string& val) = 0;
/// Extracts a string. Returns false if null was received. /// Extracts a string. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<std::string>& val);
/// Extracts a string vector.
virtual bool extract(std::size_t pos, BLOB& val) = 0; virtual bool extract(std::size_t pos, BLOB& val) = 0;
/// Extracts a BLOB. Returns false if null was received. /// Extracts a BLOB. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<BLOB>& val);
/// Extracts a BLOB vector.
virtual bool extract(std::size_t pos, DateTime& val) = 0; virtual bool extract(std::size_t pos, DateTime& val) = 0;
/// Extracts a DateTime. Returns false if null was received. /// Extracts a DateTime. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<DateTime>& val);
/// Extracts a DateTime vector.
virtual bool extract(std::size_t pos, Date& val) = 0; virtual bool extract(std::size_t pos, Date& val) = 0;
/// Extracts a Date. Returns false if null was received. /// Extracts a Date. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Date>& val);
/// Extracts a Date vector.
virtual bool extract(std::size_t pos, Time& val) = 0; virtual bool extract(std::size_t pos, Time& val) = 0;
/// Extracts a Time. Returns false if null was received. /// Extracts a Time. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Time>& val);
/// Extracts a Time vector.
virtual bool extract(std::size_t pos, Any& val) = 0; virtual bool extract(std::size_t pos, Any& val) = 0;
/// Extracts an Any. Returns false if null was received. /// Extracts an Any. Returns false if null was received.
virtual bool extract(std::size_t pos, std::vector<Any>& val);
/// Extracts an Any vector.
virtual bool extract(std::size_t pos, DynamicAny& val) = 0; virtual bool extract(std::size_t pos, DynamicAny& val) = 0;
/// Extracts a DynamicAny. Returns false if null was received. /// Extracts a DynamicAny. Returns false if null was received.
virtual bool isNull(std::size_t pos) = 0; virtual bool extract(std::size_t pos, std::vector<DynamicAny>& val);
/// Returns true if the current row value at pos column is null. /// Extracts a DynamicAny vector.
virtual bool isNull(std::size_t col, std::size_t row = -1) = 0;
/// Returns true if the value at [col,row] position is null.
virtual void reset(); virtual void reset();
/// Resets any information internally cached by the extractor. /// Resets any information internally cached by the extractor.

View File

@@ -42,6 +42,7 @@
#include "Poco/Data/Data.h" #include "Poco/Data/Data.h"
#include "Poco/RefCountedObject.h" #include "Poco/RefCountedObject.h"
#include <vector>
#include <cstddef> #include <cstddef>
@@ -64,80 +65,171 @@ class BLOB;
class Data_API AbstractPreparation: public Poco::RefCountedObject class Data_API AbstractPreparation: public Poco::RefCountedObject
/// Interface used for database preparation where we first have to register all data types (and memory output locations) /// Interface used for database preparation where we first have to register all data types (and memory output locations)
/// before extracting data, i.e. extract works as two-pase extract: first we call prepare once, then extract n-times. /// before extracting data, i.e. extract works as two-pase extract: first we call prepare once, then extract n-times.
/// Only some database connectors will need to implement this interface. /// There are cases (bulk operations using std::vector storage) when extract is called only once.
/// Note that the values in the interface serve only the purpose of type distinction. /// The value passed to a prepare() call is not be used by the prepare, serving only as an indication of the data type
/// being prepared.
/// Implementing this interface is not mandatory for a connector. Connectors that only extract data after SQL execution
/// (e.g. SQLite) do not need this functionality at all.
{ {
public: public:
AbstractPreparation(); AbstractPreparation(Poco::UInt32 length = 1u);
/// Creates the AbstractPreparation. /// Creates the AbstractPreparation.
virtual ~AbstractPreparation(); virtual ~AbstractPreparation();
/// Destroys the AbstractPreparation. /// Destroys the AbstractPreparation.
virtual void prepare(std::size_t pos, Poco::Int8) = 0; virtual void prepare(std::size_t pos, Poco::Int8&) = 0;
/// Prepares an Int8. /// Prepares an Int8.
virtual void prepare(std::size_t pos, Poco::UInt8) = 0; virtual void prepare(std::size_t pos, std::vector<Poco::Int8>& val);
/// Prepares an Int8 vector.
virtual void prepare(std::size_t pos, Poco::UInt8&) = 0;
/// Prepares an UInt8. /// Prepares an UInt8.
virtual void prepare(std::size_t pos, Poco::Int16) = 0; virtual void prepare(std::size_t pos, std::vector<Poco::UInt8>& val);
/// Prepares an UInt8 vector.
virtual void prepare(std::size_t pos, Poco::Int16&) = 0;
/// Prepares an Int16. /// Prepares an Int16.
virtual void prepare(std::size_t pos, Poco::UInt16) = 0; virtual void prepare(std::size_t pos, std::vector<Poco::Int16>& val);
/// Prepares an Int16 vector.
virtual void prepare(std::size_t pos, Poco::UInt16&) = 0;
/// Prepares an UInt16. /// Prepares an UInt16.
virtual void prepare(std::size_t pos, Poco::Int32) = 0; virtual void prepare(std::size_t pos, std::vector<Poco::UInt16>& val);
/// Prepares an UInt16 vector.
virtual void prepare(std::size_t pos, Poco::Int32&) = 0;
/// Prepares an Int32. /// Prepares an Int32.
virtual void prepare(std::size_t pos, Poco::UInt32) = 0; virtual void prepare(std::size_t pos, std::vector<Poco::Int32>& val);
/// Prepares an Int32 vector.
virtual void prepare(std::size_t pos, Poco::UInt32&) = 0;
/// Prepares an UInt32. /// Prepares an UInt32.
virtual void prepare(std::size_t pos, Poco::Int64) = 0; virtual void prepare(std::size_t pos, std::vector<Poco::UInt32>& val);
/// Prepares an UInt32 vector.
virtual void prepare(std::size_t pos, Poco::Int64&) = 0;
/// Prepares an Int64. /// Prepares an Int64.
virtual void prepare(std::size_t pos, Poco::UInt64) = 0; virtual void prepare(std::size_t pos, std::vector<Poco::Int64>& val);
/// Prepares an Int64 vector.
virtual void prepare(std::size_t pos, Poco::UInt64&) = 0;
/// Prepares an UInt64. /// Prepares an UInt64.
virtual void prepare(std::size_t pos, std::vector<Poco::UInt64>& val);
/// Prepares an UInt64 vector.
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
virtual void prepare(std::size_t pos, long) = 0; virtual void prepare(std::size_t pos, long&) = 0;
/// Prepares a long. /// Prepares a long.
virtual void prepare(std::size_t pos, std::vector<long>& val);
/// Prepares a long vector.
#endif #endif
virtual void prepare(std::size_t pos, bool) = 0; virtual void prepare(std::size_t pos, bool&) = 0;
/// Prepares a boolean. /// Prepares a boolean.
virtual void prepare(std::size_t pos, float) = 0; virtual void prepare(std::size_t pos, std::vector<bool>& val);
/// Prepares a boolean vector.
virtual void prepare(std::size_t pos, float&) = 0;
/// Prepares a float. /// Prepares a float.
virtual void prepare(std::size_t pos, double) = 0; virtual void prepare(std::size_t pos, std::vector<float>& val);
/// Prepares a float vector.
virtual void prepare(std::size_t pos, double&) = 0;
/// Prepares a double. /// Prepares a double.
virtual void prepare(std::size_t pos, char) = 0; virtual void prepare(std::size_t pos, std::vector<double>& val);
/// Prepares a double vector.
virtual void prepare(std::size_t pos, char&) = 0;
/// Prepares a single character. /// Prepares a single character.
virtual void prepare(std::size_t pos, const std::string& ) = 0; virtual void prepare(std::size_t pos, std::vector<char>& val);
/// Prepares a character vector.
virtual void prepare(std::size_t pos, const std::string&) = 0;
/// Prepares a string. /// Prepares a string.
virtual void prepare(std::size_t pos, const std::vector<std::string>& val);
/// Prepares a string vector.
virtual void prepare(std::size_t pos, const BLOB&) = 0; virtual void prepare(std::size_t pos, const BLOB&) = 0;
/// Prepares a BLOB. /// Prepares a BLOB.
virtual void prepare(std::size_t pos, const std::vector<BLOB>& val);
/// Prepares a BLOB vector.
virtual void prepare(std::size_t pos, const DateTime&) = 0; virtual void prepare(std::size_t pos, const DateTime&) = 0;
/// Prepares a DateTime. /// Prepares a DateTime.
virtual void prepare(std::size_t pos, const std::vector<DateTime>& val);
/// Prepares a DateTime vector.
virtual void prepare(std::size_t pos, const Date&) = 0; virtual void prepare(std::size_t pos, const Date&) = 0;
/// Prepares a Date. /// Prepares a Date.
virtual void prepare(std::size_t pos, const std::vector<Date>& val);
/// Prepares a Date vector.
virtual void prepare(std::size_t pos, const Time&) = 0; virtual void prepare(std::size_t pos, const Time&) = 0;
/// Prepares a Time. /// Prepares a Time.
virtual void prepare(std::size_t pos, const std::vector<Time>& val);
/// Prepares a Time vector.
virtual void prepare(std::size_t pos, const Any&) = 0; virtual void prepare(std::size_t pos, const Any&) = 0;
/// Prepares an Any. /// Prepares an Any.
virtual void prepare(std::size_t pos, const std::vector<Any>& val);
/// Prepares an Any vector.
virtual void prepare(std::size_t pos, const DynamicAny&) = 0; virtual void prepare(std::size_t pos, const DynamicAny&) = 0;
/// Prepares a DynamicAny. /// Prepares a DynamicAny.
virtual void prepare(std::size_t pos, const std::vector<DynamicAny>& val);
/// Prepares a DynamicAny vector.
void setLength(Poco::UInt32 length);
/// Sets the length of prepared data.
/// Needed only for data lengths greater than 1 (i.e. for
/// bulk operations).
Poco::UInt32 getLength() const;
/// Returns the length of prepared data. Defaults to 1.
/// The length is greater than one for bulk operations.
private:
Poco::UInt32 _length;
}; };
///
/// inlines
///
inline void AbstractPreparation::setLength(Poco::UInt32 length)
{
_length = length;
}
inline Poco::UInt32 AbstractPreparation::getLength() const
{
return _length;
}
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@@ -113,7 +113,9 @@ class Binding<std::vector<T> >: public AbstractBinding
/// Specialization for std::vector. /// Specialization for std::vector.
{ {
public: public:
explicit Binding(const std::vector<T>& val, const std::string& name = "", Direction direction = PD_IN): explicit Binding(const std::vector<T>& val,
const std::string& name = "",
Direction direction = PD_IN):
AbstractBinding(name, direction), AbstractBinding(name, direction),
_val(val), _val(val),
_begin(val.begin()), _begin(val.begin()),
@@ -148,6 +150,7 @@ public:
{ {
poco_assert_dbg(getBinder() != 0); poco_assert_dbg(getBinder() != 0);
poco_assert_dbg(canBind()); poco_assert_dbg(canBind());
TypeHandler<T>::bind(pos, *_begin, getBinder(), getDirection()); TypeHandler<T>::bind(pos, *_begin, getBinder(), getDirection());
++_begin; ++_begin;
} }
@@ -181,7 +184,9 @@ class Binding<std::vector<bool> >: public AbstractBinding
/// Only IN binding is supported. /// Only IN binding is supported.
{ {
public: public:
explicit Binding(const std::vector<bool>& val, const std::string& name = "", Direction direction = PD_IN): explicit Binding(const std::vector<bool>& val,
const std::string& name = "",
Direction direction = PD_IN):
AbstractBinding(name, direction), AbstractBinding(name, direction),
_val(val), _val(val),
_deq(_val.begin(), _val.end()), _deq(_val.begin(), _val.end()),
@@ -203,7 +208,7 @@ public:
std::size_t numOfColumnsHandled() const std::size_t numOfColumnsHandled() const
{ {
return TypeHandler<bool>::size(); return 1u;
} }
std::size_t numOfRowsHandled() const std::size_t numOfRowsHandled() const
@@ -222,6 +227,7 @@ public:
poco_assert_dbg(canBind()); poco_assert_dbg(canBind());
TypeHandler<bool>::bind(pos, *_begin, getBinder(), getDirection()); TypeHandler<bool>::bind(pos, *_begin, getBinder(), getDirection());
++_begin; ++_begin;
} }
void reset() void reset()
@@ -584,9 +590,7 @@ template <typename T>
Binding<T>* use(const T& t, const std::string& name = "") Binding<T>* use(const T& t, const std::string& name = "")
/// Convenience function for a more compact Binding creation. /// Convenience function for a more compact Binding creation.
{ {
Binding<T>* pB = new Binding<T>(t, name, AbstractBinding::PD_IN); return new Binding<T>(t, name, AbstractBinding::PD_IN);
poco_check_ptr (pB);
return pB;
} }
@@ -594,9 +598,7 @@ template <typename T>
Binding<T>* in(const T& t, const std::string& name = "") Binding<T>* in(const T& t, const std::string& name = "")
/// Convenience function for a more compact Binding creation. /// Convenience function for a more compact Binding creation.
{ {
Binding<T>* pB = new Binding<T>(t, name, AbstractBinding::PD_IN); return new Binding<T>(t, name, AbstractBinding::PD_IN);
poco_check_ptr (pB);
return pB;
} }
@@ -604,9 +606,7 @@ template <typename T>
Binding<T>* out(T& t, const std::string& name = "") Binding<T>* out(T& t, const std::string& name = "")
/// Convenience function for a more compact Binding creation. /// Convenience function for a more compact Binding creation.
{ {
Binding<T>* pB = new Binding<T>(t, name, AbstractBinding::PD_OUT); return new Binding<T>(t, name, AbstractBinding::PD_OUT);
poco_check_ptr (pB);
return pB;
} }
@@ -614,9 +614,7 @@ template <typename T>
Binding<T>* io(T& t, const std::string& name = "") Binding<T>* io(T& t, const std::string& name = "")
/// Convenience function for a more compact Binding creation. /// Convenience function for a more compact Binding creation.
{ {
Binding<T>* pB = new Binding<T>(t, name, AbstractBinding::PD_IN_OUT); return new Binding<T>(t, name, AbstractBinding::PD_IN_OUT);
poco_check_ptr (pB);
return pB;
} }

View File

@@ -0,0 +1,109 @@
//
// BulkExtraction.h
//
// $Id: //poco/Main/Data/include/Poco/Data/Bulk.h#9 $
//
// Library: Data
// Package: DataCore
// Module: Bulk
//
// Definition of the BulkExtraction class.
//
// 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.
//
#ifndef Data_Bulk_INCLUDED
#define Data_Bulk_INCLUDED
#include "Poco/Data/Limit.h"
namespace Poco {
namespace Data {
class Data_API Bulk
{
public:
Bulk(const Limit& limit);
/// Creates the Bulk.
Bulk(Poco::UInt32 value);
/// Creates the Bulk.
~Bulk();
/// Destroys the bulk.
const Limit& limit() const;
/// Returns the limit asociated with this bulk object.
Poco::UInt32 size() const;
/// Returns the value of the limit asociated with
/// this bulk object.
private:
Bulk();
Limit _limit;
};
///
/// inlines
///
inline const Limit& Bulk::limit() const
{
return _limit;
}
inline Poco::UInt32 Bulk::size() const
{
return _limit.value();
}
template <typename T>
inline Bulk bulk(const T& limit)
/// Convenience function for creation of bulk.
{
return Bulk(limit);
}
inline void bulk()
/// Dummy bulk function. Used for bulk binding creation
/// (see BulkBinding.h).
{
}
} } // namespace Poco::Data
#endif // Data_Bulk_INCLUDED

View File

@@ -0,0 +1,131 @@
//
// BulkBinding.h
//
// $Id: //poco/Main/Data/include/Poco/Data/BulkBinding.h#6 $
//
// Library: Data
// Package: DataCore
// Module: BulkBinding
//
// Definition of the BulkBinding class.
//
// 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.
//
#ifndef Data_BulkBinding_INCLUDED
#define Data_BulkBinding_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/Data/AbstractBinding.h"
#include "Poco/Data/DataException.h"
#include "Poco/Data/TypeHandler.h"
#include <vector>
#include <cstddef>
namespace Poco {
namespace Data {
template <class T>
class BulkBinding: public AbstractBinding
/// A BulkBinding maps a value to a column.
/// Bulk binding support is provided only for std::vector.
{
public:
explicit BulkBinding(const T& val, Poco::UInt32 bulkSize, const std::string& name = "", Direction direction = PD_IN):
AbstractBinding(name, direction, bulkSize),
_val(val),
_bound(false)
/// Creates the BulkBinding.
{
if (0 == _val.size())
throw InvalidArgumentException("Zero size containers not allowed.");
}
~BulkBinding()
/// Destroys the BulkBinding.
{
}
std::size_t numOfColumnsHandled() const
{
return 1;
}
std::size_t numOfRowsHandled() const
{
return _val.size();
}
bool canBind() const
{
return !_bound;
}
void bind(std::size_t pos)
{
poco_assert_dbg(getBinder() != 0);
TypeHandler<T>::bind(pos, _val, getBinder(), getDirection());
_bound = true;
}
void reset ()
{
_bound = false;
getBinder()->reset();
}
private:
const T& _val;
bool _bound;
};
typedef void (*BulkFnType)();
template <typename T>
BulkBinding<std::vector<T> >* use(const std::vector<T>& t, BulkFnType, const std::string& name = "")
/// Convenience function for a more compact BulkBinding creation.
{
return new BulkBinding<std::vector<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
}
template <typename T>
BulkBinding<std::vector<T> >* in(const std::vector<T>& t, BulkFnType, const std::string& name = "")
/// Convenience function for a more compact BulkBinding creation.
{
return new BulkBinding<std::vector<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
}
} } // namespace Poco::Data
#endif // Data_BulkBinding_INCLUDED

View File

@@ -0,0 +1,168 @@
//
// BulkExtraction.h
//
// $Id: //poco/Main/Data/include/Poco/Data/BulkExtraction.h#9 $
//
// Library: Data
// Package: DataCore
// Module: BulkExtraction
//
// Definition of the BulkExtraction class.
//
// 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.
//
#ifndef Data_BulkExtraction_INCLUDED
#define Data_BulkExtraction_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/Data/AbstractExtraction.h"
#include "Poco/Data/Bulk.h"
#include <vector>
namespace Poco {
namespace Data {
template <class T>
class BulkExtraction: public AbstractExtraction
/// Specialization for bulk extraction of values from a query result set.
/// Bulk extraction support is provided only for following STL containers:
/// - std::vector
/// - std::deque
/// - std::list
{
public:
BulkExtraction(T& result, Poco::UInt32 limit, Poco::UInt32 position = 0):
AbstractExtraction(limit, position, true),
_rResult(result),
_default()
{
if (static_cast<Poco::UInt32>(result.size()) != limit)
result.resize(limit);
}
virtual ~BulkExtraction()
{
}
std::size_t numOfColumnsHandled() const
{
return TypeHandler<T>::size();
}
std::size_t numOfRowsHandled() const
{
return _rResult.size();
}
std::size_t numOfRowsAllowed() const
{
return getLimit();
}
bool isNull(std::size_t row) const
{
try
{
return _nulls.at(row);
}catch (std::out_of_range& ex)
{
throw RangeException(ex.what());
}
}
std::size_t extract(std::size_t col)
{
AbstractExtractor* pExt = getExtractor();
TypeHandler<T>::extract(col, _rResult, _default, pExt);
typename T::iterator it = _rResult.begin();
typename T::iterator end = _rResult.end();
for (int row = 0; it !=end; ++it, ++row)
_nulls.push_back(pExt->isNull(col, row));
return _rResult.size();
}
virtual void reset()
{
}
AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t col)
{
Poco::UInt32 limit = getLimit();
if (limit != _rResult.size()) _rResult.resize(limit);
pPrep->setLength(limit);
return new Prepare<T>(pPrep, col, _rResult);
}
protected:
const T& result() const
{
return _rResult;
}
private:
T& _rResult;
T _default; // copy the default
std::deque<bool> _nulls;
};
template <typename T>
BulkExtraction<std::vector<T> >* into(std::vector<T>& t, const Bulk& bulk)
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::vector bulk extraction support.
{
return new BulkExtraction<std::vector<T> >(t, bulk.size());
}
template <typename T>
BulkExtraction<std::deque<T> >* into(std::deque<T>& t, const Bulk& bulk)
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::deque bulk extraction support.
{
return new BulkExtraction<std::deque<T> >(t, bulk.size());
}
template <typename T>
BulkExtraction<std::list<T> >* into(std::list<T>& t, const Bulk& bulk)
/// Convenience function to allow for a more compact creation of an extraction object
/// with std::list bulk extraction support.
{
return new BulkExtraction<std::list<T> >(t, bulk.size());
}
} } // namespace Poco::Data
#endif // Data_BulkExtraction_INCLUDED

View File

@@ -57,10 +57,10 @@ POCO_DECLARE_EXCEPTION(Data_API, BindingException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, ExtractException, DataException) POCO_DECLARE_EXCEPTION(Data_API, ExtractException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, LimitException, DataException) POCO_DECLARE_EXCEPTION(Data_API, LimitException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, NotSupportedException, DataException) POCO_DECLARE_EXCEPTION(Data_API, NotSupportedException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, NotImplementedException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, SessionUnavailableException, DataException) POCO_DECLARE_EXCEPTION(Data_API, SessionUnavailableException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, SessionPoolExhaustedException, DataException) POCO_DECLARE_EXCEPTION(Data_API, SessionPoolExhaustedException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, NoDataException, DataException) POCO_DECLARE_EXCEPTION(Data_API, NoDataException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, LengthExceededException, DataException)
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@@ -45,6 +45,7 @@
#include "Poco/Data/Prepare.h" #include "Poco/Data/Prepare.h"
#include "Poco/Data/TypeHandler.h" #include "Poco/Data/TypeHandler.h"
#include "Poco/Data/Column.h" #include "Poco/Data/Column.h"
#include "Poco/Data/Position.h"
#include "Poco/Data/DataException.h" #include "Poco/Data/DataException.h"
#include <set> #include <set>
#include <vector> #include <vector>
@@ -63,8 +64,8 @@ class Extraction: public AbstractExtraction
/// Concrete Data Type specific extraction of values from a query result set. /// Concrete Data Type specific extraction of values from a query result set.
{ {
public: public:
Extraction(T& result, Poco::UInt32 position = 0): Extraction(T& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default(), _default(),
_extracted(false) _extracted(false)
@@ -73,8 +74,8 @@ public:
{ {
} }
Extraction(T& result, const T& def, Poco::UInt32 position = 0): Extraction(T& result, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default(def), _default(def),
_extracted(false) _extracted(false)
@@ -108,13 +109,14 @@ public:
return _null; return _null;
} }
void extract(std::size_t pos) std::size_t extract(std::size_t pos)
{ {
if (_extracted) throw ExtractException("value already extracted"); if (_extracted) throw ExtractException("value already extracted");
_extracted = true; _extracted = true;
AbstractExtractor* pExt = getExtractor(); AbstractExtractor* pExt = getExtractor();
TypeHandler<T>::extract(pos, _rResult, _default, pExt); TypeHandler<T>::extract(pos, _rResult, _default, pExt);
_null = pExt->isNull(pos); _null = pExt->isNull(pos);
return 1u;
} }
void reset() void reset()
@@ -122,14 +124,14 @@ public:
_extracted = false; _extracted = false;
} }
AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos) const AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos)
{ {
return new Prepare<T>(pPrep, pos, _default); return new Prepare<T>(pPrep, pos, _rResult);
} }
private: private:
T& _rResult; T& _rResult;
T _default; // copy the default T _default;
bool _extracted; bool _extracted;
bool _null; bool _null;
}; };
@@ -140,18 +142,21 @@ class Extraction<std::vector<T> >: public AbstractExtraction
/// Vector Data Type specialization for extraction of values from a query result set. /// Vector Data Type specialization for extraction of values from a query result set.
{ {
public: public:
Extraction(std::vector<T>& result, Poco::UInt32 position = 0): Extraction(std::vector<T>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default() _default()
{ {
_rResult.clear();
} }
Extraction(std::vector<T>& result, const T& def, Poco::UInt32 position = 0): Extraction(std::vector<T>& result, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default(def) _default(def)
{ {
_rResult.clear();
} }
virtual ~Extraction() virtual ~Extraction()
@@ -184,24 +189,20 @@ public:
} }
} }
void extract(std::size_t pos) std::size_t extract(std::size_t pos)
{ {
AbstractExtractor* pExt = getExtractor(); AbstractExtractor* pExt = getExtractor();
_rResult.push_back(_default);
// for vector specialization, a temporary must be used to TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
// allow for extraction of bool values
T tmp = _default;
TypeHandler<T>::extract(pos, tmp, _default, pExt);
_rResult.push_back(tmp);
_nulls.push_back(pExt->isNull(pos)); _nulls.push_back(pExt->isNull(pos));
return 1u;
} }
virtual void reset() virtual void reset()
{ {
} }
AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos) const AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos)
{ {
return new Prepare<T>(pPrep, pos, _default); return new Prepare<T>(pPrep, pos, _default);
} }
@@ -215,28 +216,115 @@ protected:
private: private:
std::vector<T>& _rResult; std::vector<T>& _rResult;
T _default; // copy the default T _default;
std::deque<bool> _nulls; std::deque<bool> _nulls;
}; };
template <>
class Extraction<std::vector<bool> >: public AbstractExtraction
/// Vector bool specialization for extraction of values from a query result set.
{
public:
Extraction(std::vector<bool>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default()
{
_rResult.clear();
}
Extraction(std::vector<bool>& result, const bool& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default(def)
{
_rResult.clear();
}
virtual ~Extraction()
{
}
std::size_t numOfColumnsHandled() const
{
return TypeHandler<bool>::size();
}
std::size_t numOfRowsHandled() const
{
return _rResult.size();
}
std::size_t numOfRowsAllowed() const
{
return getLimit();
}
bool isNull(std::size_t row) const
{
try
{
return _nulls.at(row);
}catch (std::out_of_range& ex)
{
throw RangeException(ex.what());
}
}
std::size_t extract(std::size_t pos)
{
AbstractExtractor* pExt = getExtractor();
bool tmp = _default;
TypeHandler<bool>::extract(pos, tmp, _default, pExt);
_rResult.push_back(tmp);
_nulls.push_back(pExt->isNull(pos));
return 1u;
}
virtual void reset()
{
}
AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos)
{
return new Prepare<bool>(pPrep, pos, _default);
}
protected:
const std::vector<bool>& result() const
{
return _rResult;
}
private:
std::vector<bool>& _rResult;
bool _default;
std::deque<bool> _nulls;
};
template <class T> template <class T>
class Extraction<std::list<T> >: public AbstractExtraction class Extraction<std::list<T> >: public AbstractExtraction
/// List Data Type specialization for extraction of values from a query result set. /// List Data Type specialization for extraction of values from a query result set.
{ {
public: public:
Extraction(std::list<T>& result, Poco::UInt32 position = 0): Extraction(std::list<T>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default() _default()
{ {
_rResult.clear();
} }
Extraction(std::list<T>& result, const T& def, Poco::UInt32 position = 0): Extraction(std::list<T>& result, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default(def) _default(def)
{ {
_rResult.clear();
} }
virtual ~Extraction() virtual ~Extraction()
@@ -269,19 +357,20 @@ public:
} }
} }
void extract(std::size_t pos) std::size_t extract(std::size_t pos)
{ {
AbstractExtractor* pExt = getExtractor(); AbstractExtractor* pExt = getExtractor();
_rResult.push_back(_default); _rResult.push_back(_default);
TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt); TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
_nulls.push_back(pExt->isNull(pos)); _nulls.push_back(pExt->isNull(pos));
return 1u;
} }
virtual void reset() virtual void reset()
{ {
} }
AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos) const AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos)
{ {
return new Prepare<T>(pPrep, pos, _default); return new Prepare<T>(pPrep, pos, _default);
} }
@@ -295,7 +384,7 @@ protected:
private: private:
std::list<T>& _rResult; std::list<T>& _rResult;
T _default; // copy the default T _default;
std::deque<bool> _nulls; std::deque<bool> _nulls;
}; };
@@ -305,18 +394,20 @@ class Extraction<std::deque<T> >: public AbstractExtraction
/// Deque Data Type specialization for extraction of values from a query result set. /// Deque Data Type specialization for extraction of values from a query result set.
{ {
public: public:
Extraction(std::deque<T>& result, Poco::UInt32 position = 0): Extraction(std::deque<T>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default() _default()
{ {
_rResult.clear();
} }
Extraction(std::deque<T>& result, const T& def, Poco::UInt32 position = 0): Extraction(std::deque<T>& result, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default(def) _default(def)
{ {
_rResult.clear();
} }
virtual ~Extraction() virtual ~Extraction()
@@ -349,19 +440,20 @@ public:
} }
} }
void extract(std::size_t pos) std::size_t extract(std::size_t pos)
{ {
AbstractExtractor* pExt = getExtractor(); AbstractExtractor* pExt = getExtractor();
_rResult.push_back(_default); _rResult.push_back(_default);
TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt); TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
_nulls.push_back(pExt->isNull(pos)); _nulls.push_back(pExt->isNull(pos));
return 1u;
} }
virtual void reset() virtual void reset()
{ {
} }
AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos) const AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos)
{ {
return new Prepare<T>(pPrep, pos, _default); return new Prepare<T>(pPrep, pos, _default);
} }
@@ -375,7 +467,7 @@ protected:
private: private:
std::deque<T>& _rResult; std::deque<T>& _rResult;
T _default; // copy the default T _default;
std::deque<bool> _nulls; std::deque<bool> _nulls;
}; };
@@ -393,8 +485,8 @@ class InternalExtraction: public Extraction<C>
/// InternalExtraction objects can not be copied or assigned. /// InternalExtraction objects can not be copied or assigned.
{ {
public: public:
explicit InternalExtraction(C& result, Column<T,C>* pColumn, Poco::UInt32 position = 0): explicit InternalExtraction(C& result, Column<T,C>* pColumn, const Position& pos = Position(0)):
Extraction<C>(result, T(), position), Extraction<C>(result, T(), pos),
_pColumn(pColumn) _pColumn(pColumn)
/// Creates InternalExtraction. /// Creates InternalExtraction.
{ {
@@ -447,18 +539,22 @@ class Extraction<std::set<T> >: public AbstractExtraction
/// Set Data Type specialization for extraction of values from a query result set. /// Set Data Type specialization for extraction of values from a query result set.
{ {
public: public:
Extraction(std::set<T>& result, Poco::UInt32 position = 0): typedef typename std::set<T>::iterator Iterator;
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::set<T>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default() _default()
{ {
_rResult.clear();
} }
Extraction(std::set<T>& result, const T& def, Poco::UInt32 position = 0): Extraction(std::set<T>& result, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default(def) _default(def)
{ {
_rResult.clear();
} }
~Extraction() ~Extraction()
@@ -480,25 +576,26 @@ public:
return getLimit(); return getLimit();
} }
void extract(std::size_t pos) std::size_t extract(std::size_t pos)
{ {
T tmp; T tmp;
TypeHandler<T>::extract(pos, tmp, _default, getExtractor()); TypeHandler<T>::extract(pos, tmp, _default, getExtractor());
_rResult.insert(tmp); _rResult.insert(tmp);
return 1u;
} }
void reset() void reset()
{ {
} }
AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos) const AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos)
{ {
return new Prepare<T>(pPrep, pos, _default); return new Prepare<T>(pPrep, pos, _default);
} }
private: private:
std::set<T>& _rResult; std::set<T>& _rResult;
T _default; // copy the default T _default;
}; };
@@ -507,18 +604,20 @@ class Extraction<std::multiset<T> >: public AbstractExtraction
/// Multiset Data Type specialization for extraction of values from a query result set. /// Multiset Data Type specialization for extraction of values from a query result set.
{ {
public: public:
Extraction(std::multiset<T>& result, Poco::UInt32 position = 0): Extraction(std::multiset<T>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default() _default()
{ {
_rResult.clear();
} }
Extraction(std::multiset<T>& result, const T& def, Poco::UInt32 position = 0): Extraction(std::multiset<T>& result, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default(def) _default(def)
{ {
_rResult.clear();
} }
~Extraction() ~Extraction()
@@ -540,25 +639,26 @@ public:
return getLimit(); return getLimit();
} }
void extract(std::size_t pos) std::size_t extract(std::size_t pos)
{ {
T tmp; T tmp;
TypeHandler<T>::extract(pos, tmp, _default, getExtractor()); TypeHandler<T>::extract(pos, tmp, _default, getExtractor());
_rResult.insert(tmp); _rResult.insert(tmp);
return 1u;
} }
void reset() void reset()
{ {
} }
AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos) const AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos)
{ {
return new Prepare<T>(pPrep, pos, _default); return new Prepare<T>(pPrep, pos, _default);
} }
private: private:
std::multiset<T>& _rResult; std::multiset<T>& _rResult;
T _default; // copy the default T _default;
}; };
@@ -567,18 +667,20 @@ class Extraction<std::map<K, V> >: public AbstractExtraction
/// Map Data Type specialization for extraction of values from a query result set. /// Map Data Type specialization for extraction of values from a query result set.
{ {
public: public:
Extraction(std::map<K, V>& result, Poco::UInt32 position = 0): Extraction(std::map<K, V>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default() _default()
{ {
_rResult.clear();
} }
Extraction(std::map<K, V>& result, const V& def, Poco::UInt32 position = 0): Extraction(std::map<K, V>& result, const V& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default(def) _default(def)
{ {
_rResult.clear();
} }
~Extraction() ~Extraction()
@@ -600,18 +702,19 @@ public:
return getLimit(); return getLimit();
} }
void extract(std::size_t pos) std::size_t extract(std::size_t pos)
{ {
V tmp; V tmp;
TypeHandler<V>::extract(pos, tmp, _default, getExtractor()); TypeHandler<V>::extract(pos, tmp, _default, getExtractor());
_rResult.insert(std::make_pair(tmp(), tmp)); _rResult.insert(std::make_pair(tmp(), tmp));
return 1u;
} }
void reset() void reset()
{ {
} }
AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos) const AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos)
{ {
return new Prepare<V>(pPrep, pos, _default); return new Prepare<V>(pPrep, pos, _default);
} }
@@ -619,7 +722,7 @@ public:
private: private:
std::map<K, V>& _rResult; std::map<K, V>& _rResult;
V _default; // copy the default V _default;
}; };
@@ -628,18 +731,20 @@ class Extraction<std::multimap<K, V> >: public AbstractExtraction
/// Multimap Data Type specialization for extraction of values from a query result set. /// Multimap Data Type specialization for extraction of values from a query result set.
{ {
public: public:
Extraction(std::multimap<K, V>& result, Poco::UInt32 position = 0): Extraction(std::multimap<K, V>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default() _default()
{ {
_rResult.clear();
} }
Extraction(std::multimap<K, V>& result, const V& def, Poco::UInt32 position = 0): Extraction(std::multimap<K, V>& result, const V& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position), AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result), _rResult(result),
_default(def) _default(def)
{ {
_rResult.clear();
} }
~Extraction() ~Extraction()
@@ -661,38 +766,40 @@ public:
return getLimit(); return getLimit();
} }
void extract(std::size_t pos) std::size_t extract(std::size_t pos)
{ {
V tmp; V tmp;
TypeHandler<V>::extract(pos, tmp, _default, getExtractor()); TypeHandler<V>::extract(pos, tmp, _default, getExtractor());
_rResult.insert(std::make_pair(tmp(), tmp)); _rResult.insert(std::make_pair(tmp(), tmp));
return 1u;
} }
void reset() void reset()
{ {
} }
AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos) const AbstractPrepare* createPrepareObject(AbstractPreparation* pPrep, std::size_t pos)
{ {
return new Prepare<V>(pPrep, pos, _default); return new Prepare<V>(pPrep, pos, _default);
} }
private: private:
std::multimap<K, V>& _rResult; std::multimap<K, V>& _rResult;
V _default; // copy the default V _default;
}; };
template <typename T> template <typename T>
Extraction<T>* into(T& t, Poco::UInt32 pos = 0) Extraction<T>* into(T& t, const Position& pos = 0)
/// Convenience function to allow for a more compact creation of an extraction object /// Convenience function to allow for a more compact creation of an extraction object
/// with multiple recordset support.
{ {
return new Extraction<T>(t, pos); return new Extraction<T>(t, pos);
} }
template <typename T> template <typename T>
Extraction<T>* into(T& t, Poco::UInt32 pos, const T& def) Extraction<T>* into(T& t, const Position& pos, const T& def)
/// Convenience function to allow for a more compact creation of an extraction object with the given default /// Convenience function to allow for a more compact creation of an extraction object with the given default
{ {
return new Extraction<T>(t, def, pos); return new Extraction<T>(t, def, pos);

View File

@@ -77,6 +77,12 @@ public:
bool isLowerLimit() const; bool isLowerLimit() const;
/// Returns true if the limit is a lower limit, otherwise it is an upperLimit /// Returns true if the limit is a lower limit, otherwise it is an upperLimit
bool operator == (const Limit& other) const;
/// Equality operator.
bool operator != (const Limit& other) const;
/// Inequality operator.
private: private:
Poco::UInt32 _value; Poco::UInt32 _value;
bool _hardLimit; bool _hardLimit;
@@ -105,6 +111,22 @@ inline bool Limit::isLowerLimit() const
} }
inline bool Limit::operator == (const Limit& other) const
{
return other._value == _value &&
other._hardLimit == _hardLimit &&
other._isLowerLimit == _isLowerLimit;
}
inline bool Limit::operator != (const Limit& other) const
{
return other._value != _value ||
other._hardLimit != _hardLimit ||
other._isLowerLimit != _isLowerLimit;
}
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@@ -1,13 +1,13 @@
// //
// Step.h // PositionExtraction.h
// //
// $Id: //poco/Main/Data/include/Poco/Data/Step.h#7 $ // $Id: //poco/Main/Data/include/Poco/Data/Position.h#9 $
// //
// Library: Data // Library: Data
// Package: DataCore // Package: DataCore
// Module: Step // Module: Position
// //
// Definition of the Step class. // Definition of the PositionExtraction class.
// //
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
@@ -36,59 +36,56 @@
// //
#ifndef Data_Step_INCLUDED #ifndef Data_Position_INCLUDED
#define Data_Step_INCLUDED #define Data_Position_INCLUDED
#include "Poco/Data/Data.h" #include "Poco/Data/Limit.h"
namespace Poco { namespace Poco {
namespace Data { namespace Data {
class Data_API Step class Data_API Position
/// Step stores information how many rows should be returned at evry advance through the recordset. /// Utility class wrapping unsigned integer. Used to
/// indicate the recordset position in batch SQL statements.
{ {
public: public:
enum Position(Poco::UInt32 value);
{ /// Creates the Position.
DEFAULT_STEP = 1u
};
Step(Poco::UInt32 value = 1u); ~Position();
/// Creates the Step. /// Destroys the Position.
///
/// Value contains the step and defaults to DEFAULT_STEP.
~Step();
/// Destroys the Step.
Poco::UInt32 value() const; Poco::UInt32 value() const;
/// Returns the value of the limit /// Returns the position value.
private: private:
Position();
Poco::UInt32 _value; Poco::UInt32 _value;
}; };
// ///
// inlines /// inlines
// ///
inline Poco::UInt32 Step::value() const inline Poco::UInt32 Position::value() const
{ {
return _value; return _value;
} }
template <typename T> template <typename T>
Step step(T step) inline Position from(const T& value)
/// Convenience function for creation of position.
{ {
return Step(static_cast<Poco::UInt32>(step)); return Position(value);
} }
} } // namespace Poco::Data } } // namespace Poco::Data
#endif // Data_Step_INCLUDED #endif // Data_Position_INCLUDED

View File

@@ -44,11 +44,7 @@
#include "Poco/Data/AbstractPrepare.h" #include "Poco/Data/AbstractPrepare.h"
#include "Poco/Data/TypeHandler.h" #include "Poco/Data/TypeHandler.h"
#include <cstddef> #include <cstddef>
#include <map>
#include <set>
#include <vector> #include <vector>
#include <list>
#include <deque>
namespace Poco { namespace Poco {
@@ -60,7 +56,10 @@ class Prepare: public AbstractPrepare
/// Class for calling the appropriate AbstractPreparation method. /// Class for calling the appropriate AbstractPreparation method.
{ {
public: public:
Prepare(AbstractPreparation* pPrepare, std::size_t pos, const T& val): AbstractPrepare(pPrepare), _pos(pos), _val(val) Prepare(AbstractPreparation* pPrepare, std::size_t pos, T& val):
AbstractPrepare(pPrepare),
_pos(pos),
_val(val)
/// Creates the Prepare. /// Creates the Prepare.
{ {
} }
@@ -78,16 +77,21 @@ public:
private: private:
std::size_t _pos; std::size_t _pos;
const T& _val; T& _val;
}; };
template<typename T> template<typename T>
class Prepare<std::vector<T> >: public AbstractPrepare class Prepare<std::vector<T> >: public AbstractPrepare
/// Class for calling the appropriate AbstractPreparation method. /// Prepare specialization for std::vector.
/// This specialization is needed for bulk operations to enforce
/// the whole vector preparation, rather than only individual contained values.
{ {
public: public:
Prepare(AbstractPreparation* pPrepare, std::size_t pos, const T& val): AbstractPrepare(pPrepare), _pos(pos), _val(val) Prepare(AbstractPreparation* pPrepare, std::size_t pos, std::vector<T>& val = std::vector<T>()):
AbstractPrepare(pPrepare),
_pos(pos),
_val(val)
/// Creates the Prepare. /// Creates the Prepare.
{ {
} }
@@ -100,174 +104,12 @@ public:
void prepare() void prepare()
/// Prepares data. /// Prepares data.
{ {
TypeHandler<T>::prepare(_pos, _val, preparation()); TypeHandler<std::vector<T> >::prepare(_pos, _val, preparation());
} }
private: private:
std::size_t _pos; std::size_t _pos;
const T& _val; std::vector<T>& _val;
};
template<typename T>
class Prepare<std::list<T> >: public AbstractPrepare
/// Class for calling the appropriate AbstractPreparation method.
{
public:
Prepare(AbstractPreparation* pPrepare, std::size_t pos, const T& val): AbstractPrepare(pPrepare), _pos(pos), _val(val)
/// Creates the Prepare.
{
}
~Prepare()
/// Destroys the Prepare.
{
}
void prepare()
/// Prepares data.
{
TypeHandler<T>::prepare(_pos, _val, preparation());
}
private:
std::size_t _pos;
const T& _val;
};
template<typename T>
class Prepare<std::deque<T> >: public AbstractPrepare
/// Class for calling the appropriate AbstractPreparation method.
{
public:
Prepare(AbstractPreparation* pPrepare, std::size_t pos, const T& val): AbstractPrepare(pPrepare), _pos(pos), _val(val)
/// Creates the Prepare.
{
}
~Prepare()
/// Destroys the Prepare.
{
}
void prepare()
/// Prepares data.
{
TypeHandler<T>::prepare(_pos, _val, preparation());
}
private:
std::size_t _pos;
const T& _val;
};
template<typename T>
class Prepare<std::set<T> >: public AbstractPrepare
/// Class for calling the appropriate AbstractPreparation method.
{
public:
Prepare(AbstractPreparation* pPrepare, std::size_t pos, const T& val): AbstractPrepare(pPrepare), _pos(pos), _val(val)
/// Creates the Prepare.
{
}
~Prepare()
/// Destroys the Prepare.
{
}
void prepare()
/// Prepares data.
{
TypeHandler<T>::prepare(_pos, _val, preparation());
}
private:
std::size_t _pos;
const T& _val;
};
template<typename T>
class Prepare<std::multiset<T> >: public AbstractPrepare
/// Class for calling the appropriate AbstractPreparation method.
{
public:
Prepare(AbstractPreparation* pPrepare, std::size_t pos, const T& val): AbstractPrepare(pPrepare), _pos(pos), _val(val)
/// Creates the Prepare.
{
}
~Prepare()
/// Destroys the Prepare.
{
}
void prepare()
/// Prepares data.
{
TypeHandler<T>::prepare(_pos, _val, preparation());
}
private:
std::size_t _pos;
const T& _val;
};
template<typename K, typename V>
class Prepare<std::map<K, V> >: public AbstractPrepare
/// Class for calling the appropriate AbstractPreparation method.
{
public:
Prepare(AbstractPreparation* pPrepare, std::size_t pos, const V& val): AbstractPrepare(pPrepare), _pos(pos), _val(val)
/// Creates the Prepare.
{
}
~Prepare()
/// Destroys the Prepare.
{
}
void prepare()
/// Prepares data.
{
TypeHandler<V>::prepare(_pos, _val, preparation());
}
private:
std::size_t _pos;
const V& _val;
};
template<typename K, typename V>
class Prepare<std::multimap<K, V> >: public AbstractPrepare
/// Class for calling the appropriate AbstractPreparation method.
{
public:
Prepare(AbstractPreparation* pPrepare, std::size_t pos, const V& val): AbstractPrepare(pPrepare), _pos(pos), _val(val)
/// Creates the Prepare.
{
}
~Prepare()
/// Destroys the Prepare.
{
}
void prepare()
/// Prepares data.
{
TypeHandler<V>::prepare(_pos, _val, preparation());
}
private:
std::size_t _pos;
const V& _val;
}; };

View File

@@ -43,7 +43,7 @@
#include "Poco/Data/Data.h" #include "Poco/Data/Data.h"
#include "Poco/Data/StatementImpl.h" #include "Poco/Data/StatementImpl.h"
#include "Poco/Data/Range.h" #include "Poco/Data/Range.h"
#include "Poco/Data/Step.h" #include "Poco/Data/Bulk.h"
#include "Poco/SharedPtr.h" #include "Poco/SharedPtr.h"
#include "Poco/Mutex.h" #include "Poco/Mutex.h"
#include "Poco/ActiveMethod.h" #include "Poco/ActiveMethod.h"
@@ -171,15 +171,24 @@ public:
} }
Statement& operator , (Manipulator manip); Statement& operator , (Manipulator manip);
/// Handles manipulators, such as now. /// Handles manipulators, such as now, async, etc.
Statement& operator , (AbstractBinding* info); Statement& operator , (AbstractBinding* info);
/// Registers the Binding at the Statement /// Registers the Binding at the Statement.
Statement& operator , (AbstractExtraction* extract); Statement& operator , (AbstractExtraction* extract);
/// Registers objects used for extracting data at the Statement. /// Registers objects used for extracting data at the Statement.
/// the position argument is used by connectors that support multilple
/// recordsets to specify which recordset this extraction belongs to. Statement& operator , (const Bulk& bulk);
/// Sets the bulk execution mode (both binding and extraction) for this
/// statement.Statement must not have any extracors or binders set at the
/// time when this operator is applied.
/// Failure to adhere to the above constraint shall result in
/// InvalidAccessException.
/// Additionally, any binding buffers passed to the statement later
/// through use() or in() must be of the same size (determined by size
/// of the bulk passed to this function). Since they are resized automatically
/// by the framework, the extraction buffers do not have to adhere to this.
Statement& operator , (const Limit& extrLimit); Statement& operator , (const Limit& extrLimit);
/// Sets a limit on the maximum number of rows a select is allowed to return. /// Sets a limit on the maximum number of rows a select is allowed to return.
@@ -191,14 +200,8 @@ public:
/// ///
/// Set per default to Limit::LIMIT_UNLIMITED which disables the range. /// Set per default to Limit::LIMIT_UNLIMITED which disables the range.
Statement& operator , (const Step& extrStep);
/// Sets a an extraction step (the number of rows a select is allowed to return
/// on every fetch attempt).
///
/// Set per default to Step::DEFAULT_STEP (1 row at a time).
std::string toString() const; std::string toString() const;
/// Creates a string from the accumulated SQL statement /// Creates a string from the accumulated SQL statement.
ResultType execute(); ResultType execute();
/// Executes the statement synchronously or asynchronously. /// Executes the statement synchronously or asynchronously.
@@ -296,85 +299,77 @@ private:
// Manipulators // Manipulators
// //
void Data_API now(Statement& statement); inline void Data_API now(Statement& statement)
/// Enforces immediate execution of the statement. /// Enforces immediate execution of the statement.
/// If _isAsync flag has been set, execution is invoked asynchronously. /// If _isAsync flag has been set, execution is invoked asynchronously.
{
statement.execute();
}
void Data_API sync(Statement& statement); inline void Data_API sync(Statement& statement)
/// Sets the _isAsync flag to false, signalling synchronous execution. /// Sets the _isAsync flag to false, signalling synchronous execution.
/// Synchronous execution is default, so specifying this manipulator /// Synchronous execution is default, so specifying this manipulator
/// only makes sense if async() was called for the statement before. /// only makes sense if async() was called for the statement before.
{
statement.setAsync(false);
}
void Data_API async(Statement& statement); inline void Data_API async(Statement& statement)
/// Sets the _isAsync flag to true, signalling asynchronous execution. /// Sets the _async flag to true, signalling asynchronous execution.
{
statement.setAsync(true);
}
void Data_API deque(Statement& statement); inline void Data_API deque(Statement& statement)
/// Sets the internal storage to std::deque. /// Sets the internal storage to std::deque.
/// std::deque is default storage, so specifying this manipulator /// std::deque is default storage, so specifying this manipulator
/// only makes sense if list() or deque() were called for the statement before. /// only makes sense if list() or deque() were called for the statement before.
{
if (!statement.canModifyStorage())
throw InvalidAccessException("Storage not modifiable.");
statement.setStorage("deque");
}
void Data_API vector(Statement& statement); inline void Data_API vector(Statement& statement)
/// Sets the internal storage to std::vector. /// Sets the internal storage to std::vector.
{
if (!statement.canModifyStorage())
throw InvalidAccessException("Storage not modifiable.");
void Data_API list(Statement& statement); statement.setStorage("vector");
}
inline void Data_API list(Statement& statement)
/// Sets the internal storage to std::list. /// Sets the internal storage to std::list.
{
if (!statement.canModifyStorage())
throw InvalidAccessException("Storage not modifiable.");
statement.setStorage("list");
}
void Data_API reset(Statement& statement); inline void Data_API reset(Statement& statement)
/// Sets all internal settings to their respective default values. /// Sets all internal settings to their respective default values.
{
if (!statement.canModifyStorage())
throw InvalidAccessException("Storage not modifiable.");
statement.setStorage("deque");
statement.setAsync(false);
}
// //
// inlines // inlines
// //
inline Statement& Statement::operator , (Manipulator manip)
{
manip(*this);
return *this;
}
inline Statement& Statement::operator , (AbstractBinding* info)
{
_pImpl->addBinding(info);
return *this;
}
inline Statement& Statement::operator , (AbstractExtraction* extract)
{
_pImpl->addExtract(extract);
return *this;
}
inline Statement& Statement::operator , (const Limit& extrLimit)
{
_pImpl->setExtractionLimit(extrLimit);
return *this;
}
inline Statement& Statement::operator , (const Range& extrRange)
{
_pImpl->setExtractionLimit(extrRange.lower());
_pImpl->setExtractionLimit(extrRange.upper());
return *this;
}
inline Statement& Statement::operator , (const Step& extrStep)
{
_pImpl->setStep(extrStep.value());
return *this;
}
inline std::string Statement::toString() const inline std::string Statement::toString() const
{ {
@@ -460,6 +455,7 @@ inline void swap(Statement& s1, Statement& s2)
} }
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@@ -44,6 +44,7 @@
#include "Poco/Data/AbstractBinding.h" #include "Poco/Data/AbstractBinding.h"
#include "Poco/Data/AbstractExtraction.h" #include "Poco/Data/AbstractExtraction.h"
#include "Poco/Data/Range.h" #include "Poco/Data/Range.h"
#include "Poco/Data/Bulk.h"
#include "Poco/Data/Column.h" #include "Poco/Data/Column.h"
#include "Poco/Data/Extraction.h" #include "Poco/Data/Extraction.h"
#include "Poco/Data/SessionImpl.h" #include "Poco/Data/SessionImpl.h"
@@ -86,6 +87,14 @@ public:
STORAGE_UNKNOWN_IMPL STORAGE_UNKNOWN_IMPL
}; };
enum BulkType
{
BULK_UNDEFINED,
BULK_BINDING,
BULK_EXTRACTION,
BULK_FORBIDDEN
};
static const std::string DEQUE; static const std::string DEQUE;
static const std::string VECTOR; static const std::string VECTOR;
static const std::string LIST; static const std::string LIST;
@@ -133,12 +142,6 @@ public:
Storage getStorage() const; Storage getStorage() const;
/// Returns the storage type for this statement. /// Returns the storage type for this statement.
void setStep(Poco::UInt32 step);
/// Sets the step for this statement;
Poco::UInt32 getStep() const;
/// Returns the step type for this statement.
std::size_t extractionCount() const; std::size_t extractionCount() const;
/// Returns the number of extraction storage buffers associated /// Returns the number of extraction storage buffers associated
/// with the statement. /// with the statement.
@@ -168,7 +171,7 @@ protected:
/// returns the number of rows retreved. /// returns the number of rows retreved.
/// ///
/// Will throw, if the resultset is empty. /// Will throw, if the resultset is empty.
/// Expects the statement to be compiled and bound /// Expects the statement to be compiled and bound.
virtual bool canBind() const = 0; virtual bool canBind() const = 0;
/// Returns if another bind is possible. /// Returns if another bind is possible.
@@ -254,6 +257,12 @@ protected:
Poco::UInt32 activateNextDataSet(); Poco::UInt32 activateNextDataSet();
/// Returns the next data set, or -1 if the last data set was reached. /// Returns the next data set, or -1 if the last data set was reached.
Poco::UInt32 getExtractionLimit();
/// Returns the extraction limit value.
const Limit& extractionLimit() const;
/// Returns the extraction limit.
private: private:
void compile(); void compile();
/// Compiles the statement, if not yet compiled. doesn't bind yet /// Compiles the statement, if not yet compiled. doesn't bind yet
@@ -319,6 +328,31 @@ private:
bool isNull(std::size_t col, std::size_t row) const; bool isNull(std::size_t col, std::size_t row) const;
/// Returns true if the value in [col, row] is null. /// Returns true if the value in [col, row] is null.
void forbidBulk();
/// Forbids bulk operations.
void setBulkBinding();
/// Sets the bulk binding flag.
void setBulkExtraction(const Bulk& l);
/// Sets the bulk extraction flag and extraction limit.
bool bulkBindingAllowed() const;
/// Returns true if statement can be set to bind data in bulk.
/// Once bulk binding is set for a statement, it can be
/// neither altered nor mixed with non-bulk mode binding.
bool bulkExtractionAllowed() const;
/// Returns true if statement can be set to extract data in bulk.
/// Once bulk extraction is set for a statement, it can be
/// neither altered nor mixed with non-bulk mode extraction.
bool isBulkBinding() const;
/// Returns true if statement is set to bind data in bulk.
bool isBulkExtraction() const;
/// Returns true if statement is set to extract data in bulk.
StatementImpl(const StatementImpl& stmt); StatementImpl(const StatementImpl& stmt);
StatementImpl& operator = (const StatementImpl& stmt); StatementImpl& operator = (const StatementImpl& stmt);
@@ -332,7 +366,8 @@ private:
AbstractBindingVec _bindings; AbstractBindingVec _bindings;
AbstractExtractionVecVec _extractors; AbstractExtractionVecVec _extractors;
Poco::UInt32 _curDataSet; Poco::UInt32 _curDataSet;
Poco::UInt32 _step; BulkType _bulkBinding;
BulkType _bulkExtraction;
friend class Statement; friend class Statement;
}; };
@@ -411,18 +446,6 @@ inline StatementImpl::Storage StatementImpl::getStorage() const
} }
inline void StatementImpl::setStep(Poco::UInt32 step)
{
_step = step;
}
inline Poco::UInt32 StatementImpl::getStep() const
{
return _step;
}
inline std::size_t StatementImpl::extractionCount() const inline std::size_t StatementImpl::extractionCount() const
{ {
return extractions().size(); return extractions().size();
@@ -459,6 +482,57 @@ inline Poco::UInt32 StatementImpl::currentDataSet() const
} }
inline Poco::UInt32 StatementImpl::getExtractionLimit()
{
return _extrLimit.value();
}
inline const Limit& StatementImpl::extractionLimit() const
{
return _extrLimit;
}
inline void StatementImpl::forbidBulk()
{
_bulkBinding = BULK_FORBIDDEN;
_bulkExtraction = BULK_FORBIDDEN;
}
inline void StatementImpl::setBulkBinding()
{
_bulkBinding = BULK_BINDING;
}
inline bool StatementImpl::bulkBindingAllowed() const
{
return BULK_UNDEFINED == _bulkBinding ||
BULK_BINDING == _bulkBinding;
}
inline bool StatementImpl::bulkExtractionAllowed() const
{
return BULK_UNDEFINED == _bulkExtraction ||
BULK_EXTRACTION == _bulkExtraction;
}
inline bool StatementImpl::isBulkBinding() const
{
return BULK_BINDING == _bulkBinding;
}
inline bool StatementImpl::isBulkExtraction() const
{
return BULK_EXTRACTION == _bulkExtraction;
}
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@@ -52,8 +52,21 @@ namespace Poco {
namespace Data { namespace Data {
class AbstractTypeHandler
/// Parent class for type handlers.
/// The reason for this class is to prevent instantiations of type handlers.
/// For documentation on type handlers, see TypeHandler class.
{
protected:
AbstractTypeHandler();
~AbstractTypeHandler();
AbstractTypeHandler(const AbstractTypeHandler&);
AbstractTypeHandler& operator = (const AbstractTypeHandler&);
};
template <class T> template <class T>
class TypeHandler class TypeHandler: public AbstractTypeHandler
/// Converts Rows to a Type and the other way around. Provide template specializations to support your own complex types. /// Converts Rows to a Type and the other way around. Provide template specializations to support your own complex types.
/// ///
/// Take as example the following (simplified) class: /// Take as example the following (simplified) class:
@@ -66,7 +79,7 @@ class TypeHandler
/// [....] // public set/get methods, a default constructor, optional < operator (for set, multiset) or function operator (for map, multimap) /// [....] // public set/get methods, a default constructor, optional < operator (for set, multiset) or function operator (for map, multimap)
/// }; /// };
/// ///
/// The TypeHandler must provide a costum bind, size, prepare and extract method: /// The TypeHandler must provide a custom bind, size, prepare and extract method:
/// ///
/// template <> /// template <>
/// class TypeHandler<struct Person> /// class TypeHandler<struct Person>
@@ -132,19 +145,16 @@ public:
static void extract(std::size_t pos, T& obj, const T& defVal, AbstractExtractor* pExt) static void extract(std::size_t pos, T& obj, const T& defVal, AbstractExtractor* pExt)
{ {
poco_assert_dbg (pExt != 0); poco_assert_dbg (pExt != 0);
if (!pExt->extract(pos, obj)) if (!pExt->extract(pos, obj)) obj = defVal;
obj = defVal;
} }
static void prepare(std::size_t pos, const T& obj, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, T& obj, AbstractPreparation* pPrepare)
{ {
poco_assert_dbg (pPrepare != 0); poco_assert_dbg (pPrepare != 0);
pPrepare->prepare(pos, obj); pPrepare->prepare(pos, obj);
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator = (const TypeHandler&); TypeHandler& operator = (const TypeHandler&);
}; };
@@ -204,7 +214,7 @@ public:
pBinder->bind(pos++, tuple.template get<19>(), dir); pBinder->bind(pos++, tuple.template get<19>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -280,8 +290,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -336,7 +344,7 @@ public:
pBinder->bind(pos++, tuple.template get<18>(), dir); pBinder->bind(pos++, tuple.template get<18>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -409,8 +417,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -463,7 +469,7 @@ public:
pBinder->bind(pos++, tuple.template get<17>(), dir); pBinder->bind(pos++, tuple.template get<17>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -533,8 +539,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -585,7 +589,7 @@ public:
pBinder->bind(pos++, tuple.template get<16>(), dir); pBinder->bind(pos++, tuple.template get<16>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -652,8 +656,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -702,7 +704,7 @@ public:
pBinder->bind(pos++, tuple.template get<15>(), dir); pBinder->bind(pos++, tuple.template get<15>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -766,8 +768,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -814,7 +814,7 @@ public:
pBinder->bind(pos++, tuple.template get<14>(), dir); pBinder->bind(pos++, tuple.template get<14>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -875,8 +875,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -921,7 +919,7 @@ public:
pBinder->bind(pos++, tuple.template get<13>(), dir); pBinder->bind(pos++, tuple.template get<13>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -979,8 +977,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -1023,7 +1019,7 @@ public:
pBinder->bind(pos++, tuple.template get<12>(), dir); pBinder->bind(pos++, tuple.template get<12>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1078,8 +1074,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -1120,7 +1114,7 @@ public:
pBinder->bind(pos++, tuple.template get<11>(), dir); pBinder->bind(pos++, tuple.template get<11>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1172,8 +1166,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -1212,7 +1204,7 @@ public:
pBinder->bind(pos++, tuple.template get<10>(), dir); pBinder->bind(pos++, tuple.template get<10>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1261,8 +1253,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -1290,7 +1280,7 @@ public:
pBinder->bind(pos++, tuple.template get<9>(), dir); pBinder->bind(pos++, tuple.template get<9>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1336,8 +1326,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -1364,7 +1352,7 @@ public:
pBinder->bind(pos++, tuple.template get<8>(), dir); pBinder->bind(pos++, tuple.template get<8>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1407,8 +1395,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -1434,7 +1420,7 @@ public:
pBinder->bind(pos++, tuple.template get<7>(), dir); pBinder->bind(pos++, tuple.template get<7>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1474,8 +1460,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -1500,7 +1484,7 @@ public:
pBinder->bind(pos++, tuple.template get<6>(), dir); pBinder->bind(pos++, tuple.template get<6>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1537,8 +1521,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -1562,7 +1544,7 @@ public:
pBinder->bind(pos++, tuple.template get<5>(), dir); pBinder->bind(pos++, tuple.template get<5>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1596,8 +1578,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -1620,7 +1600,7 @@ public:
pBinder->bind(pos++, tuple.template get<4>(), dir); pBinder->bind(pos++, tuple.template get<4>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1651,8 +1631,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -1674,7 +1652,7 @@ public:
pBinder->bind(pos++, tuple.template get<3>(), dir); pBinder->bind(pos++, tuple.template get<3>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1702,8 +1680,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -1724,7 +1700,7 @@ public:
pBinder->bind(pos++, tuple.template get<2>(), dir); pBinder->bind(pos++, tuple.template get<2>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1749,8 +1725,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -1770,7 +1744,7 @@ public:
pBinder->bind(pos++, tuple.template get<1>(), dir); pBinder->bind(pos++, tuple.template get<1>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1792,8 +1766,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };
@@ -1812,7 +1784,7 @@ public:
pBinder->bind(pos++, tuple.template get<0>(), dir); pBinder->bind(pos++, tuple.template get<0>(), dir);
} }
static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparation* pPrepare) static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparation* pPrepare)
{ {
poco_assert (pPrepare != 0); poco_assert (pPrepare != 0);
pPrepare->prepare(pos++, tuple.template get<0>()); pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1832,8 +1804,6 @@ public:
} }
private: private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&); TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&); TypeHandler& operator=(const TypeHandler&);
}; };

View File

@@ -35,10 +35,13 @@
#include "Poco/Data/AbstractBinder.h" #include "Poco/Data/AbstractBinder.h"
#include "Poco/Data/Date.h"
#include "Poco/Data/Time.h"
#include "Poco/Data/BLOB.h"
#include "Poco/Data/DataException.h" #include "Poco/Data/DataException.h"
#include "Poco/DateTime.h"
#include "Poco/Any.h" #include "Poco/Any.h"
#include "Poco/DynamicAny.h" #include "Poco/DynamicAny.h"
#include "Poco/Data/BLOB.h"
namespace Poco { namespace Poco {
@@ -55,40 +58,162 @@ AbstractBinder::~AbstractBinder()
} }
void AbstractBinder::bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
#ifndef POCO_LONG_IS_64_BIT
void AbstractBinder::bind(std::size_t pos, const std::vector<long>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
#endif
void AbstractBinder::bind(std::size_t pos, const std::vector<bool>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<float>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<double>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<char>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<std::string>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<DateTime>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<Date>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<Time>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const std::vector<NullData>& val, Direction dir)
{
throw NotImplementedException("std::vector binder must be implemented.");
}
void AbstractBinder::bind(std::size_t pos, const Any& val, Direction dir) void AbstractBinder::bind(std::size_t pos, const Any& val, Direction dir)
{ {
if(val.type() == typeid(Int32)) const std::type_info& type = val.type();
if(type == typeid(Int32))
bind(pos, RefAnyCast<Int32>(val), dir); bind(pos, RefAnyCast<Int32>(val), dir);
else if(val.type() == typeid(std::string)) else if(type == typeid(std::string))
bind(pos, RefAnyCast<std::string>(val), dir); bind(pos, RefAnyCast<std::string>(val), dir);
else if (val.type() == typeid(bool)) else if (type == typeid(bool))
bind(pos, RefAnyCast<bool>(val), dir); bind(pos, RefAnyCast<bool>(val), dir);
else if(val.type() == typeid(char)) else if(type == typeid(char))
bind(pos, RefAnyCast<char>(val), dir); bind(pos, RefAnyCast<char>(val), dir);
else if(val.type() == typeid(Int8)) else if(type == typeid(Int8))
bind(pos, RefAnyCast<Int8>(val), dir); bind(pos, RefAnyCast<Int8>(val), dir);
else if(val.type() == typeid(UInt8)) else if(type == typeid(UInt8))
bind(pos, RefAnyCast<UInt8>(val), dir); bind(pos, RefAnyCast<UInt8>(val), dir);
else if(val.type() == typeid(Int16)) else if(type == typeid(Int16))
bind(pos, RefAnyCast<Int16>(val), dir); bind(pos, RefAnyCast<Int16>(val), dir);
else if(val.type() == typeid(UInt16)) else if(type == typeid(UInt16))
bind(pos, RefAnyCast<UInt16>(val), dir); bind(pos, RefAnyCast<UInt16>(val), dir);
else if(val.type() == typeid(UInt32)) else if(type == typeid(UInt32))
bind(pos, RefAnyCast<UInt32>(val), dir); bind(pos, RefAnyCast<UInt32>(val), dir);
else if(val.type() == typeid(Int64)) else if(type == typeid(Int64))
bind(pos, RefAnyCast<Int64>(val), dir); bind(pos, RefAnyCast<Int64>(val), dir);
else if(val.type() == typeid(UInt64)) else if(type == typeid(UInt64))
bind(pos, RefAnyCast<UInt64>(val), dir); bind(pos, RefAnyCast<UInt64>(val), dir);
else if(val.type() == typeid(float)) else if(type == typeid(float))
bind(pos, RefAnyCast<float>(val), dir); bind(pos, RefAnyCast<float>(val), dir);
else if(val.type() == typeid(double)) else if(type == typeid(double))
bind(pos, RefAnyCast<double>(val), dir); bind(pos, RefAnyCast<double>(val), dir);
else if(val.type() == typeid(DateTime)) else if(type == typeid(DateTime))
bind(pos, RefAnyCast<DateTime>(val), dir); bind(pos, RefAnyCast<DateTime>(val), dir);
else if(val.type() == typeid(BLOB)) else if(type == typeid(Date))
bind(pos, RefAnyCast<Date>(val), dir);
else if(type == typeid(Time))
bind(pos, RefAnyCast<Time>(val), dir);
else if(type == typeid(BLOB))
bind(pos, RefAnyCast<BLOB>(val), dir); bind(pos, RefAnyCast<BLOB>(val), dir);
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
else if(val.type() == typeid(long)) else if(type == typeid(long))
bind(pos, RefAnyCast<long>(val), dir); bind(pos, RefAnyCast<long>(val), dir);
#endif #endif
else else
@@ -98,38 +223,44 @@ void AbstractBinder::bind(std::size_t pos, const Any& val, Direction dir)
void AbstractBinder::bind(std::size_t pos, const DynamicAny& val, Direction dir) void AbstractBinder::bind(std::size_t pos, const DynamicAny& val, Direction dir)
{ {
if(val.type() == typeid(Int32)) const std::type_info& type = val.type();
if(type == typeid(Int32))
bind(pos, val.extract<Int32>(), dir); bind(pos, val.extract<Int32>(), dir);
else if(val.type() == typeid(std::string)) else if(type == typeid(std::string))
bind(pos, val.extract<std::string>(), dir); bind(pos, val.extract<std::string>(), dir);
else if (val.type() == typeid(bool)) else if (type == typeid(bool))
bind(pos, val.extract<bool>(), dir); bind(pos, val.extract<bool>(), dir);
else if(val.type() == typeid(char)) else if(type == typeid(char))
bind(pos, val.extract<char>(), dir); bind(pos, val.extract<char>(), dir);
else if(val.type() == typeid(Int8)) else if(type == typeid(Int8))
bind(pos, val.extract<Int8>(), dir); bind(pos, val.extract<Int8>(), dir);
else if(val.type() == typeid(UInt8)) else if(type == typeid(UInt8))
bind(pos, val.extract<UInt8>(), dir); bind(pos, val.extract<UInt8>(), dir);
else if(val.type() == typeid(Int16)) else if(type == typeid(Int16))
bind(pos, val.extract<Int16>(), dir); bind(pos, val.extract<Int16>(), dir);
else if(val.type() == typeid(UInt16)) else if(type == typeid(UInt16))
bind(pos, val.extract<UInt16>(), dir); bind(pos, val.extract<UInt16>(), dir);
else if(val.type() == typeid(UInt32)) else if(type == typeid(UInt32))
bind(pos, val.extract<UInt32>(), dir); bind(pos, val.extract<UInt32>(), dir);
else if(val.type() == typeid(Int64)) else if(type == typeid(Int64))
bind(pos, val.extract<Int64>(), dir); bind(pos, val.extract<Int64>(), dir);
else if(val.type() == typeid(UInt64)) else if(type == typeid(UInt64))
bind(pos, val.extract<UInt64>(), dir); bind(pos, val.extract<UInt64>(), dir);
else if(val.type() == typeid(float)) else if(type == typeid(float))
bind(pos, val.extract<float>(), dir); bind(pos, val.extract<float>(), dir);
else if(val.type() == typeid(double)) else if(type == typeid(double))
bind(pos, val.extract<double>(), dir); bind(pos, val.extract<double>(), dir);
else if(val.type() == typeid(DateTime)) else if(type == typeid(DateTime))
bind(pos, val.extract<DateTime>(), dir); bind(pos, val.extract<DateTime>(), dir);
else if(val.type() == typeid(BLOB)) else if(type == typeid(Date))
bind(pos, val.extract<Date>(), dir);
else if(type == typeid(Time))
bind(pos, val.extract<Time>(), dir);
else if(type == typeid(BLOB))
bind(pos, val.extract<BLOB>(), dir); bind(pos, val.extract<BLOB>(), dir);
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
else if(val.type() == typeid(long)) else if(type == typeid(long))
bind(pos, val.extract<long>(), dir); bind(pos, val.extract<long>(), dir);
#endif #endif
else else

View File

@@ -41,10 +41,13 @@ namespace Poco {
namespace Data { namespace Data {
AbstractBinding::AbstractBinding(const std::string& name, Direction direction): AbstractBinding::AbstractBinding(const std::string& name,
Direction direction,
Poco::UInt32 bulkSize):
_pBinder(0), _pBinder(0),
_name(name), _name(name),
_direction(direction) _direction(direction),
_bulkSize(bulkSize)
{ {
} }

View File

@@ -42,10 +42,12 @@ namespace Data {
AbstractExtraction::AbstractExtraction(Poco::UInt32 limit, AbstractExtraction::AbstractExtraction(Poco::UInt32 limit,
Poco::UInt32 position): Poco::UInt32 position,
bool bulk):
_pExtractor(0), _pExtractor(0),
_limit(limit), _limit(limit),
_position(position) _position(position),
_bulk(bulk)
{ {
} }

View File

@@ -35,6 +35,7 @@
#include "Poco/Data/AbstractExtractor.h" #include "Poco/Data/AbstractExtractor.h"
#include "Poco/Exception.h"
namespace Poco { namespace Poco {
@@ -51,4 +52,126 @@ AbstractExtractor::~AbstractExtractor()
} }
bool AbstractExtractor::extract(std::size_t pos, std::vector<Poco::Int8>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<Poco::UInt8>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<Poco::Int16>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<Poco::UInt16>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<Poco::Int32>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<Poco::UInt32>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<Poco::Int64>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<Poco::UInt64>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
#ifndef POCO_LONG_IS_64_BIT
bool AbstractExtractor::extract(std::size_t pos, std::vector<long>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
#endif
bool AbstractExtractor::extract(std::size_t pos, std::vector<bool>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<float>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<double>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<char>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<std::string>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<BLOB>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<DateTime>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<Date>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<Time>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<Any>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
bool AbstractExtractor::extract(std::size_t pos, std::vector<DynamicAny>& val)
{
throw NotImplementedException("std::vector extractor must be implemented.");
}
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@@ -41,7 +41,8 @@ namespace Poco {
namespace Data { namespace Data {
AbstractPreparation::AbstractPreparation() AbstractPreparation::AbstractPreparation(Poco::UInt32 length):
_length(length)
{ {
} }
@@ -51,4 +52,126 @@ AbstractPreparation::~AbstractPreparation()
} }
void AbstractPreparation::prepare(std::size_t pos, std::vector<Poco::Int8>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, std::vector<Poco::UInt8>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, std::vector<Poco::Int16>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, std::vector<Poco::UInt16>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, std::vector<Poco::Int32>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, std::vector<Poco::UInt32>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, std::vector<Poco::Int64>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, std::vector<Poco::UInt64>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
#ifndef POCO_LONG_IS_64_BIT
void AbstractPreparation::prepare(std::size_t pos, std::vector<long>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
#endif
void AbstractPreparation::prepare(std::size_t pos, std::vector<bool>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, std::vector<float>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, std::vector<double>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, std::vector<char>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, const std::vector<std::string>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, const std::vector<BLOB>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, const std::vector<DateTime>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, const std::vector<Date>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, const std::vector<Time>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, const std::vector<Any>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
void AbstractPreparation::prepare(std::size_t pos, const std::vector<DynamicAny>& val)
{
throw NotImplementedException("std::vector preparation must be implemented.");
}
} } // namespace Poco::Data } } // namespace Poco::Data

59
Data/src/Bulk.cpp Normal file
View File

@@ -0,0 +1,59 @@
//
// Bulk.cpp
//
// $Id: //poco/Main/Data/src/Bulk.cpp#7 $
//
// Library: Data
// Package: DataCore
// Module: Bulk
//
// 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/Bulk.h"
namespace Poco {
namespace Data {
Bulk::Bulk(const Limit& limit): _limit(limit.value(), false, false)
{
}
Bulk::Bulk(Poco::UInt32 value): _limit(value, false, false)
{
}
Bulk::~Bulk()
{
}
} } // namespace Poco::Data

View File

@@ -51,10 +51,10 @@ POCO_IMPLEMENT_EXCEPTION(BindingException, DataException, "Binding error")
POCO_IMPLEMENT_EXCEPTION(ExtractException, DataException, "Extraction error") POCO_IMPLEMENT_EXCEPTION(ExtractException, DataException, "Extraction error")
POCO_IMPLEMENT_EXCEPTION(LimitException, DataException, "Limit error") POCO_IMPLEMENT_EXCEPTION(LimitException, DataException, "Limit error")
POCO_IMPLEMENT_EXCEPTION(NotSupportedException, DataException, "Feature or property not supported") POCO_IMPLEMENT_EXCEPTION(NotSupportedException, DataException, "Feature or property not supported")
POCO_IMPLEMENT_EXCEPTION(NotImplementedException, DataException, "Feature or property not implemented")
POCO_IMPLEMENT_EXCEPTION(SessionUnavailableException, DataException, "Session is unavailable") POCO_IMPLEMENT_EXCEPTION(SessionUnavailableException, DataException, "Session is unavailable")
POCO_IMPLEMENT_EXCEPTION(SessionPoolExhaustedException, DataException, "No more sessions available from the session pool") POCO_IMPLEMENT_EXCEPTION(SessionPoolExhaustedException, DataException, "No more sessions available from the session pool")
POCO_IMPLEMENT_EXCEPTION(NoDataException, DataException, "No data found") POCO_IMPLEMENT_EXCEPTION(NoDataException, DataException, "No data found")
POCO_IMPLEMENT_EXCEPTION(LengthExceededException, DataException, "Data too long")
} } // namespace Poco::Data } } // namespace Poco::Data

View File

@@ -1,11 +1,11 @@
// //
// Step.cpp // Position.cpp
// //
// $Id: //poco/Main/Data/src/Step.cpp#5 $ // $Id: //poco/Main/Data/src/Position.cpp#7 $
// //
// Library: Data // Library: Data
// Package: DataCore // Package: DataCore
// Module: Step // Module: Position
// //
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
@@ -34,20 +34,19 @@
// //
#include "Poco/Data/Step.h" #include "Poco/Data/Position.h"
namespace Poco { namespace Poco {
namespace Data { namespace Data {
Step::Step(Poco::UInt32 value): Position::Position(Poco::UInt32 value): _value(value)
_value(value)
{ {
} }
Step::~Step() Position::~Position()
{ {
} }

View File

@@ -38,6 +38,7 @@
#include "Poco/Data/DataException.h" #include "Poco/Data/DataException.h"
#include "Poco/Data/Extraction.h" #include "Poco/Data/Extraction.h"
#include "Poco/Data/Session.h" #include "Poco/Data/Session.h"
#include "Poco/Data/Bulk.h"
#include "Poco/Any.h" #include "Poco/Any.h"
#include "Poco/Tuple.h" #include "Poco/Tuple.h"
#include "Poco/ActiveMethod.h" #include "Poco/ActiveMethod.h"
@@ -189,58 +190,84 @@ const std::string& Statement::getStorage() const
} }
void now(Statement& statement) Statement& Statement::operator , (Manipulator manip)
{ {
statement.execute(); manip(*this);
return *this;
} }
void sync(Statement& statement) Statement& Statement::operator , (AbstractBinding* pBind)
{ {
statement.setAsync(false); if (pBind->isBulk())
{
if(_pImpl->bulkBindingAllowed())
_pImpl->setBulkBinding();
else
throw InvalidAccessException("Bulk and non-bulk binding modes can not be mixed.");
}
else _pImpl->forbidBulk();
_pImpl->addBinding(pBind);
return *this;
} }
void async(Statement& statement) Statement& Statement::operator , (AbstractExtraction* pExtract)
{ {
statement.setAsync(true); if (pExtract->isBulk())
{
if(_pImpl->bulkExtractionAllowed())
{
Bulk b(pExtract->getLimit());
_pImpl->setBulkExtraction(b);
}
else
throw InvalidAccessException("Bulk and non-bulk extraction modes can not be mixed.");
}
else _pImpl->forbidBulk();
_pImpl->addExtract(pExtract);
return *this;
} }
void vector(Statement& statement) Statement& Statement::operator , (const Limit& extrLimit)
{ {
if (!statement.canModifyStorage()) if (_pImpl->isBulkExtraction() && _pImpl->extractionLimit() != extrLimit)
throw InvalidAccessException("Storage not modifiable."); throw InvalidArgumentException("Limit for bulk extraction already set.");
statement.setStorage("vector"); _pImpl->setExtractionLimit(extrLimit);
return *this;
} }
void list(Statement& statement) Statement& Statement::operator , (const Range& extrRange)
{ {
if (!statement.canModifyStorage()) if (_pImpl->isBulkExtraction())
throw InvalidAccessException("Storage not modifiable."); throw InvalidAccessException("Can not set range for bulk extraction.");
statement.setStorage("list"); _pImpl->setExtractionLimit(extrRange.lower());
_pImpl->setExtractionLimit(extrRange.upper());
return *this;
} }
void deque(Statement& statement) Statement& Statement::operator , (const Bulk& bulk)
{ {
if (!statement.canModifyStorage()) if (0 == _pImpl->extractions().size() &&
throw InvalidAccessException("Storage not modifiable."); 0 == _pImpl->bindings().size() &&
_pImpl->bulkExtractionAllowed() &&
_pImpl->bulkBindingAllowed())
{
Limit l(_pImpl->getExtractionLimit(), false, false);
_pImpl->setBulkExtraction(bulk);
_pImpl->setBulkBinding();
}
else
throw InvalidAccessException("Can not set bulk operations.");
statement.setStorage("deque"); return *this;
}
void reset(Statement& statement)
{
if (!statement.canModifyStorage())
throw InvalidAccessException("Storage not modifiable.");
statement.setStorage("deque");
statement.setAsync(false);
} }

View File

@@ -59,7 +59,6 @@ const std::string StatementImpl::LIST = "list";
const std::string StatementImpl::DEQUE = "deque"; const std::string StatementImpl::DEQUE = "deque";
const std::string StatementImpl::UNKNOWN = "unknown"; const std::string StatementImpl::UNKNOWN = "unknown";
StatementImpl::StatementImpl(SessionImpl& rSession): StatementImpl::StatementImpl(SessionImpl& rSession):
_state(ST_INITIALIZED), _state(ST_INITIALIZED),
_extrLimit(upperLimit((Poco::UInt32) Limit::LIMIT_UNLIMITED, false)), _extrLimit(upperLimit((Poco::UInt32) Limit::LIMIT_UNLIMITED, false)),
@@ -70,7 +69,8 @@ StatementImpl::StatementImpl(SessionImpl& rSession):
_ostr(), _ostr(),
_bindings(), _bindings(),
_curDataSet(0), _curDataSet(0),
_step(1u) _bulkBinding(BULK_UNDEFINED),
_bulkExtraction(BULK_UNDEFINED)
{ {
_extractors.resize(1); _extractors.resize(1);
} }
@@ -94,9 +94,8 @@ Poco::UInt32 StatementImpl::execute()
lim = executeWithLimit(); lim = executeWithLimit();
if (lim < _lowerLimit) if (lim < _lowerLimit)
{
throw LimitException("Did not receive enough data."); throw LimitException("Did not receive enough data.");
}
return lim; return lim;
} }
@@ -106,16 +105,17 @@ Poco::UInt32 StatementImpl::executeWithLimit()
poco_assert (_state != ST_DONE); poco_assert (_state != ST_DONE);
compile(); compile();
Poco::UInt32 count = 0; Poco::UInt32 count = 0;
Poco::UInt32 limit = _extrLimit.value();
do do
{ {
bind(); bind();
while (hasNext() && count < _extrLimit.value()) while (count < limit && hasNext())
count += next(); count += next();
} while (canBind()); } while (count < limit && canBind());
if (!canBind() && (!hasNext() || _extrLimit.value() == 0)) if (!canBind() && (!hasNext() || limit == 0))
_state = ST_DONE; _state = ST_DONE;
else if (hasNext() && _extrLimit.value() == count && _extrLimit.isHardLimit()) else if (hasNext() && limit == count && _extrLimit.isHardLimit())
throw LimitException("HardLimit reached. We got more data than we asked for"); throw LimitException("HardLimit reached. We got more data than we asked for");
else else
_state = ST_PAUSED; _state = ST_PAUSED;
@@ -176,12 +176,8 @@ void StatementImpl::bind()
{ {
if (!hasNext()) if (!hasNext())
{ {
if (canBind()) if (canBind()) bindImpl();
{ else _state = ST_DONE;
bindImpl();
}
else
_state = ST_DONE;
} }
} }
} }
@@ -203,6 +199,17 @@ void StatementImpl::setExtractionLimit(const Limit& extrLimit)
} }
void StatementImpl::setBulkExtraction(const Bulk& b)
{
Poco::UInt32 limit = getExtractionLimit();
if (Limit::LIMIT_UNLIMITED != limit && b.size() != limit)
throw InvalidArgumentException("Can not set limit for statement.");
setExtractionLimit(b.limit());
_bulkExtraction = BULK_EXTRACTION;
}
void StatementImpl::fixupExtraction() void StatementImpl::fixupExtraction()
{ {
Poco::Data::AbstractExtractionVec::iterator it = extractions().begin(); Poco::Data::AbstractExtractionVec::iterator it = extractions().begin();
@@ -339,7 +346,7 @@ Poco::UInt32 StatementImpl::activateNextDataSet()
if (_curDataSet + 1 < dataSetCount()) if (_curDataSet + 1 < dataSetCount())
return ++_curDataSet; return ++_curDataSet;
else else
throw InvalidAccessException("End of data sets reached."); throw NoDataException("End of data sets reached.");
} }

View File

@@ -65,6 +65,7 @@ using Poco::InvalidAccessException;
using Poco::RangeException; using Poco::RangeException;
using Poco::NotFoundException; using Poco::NotFoundException;
using Poco::InvalidArgumentException; using Poco::InvalidArgumentException;
using Poco::NotImplementedException;
DataTest::DataTest(const std::string& name): CppUnit::TestCase(name) DataTest::DataTest(const std::string& name): CppUnit::TestCase(name)
@@ -1026,16 +1027,34 @@ void DataTest::testDateAndTime()
Date d1(2007, 6, 15); Date d1(2007, 6, 15);
d1.assign(d.year() - 1, d.month(), d.day()); d1.assign(d.year() - 1, d.month(), d.day());
assert (d1 < d); assert (d1 != d); assert (d1 < d); assert (d1 != d);
d1.assign(d.year(), d.month() - 1, d.day()); if (d.month() > 1)
assert (d1 < d); assert (d1 != d); d1.assign(d.year(), d.month() - 1, d.day());
d1.assign(d.year(), d.month(), d.day() - 1); else
d1.assign(d.year() - 1, 12, d.day());
assert (d1 < d); assert (d1 != d); assert (d1 < d); assert (d1 != d);
if (d.day() > 1)
{
d1.assign(d.year(), d.month(), d.day() - 1);
assert (d1 < d); assert (d1 != d);
}
d1.assign(d.year() + 1, d.month(), d.day()); d1.assign(d.year() + 1, d.month(), d.day());
assert (d1 > d); assert (d1 != d); assert (d1 > d); assert (d1 != d);
d1.assign(d.year(), d.month() + 1, d.day());
assert (d1 > d); assert (d1 != d); if (d.month() < 12)
d1.assign(d.year(), d.month(), d.day() + 1); d1.assign(d.year(), d.month() + 1, d.day());
else
d1.assign(d.year() + 1, 1, d.day());
assert (d1 > d); assert (d1 != d); assert (d1 > d); assert (d1 != d);
if (d.day() < dt.daysOfMonth(dt.year(), dt.month()))
{
d1.assign(d.year(), d.month(), d.day() + 1);
assert (d1 > d); assert (d1 != d);
}
d1.assign(d.year(), d.month(), d.day()); d1.assign(d.year(), d.month(), d.day());
assert (d1 == d); assert (d1 == d);

View File

@@ -116,7 +116,7 @@ public:
bool extract(std::size_t pos, Poco::DateTime& val); bool extract(std::size_t pos, Poco::DateTime& val);
/// Extracts a DateTime. /// Extracts a DateTime.
bool isNull(std::size_t pos); bool isNull(std::size_t col, std::size_t row = -1);
/// Returns true if the current row value at pos column is null. /// Returns true if the current row value at pos column is null.
void reset(); void reset();
@@ -128,7 +128,7 @@ inline void Extractor::reset()
} }
inline bool Extractor::isNull(std::size_t pos) inline bool Extractor::isNull(std::size_t col, std::size_t row)
{ {
return false; return false;
} }

View File

@@ -50,69 +50,69 @@ Preparation::~Preparation()
} }
void Preparation::prepare(std::size_t pos, Poco::Int8) void Preparation::prepare(std::size_t pos, Poco::Int8&)
{ {
} }
void Preparation::prepare(std::size_t pos, Poco::UInt8) void Preparation::prepare(std::size_t pos, Poco::UInt8&)
{ {
} }
void Preparation::prepare(std::size_t pos, Poco::Int16) void Preparation::prepare(std::size_t pos, Poco::Int16&)
{ {
} }
void Preparation::prepare(std::size_t pos, Poco::UInt16) void Preparation::prepare(std::size_t pos, Poco::UInt16&)
{ {
} }
void Preparation::prepare(std::size_t pos, Poco::Int32) void Preparation::prepare(std::size_t pos, Poco::Int32&)
{ {
} }
void Preparation::prepare(std::size_t pos, Poco::UInt32) void Preparation::prepare(std::size_t pos, Poco::UInt32&)
{ {
} }
void Preparation::prepare(std::size_t pos, Poco::Int64) void Preparation::prepare(std::size_t pos, Poco::Int64&)
{ {
} }
void Preparation::prepare(std::size_t pos, Poco::UInt64) void Preparation::prepare(std::size_t pos, Poco::UInt64&)
{ {
} }
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
void Preparation::prepare(std::size_t pos, long) void Preparation::prepare(std::size_t pos, long&)
{ {
} }
#endif #endif
void Preparation::prepare(std::size_t pos, bool) void Preparation::prepare(std::size_t pos, bool&)
{ {
} }
void Preparation::prepare(std::size_t pos, float) void Preparation::prepare(std::size_t pos, float&)
{ {
} }
void Preparation::prepare(std::size_t pos, double) void Preparation::prepare(std::size_t pos, double&)
{ {
} }
void Preparation::prepare(std::size_t pos, char) void Preparation::prepare(std::size_t pos, char&)
{ {
} }

View File

@@ -55,45 +55,45 @@ public:
~Preparation(); ~Preparation();
/// Destroys the Preparation. /// Destroys the Preparation.
void prepare(std::size_t pos, Poco::Int8); void prepare(std::size_t pos, Poco::Int8&);
/// Prepares an Int8. /// Prepares an Int8.
void prepare(std::size_t pos, Poco::UInt8); void prepare(std::size_t pos, Poco::UInt8&);
/// Prepares an UInt8. /// Prepares an UInt8.
void prepare(std::size_t pos, Poco::Int16); void prepare(std::size_t pos, Poco::Int16&);
/// Prepares an Int16. /// Prepares an Int16.
void prepare(std::size_t pos, Poco::UInt16); void prepare(std::size_t pos, Poco::UInt16&);
/// Prepares an UInt16. /// Prepares an UInt16.
void prepare(std::size_t pos, Poco::Int32); void prepare(std::size_t pos, Poco::Int32&);
/// Prepares an Int32. /// Prepares an Int32.
void prepare(std::size_t pos, Poco::UInt32); void prepare(std::size_t pos, Poco::UInt32&);
/// Prepares an UInt32. /// Prepares an UInt32.
void prepare(std::size_t pos, Poco::Int64); void prepare(std::size_t pos, Poco::Int64&);
/// Prepares an Int64. /// Prepares an Int64.
void prepare(std::size_t pos, Poco::UInt64); void prepare(std::size_t pos, Poco::UInt64&);
/// Prepares an UInt64. /// Prepares an UInt64.
#ifndef POCO_LONG_IS_64_BIT #ifndef POCO_LONG_IS_64_BIT
void prepare(std::size_t pos, long); void prepare(std::size_t pos, long&);
/// Prepares a long. /// Prepares a long.
#endif #endif
void prepare(std::size_t pos, bool); void prepare(std::size_t pos, bool&);
/// Prepares a boolean. /// Prepares a boolean.
void prepare(std::size_t pos, float); void prepare(std::size_t pos, float&);
/// Prepares a float. /// Prepares a float.
void prepare(std::size_t pos, double); void prepare(std::size_t pos, double&);
/// Prepares a double. /// Prepares a double.
void prepare(std::size_t pos, char); void prepare(std::size_t pos, char&);
/// Prepares a single character. /// Prepares a single character.
void prepare(std::size_t pos, const std::string&); void prepare(std::size_t pos, const std::string&);