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

View File

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

View File

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

View File

@@ -81,6 +81,7 @@ public:
};
Binder(const StatementHandle& rStmt,
std::size_t maxFieldSize,
ParameterBinding dataBinding = PB_IMMEDIATE,
TypeInfo* pDataTypes = 0);
/// Creates the Binder.
@@ -91,62 +92,119 @@ public:
void bind(std::size_t pos, const Poco::Int8& val, Direction dir);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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
void bind(std::size_t pos, const long& val, Direction dir);
/// Binds a long.
void bind(std::size_t pos, const std::vector<long>& val, Direction dir);
/// Binds a long vector.
#endif
void bind(std::size_t pos, const bool& val, Direction dir);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// Set data binding type.
@@ -165,6 +223,12 @@ public:
private:
typedef std::vector<SQLLEN*> LengthVec;
typedef std::vector<std::vector<SQLLEN> > LengthVecVec;
typedef std::vector<char*> CharPtrVec;
typedef std::vector<bool*> BoolPtrVec;
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;
@@ -185,12 +249,12 @@ private:
template <typename T>
void bindImpl(std::size_t pos, T& val, SQLSMALLINT cDataType, Direction dir)
{
_lengthIndicator.push_back(0);
SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, cDataType, colSize, decDigits);
_lengthIndicator.push_back(0);
if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1,
toODBCDirection(dir),
@@ -198,14 +262,50 @@ private:
Utility::sqlDataType(cDataType),
colSize,
decDigits,
(SQLPOINTER) &val,
0,
0)))
(SQLPOINTER) &val, 0, 0)))
{
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,
SQLSMALLINT cDataType,
SQLINTEGER& colSize,
@@ -218,20 +318,40 @@ private:
/// to discover the required values are unsuccesfully exhausted, the values
/// are both set to zero and no exception is thrown.
void bindNull(std::size_t pos, SQLSMALLINT cDataType);
/// Utility function for binding null values.
/// For in-bound purposes only.
void setParamSetSize(std::size_t pos, std::size_t length);
/// Sets the parameter set size. Used for column-wise binding.
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;
LengthVec _lengthIndicator;
LengthVecVec _vecLengthIndicator;
ParamMap _inParams;
ParamMap _outParams;
ParameterBinding _paramBinding;
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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
inline void Binder::bind(std::size_t pos, const long& val, Direction 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
@@ -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)
{
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)
{
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)
{
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)
{
_paramBinding = binding;

View File

@@ -77,73 +77,133 @@ public:
bool extract(std::size_t pos, Poco::Int8& val);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// Extracts an UInt64.
bool extract(std::size_t pos, std::vector<Poco::UInt64>& val);
/// Extracts an UInt64 vector.
#ifndef POCO_LONG_IS_64_BIT
bool extract(std::size_t pos, long& val);
/// Extracts a long.
bool extract(std::size_t pos, std::vector<long>& val);
/// Extracts a long vector.
#endif
bool extract(std::size_t pos, bool& val);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// Extracts a DynamicAny.
bool extract(std::size_t pos, std::vector<Poco::DynamicAny>& val);
/// Extracts a DynamicAny vector.
void setDataExtraction(Preparation::DataExtraction ext);
/// Set data extraction mode.
Preparation::DataExtraction getDataExtraction() const;
/// Returns data extraction mode.
bool isNull(std::size_t pos);
/// Returns true if the current row value at pos column is null.
bool isNull(std::size_t col, std::size_t row = Preparation::INVALID_ROW);
/// Returns true if the value at [col,row] is null.
void reset();
/// Resets the internally cached length indicators.
@@ -171,13 +231,20 @@ private:
bool extractBoundImpl(std::size_t pos, T& val)
{
if (isNull(pos)) return false;
poco_assert (typeid(T) == _rPreparation[pos].type());
poco_assert_dbg (typeid(T) == _rPreparation[pos].type());
val = *AnyCast<T>(&_rPreparation[pos]);
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>
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,
/// while SQL_NULL_DATA (#define'd as -1 literal) remains 32-bit.
SQLINTEGER columnSize(std::size_t pos) const;
const StatementHandle& _rStmt;
Preparation& _rPreparation;
Preparation::DataExtraction _dataExtraction;
@@ -281,8 +350,6 @@ private:
///
/// inlines
///
inline void Extractor::setDataExtraction(Preparation::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

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

View File

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

View File

@@ -76,8 +76,9 @@ class ODBC_API Preparation : public AbstractPreparation
/// with respective memory output locations before extracting data.
/// 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,
/// however with numerous driver implementation dependent limitations). In order to fit this functionality
/// into Poco DataConnectors framework, every ODBC SQL statement instantiates its own Preparation object.
/// however with numerous driver implementation dependent limitations and inferior performance).
/// 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()).
///
/// Preparation object is used to :
@@ -94,12 +95,26 @@ class ODBC_API Preparation : public AbstractPreparation
///
{
public:
typedef std::vector<char*> CharArray;
enum DataExtraction
{
DE_MANUAL,
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,
const std::string& statement,
std::size_t maxFieldSize,
@@ -112,68 +127,128 @@ public:
~Preparation();
/// Destroys the Preparation.
void prepare(std::size_t pos, Poco::Int8);
void prepare(std::size_t pos, Poco::Int8& val);
/// 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.
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.
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.
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.
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.
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.
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.
void prepare(std::size_t pos, std::vector<Poco::UInt64>& val);
/// Prepares an UInt64 vector.
#ifndef POCO_LONG_IS_64_BIT
void prepare(std::size_t pos, long);
void prepare(std::size_t pos, long& val);
/// Prepares a long.
void prepare(std::size_t pos, std::vector<long>& val);
/// Prepares a long vector.
#endif
void prepare(std::size_t pos, bool);
void prepare(std::size_t pos, bool& val);
/// 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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
void prepare(std::size_t pos, const std::vector<Poco::DynamicAny>& val);
/// Prepares a DynamicAny vector.
std::size_t columns() const;
/// Returns the number of columns.
/// Resizes the internal storage iff the size is zero.
@@ -192,12 +267,16 @@ public:
/// Returned length for variable length fields is the one
/// supported by this implementation, not the underlying DB.
int actualDataSize(std::size_t pos) const;
/// Returns the returned length. This is usually
/// equal to the column size, except for variable length fields
/// (BLOB and variable length strings).
std::size_t actualDataSize(std::size_t col, std::size_t row = INVALID_ROW) const;
/// Returns the returned length for the column and row specified.
/// This is usually equal to the column size, except for
/// variable length fields (BLOB and variable length strings).
/// 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);
/// Set data extraction mode.
@@ -205,71 +284,222 @@ public:
/// Returns data extraction mode.
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& operator = (const Preparation&);
void prepareImpl(std::size_t pos);
/// Utility function to prepare Any and DynamicAny
template <typename T>
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;
/// Resize the values and lengths vectors.
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 (pos >= 0 && pos < _pValues.size());
std::size_t dataSize = sizeof(T);
_pValues[pos] = new Poco::Any(T());
_pLengths[pos] = new SQLLEN;
*_pLengths[pos] = 0;
T* pVal = AnyCast<T>(_pValues[pos]);
poco_assert_dbg (pVal);
poco_assert (pos < _values.size());
_values[pos] = Poco::Any(T());
T* pVal = AnyCast<T>(&_values[pos]);
if (Utility::isError(SQLBindCol(_rStmt,
(SQLUSMALLINT) pos + 1,
valueType,
(SQLPOINTER) pVal,
(SQLINTEGER) dataSize,
_pLengths[pos])))
&_lengths[pos])))
{
throw StatementException(_rStmt, "SQLBindCol()");
}
}
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 (pos >= 0 && pos < _pValues.size());
std::size_t dataSize = sizeof(T);
T* pChr = new T[size];
poco_assert_dbg (pChr);
memset(pChr, 0, size);
poco_assert (pos < _values.size());
poco_assert (length);
_values[pos] = Poco::Any(std::vector<T>(length));
_lengths[pos] = 0;
poco_assert (0 == _lenLengths[pos].size());
_lenLengths[pos].resize(length);
SharedPtr<T> sp = pChr;
_pValues[pos] = new Any(sp);
_pLengths[pos] = new SQLLEN;
*_pLengths[pos] = (SQLLEN) size;
std::vector<T>& cache = RefAnyCast<std::vector<T> >(_values[pos]);
if (Utility::isError(SQLBindCol(_rStmt,
(SQLUSMALLINT) pos + 1,
valueType,
(SQLPOINTER) pChr,
(SQLINTEGER) size,
_pLengths[pos])))
(SQLPOINTER) &cache[0],
(SQLINTEGER) dataSize,
&_lenLengths[pos][0])))
{
throw StatementException(_rStmt, "SQLBindCol()");
}
}
template <typename T>
void prepareVariableLen(std::size_t pos, SQLSMALLINT valueType, std::size_t size, DataType dt)
/// Utility function for preparation of variable length columns and bool vectors.
{
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 std::vector<Poco::Any*> _pValues;
mutable std::vector<SQLLEN*> _pLengths;
mutable ValueVec _values;
mutable LengthVec _lengths;
mutable LengthLengthVec _lenLengths;
mutable IndexMap _varLengthArrays;
std::size_t _maxFieldSize;
DataExtraction _dataExtraction;
};
@@ -278,128 +508,262 @@ private:
//
// 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
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
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&)
{
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&)
{
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&)
{
prepareRaw<SQL_DATE_STRUCT>(pos,
SQL_C_TYPE_DATE,
sizeof(SQL_DATE_STRUCT));
prepareFixedSize<SQL_DATE_STRUCT>(pos, SQL_C_TYPE_DATE);
}
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&)
{
prepareRaw<SQL_TIME_STRUCT>(pos,
SQL_C_TYPE_TIME,
sizeof(SQL_TIME_STRUCT));
prepareFixedSize<SQL_TIME_STRUCT>(pos, SQL_C_TYPE_TIME);
}
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&)
{
prepareRaw<SQL_TIMESTAMP_STRUCT>(pos,
SQL_C_TYPE_TIMESTAMP,
sizeof(SQL_TIMESTAMP_STRUCT));
prepareFixedSize<SQL_TIMESTAMP_STRUCT>(pos, SQL_C_TYPE_TIMESTAMP);
}
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());
poco_assert (_pLengths[pos]);
prepareFixedSize<SQL_TIMESTAMP_STRUCT>(pos, SQL_C_TYPE_TIMESTAMP, val.size());
}
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

View File

@@ -97,21 +97,39 @@ public:
static void dateSync(Date& dt, const SQL_DATE_STRUCT& ts);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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:
static const TypeInfo _dataTypes;
/// 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

@@ -49,11 +49,14 @@ namespace ODBC {
Binder::Binder(const StatementHandle& rStmt,
std::size_t maxFieldSize,
Binder::ParameterBinding dataBinding,
TypeInfo* pDataTypes):
_rStmt(rStmt),
_paramBinding(dataBinding),
_pTypeInfo(pDataTypes)
_pTypeInfo(pDataTypes),
_paramSetSize(0),
_maxFieldSize(maxFieldSize)
{
}
@@ -71,6 +74,42 @@ Binder::~Binder()
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) 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))
{
try
{
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
}
getColumnOrParameterSize(pos, size);
char* pChar = (char*) std::calloc(size, sizeof(char));
pVal = (SQLPOINTER) pChar;
_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));
}
else
throw IllegalStateException("Parameter must be [in] OR [out] bound.");
throw InvalidArgumentException("Parameter must be [in] OR [out] bound.");
SQLLEN* pLenIn = new SQLLEN;
*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))
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)
{
SQLINTEGER size = (SQLINTEGER) sizeof(SQL_DATE_STRUCT);
@@ -203,7 +349,51 @@ void Binder::bind(std::size_t pos, const Date& val, Direction dir)
0,
_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,
_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[])");
}
}
@@ -269,7 +503,51 @@ void Binder::bind(std::size_t pos, const Poco::DateTime& val, Direction dir)
0,
_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))
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));
SQLLEN* pLenIn = new SQLLEN;
@@ -316,13 +566,13 @@ void Binder::bindNull(std::size_t pos, SQLSMALLINT cDataType)
SQLINTEGER colSize = 0;
SQLSMALLINT decDigits = 0;
getColSizeAndPrecision(pos, cDataType, colSize, decDigits);
getColSizeAndPrecision(pos, SQL_C_STINYINT, colSize, decDigits);
if (Utility::isError(SQLBindParameter(_rStmt,
(SQLUSMALLINT) pos + 1,
SQL_PARAM_INPUT,
cDataType,
Utility::sqlDataType(cDataType),
SQL_C_STINYINT,
Utility::sqlDataType(SQL_C_STINYINT),
colSize,
decDigits,
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
{
ParamMap::const_iterator it = _inParams.find(pAddr);
@@ -370,40 +704,41 @@ void Binder::synchronize()
{
if (_dates.size())
{
DateMap::iterator itTS = _dates.begin();
DateMap::iterator itTSEnd = _dates.end();
for(; itTS != itTSEnd; ++itTS)
Utility::dateSync(*itTS->second, *itTS->first);
DateMap::iterator it = _dates.begin();
DateMap::iterator end = _dates.end();
for(; it != end; ++it)
Utility::dateSync(*it->second, *it->first);
}
if (_times.size())
{
TimeMap::iterator itTS = _times.begin();
TimeMap::iterator itTSEnd = _times.end();
for(; itTS != itTSEnd; ++itTS)
Utility::timeSync(*itTS->second, *itTS->first);
TimeMap::iterator it = _times.begin();
TimeMap::iterator end = _times.end();
for(; it != end; ++it)
Utility::timeSync(*it->second, *it->first);
}
if (_timestamps.size())
{
TimestampMap::iterator itTS = _timestamps.begin();
TimestampMap::iterator itTSEnd = _timestamps.end();
for(; itTS != itTSEnd; ++itTS)
Utility::dateTimeSync(*itTS->second, *itTS->first);
TimestampMap::iterator it = _timestamps.begin();
TimestampMap::iterator end = _timestamps.end();
for(; it != end; ++it)
Utility::dateTimeSync(*it->second, *it->first);
}
if (_strings.size())
{
StringMap::iterator itStr = _strings.begin();
StringMap::iterator itStrEnd = _strings.end();
for(; itStr != itStrEnd; ++itStr)
itStr->second->assign(itStr->first, strlen(itStr->first));
StringMap::iterator it = _strings.begin();
StringMap::iterator end = _strings.end();
for(; it != end; ++it)
it->second->assign(it->first, strlen(it->first));
}
}
void Binder::reset()
{
freeMemory();
LengthVec().swap(_lengthIndicator);
_inParams.clear();
_outParams.clear();
@@ -411,6 +746,11 @@ void Binder::reset()
_times.clear();
_timestamps.clear();
_strings.clear();
_dateVec.clear();
_timeVec.clear();
_dateTimeVec.clear();
_charPtrs.clear();
_boolPtrs.clear();
}
@@ -429,18 +769,16 @@ void Binder::getColSizeAndPrecision(std::size_t pos,
decDigits = _pTypeInfo->getInfo(cDataType, "MINIMUM_SCALE");
return;
}
else
throw NotFoundException();
}catch (NotFoundException&)
{
} catch (NotFoundException&) { }
try
{
Parameter p(_rStmt, pos);
colSize = (SQLINTEGER) p.columnSize();
decDigits = (SQLSMALLINT) p.decimalDigits();
return;
}catch (StatementException&)
{
} catch (StatementException&) { }
try
{
ODBCColumn c(_rStmt, pos);
@@ -448,8 +786,6 @@ void Binder::getColSizeAndPrecision(std::size_t pos,
decDigits = (SQLSMALLINT) c.precision();
return;
} catch (StatementException&) { }
}
}
// no success, set to zero and hope for the best
// (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

View File

@@ -73,11 +73,29 @@ bool Extractor::extractBoundImpl<std::string>(std::size_t pos, std::string& val)
if (isNull(pos)) return false;
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);
if (len < dataSize) dataSize = len;
checkDataSize(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;
}
@@ -89,8 +107,26 @@ bool Extractor::extractBoundImpl<Poco::Data::BLOB>(std::size_t pos, Poco::Data::
std::size_t dataSize = _rPreparation.actualDataSize(pos);
checkDataSize(dataSize);
SharedPtr<char>& sp = RefAnyCast<SharedPtr<char> >(_rPreparation[pos]);
char* sp = AnyCast<char*>(_rPreparation[pos]);
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;
}
@@ -99,12 +135,18 @@ template<>
bool Extractor::extractBoundImpl<Poco::Data::Date>(std::size_t pos, Poco::Data::Date& val)
{
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);
SharedPtr<SQL_DATE_STRUCT>& sp = RefAnyCast<SharedPtr<SQL_DATE_STRUCT> >(_rPreparation[pos]);
Utility::dateSync(val, *sp);
template<>
bool Extractor::extractBoundImpl<std::vector<Poco::Data::Date> >(std::size_t pos,
std::vector<Poco::Data::Date>& val)
{
std::vector<SQL_DATE_STRUCT>& ds = RefAnyCast<std::vector<SQL_DATE_STRUCT> >(_rPreparation[pos]);
Utility::dateSync(val, ds);
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);
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;
}
@@ -130,9 +182,31 @@ bool Extractor::extractBoundImpl<Poco::DateTime>(std::size_t pos, Poco::DateTime
std::size_t dataSize = _rPreparation.actualDataSize(pos);
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);
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]);
Utility::dateTimeSync(val, *sp);
return true;
}
@@ -163,8 +237,6 @@ bool Extractor::extractManualImpl<std::string>(std::size_t pos, std::string& val
CHUNK_SIZE, //buffer length
&len); //length indicator
_lengths[pos] += len;
if (SQL_NO_DATA != rc && Utility::isError(rc))
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.");
if (isNullLengthIndicator(len))
{
_lengths[pos] = len;
return false;
}
if (SQL_NO_DATA == rc || !len)
break;
_lengths[pos] += len;
fetchedSize = _lengths[pos] > CHUNK_SIZE ? CHUNK_SIZE : _lengths[pos];
totalSize += fetchedSize;
if (totalSize <= maxSize) val.append(pChar, fetchedSize);
else throw DataException(format(FLD_SIZE_EXCEEDED_FMT,
fetchedSize,
maxSize));
if (totalSize <= maxSize)
val.append(pChar, fetchedSize);
else
throw DataException(format(FLD_SIZE_EXCEEDED_FMT, fetchedSize, maxSize));
}while (true);
return true;
@@ -237,9 +312,7 @@ bool Extractor::extractManualImpl<Poco::Data::BLOB>(std::size_t pos,
if (totalSize <= maxSize)
val.appendRaw(pChar, fetchedSize);
else
throw DataException(format(FLD_SIZE_EXCEEDED_FMT,
fetchedSize,
maxSize));
throw DataException(format(FLD_SIZE_EXCEEDED_FMT, fetchedSize, maxSize));
}while (true);
@@ -334,6 +407,16 @@ bool Extractor::extract(std::size_t pos, Poco::Int32& val)
return extractManualImpl(pos, val, SQL_C_SLONG);
else
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
bool Extractor::extract(std::size_t pos, long& val)
{
@@ -355,6 +449,17 @@ bool Extractor::extract(std::size_t pos, long& val)
else
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
@@ -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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
try
{
return isNullLengthIndicator(_lengths.at(pos));
return isNullLengthIndicator(_lengths.at(col));
}catch (std::out_of_range& ex)
{
throw RangeException(ex.what());
}
}
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();
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/AbstractPrepare.h"
#include "Poco/Exception.h"
#include <limits>
#ifdef POCO_OS_FAMILY_WINDOWS
#undef max
#pragma warning(disable:4312)// 'type cast' : conversion from 'Poco::UInt32' to 'SQLPOINTER' of greater size
#endif
@@ -68,11 +66,6 @@ ODBCStatementImpl::ODBCStatementImpl(SessionImpl& rSession):
_nextResponse(0),
_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);
}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
// stored procedure calls: driver refuses to report the number of columns, unless all
@@ -169,6 +164,16 @@ void ODBCStatementImpl::doPrepare()
Extractions& extracts = extractions();
Extractions::iterator it = extracts.begin();
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)
{
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 itEnd = binds.end();
for (std::size_t pos = 0; it != itEnd && (*it)->canBind(); ++it)
{
(*it)->bind(pos);
pos += (*it)->numOfColumnsHandled();
}
if (reset)
{
it = binds.begin();
for (; it != itEnd && (*it)->canBind(); ++it)
(*it)->reset();
for (; it != itEnd; ++it) (*it)->reset();
}
for (std::size_t pos = 0; it != itEnd && (*it)->canBind(); ++it)
{
(*it)->bind(pos);
pos += (*it)->numOfColumnsHandled();
}
}
}
@@ -292,13 +297,12 @@ bool ODBCStatementImpl::hasNext()
if (!nextRowReady())
{
try { activateNextDataSet(); }
catch (InvalidAccessException&)
{ return false; }
try { checkError(SQLMoreResults(_stmt)); }
catch (NoDataException&)
{ return false; }
if (SQL_NO_DATA == SQLMoreResults(_stmt))
return false;
addPreparation();
doPrepare();
fixupExtraction();
@@ -324,14 +328,20 @@ void ODBCStatementImpl::makeStep()
Poco::UInt32 ODBCStatementImpl::next()
{
std::size_t count = 0;
if (nextRowReady())
{
Extractions& extracts = extractions();
Extractions::iterator it = extracts.begin();
Extractions::iterator itEnd = extracts.end();
std::size_t prevCount = 0;
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();
}
_stepCalled = false;
@@ -342,7 +352,9 @@ Poco::UInt32 ODBCStatementImpl::next()
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

View File

@@ -43,6 +43,9 @@ namespace Data {
namespace ODBC {
const std::size_t Preparation::INVALID_ROW = std::numeric_limits<std::size_t>::max();
Preparation::Preparation(const StatementHandle& rStmt,
const std::string& statement,
std::size_t maxFieldSize,
@@ -68,118 +71,73 @@ Preparation::Preparation(const Preparation& other):
Preparation::~Preparation()
{
std::vector<SQLLEN*>::iterator itLen = _pLengths.begin();
std::vector<SQLLEN*>::iterator itLenEnd = _pLengths.end();
for (; itLen != itLenEnd; ++itLen) delete *itLen;
freeMemory();
}
std::vector<Poco::Any*>::iterator itVal = _pValues.begin();
std::vector<Poco::Any*>::iterator itValEnd = _pValues.end();
for (; itVal != itValEnd; ++itVal) delete *itVal;
void Preparation::freeMemory() const
{
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
{
if (_pValues.empty()) resize();
return _pValues.size();
if (_values.empty()) resize();
return _values.size();
}
void Preparation::resize() const
{
SQLSMALLINT nCol = 0;
if (!Utility::isError(SQLNumResultCols(_rStmt, &nCol)) &&
0 != nCol)
if (!Utility::isError(SQLNumResultCols(_rStmt, &nCol)) && 0 != nCol)
{
_pValues.resize(nCol, 0);
_pLengths.resize(nCol, 0);
_values.resize(nCol, 0);
_lengths.resize(nCol, 0);
_lenLengths.resize(nCol);
if(_varLengthArrays.size())
{
freeMemory();
_varLengthArrays.clear();
}
}
Poco::Any& Preparation::operator [] (std::size_t pos)
{
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
{
poco_assert (pos >= 0 && pos < _pValues.size());
poco_assert_dbg (pos < _values.size());
std::size_t sz = 0;
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

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)
{
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)
{
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)
{
ts.year = dt.year();
@@ -162,7 +195,42 @@ void Utility::dateTimeSync(SQL_TIMESTAMP_STRUCT& ts, const Poco::DateTime& dt)
ts.hour = dt.hour();
ts.minute = dt.minute();
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, testLimitZero);
CppUnit_addTest(pSuite, ODBCDB2Test, testPrepare);
CppUnit_addTest(pSuite, ODBCDB2Test, testStep);
CppUnit_addTest(pSuite, ODBCDB2Test, testBulk);
CppUnit_addTest(pSuite, ODBCDB2Test, testSetSimple);
CppUnit_addTest(pSuite, ODBCDB2Test, testSetComplex);
CppUnit_addTest(pSuite, ODBCDB2Test, testSetComplexUnique);

View File

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

View File

@@ -146,7 +146,7 @@ void ODBCOracleTest::testBarebone()
"(First VARCHAR(30),"
"Second INTEGER,"
"Third NUMBER)";
/*
*_pSession << "CREATE OR REPLACE "
"PROCEDURE multiResultsProcedure(ret1 OUT SYS_REFCURSOR, "
"ret2 OUT SYS_REFCURSOR,"
@@ -185,7 +185,7 @@ void ODBCOracleTest::testBarebone()
SQLExecutor::DE_BOUND,
MULTI_INSERT,
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()
{
// 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()
{
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, testLimitZero);
CppUnit_addTest(pSuite, ODBCOracleTest, testPrepare);
CppUnit_addTest(pSuite, ODBCOracleTest, testStep);
CppUnit_addTest(pSuite, ODBCOracleTest, testBulk);
CppUnit_addTest(pSuite, ODBCOracleTest, testSetSimple);
CppUnit_addTest(pSuite, ODBCOracleTest, testSetComplex);
CppUnit_addTest(pSuite, ODBCOracleTest, testSetComplexUnique);

View File

@@ -56,6 +56,7 @@ public:
void testBareboneODBC();
void testBLOB();
void testBulk();
void testMultipleResults();
@@ -84,6 +85,7 @@ private:
void recreateVectorsTable();
void recreateAnysTable();
void recreateNullsTable(const std::string& notNull = "");
void recreateMiscTable();
static ODBCTest::SessionPtr _pSession;
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()
{
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()
{
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, testLimitZero);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testPrepare);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testStep);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testBulk);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSetSimple);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSetComplex);
CppUnit_addTest(pSuite, ODBCPostgreSQLTest, testSetComplexUnique);

View File

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

View File

@@ -112,9 +112,8 @@ void ODBCSQLServerTest::testBareboneODBC()
"Fifth FLOAT,"
"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_BOUND);
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_AT_EXEC, SQLExecutor::DE_MANUAL);
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()
{
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, testLimitZero);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testPrepare);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testStep);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testBulk);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSetSimple);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSetComplex);
CppUnit_addTest(pSuite, ODBCSQLServerTest, testSetComplexUnique);

View File

@@ -89,6 +89,7 @@ private:
void recreateAnysTable();
void recreateNullsTable(const std::string& notNull = "");
void recreateBoolTable();
void recreateMiscTable();
static SessionPtr _pSession;
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)
{
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()
{
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, testLimitZero);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testPrepare);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testStep);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testBulk);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSetSimple);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSetComplex);
CppUnit_addTest(pSuite, ODBCSQLiteTest, testSetComplexUnique);

View File

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

View File

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

View File

@@ -91,7 +91,7 @@ public:
virtual void testLimitPrepare();
virtual void testLimitZero();
virtual void testPrepare();
virtual void testStep();
virtual void testBulk();
virtual void testSetSimple();
virtual void testSetComplex();
@@ -165,6 +165,7 @@ protected:
virtual void recreateAnysTable() { /* no-op */ };
virtual void recreateNullsTable(const std::string& notNull="") { /* no-op */ };
virtual void recreateBoolTable() { /* no-op */ };
virtual void recreateMiscTable() { /* no-op */ };
static SessionPtr init(const std::string& driver,
std::string& dsn,

File diff suppressed because it is too large Load Diff

View File

@@ -140,7 +140,10 @@ public:
void limitPrepare();
void limitZero();
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 setComplex();
@@ -194,8 +197,17 @@ private:
static const std::string MULTI_INSERT;
static const std::string MULTI_SELECT;
Poco::Data::Session& session();
Poco::Data::Session* _pSession;
};
inline Poco::Data::Session& SQLExecutor::session()
{
poco_check_ptr (_pSession);
return *_pSession;
}
#endif // SQLExecutor_INCLUDED

View File

@@ -135,7 +135,7 @@ public:
bool extract(std::size_t pos, Poco::DynamicAny& val);
/// 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.
/// Because of the loss of information about null-ness of the
/// 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
/// been set and the second bool value in the pair is true if
/// the column is actually null.
/// The row argument, needed for connectors with bulk capabilities,
/// is ignored in this implementation.
void reset();
/// 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())
_nulls.resize(pos + 1);

View File

@@ -33,12 +33,12 @@
#include "SQLiteTest.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"
#include "Poco/Data/Common.h"
#include "Poco/Data/Date.h"
#include "Poco/Data/Time.h"
#include "Poco/Data/BLOB.h"
#include "Poco/Data/Statement.h"
#include "Poco/Data/RecordSet.h"
#include "Poco/Data/SessionFactory.h"
#include "Poco/Data/SQLite/Connector.h"
#include "Poco/Data/SQLite/SQLiteException.h"
#include "Poco/Data/TypeHandler.h"
@@ -117,7 +117,7 @@ public:
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))
poco_assert_dbg (pPrepare != 0);

View File

@@ -41,40 +41,29 @@
#include "Poco/Data/Data.h"
#include <vector>
#include <cstddef>
namespace Poco {
class DateTime;
class Any;
class DynamicAny;
namespace Data {
class Date;
class Time;
class BLOB;
enum NullData
{
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
NULL_GENERIC = 0
};
@@ -82,8 +71,7 @@ static const NullData null = NULL_GENERIC;
class Data_API AbstractBinder
/// Interface for Binding data types to placeholders. The default placeholder format
/// in the SQL query is ":name".
/// Interface for Binding data types to placeholders.
{
public:
enum Direction
@@ -103,65 +91,122 @@ public:
virtual void bind(std::size_t pos, const Poco::Int8& val, Direction dir = PD_IN) = 0;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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
virtual void bind(std::size_t pos, const long& val, Direction dir = PD_IN) = 0;
/// Binds a long.
virtual void bind(std::size_t pos, const std::vector<long>& val, Direction dir = PD_IN);
/// Binds a long vector.
#endif
virtual void bind(std::size_t pos, const bool& val, Direction dir = PD_IN) = 0;
/// 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;
/// 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;
/// 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;
/// Binds a single character.
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.
virtual void bind(std::size_t pos, const std::string& val, Direction dir = PD_IN) = 0;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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);
/// Binds an Any.

View File

@@ -64,7 +64,7 @@ public:
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.
virtual ~AbstractBinding();
@@ -86,7 +86,7 @@ public:
/// Returns the number of rows that the binding handles.
///
/// 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;
/// Returns true if we have enough data to bind
@@ -103,10 +103,17 @@ public:
const std::string& name() const;
/// 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:
AbstractBinder* _pBinder;
std::string _name;
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

View File

@@ -63,7 +63,7 @@ class Data_API AbstractExtraction: public Poco::RefCountedObject
{
public:
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)
/// 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.
@@ -95,13 +95,14 @@ public:
virtual std::size_t numOfRowsAllowed() const = 0;
/// 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.
/// Returns the number of rows extracted.
virtual void reset() = 0;
/// 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
void setLimit(Poco::UInt32 limit);
@@ -118,10 +119,14 @@ public:
/// null values and be able to later provide information about them.
/// Here, this function throws NotImplementedException.
bool isBulk() const;
/// Returns true if this is bulk extraction.
private:
AbstractExtractor* _pExtractor;
Poco::UInt32 _limit;
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

View File

@@ -41,6 +41,7 @@
#include "Poco/Data/Data.h"
#include <vector>
#include <cstddef>
@@ -74,67 +75,127 @@ public:
virtual bool extract(std::size_t pos, Poco::Int8& val) = 0;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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
virtual bool extract(std::size_t pos, long& val) = 0;
/// 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
virtual bool extract(std::size_t pos, bool& val) = 0;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// Extracts a DynamicAny. Returns false if null was received.
virtual bool isNull(std::size_t pos) = 0;
/// Returns true if the current row value at pos column is null.
virtual bool extract(std::size_t pos, std::vector<DynamicAny>& val);
/// 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();
/// Resets any information internally cached by the extractor.

View File

@@ -42,6 +42,7 @@
#include "Poco/Data/Data.h"
#include "Poco/RefCountedObject.h"
#include <vector>
#include <cstddef>
@@ -64,80 +65,171 @@ class BLOB;
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)
/// 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.
/// Note that the values in the interface serve only the purpose of type distinction.
/// There are cases (bulk operations using std::vector storage) when extract is called only once.
/// 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:
AbstractPreparation();
AbstractPreparation(Poco::UInt32 length = 1u);
/// Creates the AbstractPreparation.
virtual ~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.
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.
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.
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.
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.
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.
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.
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.
virtual void prepare(std::size_t pos, std::vector<Poco::UInt64>& val);
/// Prepares an UInt64 vector.
#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.
virtual void prepare(std::size_t pos, std::vector<long>& val);
/// Prepares a long vector.
#endif
virtual void prepare(std::size_t pos, bool) = 0;
virtual void prepare(std::size_t pos, bool&) = 0;
/// 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.
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.
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.
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.
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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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;
/// 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

View File

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

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, LimitException, 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, SessionPoolExhaustedException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, NoDataException, DataException)
POCO_DECLARE_EXCEPTION(Data_API, LengthExceededException, DataException)
} } // namespace Poco::Data

View File

@@ -45,6 +45,7 @@
#include "Poco/Data/Prepare.h"
#include "Poco/Data/TypeHandler.h"
#include "Poco/Data/Column.h"
#include "Poco/Data/Position.h"
#include "Poco/Data/DataException.h"
#include <set>
#include <vector>
@@ -63,8 +64,8 @@ class Extraction: public AbstractExtraction
/// Concrete Data Type specific extraction of values from a query result set.
{
public:
Extraction(T& result, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(T& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default(),
_extracted(false)
@@ -73,8 +74,8 @@ public:
{
}
Extraction(T& result, const T& def, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(T& result, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default(def),
_extracted(false)
@@ -108,13 +109,14 @@ public:
return _null;
}
void extract(std::size_t pos)
std::size_t extract(std::size_t pos)
{
if (_extracted) throw ExtractException("value already extracted");
_extracted = true;
AbstractExtractor* pExt = getExtractor();
TypeHandler<T>::extract(pos, _rResult, _default, pExt);
_null = pExt->isNull(pos);
return 1u;
}
void reset()
@@ -122,14 +124,14 @@ public:
_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:
T& _rResult;
T _default; // copy the default
T _default;
bool _extracted;
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.
{
public:
Extraction(std::vector<T>& result, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::vector<T>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default()
{
_rResult.clear();
}
Extraction(std::vector<T>& result, const T& def, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::vector<T>& result, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default(def)
{
_rResult.clear();
}
virtual ~Extraction()
@@ -184,24 +189,20 @@ public:
}
}
void extract(std::size_t pos)
std::size_t extract(std::size_t pos)
{
AbstractExtractor* pExt = getExtractor();
// for vector specialization, a temporary must be used to
// allow for extraction of bool values
T tmp = _default;
TypeHandler<T>::extract(pos, tmp, _default, pExt);
_rResult.push_back(tmp);
_rResult.push_back(_default);
TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
_nulls.push_back(pExt->isNull(pos));
return 1u;
}
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);
}
@@ -215,7 +216,92 @@ protected:
private:
std::vector<T>& _rResult;
T _default; // copy the default
T _default;
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;
};
@@ -225,18 +311,20 @@ class Extraction<std::list<T> >: public AbstractExtraction
/// List Data Type specialization for extraction of values from a query result set.
{
public:
Extraction(std::list<T>& result, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::list<T>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default()
{
_rResult.clear();
}
Extraction(std::list<T>& result, const T& def, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::list<T>& result, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default(def)
{
_rResult.clear();
}
virtual ~Extraction()
@@ -269,19 +357,20 @@ public:
}
}
void extract(std::size_t pos)
std::size_t extract(std::size_t pos)
{
AbstractExtractor* pExt = getExtractor();
_rResult.push_back(_default);
TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
_nulls.push_back(pExt->isNull(pos));
return 1u;
}
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);
}
@@ -295,7 +384,7 @@ protected:
private:
std::list<T>& _rResult;
T _default; // copy the default
T _default;
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.
{
public:
Extraction(std::deque<T>& result, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::deque<T>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default()
{
_rResult.clear();
}
Extraction(std::deque<T>& result, const T& def, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::deque<T>& result, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default(def)
{
_rResult.clear();
}
virtual ~Extraction()
@@ -349,19 +440,20 @@ public:
}
}
void extract(std::size_t pos)
std::size_t extract(std::size_t pos)
{
AbstractExtractor* pExt = getExtractor();
_rResult.push_back(_default);
TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
_nulls.push_back(pExt->isNull(pos));
return 1u;
}
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);
}
@@ -375,7 +467,7 @@ protected:
private:
std::deque<T>& _rResult;
T _default; // copy the default
T _default;
std::deque<bool> _nulls;
};
@@ -393,8 +485,8 @@ class InternalExtraction: public Extraction<C>
/// InternalExtraction objects can not be copied or assigned.
{
public:
explicit InternalExtraction(C& result, Column<T,C>* pColumn, Poco::UInt32 position = 0):
Extraction<C>(result, T(), position),
explicit InternalExtraction(C& result, Column<T,C>* pColumn, const Position& pos = Position(0)):
Extraction<C>(result, T(), pos),
_pColumn(pColumn)
/// 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.
{
public:
Extraction(std::set<T>& result, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
typedef typename std::set<T>::iterator Iterator;
Extraction(std::set<T>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default()
{
_rResult.clear();
}
Extraction(std::set<T>& result, const T& def, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::set<T>& result, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default(def)
{
_rResult.clear();
}
~Extraction()
@@ -480,25 +576,26 @@ public:
return getLimit();
}
void extract(std::size_t pos)
std::size_t extract(std::size_t pos)
{
T tmp;
TypeHandler<T>::extract(pos, tmp, _default, getExtractor());
_rResult.insert(tmp);
return 1u;
}
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);
}
private:
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.
{
public:
Extraction(std::multiset<T>& result, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::multiset<T>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default()
{
_rResult.clear();
}
Extraction(std::multiset<T>& result, const T& def, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::multiset<T>& result, const T& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default(def)
{
_rResult.clear();
}
~Extraction()
@@ -540,25 +639,26 @@ public:
return getLimit();
}
void extract(std::size_t pos)
std::size_t extract(std::size_t pos)
{
T tmp;
TypeHandler<T>::extract(pos, tmp, _default, getExtractor());
_rResult.insert(tmp);
return 1u;
}
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);
}
private:
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.
{
public:
Extraction(std::map<K, V>& result, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::map<K, V>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default()
{
_rResult.clear();
}
Extraction(std::map<K, V>& result, const V& def, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::map<K, V>& result, const V& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default(def)
{
_rResult.clear();
}
~Extraction()
@@ -600,18 +702,19 @@ public:
return getLimit();
}
void extract(std::size_t pos)
std::size_t extract(std::size_t pos)
{
V tmp;
TypeHandler<V>::extract(pos, tmp, _default, getExtractor());
_rResult.insert(std::make_pair(tmp(), tmp));
return 1u;
}
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);
}
@@ -619,7 +722,7 @@ public:
private:
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.
{
public:
Extraction(std::multimap<K, V>& result, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::multimap<K, V>& result, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default()
{
_rResult.clear();
}
Extraction(std::multimap<K, V>& result, const V& def, Poco::UInt32 position = 0):
AbstractExtraction(Limit::LIMIT_UNLIMITED, position),
Extraction(std::multimap<K, V>& result, const V& def, const Position& pos = Position(0)):
AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
_rResult(result),
_default(def)
{
_rResult.clear();
}
~Extraction()
@@ -661,38 +766,40 @@ public:
return getLimit();
}
void extract(std::size_t pos)
std::size_t extract(std::size_t pos)
{
V tmp;
TypeHandler<V>::extract(pos, tmp, _default, getExtractor());
_rResult.insert(std::make_pair(tmp(), tmp));
return 1u;
}
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);
}
private:
std::multimap<K, V>& _rResult;
V _default; // copy the default
V _default;
};
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
/// with multiple recordset support.
{
return new Extraction<T>(t, pos);
}
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
{
return new Extraction<T>(t, def, pos);

View File

@@ -77,6 +77,12 @@ public:
bool isLowerLimit() const;
/// 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:
Poco::UInt32 _value;
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

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

View File

@@ -44,11 +44,7 @@
#include "Poco/Data/AbstractPrepare.h"
#include "Poco/Data/TypeHandler.h"
#include <cstddef>
#include <map>
#include <set>
#include <vector>
#include <list>
#include <deque>
namespace Poco {
@@ -60,7 +56,10 @@ class Prepare: 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)
Prepare(AbstractPreparation* pPrepare, std::size_t pos, T& val):
AbstractPrepare(pPrepare),
_pos(pos),
_val(val)
/// Creates the Prepare.
{
}
@@ -78,16 +77,21 @@ public:
private:
std::size_t _pos;
const T& _val;
T& _val;
};
template<typename T>
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:
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.
{
}
@@ -100,174 +104,12 @@ public:
void prepare()
/// Prepares data.
{
TypeHandler<T>::prepare(_pos, _val, preparation());
TypeHandler<std::vector<T> >::prepare(_pos, _val, preparation());
}
private:
std::size_t _pos;
const 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;
std::vector<T>& _val;
};

View File

@@ -43,7 +43,7 @@
#include "Poco/Data/Data.h"
#include "Poco/Data/StatementImpl.h"
#include "Poco/Data/Range.h"
#include "Poco/Data/Step.h"
#include "Poco/Data/Bulk.h"
#include "Poco/SharedPtr.h"
#include "Poco/Mutex.h"
#include "Poco/ActiveMethod.h"
@@ -171,15 +171,24 @@ public:
}
Statement& operator , (Manipulator manip);
/// Handles manipulators, such as now.
/// Handles manipulators, such as now, async, etc.
Statement& operator , (AbstractBinding* info);
/// Registers the Binding at the Statement
/// Registers the Binding at the Statement.
Statement& operator , (AbstractExtraction* extract);
/// 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);
/// 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.
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;
/// Creates a string from the accumulated SQL statement
/// Creates a string from the accumulated SQL statement.
ResultType execute();
/// Executes the statement synchronously or asynchronously.
@@ -296,85 +299,77 @@ private:
// Manipulators
//
void Data_API now(Statement& statement);
inline void Data_API now(Statement& statement)
/// Enforces immediate execution of the statement.
/// 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.
/// Synchronous execution is default, so specifying this manipulator
/// only makes sense if async() was called for the statement before.
{
statement.setAsync(false);
}
void Data_API async(Statement& statement);
/// Sets the _isAsync flag to true, signalling asynchronous execution.
inline void Data_API async(Statement& statement)
/// 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.
/// std::deque is default storage, so specifying this manipulator
/// 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.
{
if (!statement.canModifyStorage())
throw InvalidAccessException("Storage not modifiable.");
statement.setStorage("vector");
}
void Data_API list(Statement& statement);
inline void Data_API list(Statement& statement)
/// 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.
{
if (!statement.canModifyStorage())
throw InvalidAccessException("Storage not modifiable.");
statement.setStorage("deque");
statement.setAsync(false);
}
//
// 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
{
@@ -460,6 +455,7 @@ inline void swap(Statement& s1, Statement& s2)
}
} } // namespace Poco::Data

View File

@@ -44,6 +44,7 @@
#include "Poco/Data/AbstractBinding.h"
#include "Poco/Data/AbstractExtraction.h"
#include "Poco/Data/Range.h"
#include "Poco/Data/Bulk.h"
#include "Poco/Data/Column.h"
#include "Poco/Data/Extraction.h"
#include "Poco/Data/SessionImpl.h"
@@ -86,6 +87,14 @@ public:
STORAGE_UNKNOWN_IMPL
};
enum BulkType
{
BULK_UNDEFINED,
BULK_BINDING,
BULK_EXTRACTION,
BULK_FORBIDDEN
};
static const std::string DEQUE;
static const std::string VECTOR;
static const std::string LIST;
@@ -133,12 +142,6 @@ public:
Storage getStorage() const;
/// 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;
/// Returns the number of extraction storage buffers associated
/// with the statement.
@@ -168,7 +171,7 @@ protected:
/// returns the number of rows retreved.
///
/// 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;
/// Returns if another bind is possible.
@@ -254,6 +257,12 @@ protected:
Poco::UInt32 activateNextDataSet();
/// 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:
void compile();
/// 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;
/// 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& operator = (const StatementImpl& stmt);
@@ -332,7 +366,8 @@ private:
AbstractBindingVec _bindings;
AbstractExtractionVecVec _extractors;
Poco::UInt32 _curDataSet;
Poco::UInt32 _step;
BulkType _bulkBinding;
BulkType _bulkExtraction;
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
{
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

View File

@@ -52,8 +52,21 @@ namespace Poco {
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>
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.
///
/// 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)
/// };
///
/// 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 <>
/// class TypeHandler<struct Person>
@@ -132,19 +145,16 @@ public:
static void extract(std::size_t pos, T& obj, const T& defVal, AbstractExtractor* pExt)
{
poco_assert_dbg (pExt != 0);
if (!pExt->extract(pos, obj))
obj = defVal;
if (!pExt->extract(pos, obj)) 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);
pPrepare->prepare(pos, obj);
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator = (const TypeHandler&);
};
@@ -204,7 +214,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -280,8 +290,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -336,7 +344,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -409,8 +417,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -463,7 +469,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -533,8 +539,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -585,7 +589,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -652,8 +656,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -702,7 +704,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -766,8 +768,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -814,7 +814,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -875,8 +875,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -921,7 +919,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -979,8 +977,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -1023,7 +1019,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1078,8 +1074,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -1120,7 +1114,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1172,8 +1166,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -1212,7 +1204,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1261,8 +1253,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -1290,7 +1280,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1336,8 +1326,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -1364,7 +1352,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1407,8 +1395,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -1434,7 +1420,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1474,8 +1460,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -1500,7 +1484,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1537,8 +1521,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -1562,7 +1544,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1596,8 +1578,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -1620,7 +1600,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1651,8 +1631,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -1674,7 +1652,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1702,8 +1680,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -1724,7 +1700,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1749,8 +1725,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -1770,7 +1744,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1792,8 +1766,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
@@ -1812,7 +1784,7 @@ public:
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);
pPrepare->prepare(pos++, tuple.template get<0>());
@@ -1832,8 +1804,6 @@ public:
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};

View File

@@ -35,10 +35,13 @@
#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/DateTime.h"
#include "Poco/Any.h"
#include "Poco/DynamicAny.h"
#include "Poco/Data/BLOB.h"
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)
{
if(val.type() == typeid(Int32))
const std::type_info& type = val.type();
if(type == typeid(Int32))
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);
else if (val.type() == typeid(bool))
else if (type == typeid(bool))
bind(pos, RefAnyCast<bool>(val), dir);
else if(val.type() == typeid(char))
else if(type == typeid(char))
bind(pos, RefAnyCast<char>(val), dir);
else if(val.type() == typeid(Int8))
else if(type == typeid(Int8))
bind(pos, RefAnyCast<Int8>(val), dir);
else if(val.type() == typeid(UInt8))
else if(type == typeid(UInt8))
bind(pos, RefAnyCast<UInt8>(val), dir);
else if(val.type() == typeid(Int16))
else if(type == typeid(Int16))
bind(pos, RefAnyCast<Int16>(val), dir);
else if(val.type() == typeid(UInt16))
else if(type == typeid(UInt16))
bind(pos, RefAnyCast<UInt16>(val), dir);
else if(val.type() == typeid(UInt32))
else if(type == typeid(UInt32))
bind(pos, RefAnyCast<UInt32>(val), dir);
else if(val.type() == typeid(Int64))
else if(type == typeid(Int64))
bind(pos, RefAnyCast<Int64>(val), dir);
else if(val.type() == typeid(UInt64))
else if(type == typeid(UInt64))
bind(pos, RefAnyCast<UInt64>(val), dir);
else if(val.type() == typeid(float))
else if(type == typeid(float))
bind(pos, RefAnyCast<float>(val), dir);
else if(val.type() == typeid(double))
else if(type == typeid(double))
bind(pos, RefAnyCast<double>(val), dir);
else if(val.type() == typeid(DateTime))
else if(type == typeid(DateTime))
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);
#ifndef POCO_LONG_IS_64_BIT
else if(val.type() == typeid(long))
else if(type == typeid(long))
bind(pos, RefAnyCast<long>(val), dir);
#endif
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)
{
if(val.type() == typeid(Int32))
const std::type_info& type = val.type();
if(type == typeid(Int32))
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);
else if (val.type() == typeid(bool))
else if (type == typeid(bool))
bind(pos, val.extract<bool>(), dir);
else if(val.type() == typeid(char))
else if(type == typeid(char))
bind(pos, val.extract<char>(), dir);
else if(val.type() == typeid(Int8))
else if(type == typeid(Int8))
bind(pos, val.extract<Int8>(), dir);
else if(val.type() == typeid(UInt8))
else if(type == typeid(UInt8))
bind(pos, val.extract<UInt8>(), dir);
else if(val.type() == typeid(Int16))
else if(type == typeid(Int16))
bind(pos, val.extract<Int16>(), dir);
else if(val.type() == typeid(UInt16))
else if(type == typeid(UInt16))
bind(pos, val.extract<UInt16>(), dir);
else if(val.type() == typeid(UInt32))
else if(type == typeid(UInt32))
bind(pos, val.extract<UInt32>(), dir);
else if(val.type() == typeid(Int64))
else if(type == typeid(Int64))
bind(pos, val.extract<Int64>(), dir);
else if(val.type() == typeid(UInt64))
else if(type == typeid(UInt64))
bind(pos, val.extract<UInt64>(), dir);
else if(val.type() == typeid(float))
else if(type == typeid(float))
bind(pos, val.extract<float>(), dir);
else if(val.type() == typeid(double))
else if(type == typeid(double))
bind(pos, val.extract<double>(), dir);
else if(val.type() == typeid(DateTime))
else if(type == typeid(DateTime))
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);
#ifndef POCO_LONG_IS_64_BIT
else if(val.type() == typeid(long))
else if(type == typeid(long))
bind(pos, val.extract<long>(), dir);
#endif
else

View File

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

View File

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

View File

@@ -35,6 +35,7 @@
#include "Poco/Data/AbstractExtractor.h"
#include "Poco/Exception.h"
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

View File

@@ -41,7 +41,8 @@ namespace Poco {
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

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(LimitException, DataException, "Limit error")
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(SessionPoolExhaustedException, DataException, "No more sessions available from the session pool")
POCO_IMPLEMENT_EXCEPTION(NoDataException, DataException, "No data found")
POCO_IMPLEMENT_EXCEPTION(LengthExceededException, DataException, "Data too long")
} } // 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
// Package: DataCore
// Module: Step
// Module: Position
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
@@ -34,20 +34,19 @@
//
#include "Poco/Data/Step.h"
#include "Poco/Data/Position.h"
namespace Poco {
namespace Data {
Step::Step(Poco::UInt32 value):
_value(value)
Position::Position(Poco::UInt32 value): _value(value)
{
}
Step::~Step()
Position::~Position()
{
}

View File

@@ -38,6 +38,7 @@
#include "Poco/Data/DataException.h"
#include "Poco/Data/Extraction.h"
#include "Poco/Data/Session.h"
#include "Poco/Data/Bulk.h"
#include "Poco/Any.h"
#include "Poco/Tuple.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())
throw InvalidAccessException("Storage not modifiable.");
if (_pImpl->isBulkExtraction() && _pImpl->extractionLimit() != extrLimit)
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())
throw InvalidAccessException("Storage not modifiable.");
if (_pImpl->isBulkExtraction())
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())
throw InvalidAccessException("Storage not modifiable.");
statement.setStorage("deque");
if (0 == _pImpl->extractions().size() &&
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.");
void reset(Statement& statement)
{
if (!statement.canModifyStorage())
throw InvalidAccessException("Storage not modifiable.");
statement.setStorage("deque");
statement.setAsync(false);
return *this;
}

View File

@@ -59,7 +59,6 @@ const std::string StatementImpl::LIST = "list";
const std::string StatementImpl::DEQUE = "deque";
const std::string StatementImpl::UNKNOWN = "unknown";
StatementImpl::StatementImpl(SessionImpl& rSession):
_state(ST_INITIALIZED),
_extrLimit(upperLimit((Poco::UInt32) Limit::LIMIT_UNLIMITED, false)),
@@ -70,7 +69,8 @@ StatementImpl::StatementImpl(SessionImpl& rSession):
_ostr(),
_bindings(),
_curDataSet(0),
_step(1u)
_bulkBinding(BULK_UNDEFINED),
_bulkExtraction(BULK_UNDEFINED)
{
_extractors.resize(1);
}
@@ -94,9 +94,8 @@ Poco::UInt32 StatementImpl::execute()
lim = executeWithLimit();
if (lim < _lowerLimit)
{
throw LimitException("Did not receive enough data.");
}
return lim;
}
@@ -106,16 +105,17 @@ Poco::UInt32 StatementImpl::executeWithLimit()
poco_assert (_state != ST_DONE);
compile();
Poco::UInt32 count = 0;
Poco::UInt32 limit = _extrLimit.value();
do
{
bind();
while (hasNext() && count < _extrLimit.value())
while (count < limit && hasNext())
count += next();
} while (canBind());
} while (count < limit && canBind());
if (!canBind() && (!hasNext() || _extrLimit.value() == 0))
if (!canBind() && (!hasNext() || limit == 0))
_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");
else
_state = ST_PAUSED;
@@ -176,12 +176,8 @@ void StatementImpl::bind()
{
if (!hasNext())
{
if (canBind())
{
bindImpl();
}
else
_state = ST_DONE;
if (canBind()) 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()
{
Poco::Data::AbstractExtractionVec::iterator it = extractions().begin();
@@ -339,7 +346,7 @@ Poco::UInt32 StatementImpl::activateNextDataSet()
if (_curDataSet + 1 < dataSetCount())
return ++_curDataSet;
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::NotFoundException;
using Poco::InvalidArgumentException;
using Poco::NotImplementedException;
DataTest::DataTest(const std::string& name): CppUnit::TestCase(name)
@@ -1026,16 +1027,34 @@ void DataTest::testDateAndTime()
Date d1(2007, 6, 15);
d1.assign(d.year() - 1, d.month(), d.day());
assert (d1 < d); assert (d1 != d);
if (d.month() > 1)
d1.assign(d.year(), d.month() - 1, d.day());
else
d1.assign(d.year() - 1, 12, d.day());
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());
assert (d1 > d); assert (d1 != d);
if (d.month() < 12)
d1.assign(d.year(), d.month() + 1, d.day());
else
d1.assign(d.year() + 1, 1, d.day());
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());
assert (d1 == d);

View File

@@ -116,7 +116,7 @@ public:
bool extract(std::size_t pos, Poco::DateTime& val);
/// 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.
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;
}

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
void Preparation::prepare(std::size_t pos, long)
void Preparation::prepare(std::size_t pos, long&)
{
}
#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();
/// Destroys the Preparation.
void prepare(std::size_t pos, Poco::Int8);
void prepare(std::size_t pos, Poco::Int8&);
/// Prepares an Int8.
void prepare(std::size_t pos, Poco::UInt8);
void prepare(std::size_t pos, Poco::UInt8&);
/// Prepares an UInt8.
void prepare(std::size_t pos, Poco::Int16);
void prepare(std::size_t pos, Poco::Int16&);
/// Prepares an Int16.
void prepare(std::size_t pos, Poco::UInt16);
void prepare(std::size_t pos, Poco::UInt16&);
/// Prepares an UInt16.
void prepare(std::size_t pos, Poco::Int32);
void prepare(std::size_t pos, Poco::Int32&);
/// Prepares an Int32.
void prepare(std::size_t pos, Poco::UInt32);
void prepare(std::size_t pos, Poco::UInt32&);
/// Prepares an UInt32.
void prepare(std::size_t pos, Poco::Int64);
void prepare(std::size_t pos, Poco::Int64&);
/// Prepares an Int64.
void prepare(std::size_t pos, Poco::UInt64);
void prepare(std::size_t pos, Poco::UInt64&);
/// Prepares an UInt64.
#ifndef POCO_LONG_IS_64_BIT
void prepare(std::size_t pos, long);
void prepare(std::size_t pos, long&);
/// Prepares a long.
#endif
void prepare(std::size_t pos, bool);
void prepare(std::size_t pos, bool&);
/// Prepares a boolean.
void prepare(std::size_t pos, float);
void prepare(std::size_t pos, float&);
/// Prepares a float.
void prepare(std::size_t pos, double);
void prepare(std::size_t pos, double&);
/// Prepares a double.
void prepare(std::size_t pos, char);
void prepare(std::size_t pos, char&);
/// Prepares a single character.
void prepare(std::size_t pos, const std::string&);