Insert NULL using BULK #4001 (#4755)

* fix(ODBC): Insert NULL using BULK #4001
resolve bound types and sizes at compile time

* fix: remove string suffix for static_assert

* Insert NULL using BULK #4001

* fix: typo

* fix(SQLite): missing functions; consolidate extract calls

* chore(SQLite): remove unnecessary typedef

* fix(SQLite): remove duplicate functions

* fix(SQLite): compile errors and warnings

* fix(SQLite): extract implementation signatures

* fix(SQLite): long64 platforms compile errors

* fix(SQLite): long64 platforms compile errors, part ii

* fix(ODBC): windows build

* fix(ODBC): MSSQL big string on windows

* fix(Data): psql and mysql compile errors

* fix(PostgreSQL): add missing functions

* fix(ODBC): revert column size discovery (breaks Oracle)

* fix(PostgreSQL): Nullable extraction #4001

* fix(MySQL): Nullable extraction #4001

* chore(Data): code tidy up

* fix(ODBC): add missing changes
This commit is contained in:
Aleksandar Fabijanic
2024-11-11 11:23:21 -06:00
committed by GitHub
parent fe9c13102d
commit 9530a77347
43 changed files with 5512 additions and 1313 deletions

View File

@@ -28,6 +28,9 @@
#include "Poco/Data/Time.h"
#include "Poco/Data/Date.h"
#include "Poco/Data/Time.h"
#include "Poco/Nullable.h"
#include "Poco/UUID.h"
#include "Poco/UTFString.h"
#include "Poco/Any.h"
#include "Poco/Dynamic/Var.h"
#include "sqlite3.h"
@@ -45,7 +48,7 @@ class SQLite_API Extractor: public Poco::Data::AbstractExtractor
/// If NULL is received, the incoming val value is not changed and false is returned
{
public:
typedef std::vector<std::pair<bool, bool> > NullIndVec;
using NullIndVec = std::vector<std::pair<bool, bool> >;
/// Type for null indicators container.
Extractor(sqlite3_stmt* pStmt);
@@ -54,78 +57,373 @@ public:
~Extractor();
/// Destroys the Extractor.
bool extract(std::size_t pos, Poco::Int8& val);
bool extract(std::size_t pos, Poco::Int8& val) override;
/// Extracts an Int8.
bool extract(std::size_t pos, Poco::UInt8& val);
bool extract(std::size_t pos, Poco::UInt8& val) override;
/// Extracts an UInt8.
bool extract(std::size_t pos, Poco::Int16& val);
bool extract(std::size_t pos, Poco::Int16& val) override;
/// Extracts an Int16.
bool extract(std::size_t pos, Poco::UInt16& val);
bool extract(std::size_t pos, Poco::UInt16& val) override;
/// Extracts an UInt16.
bool extract(std::size_t pos, Poco::Int32& val);
bool extract(std::size_t pos, Poco::Int32& val) override;
/// Extracts an Int32.
bool extract(std::size_t pos, Poco::UInt32& val);
bool extract(std::size_t pos, Poco::UInt32& val) override;
/// Extracts an UInt32.
bool extract(std::size_t pos, Poco::Int64& val);
bool extract(std::size_t pos, Poco::Int64& val) override;
/// Extracts an Int64.
bool extract(std::size_t pos, Poco::UInt64& val);
bool extract(std::size_t pos, Poco::UInt64& val) override;
/// Extracts an UInt64.
#ifndef POCO_INT64_IS_LONG
bool extract(std::size_t pos, long& val);
/// Extracts a long.
bool extract(std::size_t pos, unsigned long& val);
/// Extracts an unsigned long.
#endif
bool extract(std::size_t pos, bool& val);
bool extract(std::size_t pos, bool& val) override;
/// Extracts a boolean.
bool extract(std::size_t pos, float& val);
bool extract(std::size_t pos, float& val) override;
/// Extracts a float.
bool extract(std::size_t pos, double& val);
bool extract(std::size_t pos, double& val) override;
/// Extracts a double.
bool extract(std::size_t pos, char& val);
bool extract(std::size_t pos, char& val) override;
/// Extracts a single character.
bool extract(std::size_t pos, std::string& val);
bool extract(std::size_t pos, std::string& val) override;
/// Extracts a string.
bool extract(std::size_t pos, Poco::Data::BLOB& val);
bool extract(std::size_t pos, UTF16String& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, Poco::Data::BLOB& val) override;
/// Extracts a BLOB.
bool extract(std::size_t pos, Poco::Data::CLOB& val);
bool extract(std::size_t pos, Poco::Data::CLOB& val) override;
/// Extracts a CLOB.
bool extract(std::size_t pos, Poco::Data::Date& val);
bool extract(std::size_t pos, Poco::Data::Date& val) override;
/// Extracts a Date.
bool extract(std::size_t pos, Poco::Data::Time& val);
bool extract(std::size_t pos, Poco::Data::Time& val) override;
/// Extracts a Time.
bool extract(std::size_t pos, Poco::DateTime& val);
bool extract(std::size_t pos, Poco::DateTime& val) override;
/// Extracts a DateTime.
bool extract(std::size_t pos, Poco::UUID& val);
/// Extracts a Time.
bool extract(std::size_t pos, Poco::UUID& val) override;
/// Extracts a UUID.
bool extract(std::size_t pos, Poco::Any& val);
bool extract(std::size_t pos, Poco::Any& val) override;
/// Extracts an Any.
bool extract(std::size_t pos, Poco::Dynamic::Var& val);
bool extract(std::size_t pos, Poco::Dynamic::Var& val) override;
/// Extracts a Dynamic::Var.
bool isNull(std::size_t pos, std::size_t row = POCO_DATA_INVALID_ROW);
// Nullable extraction
bool extract(std::size_t pos, Poco::Nullable<Poco::Int8>& val) override;
/// Extracts an Nullable<Int8>.
bool extract(std::size_t pos, Poco::Nullable<Poco::UInt8>& val) override;
/// Extracts an Nullable<UInt8>.
bool extract(std::size_t pos, Poco::Nullable<Poco::Int16>& val) override;
/// Extracts an Nullable<Int16>.
bool extract(std::size_t pos, Poco::Nullable<Poco::UInt16>& val) override;
/// Extracts an Nullable<UInt16>.
bool extract(std::size_t pos, Poco::Nullable<Poco::Int32>& val) override;
/// Extracts an Nullable<Int32>.
bool extract(std::size_t pos, Poco::Nullable<Poco::UInt32>& val) override;
/// Extracts an Nullable<UInt32>.
bool extract(std::size_t pos, Poco::Nullable<Poco::Int64>& val) override;
/// Extracts an Nullable<Int64>.
bool extract(std::size_t pos, Poco::Nullable<Poco::UInt64>& val) override;
/// Extracts an Nullable<UInt64>.
#ifndef POCO_INT64_IS_LONG
bool extract(std::size_t pos, long& val) override;
/// Extracts a long.
bool extract(std::size_t pos, unsigned long& val) override;
/// Extracts an unsigned long.
bool extract(std::size_t pos, std::vector<long>& val) override;
/// Extracts a long vector.
bool extract(std::size_t pos, std::deque<long>& val) override;
/// Extracts a long deque.
bool extract(std::size_t pos, std::list<long>& val) override;
/// Extracts a long list.
bool extract(std::size_t pos, std::vector<unsigned long>& val) override;
/// Extracts an unsigned long vector.
bool extract(std::size_t pos, std::deque<unsigned long>& val) override;
/// Extracts an unsigned long deque.
bool extract(std::size_t pos, std::list<unsigned long>& val) override;
/// Extracts an unsigned long list.
bool extract(std::size_t pos, Poco::Nullable<long>& val) override;
/// Extracts a Nullable<long>.
bool extract(std::size_t pos, Poco::Nullable<unsigned long>& val) override;
/// Extracts a Nullable<unsigned long>.
#endif
bool extract(std::size_t pos, Poco::Nullable<bool>& val) override;
/// Extracts a Nullable<bool>.
bool extract(std::size_t pos, Poco::Nullable<float>& val) override;
/// Extracts a Nullable<float>.
bool extract(std::size_t pos, Poco::Nullable<double>& val) override;
/// Extracts a Nullable<double>.
bool extract(std::size_t pos, Poco::Nullable<char>& val) override;
/// Extracts a single Nullable character.
bool extract(std::size_t pos, Poco::Nullable<std::string>& val) override;
/// Extracts a Nullable<string>.
bool extract(std::size_t pos, Poco::Nullable<UTF16String>& val) override;
/// Extracts a Nullable<UTF16String>.
bool extract(std::size_t pos, Poco::Nullable<Poco::Data::BLOB>& val) override;
/// Extracts a Nullable<BLOB>.
bool extract(std::size_t pos, Poco::Nullable<Poco::Data::CLOB>& val) override;
/// Extracts a Nullable<BLOB>.
bool extract(std::size_t pos, Poco::Nullable<Poco::Data::Date>& val) override;
/// Extracts a Nullable<Date>.
bool extract(std::size_t pos, Poco::Nullable<Poco::Data::Time>& val) override;
/// Extracts a :Nullable<Time>.
bool extract(std::size_t pos, Poco::Nullable<Poco::DateTime>& val) override;
/// Extracts Nullable<DateTime>.
bool extract(std::size_t pos, Poco::Nullable<Poco::UUID>& val) override;
/// Extracts a Nullable<UUID>.
bool extract(std::size_t pos, Poco::Nullable<Poco::Any>& val) override;
/// Extracts a Nullable<Any>.
bool extract(std::size_t pos, Poco::Nullable<Poco::Dynamic::Var>& val) override;
/// Extracts a Nullable<Var>.
// Containers
bool extract(std::size_t pos, std::vector<Poco::Int8>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::Int8>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::Int8>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::UInt8>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::UInt8>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::UInt8>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::Int16>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::Int16>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::Int16>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::UInt16>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::UInt16>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::UInt16>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::Int32>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::Int32>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::Int32>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::UInt32>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::UInt32>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::UInt32>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::Int64>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::Int64>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::Int64>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::UInt64>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::UInt64>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::UInt64>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<bool>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<bool>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<bool>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<char>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<char>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<char>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<std::string>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<std::string>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<std::string>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<UTF16String>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<UTF16String>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<UTF16String>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<float>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<float>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<float>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<double>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<double>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<double>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::Data::Date>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::Data::Date>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::Data::Date>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::Data::Time>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::Data::Time>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::Data::Time>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::Data::BLOB>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::Data::BLOB>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::Data::BLOB>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::Data::CLOB>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::Data::CLOB>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::Data::CLOB>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::DateTime>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::DateTime>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::DateTime>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::UUID>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::UUID>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::UUID>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::Any>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::Any>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::Any>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::vector<Poco::Dynamic::Var>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::deque<Poco::Dynamic::Var>& val) override;
/// Throws NotImplementedException.
bool extract(std::size_t pos, std::list<Poco::Dynamic::Var>& val) override;
/// Throws NotImplementedException.
bool isNull(std::size_t pos, std::size_t row = POCO_DATA_INVALID_ROW) override;
/// 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,
@@ -141,10 +439,18 @@ public:
/// The row argument, needed for connectors with bulk capabilities,
/// is ignored in this implementation.
void reset();
void reset() override;
/// Clears the cached nulls indicator vector.
private:
template <typename F, typename T>
bool extract(F func, std::size_t pos, T& val)
{
if (isNull(pos)) return false;
val = func(_pStmt, (int) pos);
return true;
}
template <typename T>
bool extractImpl(std::size_t pos, T& val)
/// Utility function for extraction of Any and Dynamic::Var.

View File

@@ -20,6 +20,7 @@
#include "Poco/Data/DataException.h"
#include "Poco/DateTimeParser.h"
#include "Poco/Exception.h"
#include "Poco/Debugger.h"
#if defined(POCO_UNBUNDLED)
#include <sqlite3.h>
#else
@@ -49,43 +50,19 @@ Extractor::~Extractor()
bool Extractor::extract(std::size_t pos, Poco::Int32& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_int(_pStmt, (int) pos);
return true;
return extract(sqlite3_column_int, pos, val);
}
bool Extractor::extract(std::size_t pos, Poco::Int64& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_int64(_pStmt, (int) pos);
return true;
return extract(sqlite3_column_int64, pos, val);
}
#ifndef POCO_INT64_IS_LONG
bool Extractor::extract(std::size_t pos, long& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_int(_pStmt, (int) pos);
return true;
}
bool Extractor::extract(std::size_t pos, unsigned long& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_int(_pStmt, (int) pos);
return true;
}
#endif
bool Extractor::extract(std::size_t pos, double& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_double(_pStmt, (int) pos);
return true;
return extract(sqlite3_column_double, pos, val);
}
@@ -101,59 +78,51 @@ bool Extractor::extract(std::size_t pos, std::string& val)
}
bool Extractor::extract(std::size_t pos, UTF16String& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, Poco::Int8& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_int(_pStmt, (int) pos);
return true;
return extract(sqlite3_column_int, pos, val);
}
bool Extractor::extract(std::size_t pos, Poco::UInt8& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_int(_pStmt, (int) pos);
return true;
return extract(sqlite3_column_int, pos, val);
}
bool Extractor::extract(std::size_t pos, Poco::Int16& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_int(_pStmt, (int) pos);
return true;
return extract(sqlite3_column_int, pos, val);
}
bool Extractor::extract(std::size_t pos, Poco::UInt16& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_int(_pStmt, (int) pos);
return true;
return extract(sqlite3_column_int, pos, val);
}
bool Extractor::extract(std::size_t pos, Poco::UInt32& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_int(_pStmt, (int) pos);
return true;
return extract(sqlite3_column_int, pos, val);
}
bool Extractor::extract(std::size_t pos, Poco::UInt64& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_int64(_pStmt, (int) pos);
return true;
return extract(sqlite3_column_int64, pos, val);
}
bool Extractor::extract(std::size_t pos, bool& val)
{
if (isNull(pos)) return false;
val = (0 != sqlite3_column_int(_pStmt, (int) pos));
return true;
return extract(sqlite3_column_int, pos, val);
}
@@ -167,9 +136,7 @@ bool Extractor::extract(std::size_t pos, float& val)
bool Extractor::extract(std::size_t pos, char& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_int(_pStmt, (int) pos);
return true;
return extract(sqlite3_column_int, pos, val);
}
@@ -230,6 +197,299 @@ bool Extractor::extract(std::size_t pos, Dynamic::Var& val)
}
// Nullable
bool Extractor::extract(std::size_t pos, Nullable<Poco::Int32>& val)
{
if (isNull(pos)) val.clear();
else val = sqlite3_column_int(_pStmt, (int) pos);
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<Poco::Int64>& val)
{
if (isNull(pos)) val.clear();
else val = sqlite3_column_int64(_pStmt, (int) pos);
return true;
}
#ifndef POCO_INT64_IS_LONG
bool Extractor::extract(std::size_t pos, long& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_int64(_pStmt, (int) pos);
return true;
}
bool Extractor::extract(std::size_t pos, unsigned long& val)
{
if (isNull(pos)) return false;
val = sqlite3_column_int64(_pStmt, (int) pos);
return true;
}
bool Extractor::extract(std::size_t pos, std::vector<long>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<long>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<long>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<unsigned long>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<unsigned long>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<unsigned long>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, Nullable<long>& val)
{
if (isNull(pos)) val.clear();
else val = sqlite3_column_int(_pStmt, (int) pos);
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<unsigned long>& val)
{
if (isNull(pos)) val.clear();
else val = sqlite3_column_int(_pStmt, (int) pos);
return true;
}
#endif // POCO_INT64_IS_LONG
bool Extractor::extract(std::size_t pos, Nullable<double>& val)
{
if (isNull(pos)) val.clear();
else val = sqlite3_column_double(_pStmt, (int) pos);
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<std::string>& val)
{
if (isNull(pos)) val.clear();
else
{
const char *pBuf = reinterpret_cast<const char*>(sqlite3_column_text(_pStmt, (int) pos));
if (!pBuf) val = ""s;
else val = pBuf;
}
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<UTF16String>& val)
{
throw NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, Nullable<Poco::Int8>& val)
{
if (isNull(pos)) val.clear();
else val = sqlite3_column_int(_pStmt, (int) pos);
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<Poco::UInt8>& val)
{
if (isNull(pos)) val.clear();
else val = sqlite3_column_int(_pStmt, (int) pos);
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<Poco::Int16>& val)
{
if (isNull(pos)) val.clear();
else val = sqlite3_column_int(_pStmt, (int) pos);
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<Poco::UInt16>& val)
{
if (isNull(pos)) val.clear();
else val = sqlite3_column_int(_pStmt, (int) pos);
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<Poco::UInt32>& val)
{
if (isNull(pos)) val.clear();
else val = sqlite3_column_int(_pStmt, (int) pos);
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<Poco::UInt64>& val)
{
if (isNull(pos)) val.clear();
else val = sqlite3_column_int64(_pStmt, (int) pos);
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<bool>& val)
{
if (isNull(pos)) val.clear();
else val = (0 != sqlite3_column_int(_pStmt, (int) pos));
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<float>& val)
{
if (isNull(pos)) val.clear();
else val = static_cast<float>(sqlite3_column_double(_pStmt, (int) pos));
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<char>& val)
{
if (isNull(pos)) val.clear();
else val = sqlite3_column_int(_pStmt, (int) pos);
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<Date>& val)
{
if (isNull(pos)) val.clear();
else
{
std::string str;
extract(pos, str);
int tzd;
val = DateTimeParser::parse(Utility::SQLITE_DATE_FORMAT, str, tzd);
}
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<Time>& val)
{
if (isNull(pos)) val.clear();
else
{
std::string str;
extract(pos, str);
int tzd;
val = DateTimeParser::parse(Utility::SQLITE_TIME_FORMAT, str, tzd);
}
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<DateTime>& val)
{
if (isNull(pos)) val.clear();
else
{
std::string dt;
extract(pos, dt);
int tzd;
if (val.isNull()) val = DateTime();
DateTimeParser::parse(dt, val.value(), tzd);
}
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<UUID>& val)
{
if (isNull(pos)) val.clear();
else
{
std::string str;
extract(pos, str);
if (val.isNull()) val = UUID();
val.value().parse(str);
}
return true;
}
bool Extractor::extract(std::size_t pos, Nullable<Poco::Any>& val)
{
if (isNull(pos))
{
val.clear();
return true;
}
if (val.isNull()) val = Poco::Any();
return extractImpl(pos, val.value());
}
bool Extractor::extract(std::size_t pos, Nullable<Dynamic::Var>& val)
{
if (isNull(pos))
{
val.clear();
return true;
}
if (val.isNull()) val = Dynamic::Var();
return extractImpl(pos, val.value());
}
inline bool Extractor::extract(std::size_t pos, Nullable<Poco::Data::BLOB>& val)
{
if (isNull(pos))
{
val.clear();
return true;
}
if (val.isNull()) val = Poco::Data::BLOB();
return extractLOB<Poco::Data::BLOB::ValueType>(pos, val.value());
}
inline bool Extractor::extract(std::size_t pos, Nullable<Poco::Data::CLOB>& val)
{
if (isNull(pos))
{
val.clear();
return true;
}
if (val.isNull()) val = Poco::Data::CLOB();
return extractLOB<Poco::Data::CLOB::ValueType>(pos, val.value());
}
bool Extractor::isNull(std::size_t pos, std::size_t)
{
if (pos >= _nulls.size())
@@ -245,4 +505,401 @@ bool Extractor::isNull(std::size_t pos, std::size_t)
}
// Containers
bool Extractor::extract(std::size_t pos, std::vector<Poco::Int8>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::Int8>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::Int8>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::UInt8>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::UInt8>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::UInt8>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::Int16>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::Int16>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::Int16>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::UInt16>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::UInt16>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::UInt16>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::Int32>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::Int32>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::Int32>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::UInt32>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::UInt32>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::UInt32>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::Int64>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::Int64>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::Int64>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::UInt64>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::UInt64>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::UInt64>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<bool>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<bool>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<bool>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<char>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<char>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<char>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<std::string>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<std::string>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<std::string>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<UTF16String>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<UTF16String>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<UTF16String>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<float>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<float>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<float>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<double>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<double>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<double>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::Data::Date>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::Data::Date>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::Data::Date>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::Data::Time>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::Data::Time>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::Data::Time>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::Data::BLOB>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::Data::BLOB>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::Data::BLOB>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::Data::CLOB>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::Data::CLOB>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::Data::CLOB>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::DateTime>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::DateTime>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::DateTime>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::UUID>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::UUID>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::UUID>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::Any>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::Any>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::Any>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::vector<Poco::Dynamic::Var>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::deque<Poco::Dynamic::Var>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
bool Extractor::extract(std::size_t pos, std::list<Poco::Dynamic::Var>& val)
{
throw Poco::NotImplementedException(poco_src_loc);
}
} } } // namespace Poco::Data::SQLite

View File

@@ -45,6 +45,7 @@
#include <iostream>
using namespace std::string_literals;
using namespace Poco::Data::Keywords;
using Poco::Data::Session;
using Poco::Data::Statement;
@@ -62,6 +63,7 @@ using Poco::Data::Transaction;
using Poco::Data::AbstractExtractionVec;
using Poco::Data::AbstractExtractionVecVec;
using Poco::Data::AbstractBindingVec;
using Poco::Data::NullData;
using Poco::Data::NotConnectedException;
using Poco::Data::SQLite::Notifier;
using Poco::Nullable;
@@ -2189,6 +2191,120 @@ void SQLiteTest::testNullable()
}
void SQLiteTest::testNullableVector()
{
Session ses (Poco::Data::SQLite::Connector::KEY, "dummy.db");
ses << "DROP TABLE IF EXISTS NullableTest", now;
ses << "CREATE TABLE NullableTest (i INTEGER, r REAL, s VARCHAR, d DATETIME)", now;
const int sz = 3;
std::vector<NullData> nd(sz, null);
ses << "INSERT INTO NullableTest VALUES(:i, :r, :s, :d)", use(nd), use(nd), use(nd), use(nd), now;
std::vector<Nullable<int>> v(sz, 1);
std::vector<Nullable<double>> f(sz, 1.5);
std::vector<Nullable<std::string>> s(sz, "abc"s);
std::vector<Nullable<DateTime>> d(sz, DateTime());
for (int i = 0; i < sz; ++i)
{
assertFalse (v[i].isNull());
assertFalse (f[i].isNull());
assertFalse (s[i].isNull());
assertFalse (d[i].isNull());
}
v.clear();
f.clear();
s.clear();
d.clear();
assertEqual (0, v.size());
assertEqual (0, f.size());
assertEqual (0, s.size());
assertEqual (0, d.size());
ses << "SELECT i, r, s, d FROM NullableTest", into(v), into(f), into(s), into(d), now;
assertEqual (sz, v.size());
assertEqual (sz, f.size());
assertEqual (sz, s.size());
assertEqual (sz, d.size());
for (int i = 0; i < sz; ++i)
{
assertTrue (v[i].isNull());
assertTrue (f[i].isNull());
assertTrue (s[i].isNull());
assertTrue (d[i].isNull());
}
ses << "DELETE FROM NullableTest", now;
ses << "SELECT i, r, s, d FROM NullableTest", into(v), into(f), into(s), into(d), now;
assertEqual (0, v.size());
assertEqual (0, f.size());
assertEqual (0, s.size());
assertEqual (0, d.size());
const std::vector<Nullable<int>> nv = {null, 2, 3};
const std::vector<Nullable<double>> nf = {1.5, null, 3.5};
const std::vector<Nullable<std::string>> ns = {"123"s, "abc"s, null};
const std::vector<Nullable<DateTime>> ndt = {null, DateTime(1965, 6, 18), null};
v = nv;
f = nf;
s = ns;
d = ndt;
ses << "INSERT INTO NullableTest VALUES(:i, :r, :s, :d)", use(v), use(f), use(s), use(d), now;
v.clear();
f.clear();
s.clear();
d.clear();
assertEqual (0, v.size());
assertEqual (0, f.size());
assertEqual (0, s.size());
assertEqual (0, d.size());
ses << "SELECT i, r, s, d FROM NullableTest", into(v), into(f), into(s), into(d), now;
assertEqual (sz, v.size());
assertEqual (sz, f.size());
assertEqual (sz, s.size());
assertEqual (sz, d.size());
assertTrue (v == nv);
assertTrue (f == nf);
assertTrue (s == ns);
assertTrue (d == ndt);
RecordSet rs(ses, "SELECT * FROM NullableTest");
rs.moveFirst();
assertTrue (rs.isNull("i"));
assertTrue (!rs.isNull("r"));
assertTrue (!rs.isNull("s"));
assertTrue (rs.isNull("d"));
assertTrue (rs.moveNext());
assertTrue (!rs.isNull("i"));
assertTrue (rs.isNull("r"));
assertTrue (!rs.isNull("s"));
assertTrue (!rs.isNull("d"));
assertTrue (rs.moveNext());
assertTrue (!rs.isNull("i"));
assertTrue (!rs.isNull("r"));
assertTrue (rs.isNull("s"));
assertTrue (rs.isNull("d"));
}
void SQLiteTest::testNulls()
{
Session ses (Poco::Data::SQLite::Connector::KEY, "dummy.db");
@@ -3272,21 +3388,21 @@ void SQLiteTest::testSessionTransactionReadUncommitted()
Connector::enableSharedCache();
Session session (Poco::Data::SQLite::Connector::KEY, "dummy.db");
assertTrue (session.isConnected());
session << "DROP TABLE IF EXISTS Person", now;
session << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Age INTEGER(3))", now;
if (!session.canTransact())
{
std::cout << "Session not capable of transactions." << std::endl;
return;
}
Session local (Poco::Data::SQLite::Connector::KEY, "dummy.db");
assertTrue (local.isConnected());
assertTrue (local.getFeature("autoCommit"));
std::string funct = "transaction()";
std::vector<std::string> lastNames;
std::vector<std::string> firstNames;
@@ -3303,55 +3419,55 @@ void SQLiteTest::testSessionTransactionReadUncommitted()
ages.push_back(2);
int count = 0, locCount = 0;
std::string result;
setTransactionIsolation(session, Session::TRANSACTION_READ_UNCOMMITTED);
setTransactionIsolation(local, Session::TRANSACTION_READ_UNCOMMITTED);
session.begin();
assertTrue (!session.getFeature("autoCommit"));
assertTrue (session.isTransaction());
session << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
assertTrue (session.isTransaction());
Statement stmt = (local << "SELECT COUNT(*) FROM Person", into(locCount), async, now);
session << "SELECT COUNT(*) FROM Person", into(count), now;
assertTrue (2 == count);
stmt.wait();
assertTrue (session.isTransaction());
session.rollback();
assertTrue (!session.isTransaction());
assertTrue (session.getFeature("autoCommit"));
assertEqual(2, locCount);
session << "SELECT count(*) FROM Person", into(count), now;
assertTrue (0 == count);
assertTrue (!session.isTransaction());
session.begin();
session << "INSERT INTO Person VALUES (?,?,?,?)", use(lastNames), use(firstNames), use(addresses), use(ages), now;
assertTrue (session.isTransaction());
assertTrue (!session.getFeature("autoCommit"));
Statement stmt1 = (local << "SELECT COUNT(*) FROM Person", into(locCount), now);
assertTrue (2 == locCount);
session << "SELECT count(*) FROM Person", into(count), now;
assertTrue (2 == count);
session.commit();
assertTrue (!session.isTransaction());
assertTrue (session.getFeature("autoCommit"));
session << "SELECT count(*) FROM Person", into(count), now;
assertTrue (2 == count);
session.close();
assertTrue (!session.isConnected());
local.close();
assertTrue (!local.isConnected());
}
@@ -3841,6 +3957,7 @@ CppUnit::Test* SQLiteTest::suite()
CppUnit_addTest(pSuite, SQLiteTest, testInternalExtraction);
CppUnit_addTest(pSuite, SQLiteTest, testPrimaryKeyConstraint);
CppUnit_addTest(pSuite, SQLiteTest, testNullable);
CppUnit_addTest(pSuite, SQLiteTest, testNullableVector);
CppUnit_addTest(pSuite, SQLiteTest, testNulls);
CppUnit_addTest(pSuite, SQLiteTest, testRowIterator);
CppUnit_addTest(pSuite, SQLiteTest, testAsync);

View File

@@ -108,6 +108,7 @@ public:
void testInternalExtraction();
void testPrimaryKeyConstraint();
void testNullable();
void testNullableVector();
void testNulls();
void testRowIterator();
void testAsync();