mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 15:42:02 +00:00
Merge branch 'master' of github.com:yandex/ClickHouse
This commit is contained in:
commit
422dd9e6ef
@ -78,7 +78,7 @@ option(ENABLE_NETSSL "Enable NetSSL" ON)
|
||||
option(ENABLE_NETSSL_WIN "Enable NetSSL Windows" OFF)
|
||||
option(ENABLE_CRYPTO "Enable Crypto" ON)
|
||||
option(ENABLE_DATA "Enable Data" ON)
|
||||
option(ENABLE_DATA_SQLITE "Enable Data SQlite" ON)
|
||||
option(ENABLE_DATA_SQLITE "Enable Data SQlite" OFF)
|
||||
option(ENABLE_DATA_MYSQL "Enable Data MySQL" ON)
|
||||
option(ENABLE_DATA_ODBC "Enable Data ODBC" ON)
|
||||
option(ENABLE_SEVENZIP "Enable SevenZip" OFF)
|
||||
|
@ -28,11 +28,6 @@ set_target_properties( "${LIBNAME}"
|
||||
|
||||
target_link_libraries( "${LIBNAME}" PocoFoundation)
|
||||
|
||||
if(ENABLE_DATA_SQLITE)
|
||||
# SQlite3 is built in any case
|
||||
add_subdirectory( SQLite )
|
||||
endif(ENABLE_DATA_SQLITE)
|
||||
|
||||
if(ENABLE_DATA_MYSQL)
|
||||
find_package(MySQL)
|
||||
if(MYSQL_FOUND)
|
||||
|
@ -1,50 +0,0 @@
|
||||
set(LIBNAME "PocoDataSQLite")
|
||||
set(POCO_LIBNAME "${LIBNAME}")
|
||||
|
||||
# Sources
|
||||
file(GLOB SRCS_G "src/*.cpp")
|
||||
POCO_SOURCES_AUTO( SQLITE_SRCS ${SRCS_G})
|
||||
|
||||
# Headers
|
||||
file(GLOB_RECURSE HDRS_G "include/*.h" )
|
||||
POCO_HEADERS_AUTO( SQLITE_SRCS ${HDRS_G})
|
||||
|
||||
if (POCO_UNBUNDLED)
|
||||
find_package(SQLite3)
|
||||
set(DATASQLITELIBS ${SQLITE3_LIBRARIES})
|
||||
include_directories("${SQLITE3_INCLUDE_DIRS}")
|
||||
else()
|
||||
# sqlite3
|
||||
POCO_SOURCES( SQLITE_SRCS sqlite3
|
||||
src/sqlite3.c
|
||||
)
|
||||
|
||||
POCO_HEADERS( SQLITE_SRCS sqlite3
|
||||
src/sqlite3.h
|
||||
)
|
||||
|
||||
set(DATASQLITELIBS "")
|
||||
endif()
|
||||
|
||||
if(WINCE)
|
||||
add_definitions(-DSQLITE_MSVC_LOCALTIME_API)
|
||||
endif(WINCE)
|
||||
|
||||
add_definitions(-DSQLITE_THREADSAFE=1 -DSQLITE_DISABLE_LFS -DSQLITE_OMIT_UTF16 -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_COMPLETE -DSQLITE_OMIT_TCL_VARIABLE -DSQLITE_OMIT_DEPRECATED)
|
||||
|
||||
include_directories(src)
|
||||
|
||||
add_library( "${LIBNAME}" ${LIB_MODE} ${SQLITE_SRCS} )
|
||||
set_target_properties( "${LIBNAME}"
|
||||
PROPERTIES
|
||||
VERSION ${SHARED_LIBRARY_VERSION} SOVERSION ${SHARED_LIBRARY_VERSION}
|
||||
OUTPUT_NAME ${POCO_LIBNAME}
|
||||
DEFINE_SYMBOL SQLite_EXPORTS
|
||||
)
|
||||
|
||||
target_link_libraries( "${LIBNAME}" PocoFoundation PocoData ${DATASQLITELIBS} )
|
||||
|
||||
if (ENABLE_TESTS)
|
||||
add_subdirectory(testsuite)
|
||||
endif ()
|
||||
|
@ -1,4 +0,0 @@
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(PocoFoundation)
|
||||
find_dependency(PocoData)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/PocoDataSQLiteTargets.cmake")
|
@ -1,222 +0,0 @@
|
||||
//
|
||||
// Binder.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/include/Poco/Data/SQLite/Binder.h#4 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: Binder
|
||||
//
|
||||
// Definition of the Binder class.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef Data_SQLite_Binder_INCLUDED
|
||||
#define Data_SQLite_Binder_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
#include "Poco/Data/AbstractBinder.h"
|
||||
#include "Poco/Data/LOB.h"
|
||||
#include "Poco/Any.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
#include "sqlite3.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
class SQLite_API Binder: public Poco::Data::AbstractBinder
|
||||
/// Binds placeholders in the sql query to the provided values. Performs data types mapping.
|
||||
{
|
||||
public:
|
||||
Binder(sqlite3_stmt* pStmt);
|
||||
/// Creates the Binder.
|
||||
|
||||
~Binder();
|
||||
/// Destroys the Binder.
|
||||
|
||||
void bind(std::size_t pos, const Poco::Int8 &val, Direction dir);
|
||||
/// Binds an Int8.
|
||||
|
||||
void bind(std::size_t pos, const Poco::UInt8 &val, Direction dir);
|
||||
/// Binds an UInt8.
|
||||
|
||||
void bind(std::size_t pos, const Poco::Int16 &val, Direction dir);
|
||||
/// Binds an Int16.
|
||||
|
||||
void bind(std::size_t pos, const Poco::UInt16 &val, Direction dir);
|
||||
/// Binds an UInt16.
|
||||
|
||||
void bind(std::size_t pos, const Poco::Int32 &val, Direction dir);
|
||||
/// Binds an Int32.
|
||||
|
||||
void bind(std::size_t pos, const Poco::UInt32 &val, Direction dir);
|
||||
/// Binds an UInt32.
|
||||
|
||||
void bind(std::size_t pos, const Poco::Int64 &val, Direction dir);
|
||||
/// Binds an Int64.
|
||||
|
||||
void bind(std::size_t pos, const Poco::UInt64 &val, Direction dir);
|
||||
/// Binds an UInt64.
|
||||
|
||||
#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 unsigned long &val, Direction dir);
|
||||
/// Binds an unsigned long
|
||||
#endif
|
||||
|
||||
void bind(std::size_t pos, const bool &val, Direction dir);
|
||||
/// Binds a boolean.
|
||||
|
||||
void bind(std::size_t pos, const float &val, Direction dir);
|
||||
/// Binds a float.
|
||||
|
||||
void bind(std::size_t pos, const double &val, Direction dir);
|
||||
/// Binds a double.
|
||||
|
||||
void bind(std::size_t pos, const char &val, Direction dir);
|
||||
/// Binds a single character.
|
||||
|
||||
void bind(std::size_t pos, const char* const &pVal, Direction dir);
|
||||
/// Binds a const char ptr.
|
||||
|
||||
void bind(std::size_t pos, const std::string& val, Direction dir);
|
||||
/// Binds a string.
|
||||
|
||||
void bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir);
|
||||
/// Binds a BLOB.
|
||||
|
||||
void bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir);
|
||||
/// Binds a CLOB.
|
||||
|
||||
void bind(std::size_t pos, const Date& val, Direction dir);
|
||||
/// Binds a Date.
|
||||
|
||||
void bind(std::size_t pos, const Time& val, Direction dir);
|
||||
/// Binds a Time.
|
||||
|
||||
void bind(std::size_t pos, const DateTime& val, Direction dir);
|
||||
/// Binds a DateTime.
|
||||
|
||||
void bind(std::size_t pos, const NullData& val, Direction dir);
|
||||
/// Binds a null.
|
||||
|
||||
private:
|
||||
void checkReturn(int rc);
|
||||
/// Checks the SQLite return code and throws an appropriate exception
|
||||
/// if error has occurred.
|
||||
|
||||
template <typename T>
|
||||
void bindLOB(std::size_t pos, const Poco::Data::LOB<T>& val, Direction dir)
|
||||
{
|
||||
// convert a blob to a an unsigned char* array
|
||||
const T* pData = reinterpret_cast<const T*>(val.rawContent());
|
||||
int valSize = static_cast<int>(val.size());
|
||||
|
||||
int rc = sqlite3_bind_blob(_pStmt, static_cast<int>(pos), pData, valSize, SQLITE_STATIC); // no deep copy, do not free memory
|
||||
checkReturn(rc);
|
||||
}
|
||||
|
||||
sqlite3_stmt* _pStmt;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline void Binder::bind(std::size_t pos, const Poco::Int8 &val, Direction dir)
|
||||
{
|
||||
Poco::Int32 tmp = val;
|
||||
bind(pos, tmp, dir);
|
||||
}
|
||||
|
||||
|
||||
inline void Binder::bind(std::size_t pos, const Poco::UInt8 &val, Direction dir)
|
||||
{
|
||||
Poco::Int32 tmp = val;
|
||||
bind(pos, tmp, dir);
|
||||
}
|
||||
|
||||
|
||||
inline void Binder::bind(std::size_t pos, const Poco::Int16 &val, Direction dir)
|
||||
{
|
||||
Poco::Int32 tmp = val;
|
||||
bind(pos, tmp, dir);
|
||||
}
|
||||
|
||||
|
||||
inline void Binder::bind(std::size_t pos, const Poco::UInt16 &val, Direction dir)
|
||||
{
|
||||
Poco::Int32 tmp = val;
|
||||
bind(pos, tmp, dir);
|
||||
}
|
||||
|
||||
|
||||
inline void Binder::bind(std::size_t pos, const Poco::UInt32 &val, Direction dir)
|
||||
{
|
||||
Poco::Int32 tmp = static_cast<Poco::Int32>(val);
|
||||
bind(pos, tmp, dir);
|
||||
}
|
||||
|
||||
|
||||
inline void Binder::bind(std::size_t pos, const Poco::UInt64 &val, Direction dir)
|
||||
{
|
||||
Poco::Int64 tmp = static_cast<Poco::Int64>(val);
|
||||
bind(pos, tmp, dir);
|
||||
}
|
||||
|
||||
|
||||
inline void Binder::bind(std::size_t pos, const bool &val, Direction dir)
|
||||
{
|
||||
Poco::Int32 tmp = (val ? 1 : 0);
|
||||
bind(pos, tmp, dir);
|
||||
}
|
||||
|
||||
|
||||
inline void Binder::bind(std::size_t pos, const float &val, Direction dir)
|
||||
{
|
||||
double tmp = val;
|
||||
bind(pos, tmp, dir);
|
||||
}
|
||||
|
||||
|
||||
inline void Binder::bind(std::size_t pos, const char &val, Direction dir)
|
||||
{
|
||||
Poco::Int32 tmp = val;
|
||||
bind(pos, tmp, dir);
|
||||
}
|
||||
|
||||
|
||||
inline void Binder::bind(std::size_t pos, const char* const &pVal, Direction dir)
|
||||
{
|
||||
std::string val(pVal);
|
||||
bind(pos, val, dir);
|
||||
}
|
||||
|
||||
|
||||
inline void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir)
|
||||
{
|
||||
bindLOB<Poco::Data::BLOB::ValueType>(pos, val, dir);
|
||||
}
|
||||
|
||||
|
||||
inline void Binder::bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir)
|
||||
{
|
||||
bindLOB<Poco::Data::CLOB::ValueType>(pos, val, dir);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif // Data_SQLite_Binder_INCLUDED
|
@ -1,145 +0,0 @@
|
||||
//
|
||||
// Connector.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/include/Poco/Data/SQLite/Connector.h#2 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: Connector
|
||||
//
|
||||
// Definition of the Connector class.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef Data_SQLite_Connector_INCLUDED
|
||||
#define Data_SQLite_Connector_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
#include "Poco/Data/Connector.h"
|
||||
|
||||
|
||||
// Note: to avoid static (de)initialization problems,
|
||||
// during connector automatic (un)registration, it is
|
||||
// best to have this as a macro.
|
||||
#define POCO_DATA_SQLITE_CONNECTOR_NAME "sqlite"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
class SQLite_API Connector: public Poco::Data::Connector
|
||||
/// Connector instantiates SqLite SessionImpl objects.
|
||||
{
|
||||
public:
|
||||
static const std::string KEY;
|
||||
/// Keyword for creating SQLite sessions ("SQLite").
|
||||
|
||||
Connector();
|
||||
/// Creates the Connector.
|
||||
|
||||
~Connector();
|
||||
/// Destroys the Connector.
|
||||
|
||||
const std::string& name() const;
|
||||
/// Returns the name associated with this connector.
|
||||
|
||||
Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString,
|
||||
std::size_t timeout = Poco::Data::SessionImpl::LOGIN_TIMEOUT_DEFAULT);
|
||||
/// Creates a SQLite SessionImpl object and initializes it with the given connectionString.
|
||||
|
||||
static void registerConnector();
|
||||
/// Registers the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory.
|
||||
|
||||
static void unregisterConnector();
|
||||
/// Unregisters the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory.
|
||||
|
||||
static void enableSharedCache(bool flag = true);
|
||||
/// Enables or disables SQlite shared cache mode
|
||||
/// (see http://www.sqlite.org/sharedcache.html for a discussion).
|
||||
|
||||
static void enableSoftHeapLimit(int limit);
|
||||
/// Sets a soft upper limit to the amount of memory allocated
|
||||
/// by SQLite. For more information, please see the SQLite
|
||||
/// sqlite_soft_heap_limit() function (http://www.sqlite.org/c3ref/soft_heap_limit.html).
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// inlines
|
||||
///
|
||||
inline const std::string& Connector::name() const
|
||||
{
|
||||
static const std::string n(POCO_DATA_SQLITE_CONNECTOR_NAME);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
//
|
||||
// Automatic Connector registration
|
||||
//
|
||||
|
||||
struct SQLite_API SQLiteConnectorRegistrator
|
||||
/// Connector registering class.
|
||||
/// A global instance of this class is instantiated
|
||||
/// with sole purpose to automatically register the
|
||||
/// SQLite connector with central Poco Data registry.
|
||||
{
|
||||
SQLiteConnectorRegistrator()
|
||||
/// Calls Poco::Data::SQLite::registerConnector();
|
||||
{
|
||||
Poco::Data::SQLite::Connector::registerConnector();
|
||||
}
|
||||
|
||||
~SQLiteConnectorRegistrator()
|
||||
/// Calls Poco::Data::SQLite::unregisterConnector();
|
||||
{
|
||||
try
|
||||
{
|
||||
Poco::Data::SQLite::Connector::unregisterConnector();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
poco_unexpected();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#if !defined(POCO_NO_AUTOMATIC_LIB_INIT)
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS) && !defined(__GNUC__)
|
||||
extern "C" const struct SQLite_API SQLiteConnectorRegistrator pocoSQLiteConnectorRegistrator;
|
||||
#if defined(SQLite_EXPORTS)
|
||||
#if defined(_WIN64) || defined(_WIN32_WCE)
|
||||
#define POCO_DATA_SQLITE_FORCE_SYMBOL(s) __pragma(comment (linker, "/export:"#s))
|
||||
#elif defined(_WIN32)
|
||||
#define POCO_DATA_SQLITE_FORCE_SYMBOL(s) __pragma(comment (linker, "/export:_"#s))
|
||||
#endif
|
||||
#else // !SQLite_EXPORTS
|
||||
#if defined(_WIN64) || defined(_WIN32_WCE)
|
||||
#define POCO_DATA_SQLITE_FORCE_SYMBOL(s) __pragma(comment (linker, "/include:"#s))
|
||||
#elif defined(_WIN32)
|
||||
#define POCO_DATA_SQLITE_FORCE_SYMBOL(s) __pragma(comment (linker, "/include:_"#s))
|
||||
#endif
|
||||
#endif // SQLite_EXPORTS
|
||||
#else // !POCO_OS_FAMILY_WINDOWS
|
||||
#define POCO_DATA_SQLITE_FORCE_SYMBOL(s) extern "C" const struct SQLiteConnectorRegistrator s;
|
||||
#endif // POCO_OS_FAMILY_WINDOWS
|
||||
POCO_DATA_SQLITE_FORCE_SYMBOL(pocoSQLiteConnectorRegistrator)
|
||||
#endif // POCO_NO_AUTOMATIC_LIB_INIT
|
||||
|
||||
//
|
||||
// End automatic Connector registration
|
||||
//
|
||||
|
||||
#endif // Data_SQLite_Connector_INCLUDED
|
@ -1,315 +0,0 @@
|
||||
//
|
||||
// Extractor.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/include/Poco/Data/SQLite/Extractor.h#4 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: Extractor
|
||||
//
|
||||
// Definition of the Extractor class.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef Data_SQLite_Extractor_INCLUDED
|
||||
#define Data_SQLite_Extractor_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/AbstractExtractor.h"
|
||||
#include "Poco/Data/MetaColumn.h"
|
||||
#include "Poco/Data/DataException.h"
|
||||
#include "Poco/Data/Constants.h"
|
||||
#include "Poco/Data/Date.h"
|
||||
#include "Poco/Data/Time.h"
|
||||
#include "Poco/Data/Date.h"
|
||||
#include "Poco/Data/Time.h"
|
||||
#include "Poco/Any.h"
|
||||
#include "Poco/DynamicAny.h"
|
||||
#include "sqlite3.h"
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
class SQLite_API Extractor: public Poco::Data::AbstractExtractor
|
||||
/// Extracts and converts data values form the result row returned by SQLite.
|
||||
/// If NULL is received, the incoming val value is not changed and false is returned
|
||||
{
|
||||
public:
|
||||
typedef std::vector<std::pair<bool, bool> > NullIndVec;
|
||||
/// Type for null indicators container.
|
||||
|
||||
Extractor(sqlite3_stmt* pStmt);
|
||||
/// Creates the Extractor.
|
||||
|
||||
~Extractor();
|
||||
/// Destroys the Extractor.
|
||||
|
||||
bool extract(std::size_t pos, Poco::Int8& val);
|
||||
/// Extracts an Int8.
|
||||
|
||||
bool extract(std::size_t pos, Poco::UInt8& val);
|
||||
/// Extracts an UInt8.
|
||||
|
||||
bool extract(std::size_t pos, Poco::Int16& val);
|
||||
/// Extracts an Int16.
|
||||
|
||||
bool extract(std::size_t pos, Poco::UInt16& val);
|
||||
/// Extracts an UInt16.
|
||||
|
||||
bool extract(std::size_t pos, Poco::Int32& val);
|
||||
/// Extracts an Int32.
|
||||
|
||||
bool extract(std::size_t pos, Poco::UInt32& val);
|
||||
/// Extracts an UInt32.
|
||||
|
||||
bool extract(std::size_t pos, Poco::Int64& val);
|
||||
/// Extracts an Int64.
|
||||
|
||||
bool extract(std::size_t pos, Poco::UInt64& val);
|
||||
/// Extracts an UInt64.
|
||||
|
||||
#ifndef POCO_LONG_IS_64_BIT
|
||||
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);
|
||||
/// Extracts a boolean.
|
||||
|
||||
bool extract(std::size_t pos, float& val);
|
||||
/// Extracts a float.
|
||||
|
||||
bool extract(std::size_t pos, double& val);
|
||||
/// Extracts a double.
|
||||
|
||||
bool extract(std::size_t pos, char& val);
|
||||
/// Extracts a single character.
|
||||
|
||||
bool extract(std::size_t pos, std::string& val);
|
||||
/// Extracts a string.
|
||||
|
||||
bool extract(std::size_t pos, Poco::Data::BLOB& val);
|
||||
/// Extracts a BLOB.
|
||||
|
||||
bool extract(std::size_t pos, Poco::Data::CLOB& val);
|
||||
/// Extracts a CLOB.
|
||||
|
||||
bool extract(std::size_t pos, Poco::Data::Date& val);
|
||||
/// Extracts a Date.
|
||||
|
||||
bool extract(std::size_t pos, Poco::Data::Time& val);
|
||||
/// Extracts a Time.
|
||||
|
||||
bool extract(std::size_t pos, Poco::DateTime& val);
|
||||
/// Extracts a DateTime.
|
||||
|
||||
bool extract(std::size_t pos, Poco::Any& val);
|
||||
/// Extracts an Any.
|
||||
|
||||
bool extract(std::size_t pos, Poco::DynamicAny& val);
|
||||
/// Extracts a DynamicAny.
|
||||
|
||||
bool isNull(std::size_t pos, std::size_t row = POCO_DATA_INVALID_ROW);
|
||||
/// 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,
|
||||
/// (once null value is converted to default value, SQLite API
|
||||
/// treats it as non-null), a null indicator container member
|
||||
/// variable is used to cache the indicators of the underlying nulls
|
||||
/// thus rendering this function idempotent.
|
||||
/// The container is a vector of [bool, bool] pairs.
|
||||
/// The vector index corresponds to the column position, the first
|
||||
/// 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.
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
bool extractImpl(std::size_t pos, T& val)
|
||||
/// Utility function for extraction of Any and DynamicAny.
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
|
||||
bool ret = false;
|
||||
|
||||
switch (Utility::getColumnType(_pStmt, pos))
|
||||
{
|
||||
case MetaColumn::FDT_BOOL:
|
||||
{
|
||||
bool i = false;
|
||||
ret = extract(pos, i);
|
||||
val = i;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_INT8:
|
||||
{
|
||||
Poco::Int8 i = 0;
|
||||
ret = extract(pos, i);
|
||||
val = i;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_UINT8:
|
||||
{
|
||||
Poco::UInt8 i = 0;
|
||||
ret = extract(pos, i);
|
||||
val = i;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_INT16:
|
||||
{
|
||||
Poco::Int16 i = 0;
|
||||
ret = extract(pos, i);
|
||||
val = i;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_UINT16:
|
||||
{
|
||||
Poco::UInt16 i = 0;
|
||||
ret = extract(pos, i);
|
||||
val = i;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_INT32:
|
||||
{
|
||||
Poco::Int32 i = 0;
|
||||
ret = extract(pos, i);
|
||||
val = i;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_UINT32:
|
||||
{
|
||||
Poco::UInt32 i = 0;
|
||||
ret = extract(pos, i);
|
||||
val = i;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_INT64:
|
||||
{
|
||||
Poco::Int64 i = 0;
|
||||
ret = extract(pos, i);
|
||||
val = i;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_UINT64:
|
||||
{
|
||||
Poco::UInt64 i = 0;
|
||||
ret = extract(pos, i);
|
||||
val = i;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_STRING:
|
||||
{
|
||||
std::string s;
|
||||
ret = extract(pos, s);
|
||||
val = s;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_DOUBLE:
|
||||
{
|
||||
double d(0.0);
|
||||
ret = extract(pos, d);
|
||||
val = d;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_FLOAT:
|
||||
{
|
||||
float f(0.0);
|
||||
ret = extract(pos, f);
|
||||
val = f;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_BLOB:
|
||||
{
|
||||
BLOB b;
|
||||
ret = extract(pos, b);
|
||||
val = b;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_DATE:
|
||||
{
|
||||
Date d;
|
||||
ret = extract(pos, d);
|
||||
val = d;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_TIME:
|
||||
{
|
||||
Time t;
|
||||
ret = extract(pos, t);
|
||||
val = t;
|
||||
break;
|
||||
}
|
||||
case MetaColumn::FDT_TIMESTAMP:
|
||||
{
|
||||
DateTime dt;
|
||||
ret = extract(pos, dt);
|
||||
val = dt;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw Poco::Data::UnknownTypeException("Unknown type during extraction");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool extractLOB(std::size_t pos, Poco::Data::LOB<T>& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
int size = sqlite3_column_bytes(_pStmt, (int) pos);
|
||||
const T* pTmp = reinterpret_cast<const T*>(sqlite3_column_blob(_pStmt, (int) pos));
|
||||
val = Poco::Data::LOB<T>(pTmp, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
sqlite3_stmt* _pStmt;
|
||||
NullIndVec _nulls;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// inlines
|
||||
///
|
||||
inline void Extractor::reset()
|
||||
{
|
||||
_nulls.clear();
|
||||
}
|
||||
|
||||
|
||||
inline bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val)
|
||||
{
|
||||
return extractLOB<Poco::Data::BLOB::ValueType>(pos, val);
|
||||
}
|
||||
|
||||
|
||||
inline bool Extractor::extract(std::size_t pos, Poco::Data::CLOB& val)
|
||||
{
|
||||
return extractLOB<Poco::Data::CLOB::ValueType>(pos, val);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif // Data_SQLite_Extractor_INCLUDED
|
@ -1,197 +0,0 @@
|
||||
//
|
||||
// Notifier.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/include/Poco/Data/SQLite/Notifier.h#2 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: Notifier
|
||||
//
|
||||
// Definition of Notifier.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef SQLite_Notifier_INCLUDED
|
||||
#define SQLite_Notifier_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/Session.h"
|
||||
#include "Poco/Mutex.h"
|
||||
#include "Poco/Types.h"
|
||||
#include "Poco/Dynamic/Var.h"
|
||||
#include "Poco/BasicEvent.h"
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
class SQLite_API Notifier
|
||||
/// Notifier is a wrapper for SQLite callback calls. It supports event callbacks
|
||||
/// for insert, update, delete, commit and rollback events. While (un)registering
|
||||
/// callbacks is thread-safe, execution of the callbacks themselves are not;
|
||||
/// it is the user's responsibility to ensure the thread-safey of the functions
|
||||
/// they provide as callback target. Additionally, commit callbacks may prevent
|
||||
/// database transactions from succeeding (see sqliteCommitCallbackFn documentation
|
||||
/// for details).
|
||||
///
|
||||
/// There can be only one set of callbacks per session (i.e. registering a new
|
||||
/// callback automatically unregisters the previous one). All callbacks are
|
||||
/// registered and enabled at Notifier contruction time and can be disabled
|
||||
/// at a later point time.
|
||||
{
|
||||
public:
|
||||
typedef unsigned char EnabledEventType;
|
||||
/// A type definition for events-enabled bitmap.
|
||||
|
||||
typedef Poco::BasicEvent<void> Event;
|
||||
|
||||
//
|
||||
// Events
|
||||
//
|
||||
Event update;
|
||||
Event insert;
|
||||
Event erase;
|
||||
Event commit;
|
||||
Event rollback;
|
||||
|
||||
// Event types.
|
||||
static const EnabledEventType SQLITE_NOTIFY_UPDATE = 1;
|
||||
static const EnabledEventType SQLITE_NOTIFY_COMMIT = 2;
|
||||
static const EnabledEventType SQLITE_NOTIFY_ROLLBACK = 4;
|
||||
|
||||
Notifier(const Session& session,
|
||||
EnabledEventType enabled = SQLITE_NOTIFY_UPDATE | SQLITE_NOTIFY_COMMIT | SQLITE_NOTIFY_ROLLBACK);
|
||||
/// Creates a Notifier and enables all callbacks.
|
||||
|
||||
Notifier(const Session& session,
|
||||
const Any& value,
|
||||
EnabledEventType enabled = SQLITE_NOTIFY_UPDATE | SQLITE_NOTIFY_COMMIT | SQLITE_NOTIFY_ROLLBACK);
|
||||
/// Creates a Notifier, assigns the value to the internal storage and and enables all callbacks.
|
||||
|
||||
~Notifier();
|
||||
/// Disables all callbacks and destroys the Notifier.
|
||||
|
||||
bool enableUpdate();
|
||||
/// Enables update callbacks.
|
||||
|
||||
bool disableUpdate();
|
||||
/// Disables update callbacks.
|
||||
|
||||
bool updateEnabled() const;
|
||||
/// Returns true if update callbacks are enabled, false otherwise.
|
||||
|
||||
bool enableCommit();
|
||||
/// Enables commit callbacks.
|
||||
|
||||
bool disableCommit();
|
||||
/// Disables commit callbacks.
|
||||
|
||||
bool commitEnabled() const;
|
||||
/// Returns true if update callbacks are enabled, false otherwise.
|
||||
|
||||
bool enableRollback();
|
||||
/// Enables rollback callbacks.
|
||||
|
||||
bool disableRollback();
|
||||
/// Disables rollback callbacks.
|
||||
|
||||
bool rollbackEnabled() const;
|
||||
/// Returns true if rollback callbacks are enabled, false otherwise.
|
||||
|
||||
bool enableAll();
|
||||
/// Enables all callbacks.
|
||||
|
||||
bool disableAll();
|
||||
/// Disables all callbacks.
|
||||
|
||||
static void sqliteUpdateCallbackFn(void* pVal, int opCode, const char* pDB, const char* pTable, Poco::Int64 row);
|
||||
/// Update callback event dispatcher. Determines the type of the event, updates the row number
|
||||
/// and triggers the event.
|
||||
|
||||
static int sqliteCommitCallbackFn(void* pVal);
|
||||
/// Commit callback event dispatcher. If an exception occurs, it is catched inside this function,
|
||||
/// non-zero value is returned, which causes SQLite engine to turn commit into a rollback.
|
||||
/// Therefore, callers should check for return value - if it is zero, callback completed succesfuly
|
||||
/// and transaction was committed.
|
||||
|
||||
static void sqliteRollbackCallbackFn(void* pVal);
|
||||
/// Rollback callback event dispatcher.
|
||||
|
||||
bool operator == (const Notifier& other) const;
|
||||
/// Equality operator. Compares value, row and database handles and
|
||||
/// returns true iff all are equal.
|
||||
|
||||
Poco::Int64 getRow() const;
|
||||
/// Returns the row number.
|
||||
|
||||
void setRow(Poco::Int64 row);
|
||||
/// Sets the row number.
|
||||
|
||||
const Poco::Dynamic::Var& getValue() const;
|
||||
/// Returns the value.
|
||||
|
||||
template <typename T>
|
||||
inline void setValue(const T& val)
|
||||
/// Sets the value.
|
||||
{
|
||||
_value = val;
|
||||
}
|
||||
|
||||
private:
|
||||
Notifier();
|
||||
Notifier(const Notifier&);
|
||||
Notifier& operator=(const Notifier&);
|
||||
|
||||
const Session& _session;
|
||||
Poco::Dynamic::Var _value;
|
||||
Poco::Int64 _row;
|
||||
EnabledEventType _enabledEvents;
|
||||
Poco::Mutex _mutex;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
inline bool Notifier::operator == (const Notifier& other) const
|
||||
{
|
||||
return _value == other._value &&
|
||||
_row == other._row &&
|
||||
Utility::dbHandle(_session) == Utility::dbHandle(other._session);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::Int64 Notifier::getRow() const
|
||||
{
|
||||
return _row;
|
||||
}
|
||||
|
||||
|
||||
inline void Notifier::setRow(Poco::Int64 row)
|
||||
/// Sets the row number.
|
||||
{
|
||||
_row = row;
|
||||
}
|
||||
|
||||
|
||||
inline const Poco::Dynamic::Var& Notifier::getValue() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif // SQLite_Notifier_INCLUDED
|
@ -1,64 +0,0 @@
|
||||
//
|
||||
// SQLite.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/include/Poco/Data/SQLite/SQLite.h#3 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: SQLite
|
||||
//
|
||||
// Basic definitions for the Poco SQLite library.
|
||||
// This file must be the first file included by every other SQLite
|
||||
// header file.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef SQLite_SQLite_INCLUDED
|
||||
#define SQLite_SQLite_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
|
||||
|
||||
//
|
||||
// The following block is the standard way of creating macros which make exporting
|
||||
// from a DLL simpler. All files within this DLL are compiled with the SQLite_EXPORTS
|
||||
// symbol defined on the command line. this symbol should not be defined on any project
|
||||
// that uses this DLL. This way any other project whose source files include this file see
|
||||
// SQLite_API functions as being imported from a DLL, wheras this DLL sees symbols
|
||||
// defined with this macro as being exported.
|
||||
//
|
||||
#if defined(_WIN32) && defined(POCO_DLL)
|
||||
#if defined(SQLite_EXPORTS)
|
||||
#define SQLite_API __declspec(dllexport)
|
||||
#else
|
||||
#define SQLite_API __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(SQLite_API)
|
||||
#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
|
||||
#define SQLite_API __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define SQLite_API
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// Automatically link SQLite library.
|
||||
//
|
||||
#if defined(_MSC_VER)
|
||||
#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(SQLite_EXPORTS)
|
||||
#pragma comment(lib, "PocoDataSQLite" POCO_LIB_SUFFIX)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif // SQLite_SQLite_INCLUDED
|
@ -1,62 +0,0 @@
|
||||
//
|
||||
// SQLiteException.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/include/Poco/Data/SQLite/SQLiteException.h#2 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: SQLiteException
|
||||
//
|
||||
// Definition of SQLiteException.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef SQLite_SQLiteException_INCLUDED
|
||||
#define SQLite_SQLiteException_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
#include "Poco/Data/DataException.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, SQLiteException, Poco::Data::DataException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, InvalidSQLStatementException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, InternalDBErrorException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, DBAccessDeniedException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, ExecutionAbortedException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, DBLockedException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, TableLockedException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, NoMemoryException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, ReadOnlyException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, InterruptException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, IOErrorException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, CorruptImageException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, TableNotFoundException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, DatabaseFullException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, CantOpenDBFileException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, LockProtocolException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, SchemaDiffersException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, RowTooBigException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, ConstraintViolationException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, DataTypeMismatchException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, ParameterCountMismatchException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, InvalidLibraryUseException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, OSFeaturesMissingException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, AuthorizationDeniedException, SQLiteException)
|
||||
POCO_DECLARE_EXCEPTION(SQLite_API, TransactionException, SQLiteException)
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif
|
@ -1,157 +0,0 @@
|
||||
//
|
||||
// SQLiteStatementImpl.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/include/Poco/Data/SQLite/SQLiteStatementImpl.h#4 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: SQLiteStatementImpl
|
||||
//
|
||||
// Definition of the SQLiteStatementImpl class.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef Data_SQLite_SQLiteStatementImpl_INCLUDED
|
||||
#define Data_SQLite_SQLiteStatementImpl_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
#include "Poco/Data/SQLite/Binder.h"
|
||||
#include "Poco/Data/SQLite/Extractor.h"
|
||||
#include "Poco/Data/StatementImpl.h"
|
||||
#include "Poco/Data/MetaColumn.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
typedef struct sqlite3 sqlite3;
|
||||
typedef struct sqlite3_stmt sqlite3_stmt;
|
||||
}
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
class SQLite_API SQLiteStatementImpl: public Poco::Data::StatementImpl
|
||||
/// Implements statement functionality needed for SQLite
|
||||
{
|
||||
public:
|
||||
SQLiteStatementImpl(Poco::Data::SessionImpl& rSession, sqlite3* pDB);
|
||||
/// Creates the SQLiteStatementImpl.
|
||||
|
||||
~SQLiteStatementImpl();
|
||||
/// Destroys the SQLiteStatementImpl.
|
||||
|
||||
protected:
|
||||
std::size_t columnsReturned() const;
|
||||
/// Returns number of columns returned by query.
|
||||
|
||||
int affectedRowCount() const;
|
||||
/// Returns the number of affected rows.
|
||||
/// Used to find out the number of rows affected by insert, delete or update.
|
||||
/// All changes are counted, even if they are later undone by a ROLLBACK or ABORT.
|
||||
/// Changes associated with creating and dropping tables are not counted.
|
||||
|
||||
const MetaColumn& metaColumn(std::size_t pos) const;
|
||||
/// Returns column meta data.
|
||||
|
||||
bool hasNext();
|
||||
/// Returns true if a call to next() will return data.
|
||||
|
||||
std::size_t next();
|
||||
/// Retrieves the next row from the resultset and returns 1.
|
||||
/// Will throw, if the resultset is empty.
|
||||
|
||||
bool canBind() const;
|
||||
/// Returns true if a valid statement is set and we can bind.
|
||||
|
||||
bool canCompile() const;
|
||||
/// Returns true if statement can compile.
|
||||
|
||||
void compileImpl();
|
||||
/// Compiles the statement, doesn't bind yet.
|
||||
/// Returns true if the statement was succesfully compiled.
|
||||
/// The way SQLite handles batches of statmeents is by compiling
|
||||
/// one at a time and returning a pointer to the next one.
|
||||
/// The remainder of the statement is kept in a string
|
||||
/// buffer pointed to by _pLeftover member.
|
||||
|
||||
void bindImpl();
|
||||
/// Binds parameters
|
||||
|
||||
AbstractExtraction::ExtractorPtr extractor();
|
||||
/// Returns the concrete extractor used by the statement.
|
||||
|
||||
AbstractBinding::BinderPtr binder();
|
||||
/// Returns the concrete binder used by the statement.
|
||||
|
||||
private:
|
||||
void clear();
|
||||
/// Removes the _pStmt
|
||||
|
||||
typedef Poco::SharedPtr<Binder> BinderPtr;
|
||||
typedef Poco::SharedPtr<Extractor> ExtractorPtr;
|
||||
typedef Poco::Data::AbstractBindingVec Bindings;
|
||||
typedef Poco::Data::AbstractExtractionVec Extractions;
|
||||
typedef std::vector<Poco::Data::MetaColumn> MetaColumnVec;
|
||||
typedef std::vector<MetaColumnVec> MetaColumnVecVec;
|
||||
typedef Poco::SharedPtr<std::string> StrPtr;
|
||||
typedef Bindings::iterator BindIt;
|
||||
|
||||
sqlite3* _pDB;
|
||||
sqlite3_stmt* _pStmt;
|
||||
bool _stepCalled;
|
||||
int _nextResponse;
|
||||
BinderPtr _pBinder;
|
||||
ExtractorPtr _pExtractor;
|
||||
MetaColumnVecVec _columns;
|
||||
int _affectedRowCount;
|
||||
StrPtr _pLeftover;
|
||||
BindIt _bindBegin;
|
||||
bool _canBind;
|
||||
bool _isExtracted;
|
||||
bool _canCompile;
|
||||
|
||||
static const int POCO_SQLITE_INV_ROW_CNT;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline AbstractExtraction::ExtractorPtr SQLiteStatementImpl::extractor()
|
||||
{
|
||||
return _pExtractor;
|
||||
}
|
||||
|
||||
|
||||
inline AbstractBinding::BinderPtr SQLiteStatementImpl::binder()
|
||||
{
|
||||
return _pBinder;
|
||||
}
|
||||
|
||||
|
||||
inline bool SQLiteStatementImpl::canBind() const
|
||||
{
|
||||
return _canBind;
|
||||
}
|
||||
|
||||
|
||||
inline bool SQLiteStatementImpl::canCompile() const
|
||||
{
|
||||
return _canCompile;
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif // Data_SQLite_SQLiteStatementImpl_INCLUDED
|
@ -1,168 +0,0 @@
|
||||
//
|
||||
// SessionImpl.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/include/Poco/Data/SQLite/SessionImpl.h#2 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: SessionImpl
|
||||
//
|
||||
// Definition of the SessionImpl class.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef Data_SQLite_SessionImpl_INCLUDED
|
||||
#define Data_SQLite_SessionImpl_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
#include "Poco/Data/SQLite/Connector.h"
|
||||
#include "Poco/Data/SQLite/Binder.h"
|
||||
#include "Poco/Data/AbstractSessionImpl.h"
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include "Poco/Mutex.h"
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
typedef struct sqlite3 sqlite3;
|
||||
}
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
class SQLite_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
|
||||
/// Implements SessionImpl interface.
|
||||
{
|
||||
public:
|
||||
SessionImpl(const std::string& fileName,
|
||||
std::size_t loginTimeout = LOGIN_TIMEOUT_DEFAULT);
|
||||
/// Creates the SessionImpl. Opens a connection to the database.
|
||||
|
||||
~SessionImpl();
|
||||
/// Destroys the SessionImpl.
|
||||
|
||||
Poco::Data::StatementImpl* createStatementImpl();
|
||||
/// Returns an SQLite StatementImpl.
|
||||
|
||||
void open(const std::string& connect = "");
|
||||
/// Opens a connection to the Database.
|
||||
///
|
||||
/// An in-memory system database (sys), with a single table (dual)
|
||||
/// containing single field (dummy) is attached to the database.
|
||||
/// The in-memory system database is used to force change count
|
||||
/// to be reset to zero on every new query (or batch of queries)
|
||||
/// execution. Without this functionality, select statements
|
||||
/// executions that do not return any rows return the count of
|
||||
/// changes effected by the most recent insert, update or delete.
|
||||
/// In-memory system database can be queried and updated but can not
|
||||
/// be dropped. It may be used for other purposes
|
||||
/// in the future.
|
||||
|
||||
void close();
|
||||
/// Closes the session.
|
||||
|
||||
bool isConnected();
|
||||
/// Returns true if connected, false otherwise.
|
||||
|
||||
void setConnectionTimeout(std::size_t timeout);
|
||||
/// Sets the session connection timeout value.
|
||||
|
||||
std::size_t getConnectionTimeout();
|
||||
/// Returns the session connection timeout value.
|
||||
|
||||
void begin();
|
||||
/// Starts a transaction.
|
||||
|
||||
void commit();
|
||||
/// Commits and ends a transaction.
|
||||
|
||||
void rollback();
|
||||
/// Aborts a transaction.
|
||||
|
||||
bool canTransact();
|
||||
/// Returns true if session has transaction capabilities.
|
||||
|
||||
bool isTransaction();
|
||||
/// Returns true iff a transaction is a transaction is in progress, false otherwise.
|
||||
|
||||
void setTransactionIsolation(Poco::UInt32 ti);
|
||||
/// Sets the transaction isolation level.
|
||||
|
||||
Poco::UInt32 getTransactionIsolation();
|
||||
/// Returns the transaction isolation level.
|
||||
|
||||
bool hasTransactionIsolation(Poco::UInt32 ti);
|
||||
/// Returns true iff the transaction isolation level corresponding
|
||||
/// to the supplied bitmask is supported.
|
||||
|
||||
bool isTransactionIsolation(Poco::UInt32 ti);
|
||||
/// Returns true iff the transaction isolation level corresponds
|
||||
/// to the supplied bitmask.
|
||||
|
||||
void autoCommit(const std::string&, bool val);
|
||||
/// Sets autocommit property for the session.
|
||||
|
||||
bool isAutoCommit(const std::string& name="");
|
||||
/// Returns autocommit property value.
|
||||
|
||||
const std::string& connectorName() const;
|
||||
/// Returns the name of the connector.
|
||||
|
||||
protected:
|
||||
void setConnectionTimeout(const std::string& prop, const Poco::Any& value);
|
||||
Poco::Any getConnectionTimeout(const std::string& prop);
|
||||
|
||||
private:
|
||||
std::string _connector;
|
||||
sqlite3* _pDB;
|
||||
bool _connected;
|
||||
bool _isTransaction;
|
||||
int _timeout;
|
||||
Poco::Mutex _mutex;
|
||||
|
||||
static const std::string DEFERRED_BEGIN_TRANSACTION;
|
||||
static const std::string COMMIT_TRANSACTION;
|
||||
static const std::string ABORT_TRANSACTION;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline bool SessionImpl::canTransact()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline bool SessionImpl::isTransaction()
|
||||
{
|
||||
return _isTransaction;
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& SessionImpl::connectorName() const
|
||||
{
|
||||
return _connector;
|
||||
}
|
||||
|
||||
|
||||
inline std::size_t SessionImpl::getConnectionTimeout()
|
||||
{
|
||||
return static_cast<std::size_t>(_timeout);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif // Data_SQLite_SessionImpl_INCLUDED
|
@ -1,230 +0,0 @@
|
||||
//
|
||||
// Utility.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/include/Poco/Data/SQLite/Utility.h#2 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: Utility
|
||||
//
|
||||
// Definition of Utility.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef SQLite_Utility_INCLUDED
|
||||
#define SQLite_Utility_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
#include "Poco/Data/MetaColumn.h"
|
||||
#include "Poco/Data/Session.h"
|
||||
#include "Poco/Mutex.h"
|
||||
#include "Poco/Types.h"
|
||||
#include <map>
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
typedef struct sqlite3 sqlite3;
|
||||
typedef struct sqlite3_stmt sqlite3_stmt;
|
||||
}
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
class SQLite_API Utility
|
||||
/// Various utility functions for SQLite.
|
||||
{
|
||||
public:
|
||||
static const std::string SQLITE_DATE_FORMAT;
|
||||
static const std::string SQLITE_TIME_FORMAT;
|
||||
typedef std::map<std::string, MetaColumn::ColumnDataType> TypeMap;
|
||||
|
||||
static const int THREAD_MODE_SINGLE;
|
||||
static const int THREAD_MODE_MULTI;
|
||||
static const int THREAD_MODE_SERIAL;
|
||||
|
||||
static const int OPERATION_INSERT;
|
||||
static const int OPERATION_DELETE;
|
||||
static const int OPERATION_UPDATE;
|
||||
|
||||
static sqlite3* dbHandle(const Session& session);
|
||||
/// Returns native DB handle.
|
||||
|
||||
static std::string lastError(sqlite3* pDb);
|
||||
/// Retreives the last error code from sqlite and converts it to a string.
|
||||
|
||||
static std::string lastError(const Session& session);
|
||||
/// Retreives the last error code from sqlite and converts it to a string.
|
||||
|
||||
static void throwException(int rc, const std::string& addErrMsg = std::string());
|
||||
/// Throws for an error code the appropriate exception
|
||||
|
||||
static MetaColumn::ColumnDataType getColumnType(sqlite3_stmt* pStmt, std::size_t pos);
|
||||
/// Returns column data type.
|
||||
|
||||
static bool fileToMemory(sqlite3* pInMemory, const std::string& fileName);
|
||||
/// Loads the contents of a database file on disk into an opened
|
||||
/// database in memory.
|
||||
///
|
||||
/// Returns true if succesful.
|
||||
|
||||
static bool fileToMemory(const Session& session, const std::string& fileName);
|
||||
/// Loads the contents of a database file on disk into an opened
|
||||
/// database in memory.
|
||||
///
|
||||
/// Returns true if succesful.
|
||||
|
||||
static bool memoryToFile(const std::string& fileName, sqlite3* pInMemory);
|
||||
/// Saves the contents of an opened database in memory to the
|
||||
/// database on disk.
|
||||
///
|
||||
/// Returns true if succesful.
|
||||
|
||||
static bool memoryToFile(const std::string& fileName, const Session& session);
|
||||
/// Saves the contents of an opened database in memory to the
|
||||
/// database on disk.
|
||||
///
|
||||
/// Returns true if succesful.
|
||||
|
||||
static bool isThreadSafe();
|
||||
/// Returns true if SQLite was compiled in multi-thread or serialized mode.
|
||||
/// See http://www.sqlite.org/c3ref/threadsafe.html for details.
|
||||
///
|
||||
/// Returns true if succesful
|
||||
|
||||
static bool setThreadMode(int mode);
|
||||
/// Sets the threading mode to single, multi or serialized.
|
||||
/// See http://www.sqlite.org/threadsafe.html for details.
|
||||
///
|
||||
/// Returns true if succesful
|
||||
|
||||
static int getThreadMode();
|
||||
/// Returns the thread mode.
|
||||
|
||||
typedef void(*UpdateCallbackType)(void*, int, const char*, const char*, Poco::Int64);
|
||||
/// Update callback function type.
|
||||
|
||||
typedef int(*CommitCallbackType)(void*);
|
||||
/// Commit callback function type.
|
||||
|
||||
typedef void(*RollbackCallbackType)(void*);
|
||||
/// Rollback callback function type.
|
||||
|
||||
template <typename T, typename CBT>
|
||||
static bool registerUpdateHandler(sqlite3* pDB, CBT callbackFn, T* pParam)
|
||||
/// Registers the callback for (1)(insert, delete, update), (2)(commit) or
|
||||
/// or (3)(rollback) events. Only one function per group can be registered
|
||||
/// at a time. Registration is not thread-safe. Storage pointed to by pParam
|
||||
/// must remain valid as long as registration is active. Registering with
|
||||
/// callbackFn set to zero disables notifications.
|
||||
///
|
||||
/// See http://www.sqlite.org/c3ref/update_hook.html and
|
||||
/// http://www.sqlite.org/c3ref/commit_hook.html for details.
|
||||
{
|
||||
typedef std::pair<CBT, T*> CBPair;
|
||||
typedef std::multimap<sqlite3*, CBPair> CBMap;
|
||||
typedef typename CBMap::iterator CBMapIt;
|
||||
typedef std::pair<CBMapIt, CBMapIt> CBMapItPair;
|
||||
|
||||
static CBMap retMap;
|
||||
T* pRet = reinterpret_cast<T*>(eventHookRegister(pDB, callbackFn, pParam));
|
||||
|
||||
if (pRet == 0)
|
||||
{
|
||||
if (retMap.find(pDB) == retMap.end())
|
||||
{
|
||||
retMap.insert(std::make_pair(pDB, CBPair(callbackFn, pParam)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CBMapItPair retMapRange = retMap.equal_range(pDB);
|
||||
for (CBMapIt it = retMapRange.first; it != retMapRange.second; ++it)
|
||||
{
|
||||
poco_assert (it->second.first != 0);
|
||||
if ((callbackFn == 0) && (*pRet == *it->second.second))
|
||||
{
|
||||
retMap.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((callbackFn == it->second.first) && (*pRet == *it->second.second))
|
||||
{
|
||||
it->second.second = pParam;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T, typename CBT>
|
||||
static bool registerUpdateHandler(const Session& session, CBT callbackFn, T* pParam)
|
||||
/// Registers the callback by calling registerUpdateHandler(sqlite3*, CBT, T*).
|
||||
{
|
||||
return registerUpdateHandler(dbHandle(session), callbackFn, pParam);
|
||||
}
|
||||
|
||||
private:
|
||||
Utility();
|
||||
/// Maps SQLite column declared types to Poco::Data types through
|
||||
/// static TypeMap member.
|
||||
///
|
||||
/// Note: SQLite is type-agnostic and it is the end-user responsibility
|
||||
/// to ensure that column declared data type corresponds to the type of
|
||||
/// data actually held in the database.
|
||||
///
|
||||
/// Column types are case-insensitive.
|
||||
|
||||
Utility(const Utility&);
|
||||
Utility& operator = (const Utility&);
|
||||
|
||||
static void* eventHookRegister(sqlite3* pDB, UpdateCallbackType callbackFn, void* pParam);
|
||||
static void* eventHookRegister(sqlite3* pDB, CommitCallbackType callbackFn, void* pParam);
|
||||
static void* eventHookRegister(sqlite3* pDB, RollbackCallbackType callbackFn, void* pParam);
|
||||
|
||||
static TypeMap _types;
|
||||
static Poco::Mutex _mutex;
|
||||
static int _threadMode;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline std::string Utility::lastError(const Session& session)
|
||||
{
|
||||
poco_assert_dbg ((0 == icompare(session.connector(), 0, 6, "sqlite")));
|
||||
return lastError(dbHandle(session));
|
||||
}
|
||||
|
||||
|
||||
inline bool Utility::memoryToFile(const std::string& fileName, const Session& session)
|
||||
{
|
||||
poco_assert_dbg ((0 == icompare(session.connector(), 0, 6, "sqlite")));
|
||||
return memoryToFile(fileName, dbHandle(session));
|
||||
}
|
||||
|
||||
|
||||
inline bool Utility::fileToMemory(const Session& session, const std::string& fileName)
|
||||
{
|
||||
poco_assert_dbg ((0 == icompare(session.connector(), 0, 6, "sqlite")));
|
||||
return fileToMemory(dbHandle(session), fileName);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
||||
|
||||
|
||||
#endif // SQLite_Utility_INCLUDED
|
@ -1,129 +0,0 @@
|
||||
//
|
||||
// Binder.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/src/Binder.cpp#5 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: Binder
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/Binder.h"
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/Date.h"
|
||||
#include "Poco/Data/Time.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/DateTimeFormatter.h"
|
||||
#include "Poco/DateTimeFormat.h"
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
using Poco::DateTimeFormatter;
|
||||
using Poco::DateTimeFormat;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
Binder::Binder(sqlite3_stmt* pStmt):
|
||||
_pStmt(pStmt)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Binder::~Binder()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const Poco::Int32 &val, Direction dir)
|
||||
{
|
||||
int rc = sqlite3_bind_int(_pStmt, (int) pos, val);
|
||||
checkReturn(rc);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const Poco::Int64 &val, Direction dir)
|
||||
{
|
||||
int rc = sqlite3_bind_int64(_pStmt, (int) pos, val);
|
||||
checkReturn(rc);
|
||||
}
|
||||
|
||||
|
||||
#ifndef POCO_LONG_IS_64_BIT
|
||||
void Binder::bind(std::size_t pos, const long &val, Direction dir)
|
||||
{
|
||||
long tmp = static_cast<long>(val);
|
||||
int rc = sqlite3_bind_int(_pStmt, (int) pos, tmp);
|
||||
checkReturn(rc);
|
||||
}
|
||||
|
||||
void Binder::bind(std::size_t pos, const unsigned long &val, Direction dir)
|
||||
{
|
||||
long tmp = static_cast<long>(val);
|
||||
int rc = sqlite3_bind_int(_pStmt, (int) pos, tmp);
|
||||
checkReturn(rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const double &val, Direction dir)
|
||||
{
|
||||
int rc = sqlite3_bind_double(_pStmt, (int) pos, val);
|
||||
checkReturn(rc);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const std::string& val, Direction dir)
|
||||
{
|
||||
int rc = sqlite3_bind_text(_pStmt, (int) pos, val.c_str(), (int) val.size()*sizeof(char), SQLITE_TRANSIENT);
|
||||
checkReturn(rc);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const Date& val, Direction dir)
|
||||
{
|
||||
DateTime dt(val.year(), val.month(), val.day());
|
||||
std::string str(DateTimeFormatter::format(dt, Utility::SQLITE_DATE_FORMAT));
|
||||
bind(pos, str, dir);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const Time& val, Direction dir)
|
||||
{
|
||||
DateTime dt;
|
||||
dt.assign(dt.year(), dt.month(), dt.day(), val.hour(), val.minute(), val.second());
|
||||
std::string str(DateTimeFormatter::format(dt, Utility::SQLITE_TIME_FORMAT));
|
||||
bind(pos, str, dir);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const DateTime& val, Direction dir)
|
||||
{
|
||||
std::string dt(DateTimeFormatter::format(val, DateTimeFormat::ISO8601_FORMAT));
|
||||
bind(pos, dt, dir);
|
||||
}
|
||||
|
||||
|
||||
void Binder::bind(std::size_t pos, const NullData&, Direction)
|
||||
{
|
||||
sqlite3_bind_null(_pStmt, pos);
|
||||
}
|
||||
|
||||
|
||||
void Binder::checkReturn(int rc)
|
||||
{
|
||||
if (rc != SQLITE_OK)
|
||||
Utility::throwException(rc);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
@ -1,79 +0,0 @@
|
||||
//
|
||||
// Connector.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/src/Connector.cpp#2 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: Connector
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/Connector.h"
|
||||
#include "Poco/Data/SQLite/SessionImpl.h"
|
||||
#include "Poco/Data/SessionFactory.h"
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <sqlite3.h>
|
||||
#else
|
||||
#include "sqlite3.h"
|
||||
#endif
|
||||
|
||||
|
||||
const SQLiteConnectorRegistrator pocoSQLiteConnectorRegistrator;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
const std::string Connector::KEY(POCO_DATA_SQLITE_CONNECTOR_NAME);
|
||||
|
||||
|
||||
Connector::Connector()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Connector::~Connector()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Poco::AutoPtr<Poco::Data::SessionImpl> Connector::createSession(const std::string& connectionString,
|
||||
std::size_t timeout)
|
||||
{
|
||||
return Poco::AutoPtr<Poco::Data::SessionImpl>(new SessionImpl(connectionString, timeout));
|
||||
}
|
||||
|
||||
|
||||
void Connector::registerConnector()
|
||||
{
|
||||
Poco::Data::SessionFactory::instance().add(new Connector());
|
||||
}
|
||||
|
||||
|
||||
void Connector::unregisterConnector()
|
||||
{
|
||||
Poco::Data::SessionFactory::instance().remove(POCO_DATA_SQLITE_CONNECTOR_NAME);
|
||||
}
|
||||
|
||||
|
||||
void Connector::enableSharedCache(bool flag)
|
||||
{
|
||||
sqlite3_enable_shared_cache(flag ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
void Connector::enableSoftHeapLimit(int limit)
|
||||
{
|
||||
sqlite3_soft_heap_limit(limit);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
@ -1,240 +0,0 @@
|
||||
//
|
||||
// Extractor.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/src/Extractor.cpp#5 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: Extractor
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/Extractor.h"
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/Date.h"
|
||||
#include "Poco/Data/Time.h"
|
||||
#include "Poco/Data/LOB.h"
|
||||
#include "Poco/Data/DataException.h"
|
||||
#include "Poco/DateTimeParser.h"
|
||||
#include "Poco/Exception.h"
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <sqlite3.h>
|
||||
#else
|
||||
#include "sqlite3.h"
|
||||
#endif
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
using Poco::DateTimeParser;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
Extractor::Extractor(sqlite3_stmt* pStmt):
|
||||
_pStmt(pStmt)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::Int64& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int64(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifndef POCO_LONG_IS_64_BIT
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, std::string& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
const char *pBuf = reinterpret_cast<const char*>(sqlite3_column_text(_pStmt, (int) pos));
|
||||
if (!pBuf)
|
||||
val.clear();
|
||||
else
|
||||
val.assign(pBuf);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::Int8& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::UInt8& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::Int16& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::UInt16& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::UInt32& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::UInt64& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int64(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, bool& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = (0 != sqlite3_column_int(_pStmt, (int) pos));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, float& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = static_cast<float>(sqlite3_column_double(_pStmt, (int) pos));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, char& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
val = sqlite3_column_int(_pStmt, (int) pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Date& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
std::string str;
|
||||
extract(pos, str);
|
||||
int tzd;
|
||||
DateTime dt = DateTimeParser::parse(Utility::SQLITE_DATE_FORMAT, str, tzd);
|
||||
val = dt;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Time& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
std::string str;
|
||||
extract(pos, str);
|
||||
int tzd;
|
||||
DateTime dt = DateTimeParser::parse(Utility::SQLITE_TIME_FORMAT, str, tzd);
|
||||
val = dt;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, DateTime& val)
|
||||
{
|
||||
if (isNull(pos)) return false;
|
||||
std::string dt;
|
||||
extract(pos, dt);
|
||||
int tzd;
|
||||
DateTimeParser::parse(dt, val, tzd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::Any& val)
|
||||
{
|
||||
return extractImpl(pos, val);
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::extract(std::size_t pos, Poco::DynamicAny& val)
|
||||
{
|
||||
return extractImpl(pos, val);
|
||||
}
|
||||
|
||||
|
||||
bool Extractor::isNull(std::size_t pos, std::size_t)
|
||||
{
|
||||
if (pos >= _nulls.size())
|
||||
_nulls.resize(pos + 1);
|
||||
|
||||
if (!_nulls[pos].first)
|
||||
{
|
||||
_nulls[pos].first = true;
|
||||
_nulls[pos].second = (SQLITE_NULL == sqlite3_column_type(_pStmt, pos));
|
||||
}
|
||||
|
||||
return _nulls[pos].second;
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
@ -1,201 +0,0 @@
|
||||
//
|
||||
// Notifier.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/src/Notifier.cpp#5 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: Notifier
|
||||
//
|
||||
// Implementation of Notifier
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/Notifier.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
Notifier::Notifier(const Session& session, EnabledEventType enabled):
|
||||
_session(session)
|
||||
{
|
||||
if (enabled & SQLITE_NOTIFY_UPDATE) enableUpdate();
|
||||
if (enabled & SQLITE_NOTIFY_COMMIT) enableCommit();
|
||||
if (enabled & SQLITE_NOTIFY_ROLLBACK) enableRollback();
|
||||
}
|
||||
|
||||
|
||||
Notifier::Notifier(const Session& session, const Any& value, EnabledEventType enabled):
|
||||
_session(session),
|
||||
_value(value)
|
||||
{
|
||||
if (enabled & SQLITE_NOTIFY_UPDATE) enableUpdate();
|
||||
if (enabled & SQLITE_NOTIFY_COMMIT) enableCommit();
|
||||
if (enabled & SQLITE_NOTIFY_ROLLBACK) enableRollback();
|
||||
}
|
||||
|
||||
|
||||
Notifier::~Notifier()
|
||||
{
|
||||
try
|
||||
{
|
||||
disableAll();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
poco_unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::enableUpdate()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
|
||||
if (Utility::registerUpdateHandler(Utility::dbHandle(_session), &sqliteUpdateCallbackFn, this))
|
||||
_enabledEvents |= SQLITE_NOTIFY_UPDATE;
|
||||
|
||||
return updateEnabled();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::disableUpdate()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
|
||||
if (Utility::registerUpdateHandler(Utility::dbHandle(_session), (Utility::UpdateCallbackType) 0, this))
|
||||
_enabledEvents &= ~SQLITE_NOTIFY_UPDATE;
|
||||
|
||||
return !updateEnabled();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::updateEnabled() const
|
||||
{
|
||||
return 0 != (_enabledEvents & SQLITE_NOTIFY_UPDATE);
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::enableCommit()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
|
||||
if (Utility::registerUpdateHandler(Utility::dbHandle(_session), &sqliteCommitCallbackFn, this))
|
||||
_enabledEvents |= SQLITE_NOTIFY_COMMIT;
|
||||
|
||||
return commitEnabled();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::disableCommit()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
|
||||
if (Utility::registerUpdateHandler(Utility::dbHandle(_session), (Utility::CommitCallbackType) 0, this))
|
||||
_enabledEvents &= ~SQLITE_NOTIFY_COMMIT;
|
||||
|
||||
return !commitEnabled();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::commitEnabled() const
|
||||
{
|
||||
return 0 != (_enabledEvents & SQLITE_NOTIFY_COMMIT);
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::enableRollback()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
|
||||
if (Utility::registerUpdateHandler(Utility::dbHandle(_session), &sqliteRollbackCallbackFn, this))
|
||||
_enabledEvents |= SQLITE_NOTIFY_ROLLBACK;
|
||||
|
||||
return rollbackEnabled();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::disableRollback()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
|
||||
if (Utility::registerUpdateHandler(Utility::dbHandle(_session), (Utility::RollbackCallbackType) 0, this))
|
||||
_enabledEvents &= ~SQLITE_NOTIFY_ROLLBACK;
|
||||
|
||||
return !rollbackEnabled();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::rollbackEnabled() const
|
||||
{
|
||||
return 0 != (_enabledEvents & SQLITE_NOTIFY_ROLLBACK);
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::enableAll()
|
||||
{
|
||||
return enableUpdate() && enableCommit() && enableRollback();
|
||||
}
|
||||
|
||||
|
||||
bool Notifier::disableAll()
|
||||
{
|
||||
return disableUpdate() && disableCommit() && disableRollback();
|
||||
}
|
||||
|
||||
|
||||
void Notifier::sqliteUpdateCallbackFn(void* pVal, int opCode, const char* pDB, const char* pTable, Poco::Int64 row)
|
||||
{
|
||||
poco_check_ptr(pVal);
|
||||
Notifier* pV = reinterpret_cast<Notifier*>(pVal);
|
||||
if (opCode == Utility::OPERATION_INSERT)
|
||||
{
|
||||
pV->_row = row;
|
||||
pV->insert.notify(pV);
|
||||
}
|
||||
else if (opCode == Utility::OPERATION_UPDATE)
|
||||
{
|
||||
pV->_row = row;
|
||||
pV->update.notify(pV);
|
||||
}
|
||||
else if (opCode == Utility::OPERATION_DELETE)
|
||||
{
|
||||
pV->_row = row;
|
||||
pV->erase.notify(pV);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Notifier::sqliteCommitCallbackFn(void* pVal)
|
||||
{
|
||||
Notifier* pV = reinterpret_cast<Notifier*>(pVal);
|
||||
|
||||
try
|
||||
{
|
||||
pV->commit.notify(pV);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Notifier::sqliteRollbackCallbackFn(void* pVal)
|
||||
{
|
||||
Notifier* pV = reinterpret_cast<Notifier*>(pVal);
|
||||
pV->rollback.notify(pV);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
@ -1,53 +0,0 @@
|
||||
//
|
||||
// SQLiteException.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/src/SQLiteException.cpp#2 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: SQLiteException
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||
#include <typeinfo>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
POCO_IMPLEMENT_EXCEPTION(SQLiteException, Poco::Data::DataException, "Generic SQLite error")
|
||||
POCO_IMPLEMENT_EXCEPTION(InvalidSQLStatementException, SQLiteException, "SQL Statement invalid")
|
||||
POCO_IMPLEMENT_EXCEPTION(InternalDBErrorException, SQLiteException, "Internal error")
|
||||
POCO_IMPLEMENT_EXCEPTION(DBAccessDeniedException, SQLiteException, "Access permission denied")
|
||||
POCO_IMPLEMENT_EXCEPTION(ExecutionAbortedException, SQLiteException, "Execution of SQL statement aborted")
|
||||
POCO_IMPLEMENT_EXCEPTION(DBLockedException, SQLiteException, "The database is locked")
|
||||
POCO_IMPLEMENT_EXCEPTION(TableLockedException, SQLiteException, "A table in the database is locked")
|
||||
POCO_IMPLEMENT_EXCEPTION(NoMemoryException, SQLiteException, "Out of Memory")
|
||||
POCO_IMPLEMENT_EXCEPTION(ReadOnlyException, SQLiteException, "Attempt to write a readonly database")
|
||||
POCO_IMPLEMENT_EXCEPTION(InterruptException, SQLiteException, "Operation terminated by an interrupt")
|
||||
POCO_IMPLEMENT_EXCEPTION(IOErrorException, SQLiteException, "Some kind of disk I/O error occurred")
|
||||
POCO_IMPLEMENT_EXCEPTION(CorruptImageException, SQLiteException, "The database disk image is malformed")
|
||||
POCO_IMPLEMENT_EXCEPTION(TableNotFoundException, SQLiteException, "Table not found")
|
||||
POCO_IMPLEMENT_EXCEPTION(DatabaseFullException, SQLiteException, "Insertion failed because database is full")
|
||||
POCO_IMPLEMENT_EXCEPTION(CantOpenDBFileException, SQLiteException, "Unable to open the database file")
|
||||
POCO_IMPLEMENT_EXCEPTION(LockProtocolException, SQLiteException, "Database lock protocol error")
|
||||
POCO_IMPLEMENT_EXCEPTION(SchemaDiffersException, SQLiteException, "The database schema changed")
|
||||
POCO_IMPLEMENT_EXCEPTION(RowTooBigException, SQLiteException, "Too much data for one row of a table")
|
||||
POCO_IMPLEMENT_EXCEPTION(ConstraintViolationException, SQLiteException, "Abort due to constraint violation")
|
||||
POCO_IMPLEMENT_EXCEPTION(DataTypeMismatchException, SQLiteException, "Data type mismatch")
|
||||
POCO_IMPLEMENT_EXCEPTION(ParameterCountMismatchException, SQLiteException, "Parameter count mismatch")
|
||||
POCO_IMPLEMENT_EXCEPTION(InvalidLibraryUseException, SQLiteException, "Library used incorrectly")
|
||||
POCO_IMPLEMENT_EXCEPTION(OSFeaturesMissingException, SQLiteException, "Uses OS features not supported on host")
|
||||
POCO_IMPLEMENT_EXCEPTION(AuthorizationDeniedException, SQLiteException, "Authorization denied")
|
||||
POCO_IMPLEMENT_EXCEPTION(TransactionException, SQLiteException, "Transaction exception")
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
@ -1,312 +0,0 @@
|
||||
//
|
||||
// SQLiteStatementImpl.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/src/SQLiteStatementImpl.cpp#8 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: SQLiteStatementImpl
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLiteStatementImpl.h"
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||
#include "Poco/String.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <sqlite3.h>
|
||||
#else
|
||||
#include "sqlite3.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
const int SQLiteStatementImpl::POCO_SQLITE_INV_ROW_CNT = -1;
|
||||
|
||||
|
||||
SQLiteStatementImpl::SQLiteStatementImpl(Poco::Data::SessionImpl& rSession, sqlite3* pDB):
|
||||
StatementImpl(rSession),
|
||||
_pDB(pDB),
|
||||
_pStmt(0),
|
||||
_stepCalled(false),
|
||||
_nextResponse(0),
|
||||
_affectedRowCount(POCO_SQLITE_INV_ROW_CNT),
|
||||
_canBind(false),
|
||||
_isExtracted(false),
|
||||
_canCompile(true)
|
||||
{
|
||||
_columns.resize(1);
|
||||
}
|
||||
|
||||
|
||||
SQLiteStatementImpl::~SQLiteStatementImpl()
|
||||
{
|
||||
try
|
||||
{
|
||||
clear();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
poco_unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SQLiteStatementImpl::compileImpl()
|
||||
{
|
||||
if (!_pLeftover)
|
||||
{
|
||||
_bindBegin = bindings().begin();
|
||||
}
|
||||
|
||||
std::string statement(toString());
|
||||
|
||||
sqlite3_stmt* pStmt = 0;
|
||||
const char* pSql = _pLeftover ? _pLeftover->c_str() : statement.c_str();
|
||||
|
||||
if (0 == std::strlen(pSql))
|
||||
throw InvalidSQLStatementException("Empty statements are illegal");
|
||||
|
||||
int rc = SQLITE_OK;
|
||||
const char* pLeftover = 0;
|
||||
bool queryFound = false;
|
||||
|
||||
do
|
||||
{
|
||||
rc = sqlite3_prepare_v2(_pDB, pSql, -1, &pStmt, &pLeftover);
|
||||
if (rc != SQLITE_OK)
|
||||
{
|
||||
if (pStmt) sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
std::string errMsg = sqlite3_errmsg(_pDB);
|
||||
Utility::throwException(rc, errMsg);
|
||||
}
|
||||
else if (rc == SQLITE_OK && pStmt)
|
||||
{
|
||||
queryFound = true;
|
||||
}
|
||||
else if (rc == SQLITE_OK && !pStmt) // comment/whitespace ignore
|
||||
{
|
||||
pSql = pLeftover;
|
||||
if (std::strlen(pSql) == 0)
|
||||
{
|
||||
// empty statement or an conditional statement! like CREATE IF NOT EXISTS
|
||||
// this is valid
|
||||
queryFound = true;
|
||||
}
|
||||
}
|
||||
} while (rc == SQLITE_OK && !pStmt && !queryFound);
|
||||
|
||||
//Finalization call in clear() invalidates the pointer, so the value is remembered here.
|
||||
//For last statement in a batch (or a single statement), pLeftover == "", so the next call
|
||||
// to compileImpl() shall return false immediately when there are no more statements left.
|
||||
std::string leftOver(pLeftover);
|
||||
trimInPlace(leftOver);
|
||||
clear();
|
||||
_pStmt = pStmt;
|
||||
if (!leftOver.empty())
|
||||
{
|
||||
_pLeftover = new std::string(leftOver);
|
||||
_canCompile = true;
|
||||
}
|
||||
else _canCompile = false;
|
||||
|
||||
_pBinder = new Binder(_pStmt);
|
||||
_pExtractor = new Extractor(_pStmt);
|
||||
|
||||
if (SQLITE_DONE == _nextResponse && _isExtracted)
|
||||
{
|
||||
//if this is not the first compile and there has already been extraction
|
||||
//during previous step, switch to the next set if there is one provided
|
||||
if (hasMoreDataSets())
|
||||
{
|
||||
activateNextDataSet();
|
||||
_isExtracted = false;
|
||||
}
|
||||
}
|
||||
|
||||
int colCount = sqlite3_column_count(_pStmt);
|
||||
|
||||
if (colCount)
|
||||
{
|
||||
std::size_t curDataSet = currentDataSet();
|
||||
if (curDataSet >= _columns.size()) _columns.resize(curDataSet + 1);
|
||||
for (int i = 0; i < colCount; ++i)
|
||||
{
|
||||
MetaColumn mc(i, sqlite3_column_name(_pStmt, i), Utility::getColumnType(_pStmt, i));
|
||||
_columns[curDataSet].push_back(mc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SQLiteStatementImpl::bindImpl()
|
||||
{
|
||||
_stepCalled = false;
|
||||
_nextResponse = 0;
|
||||
if (_pStmt == 0) return;
|
||||
|
||||
sqlite3_reset(_pStmt);
|
||||
|
||||
int paramCount = sqlite3_bind_parameter_count(_pStmt);
|
||||
BindIt bindEnd = bindings().end();
|
||||
if (0 == paramCount || bindEnd == _bindBegin)
|
||||
{
|
||||
_canBind = false;
|
||||
return;
|
||||
}
|
||||
|
||||
std::size_t availableCount = 0;
|
||||
Bindings::difference_type bindCount = 0;
|
||||
Bindings::iterator it = _bindBegin;
|
||||
for (; it != bindEnd; ++it)
|
||||
{
|
||||
availableCount += (*it)->numOfColumnsHandled();
|
||||
if (availableCount <= (size_t)paramCount) ++bindCount;
|
||||
else break;
|
||||
}
|
||||
|
||||
Bindings::difference_type remainingBindCount = bindEnd - _bindBegin;
|
||||
if (bindCount < remainingBindCount)
|
||||
{
|
||||
bindEnd = _bindBegin + bindCount;
|
||||
_canBind = true;
|
||||
}
|
||||
else if (bindCount > remainingBindCount)
|
||||
throw ParameterCountMismatchException();
|
||||
|
||||
std::size_t boundRowCount;
|
||||
if (_bindBegin != bindings().end())
|
||||
{
|
||||
boundRowCount = (*_bindBegin)->numOfRowsHandled();
|
||||
|
||||
Bindings::iterator oldBegin = _bindBegin;
|
||||
for (std::size_t pos = 1; _bindBegin != bindEnd && (*_bindBegin)->canBind(); ++_bindBegin)
|
||||
{
|
||||
if (boundRowCount != (*_bindBegin)->numOfRowsHandled())
|
||||
throw BindingException("Size mismatch in Bindings. All Bindings MUST have the same size");
|
||||
|
||||
(*_bindBegin)->bind(pos);
|
||||
pos += (*_bindBegin)->numOfColumnsHandled();
|
||||
}
|
||||
|
||||
if ((*oldBegin)->canBind())
|
||||
{
|
||||
//container binding will come back for more, so we must rewind
|
||||
_bindBegin = oldBegin;
|
||||
_canBind = true;
|
||||
}
|
||||
else _canBind = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SQLiteStatementImpl::clear()
|
||||
{
|
||||
_columns[currentDataSet()].clear();
|
||||
_affectedRowCount = POCO_SQLITE_INV_ROW_CNT;
|
||||
|
||||
if (_pStmt)
|
||||
{
|
||||
sqlite3_finalize(_pStmt);
|
||||
_pStmt=0;
|
||||
}
|
||||
_pLeftover = 0;
|
||||
}
|
||||
|
||||
|
||||
bool SQLiteStatementImpl::hasNext()
|
||||
{
|
||||
if (_stepCalled)
|
||||
return (_nextResponse == SQLITE_ROW);
|
||||
|
||||
// _pStmt is allowed to be null for conditional SQL statements
|
||||
if (_pStmt == 0)
|
||||
{
|
||||
_stepCalled = true;
|
||||
_nextResponse = SQLITE_DONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_stepCalled = true;
|
||||
_nextResponse = sqlite3_step(_pStmt);
|
||||
|
||||
if (_affectedRowCount == POCO_SQLITE_INV_ROW_CNT) _affectedRowCount = 0;
|
||||
if (!sqlite3_stmt_readonly(_pStmt))
|
||||
_affectedRowCount += sqlite3_changes(_pDB);
|
||||
|
||||
if (_nextResponse != SQLITE_ROW && _nextResponse != SQLITE_OK && _nextResponse != SQLITE_DONE)
|
||||
Utility::throwException(_nextResponse);
|
||||
|
||||
_pExtractor->reset();//clear the cached null indicators
|
||||
|
||||
return (_nextResponse == SQLITE_ROW);
|
||||
}
|
||||
|
||||
|
||||
std::size_t SQLiteStatementImpl::next()
|
||||
{
|
||||
if (SQLITE_ROW == _nextResponse)
|
||||
{
|
||||
poco_assert (columnsReturned() == (size_t)sqlite3_column_count(_pStmt));
|
||||
|
||||
Extractions& extracts = extractions();
|
||||
Extractions::iterator it = extracts.begin();
|
||||
Extractions::iterator itEnd = extracts.end();
|
||||
std::size_t pos = 0; // sqlite starts with pos 0 for results!
|
||||
for (; it != itEnd; ++it)
|
||||
{
|
||||
(*it)->extract(pos);
|
||||
pos += (*it)->numOfColumnsHandled();
|
||||
_isExtracted = true;
|
||||
}
|
||||
_stepCalled = false;
|
||||
if (_affectedRowCount == POCO_SQLITE_INV_ROW_CNT) _affectedRowCount = 0;
|
||||
_affectedRowCount += (*extracts.begin())->numOfRowsHandled();
|
||||
}
|
||||
else if (SQLITE_DONE == _nextResponse)
|
||||
{
|
||||
throw Poco::Data::DataException("No data received");
|
||||
}
|
||||
else
|
||||
{
|
||||
Utility::throwException(_nextResponse, std::string("Iterator Error: trying to access the next value"));
|
||||
}
|
||||
|
||||
return 1u;
|
||||
}
|
||||
|
||||
|
||||
std::size_t SQLiteStatementImpl::columnsReturned() const
|
||||
{
|
||||
return (std::size_t) _columns[currentDataSet()].size();
|
||||
}
|
||||
|
||||
|
||||
const MetaColumn& SQLiteStatementImpl::metaColumn(std::size_t pos) const
|
||||
{
|
||||
std::size_t curDataSet = currentDataSet();
|
||||
poco_assert (pos >= 0 && pos <= _columns[curDataSet].size());
|
||||
return _columns[curDataSet][pos];
|
||||
}
|
||||
|
||||
|
||||
int SQLiteStatementImpl::affectedRowCount() const
|
||||
{
|
||||
if (_affectedRowCount != POCO_SQLITE_INV_ROW_CNT) return _affectedRowCount;
|
||||
return _pStmt == 0 || sqlite3_stmt_readonly(_pStmt) ? 0 : sqlite3_changes(_pDB);
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
@ -1,272 +0,0 @@
|
||||
//
|
||||
// SessionImpl.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/src/SessionImpl.cpp#5 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: SessionImpl
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SessionImpl.h"
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/SQLite/SQLiteStatementImpl.h"
|
||||
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||
#include "Poco/Data/Session.h"
|
||||
#include "Poco/ActiveMethod.h"
|
||||
#include "Poco/ActiveResult.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Mutex.h"
|
||||
#include "Poco/Data/DataException.h"
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <sqlite3.h>
|
||||
#else
|
||||
#include "sqlite3.h"
|
||||
#endif
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
#ifndef SQLITE_OPEN_URI
|
||||
#define SQLITE_OPEN_URI 0
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
const std::string SessionImpl::DEFERRED_BEGIN_TRANSACTION("BEGIN DEFERRED");
|
||||
const std::string SessionImpl::COMMIT_TRANSACTION("COMMIT");
|
||||
const std::string SessionImpl::ABORT_TRANSACTION("ROLLBACK");
|
||||
|
||||
|
||||
SessionImpl::SessionImpl(const std::string& fileName, std::size_t loginTimeout):
|
||||
Poco::Data::AbstractSessionImpl<SessionImpl>(fileName, loginTimeout),
|
||||
_connector(Connector::KEY),
|
||||
_pDB(0),
|
||||
_connected(false),
|
||||
_isTransaction(false)
|
||||
{
|
||||
open();
|
||||
setConnectionTimeout(CONNECTION_TIMEOUT_DEFAULT);
|
||||
setProperty("handle", _pDB);
|
||||
addFeature("autoCommit",
|
||||
&SessionImpl::autoCommit,
|
||||
&SessionImpl::isAutoCommit);
|
||||
addProperty("connectionTimeout", &SessionImpl::setConnectionTimeout, &SessionImpl::getConnectionTimeout);
|
||||
}
|
||||
|
||||
|
||||
SessionImpl::~SessionImpl()
|
||||
{
|
||||
try
|
||||
{
|
||||
close();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
poco_unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Poco::Data::StatementImpl* SessionImpl::createStatementImpl()
|
||||
{
|
||||
poco_check_ptr (_pDB);
|
||||
return new SQLiteStatementImpl(*this, _pDB);
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::begin()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
SQLiteStatementImpl tmp(*this, _pDB);
|
||||
tmp.add(DEFERRED_BEGIN_TRANSACTION);
|
||||
tmp.execute();
|
||||
_isTransaction = true;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::commit()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
SQLiteStatementImpl tmp(*this, _pDB);
|
||||
tmp.add(COMMIT_TRANSACTION);
|
||||
tmp.execute();
|
||||
_isTransaction = false;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::rollback()
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
SQLiteStatementImpl tmp(*this, _pDB);
|
||||
tmp.add(ABORT_TRANSACTION);
|
||||
tmp.execute();
|
||||
_isTransaction = false;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::setTransactionIsolation(Poco::UInt32 ti)
|
||||
{
|
||||
if (ti != Session::TRANSACTION_READ_COMMITTED)
|
||||
throw Poco::InvalidArgumentException("setTransactionIsolation()");
|
||||
}
|
||||
|
||||
|
||||
Poco::UInt32 SessionImpl::getTransactionIsolation()
|
||||
{
|
||||
return Session::TRANSACTION_READ_COMMITTED;
|
||||
}
|
||||
|
||||
|
||||
bool SessionImpl::hasTransactionIsolation(Poco::UInt32 ti)
|
||||
{
|
||||
if (ti == Session::TRANSACTION_READ_COMMITTED) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SessionImpl::isTransactionIsolation(Poco::UInt32 ti)
|
||||
{
|
||||
if (ti == Session::TRANSACTION_READ_COMMITTED) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
class ActiveConnector
|
||||
{
|
||||
public:
|
||||
ActiveConnector(const std::string& connectString, sqlite3** ppDB):
|
||||
connect(this, &ActiveConnector::connectImpl),
|
||||
_connectString(connectString),
|
||||
_ppDB(ppDB)
|
||||
{
|
||||
poco_check_ptr(_ppDB);
|
||||
}
|
||||
|
||||
ActiveMethod<int, void, ActiveConnector> connect;
|
||||
|
||||
private:
|
||||
ActiveConnector();
|
||||
|
||||
inline int connectImpl()
|
||||
{
|
||||
return sqlite3_open_v2(_connectString.c_str(), _ppDB, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, NULL);
|
||||
}
|
||||
|
||||
std::string _connectString;
|
||||
sqlite3** _ppDB;
|
||||
};
|
||||
|
||||
|
||||
void SessionImpl::open(const std::string& connect)
|
||||
{
|
||||
if (connect != connectionString())
|
||||
{
|
||||
if (isConnected())
|
||||
throw InvalidAccessException("Session already connected");
|
||||
|
||||
if (!connect.empty())
|
||||
setConnectionString(connect);
|
||||
}
|
||||
|
||||
poco_assert_dbg (!connectionString().empty());
|
||||
|
||||
try
|
||||
{
|
||||
ActiveConnector connector(connectionString(), &_pDB);
|
||||
ActiveResult<int> result = connector.connect();
|
||||
if (!result.tryWait(getLoginTimeout() * 1000))
|
||||
throw ConnectionFailedException("Timed out.");
|
||||
|
||||
int rc = result.data();
|
||||
if (rc != 0)
|
||||
{
|
||||
close();
|
||||
Utility::throwException(rc);
|
||||
}
|
||||
}
|
||||
catch (SQLiteException& ex)
|
||||
{
|
||||
throw ConnectionFailedException(ex.displayText());
|
||||
}
|
||||
|
||||
_connected = true;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::close()
|
||||
{
|
||||
if (_pDB)
|
||||
{
|
||||
sqlite3_close(_pDB);
|
||||
_pDB = 0;
|
||||
}
|
||||
|
||||
_connected = false;
|
||||
}
|
||||
|
||||
|
||||
bool SessionImpl::isConnected()
|
||||
{
|
||||
return _connected;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::setConnectionTimeout(std::size_t timeout)
|
||||
{
|
||||
int tout = 1000 * timeout;
|
||||
int rc = sqlite3_busy_timeout(_pDB, tout);
|
||||
if (rc != 0) Utility::throwException(rc);
|
||||
_timeout = tout;
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::setConnectionTimeout(const std::string& prop, const Poco::Any& value)
|
||||
{
|
||||
setConnectionTimeout(Poco::RefAnyCast<std::size_t>(value));
|
||||
}
|
||||
|
||||
|
||||
Poco::Any SessionImpl::getConnectionTimeout(const std::string& prop)
|
||||
{
|
||||
return Poco::Any(_timeout/1000);
|
||||
}
|
||||
|
||||
|
||||
void SessionImpl::autoCommit(const std::string&, bool)
|
||||
{
|
||||
// The problem here is to decide whether to call commit or rollback
|
||||
// when autocommit is set to true. Hence, it is best not to implement
|
||||
// this explicit call and only implicitly support autocommit setting.
|
||||
throw NotImplementedException(
|
||||
"SQLite autocommit is implicit with begin/commit/rollback.");
|
||||
}
|
||||
|
||||
|
||||
bool SessionImpl::isAutoCommit(const std::string&)
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(_mutex);
|
||||
return (0 != sqlite3_get_autocommit(_pDB));
|
||||
}
|
||||
|
||||
|
||||
// NOTE: Utility::dbHandle() has been moved here from Utility.cpp
|
||||
// as a workaround for a failing AnyCast with Clang.
|
||||
// See <https://github.com/pocoproject/poco/issues/578>
|
||||
// for a discussion.
|
||||
sqlite3* Utility::dbHandle(const Session& session)
|
||||
{
|
||||
return AnyCast<sqlite3*>(session.getProperty("handle"));
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
@ -1,325 +0,0 @@
|
||||
//
|
||||
// Utility.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/src/Utility.cpp#5 $
|
||||
//
|
||||
// Library: SQLite
|
||||
// Package: SQLite
|
||||
// Module: Utility
|
||||
//
|
||||
// Implementation of Utility
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/Utility.h"
|
||||
#include "Poco/Data/SQLite/SQLiteException.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Any.h"
|
||||
#include "Poco/Exception.h"
|
||||
#if defined(POCO_UNBUNDLED)
|
||||
#include <sqlite3.h>
|
||||
#else
|
||||
#include "sqlite3.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SQLITE_OPEN_URI
|
||||
#define SQLITE_OPEN_URI 0
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
namespace SQLite {
|
||||
|
||||
|
||||
const int Utility::THREAD_MODE_SINGLE = SQLITE_CONFIG_SINGLETHREAD;
|
||||
const int Utility::THREAD_MODE_MULTI = SQLITE_CONFIG_MULTITHREAD;
|
||||
const int Utility::THREAD_MODE_SERIAL = SQLITE_CONFIG_SERIALIZED;
|
||||
int Utility::_threadMode =
|
||||
#if (SQLITE_THREADSAFE == 0)
|
||||
SQLITE_CONFIG_SINGLETHREAD;
|
||||
#elif (SQLITE_THREADSAFE == 1)
|
||||
SQLITE_CONFIG_SERIALIZED;
|
||||
#elif (SQLITE_THREADSAFE == 2)
|
||||
SQLITE_CONFIG_MULTITHREAD;
|
||||
#endif
|
||||
|
||||
const int Utility::OPERATION_INSERT = SQLITE_INSERT;
|
||||
const int Utility::OPERATION_DELETE = SQLITE_DELETE;
|
||||
const int Utility::OPERATION_UPDATE = SQLITE_UPDATE;
|
||||
|
||||
const std::string Utility::SQLITE_DATE_FORMAT = "%Y-%m-%d";
|
||||
const std::string Utility::SQLITE_TIME_FORMAT = "%H:%M:%S";
|
||||
Utility::TypeMap Utility::_types;
|
||||
Poco::Mutex Utility::_mutex;
|
||||
|
||||
|
||||
Utility::Utility()
|
||||
{
|
||||
if (_types.empty())
|
||||
{
|
||||
_types.insert(TypeMap::value_type("", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("BOOL", MetaColumn::FDT_BOOL));
|
||||
_types.insert(TypeMap::value_type("BOOLEAN", MetaColumn::FDT_BOOL));
|
||||
_types.insert(TypeMap::value_type("BIT", MetaColumn::FDT_BOOL));
|
||||
_types.insert(TypeMap::value_type("UINT8", MetaColumn::FDT_UINT8));
|
||||
_types.insert(TypeMap::value_type("UTINY", MetaColumn::FDT_UINT8));
|
||||
_types.insert(TypeMap::value_type("UINTEGER8", MetaColumn::FDT_UINT8));
|
||||
_types.insert(TypeMap::value_type("INT8", MetaColumn::FDT_INT8));
|
||||
_types.insert(TypeMap::value_type("TINY", MetaColumn::FDT_INT8));
|
||||
_types.insert(TypeMap::value_type("INTEGER8", MetaColumn::FDT_INT8));
|
||||
_types.insert(TypeMap::value_type("UINT16", MetaColumn::FDT_UINT16));
|
||||
_types.insert(TypeMap::value_type("USHORT", MetaColumn::FDT_UINT16));
|
||||
_types.insert(TypeMap::value_type("UINTEGER16", MetaColumn::FDT_UINT16));
|
||||
_types.insert(TypeMap::value_type("INT16", MetaColumn::FDT_INT16));
|
||||
_types.insert(TypeMap::value_type("SHORT", MetaColumn::FDT_INT16));
|
||||
_types.insert(TypeMap::value_type("INTEGER16", MetaColumn::FDT_INT16));
|
||||
_types.insert(TypeMap::value_type("UINT", MetaColumn::FDT_UINT32));
|
||||
_types.insert(TypeMap::value_type("UINT32", MetaColumn::FDT_UINT32));
|
||||
_types.insert(TypeMap::value_type("UINTEGER32", MetaColumn::FDT_UINT32));
|
||||
_types.insert(TypeMap::value_type("INT", MetaColumn::FDT_INT32));
|
||||
_types.insert(TypeMap::value_type("INT32", MetaColumn::FDT_INT32));
|
||||
_types.insert(TypeMap::value_type("INTEGER", MetaColumn::FDT_INT32));
|
||||
_types.insert(TypeMap::value_type("INTEGER32", MetaColumn::FDT_INT32));
|
||||
_types.insert(TypeMap::value_type("UINT64", MetaColumn::FDT_UINT64));
|
||||
_types.insert(TypeMap::value_type("ULONG", MetaColumn::FDT_INT64));
|
||||
_types.insert(TypeMap::value_type("UINTEGER64", MetaColumn::FDT_UINT64));
|
||||
_types.insert(TypeMap::value_type("INT64", MetaColumn::FDT_INT64));
|
||||
_types.insert(TypeMap::value_type("LONG", MetaColumn::FDT_INT64));
|
||||
_types.insert(TypeMap::value_type("INTEGER64", MetaColumn::FDT_INT64));
|
||||
_types.insert(TypeMap::value_type("TINYINT", MetaColumn::FDT_INT8));
|
||||
_types.insert(TypeMap::value_type("SMALLINT", MetaColumn::FDT_INT16));
|
||||
_types.insert(TypeMap::value_type("BIGINT", MetaColumn::FDT_INT64));
|
||||
_types.insert(TypeMap::value_type("COUNTER", MetaColumn::FDT_UINT64));
|
||||
_types.insert(TypeMap::value_type("AUTOINCREMENT", MetaColumn::FDT_UINT64));
|
||||
_types.insert(TypeMap::value_type("REAL", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("FLOA", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("FLOAT", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("DOUB", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("DOUBLE", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("DECIMAL", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("NUMERIC", MetaColumn::FDT_DOUBLE));
|
||||
_types.insert(TypeMap::value_type("CHAR", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("CLOB", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("TEXT", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("VARCHAR", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("NCHAR", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("NCLOB", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("NTEXT", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("NVARCHAR", MetaColumn::FDT_STRING));
|
||||
_types.insert(TypeMap::value_type("BLOB", MetaColumn::FDT_BLOB));
|
||||
_types.insert(TypeMap::value_type("DATE", MetaColumn::FDT_DATE));
|
||||
_types.insert(TypeMap::value_type("TIME", MetaColumn::FDT_TIME));
|
||||
_types.insert(TypeMap::value_type("DATETIME", MetaColumn::FDT_TIMESTAMP));
|
||||
_types.insert(TypeMap::value_type("TIMESTAMP", MetaColumn::FDT_TIMESTAMP));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string Utility::lastError(sqlite3* pDB)
|
||||
{
|
||||
return std::string(sqlite3_errmsg(pDB));
|
||||
}
|
||||
|
||||
|
||||
MetaColumn::ColumnDataType Utility::getColumnType(sqlite3_stmt* pStmt, std::size_t pos)
|
||||
{
|
||||
poco_assert_dbg (pStmt);
|
||||
|
||||
// Ensure statics are initialized
|
||||
{
|
||||
Poco::Mutex::ScopedLock lock(_mutex);
|
||||
static Utility u;
|
||||
}
|
||||
|
||||
const char* pc = sqlite3_column_decltype(pStmt, (int) pos);
|
||||
std::string sqliteType = pc ? pc : "";
|
||||
Poco::toUpperInPlace(sqliteType);
|
||||
sqliteType = sqliteType.substr(0, sqliteType.find_first_of(" ("));
|
||||
|
||||
TypeMap::const_iterator it = _types.find(Poco::trimInPlace(sqliteType));
|
||||
if (_types.end() == it) throw Poco::NotFoundException();
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
|
||||
void Utility::throwException(int rc, const std::string& addErrMsg)
|
||||
{
|
||||
switch (rc)
|
||||
{
|
||||
case SQLITE_OK:
|
||||
break;
|
||||
case SQLITE_ERROR:
|
||||
throw InvalidSQLStatementException(std::string("SQL error or missing database"), addErrMsg);
|
||||
case SQLITE_INTERNAL:
|
||||
throw InternalDBErrorException(std::string("An internal logic error in SQLite"), addErrMsg);
|
||||
case SQLITE_PERM:
|
||||
throw DBAccessDeniedException(std::string("Access permission denied"), addErrMsg);
|
||||
case SQLITE_ABORT:
|
||||
throw ExecutionAbortedException(std::string("Callback routine requested an abort"), addErrMsg);
|
||||
case SQLITE_BUSY:
|
||||
case SQLITE_BUSY_RECOVERY:
|
||||
case SQLITE_BUSY_SNAPSHOT:
|
||||
throw DBLockedException(std::string("The database file is locked"), addErrMsg);
|
||||
case SQLITE_LOCKED:
|
||||
throw TableLockedException(std::string("A table in the database is locked"), addErrMsg);
|
||||
case SQLITE_NOMEM:
|
||||
throw NoMemoryException(std::string("A malloc() failed"), addErrMsg);
|
||||
case SQLITE_READONLY:
|
||||
throw ReadOnlyException(std::string("Attempt to write a readonly database"), addErrMsg);
|
||||
case SQLITE_INTERRUPT:
|
||||
throw InterruptException(std::string("Operation terminated by sqlite_interrupt()"), addErrMsg);
|
||||
case SQLITE_IOERR:
|
||||
throw IOErrorException(std::string("Some kind of disk I/O error occurred"), addErrMsg);
|
||||
case SQLITE_CORRUPT:
|
||||
throw CorruptImageException(std::string("The database disk image is malformed"), addErrMsg);
|
||||
case SQLITE_NOTFOUND:
|
||||
throw TableNotFoundException(std::string("Table or record not found"), addErrMsg);
|
||||
case SQLITE_FULL:
|
||||
throw DatabaseFullException(std::string("Insertion failed because database is full"), addErrMsg);
|
||||
case SQLITE_CANTOPEN:
|
||||
throw CantOpenDBFileException(std::string("Unable to open the database file"), addErrMsg);
|
||||
case SQLITE_PROTOCOL:
|
||||
throw LockProtocolException(std::string("Database lock protocol error"), addErrMsg);
|
||||
case SQLITE_EMPTY:
|
||||
throw InternalDBErrorException(std::string("(Internal Only) Database table is empty"), addErrMsg);
|
||||
case SQLITE_SCHEMA:
|
||||
throw SchemaDiffersException(std::string("The database schema changed"), addErrMsg);
|
||||
case SQLITE_TOOBIG:
|
||||
throw RowTooBigException(std::string("Too much data for one row of a table"), addErrMsg);
|
||||
case SQLITE_CONSTRAINT:
|
||||
throw ConstraintViolationException(std::string("Abort due to constraint violation"), addErrMsg);
|
||||
case SQLITE_MISMATCH:
|
||||
throw DataTypeMismatchException(std::string("Data type mismatch"), addErrMsg);
|
||||
case SQLITE_MISUSE:
|
||||
throw InvalidLibraryUseException(std::string("Library used incorrectly"), addErrMsg);
|
||||
case SQLITE_NOLFS:
|
||||
throw OSFeaturesMissingException(std::string("Uses OS features not supported on host"), addErrMsg);
|
||||
case SQLITE_AUTH:
|
||||
throw AuthorizationDeniedException(std::string("Authorization denied"), addErrMsg);
|
||||
case SQLITE_FORMAT:
|
||||
throw CorruptImageException(std::string("Auxiliary database format error"), addErrMsg);
|
||||
case SQLITE_NOTADB:
|
||||
throw CorruptImageException(std::string("File opened that is not a database file"), addErrMsg);
|
||||
case SQLITE_RANGE:
|
||||
throw InvalidSQLStatementException(std::string("Bind Parameter out of range (Access of invalid position 0? bind starts with 1!)"), addErrMsg);
|
||||
case SQLITE_ROW:
|
||||
break; // sqlite_step() has another row ready
|
||||
case SQLITE_DONE:
|
||||
break; // sqlite_step() has finished executing
|
||||
default:
|
||||
throw SQLiteException(std::string("Unknown error code: ") + Poco::NumberFormatter::format(rc), addErrMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Utility::fileToMemory(sqlite3* pInMemory, const std::string& fileName)
|
||||
{
|
||||
int rc;
|
||||
sqlite3* pFile;
|
||||
sqlite3_backup* pBackup;
|
||||
|
||||
rc = sqlite3_open_v2(fileName.c_str(), &pFile, SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, NULL);
|
||||
if(rc == SQLITE_OK )
|
||||
{
|
||||
pBackup = sqlite3_backup_init(pInMemory, "main", pFile, "main");
|
||||
if( pBackup )
|
||||
{
|
||||
sqlite3_backup_step(pBackup, -1);
|
||||
sqlite3_backup_finish(pBackup);
|
||||
}
|
||||
rc = sqlite3_errcode(pFile);
|
||||
}
|
||||
|
||||
sqlite3_close(pFile);
|
||||
return SQLITE_OK == rc;
|
||||
}
|
||||
|
||||
|
||||
bool Utility::memoryToFile(const std::string& fileName, sqlite3* pInMemory)
|
||||
{
|
||||
int rc;
|
||||
sqlite3* pFile;
|
||||
sqlite3_backup* pBackup;
|
||||
|
||||
rc = sqlite3_open_v2(fileName.c_str(), &pFile, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, NULL);
|
||||
if(rc == SQLITE_OK )
|
||||
{
|
||||
pBackup = sqlite3_backup_init(pFile, "main", pInMemory, "main");
|
||||
if( pBackup )
|
||||
{
|
||||
sqlite3_backup_step(pBackup, -1);
|
||||
sqlite3_backup_finish(pBackup);
|
||||
}
|
||||
rc = sqlite3_errcode(pFile);
|
||||
}
|
||||
|
||||
sqlite3_close(pFile);
|
||||
return SQLITE_OK == rc;
|
||||
}
|
||||
|
||||
|
||||
bool Utility::isThreadSafe()
|
||||
{
|
||||
return 0 != sqlite3_threadsafe();
|
||||
}
|
||||
|
||||
|
||||
int Utility::getThreadMode()
|
||||
{
|
||||
return _threadMode;
|
||||
}
|
||||
|
||||
|
||||
bool Utility::setThreadMode(int mode)
|
||||
{
|
||||
#if (SQLITE_THREADSAFE != 0)
|
||||
if (SQLITE_OK == sqlite3_shutdown())
|
||||
{
|
||||
if (SQLITE_OK == sqlite3_config(mode))
|
||||
{
|
||||
_threadMode = mode;
|
||||
if (SQLITE_OK == sqlite3_initialize())
|
||||
return true;
|
||||
}
|
||||
sqlite3_initialize();
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void* Utility::eventHookRegister(sqlite3* pDB, UpdateCallbackType callbackFn, void* pParam)
|
||||
{
|
||||
typedef void(*pF)(void*, int, const char*, const char*, sqlite3_int64);
|
||||
return sqlite3_update_hook(pDB, reinterpret_cast<pF>(callbackFn), pParam);
|
||||
}
|
||||
|
||||
|
||||
void* Utility::eventHookRegister(sqlite3* pDB, CommitCallbackType callbackFn, void* pParam)
|
||||
{
|
||||
return sqlite3_commit_hook(pDB, callbackFn, pParam);
|
||||
}
|
||||
|
||||
|
||||
void* Utility::eventHookRegister(sqlite3* pDB, RollbackCallbackType callbackFn, void* pParam)
|
||||
{
|
||||
return sqlite3_rollback_hook(pDB, callbackFn, pParam);
|
||||
}
|
||||
|
||||
|
||||
// NOTE: Utility::dbHandle() has been moved to SessionImpl.cpp,
|
||||
// as a workaround for a failing AnyCast with Clang.
|
||||
// See <https://github.com/pocoproject/poco/issues/578>
|
||||
// for a discussion.
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::SQLite
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,21 +0,0 @@
|
||||
set(TESTUNIT "${LIBNAME}-testrunner")
|
||||
|
||||
# Sources
|
||||
file(GLOB SRCS_G "src/*.cpp")
|
||||
POCO_SOURCES_AUTO( TEST_SRCS ${SRCS_G})
|
||||
|
||||
# Headers
|
||||
file(GLOB_RECURSE HDRS_G "src/*.h" )
|
||||
POCO_HEADERS_AUTO( TEST_SRCS ${HDRS_G})
|
||||
|
||||
POCO_SOURCES_AUTO_PLAT( TEST_SRCS OFF
|
||||
src/WinDriver.cpp
|
||||
)
|
||||
|
||||
POCO_SOURCES_AUTO_PLAT( TEST_SRCS WINCE
|
||||
src/WinCEDriver.cpp
|
||||
)
|
||||
|
||||
add_executable( ${TESTUNIT} ${TEST_SRCS} )
|
||||
add_test(NAME ${LIBNAME} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${TESTUNIT} -all)
|
||||
target_link_libraries( ${TESTUNIT} PocoDataSQLite PocoData PocoFoundation CppUnit )
|
@ -1,19 +0,0 @@
|
||||
//
|
||||
// Driver.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/testsuite/src/Driver.cpp#2 $
|
||||
//
|
||||
// Console-based test driver for Poco SQLite.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "CppUnit/TestRunner.h"
|
||||
#include "SQLiteTestSuite.h"
|
||||
|
||||
|
||||
CppUnitMain(SQLiteTestSuite)
|
File diff suppressed because it is too large
Load Diff
@ -1,165 +0,0 @@
|
||||
//
|
||||
// SQLiteTest.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/testsuite/src/SQLiteTest.h#4 $
|
||||
//
|
||||
// Definition of the SQLiteTest class.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef SQLiteTest_INCLUDED
|
||||
#define SQLiteTest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Data/SQLite/SQLite.h"
|
||||
#include "CppUnit/TestCase.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Data {
|
||||
|
||||
class Session;
|
||||
|
||||
} }
|
||||
|
||||
|
||||
class SQLiteTest: public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
SQLiteTest(const std::string& name);
|
||||
~SQLiteTest();
|
||||
|
||||
void testBinding();
|
||||
void testZeroRows();
|
||||
void testSimpleAccess();
|
||||
void testInMemory();
|
||||
void testNullCharPointer();
|
||||
void testInsertCharPointer();
|
||||
void testInsertCharPointer2();
|
||||
void testComplexType();
|
||||
void testSimpleAccessVector();
|
||||
void testComplexTypeVector();
|
||||
void testSharedPtrComplexTypeVector();
|
||||
void testInsertVector();
|
||||
void testInsertEmptyVector();
|
||||
void testAffectedRows();
|
||||
void testInsertSingleBulk();
|
||||
void testInsertSingleBulkVec();
|
||||
|
||||
void testLimit();
|
||||
void testLimitOnce();
|
||||
void testLimitPrepare();
|
||||
void testLimitZero();
|
||||
void testPrepare();
|
||||
|
||||
void testSetSimple();
|
||||
void testSetComplex();
|
||||
void testSetComplexUnique();
|
||||
void testMultiSetSimple();
|
||||
void testMultiSetComplex();
|
||||
void testMapComplex();
|
||||
void testMapComplexUnique();
|
||||
void testMultiMapComplex();
|
||||
void testSelectIntoSingle();
|
||||
void testSelectIntoSingleStep();
|
||||
void testSelectIntoSingleFail();
|
||||
void testLowerLimitOk();
|
||||
void testLowerLimitFail();
|
||||
void testCombinedLimits();
|
||||
void testCombinedIllegalLimits();
|
||||
void testRange();
|
||||
void testIllegalRange();
|
||||
void testSingleSelect();
|
||||
void testEmptyDB();
|
||||
|
||||
void testCLOB();
|
||||
|
||||
void testTuple1();
|
||||
void testTupleVector1();
|
||||
void testTuple2();
|
||||
void testTupleVector2();
|
||||
void testTuple3();
|
||||
void testTupleVector3();
|
||||
void testTuple4();
|
||||
void testTupleVector4();
|
||||
void testTuple5();
|
||||
void testTupleVector5();
|
||||
void testTuple6();
|
||||
void testTupleVector6();
|
||||
void testTuple7();
|
||||
void testTupleVector7();
|
||||
void testTuple8();
|
||||
void testTupleVector8();
|
||||
void testTuple9();
|
||||
void testTupleVector9();
|
||||
void testTuple10();
|
||||
void testTupleVector10();
|
||||
|
||||
void testDateTime();
|
||||
|
||||
void testInternalExtraction();
|
||||
void testPrimaryKeyConstraint();
|
||||
void testNullable();
|
||||
void testNulls();
|
||||
void testRowIterator();
|
||||
void testAsync();
|
||||
|
||||
void testAny();
|
||||
void testDynamicAny();
|
||||
void testPair();
|
||||
|
||||
void testSQLChannel();
|
||||
void testSQLLogger();
|
||||
|
||||
void testExternalBindingAndExtraction();
|
||||
void testBindingCount();
|
||||
void testMultipleResults();
|
||||
|
||||
void testReconnect();
|
||||
|
||||
void testThreadModes();
|
||||
|
||||
void testUpdateCallback();
|
||||
void testCommitCallback();
|
||||
void testRollbackCallback();
|
||||
void testNotifier();
|
||||
|
||||
void testSessionTransaction();
|
||||
void testTransaction();
|
||||
void testTransactor();
|
||||
|
||||
void testFTS3();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
static void sqliteUpdateCallbackFn(void*, int, const char*, const char*, Poco::Int64);
|
||||
static int sqliteCommitCallbackFn(void*);
|
||||
static void sqliteRollbackCallbackFn(void*);
|
||||
|
||||
void onInsert(const void* pSender);
|
||||
void onUpdate(const void* pSender);
|
||||
void onDelete(const void* pSender);
|
||||
void onCommit(const void* pSender);
|
||||
void onRollback(const void* pSender);
|
||||
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti);
|
||||
|
||||
static int _insertCounter;
|
||||
static int _updateCounter;
|
||||
static int _deleteCounter;
|
||||
|
||||
int _commitCounter;
|
||||
int _rollbackCounter;
|
||||
};
|
||||
|
||||
|
||||
#endif // SQLiteTest_INCLUDED
|
@ -1,24 +0,0 @@
|
||||
//
|
||||
// SQLiteTestSuite.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/testsuite/src/SQLiteTestSuite.cpp#2 $
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "SQLiteTestSuite.h"
|
||||
#include "SQLiteTest.h"
|
||||
|
||||
|
||||
CppUnit::Test* SQLiteTestSuite::suite()
|
||||
{
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SQLiteTestSuite");
|
||||
|
||||
pSuite->addTest(SQLiteTest::suite());
|
||||
|
||||
return pSuite;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
//
|
||||
// SQLiteTestSuite.h
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/testsuite/src/SQLiteTestSuite.h#2 $
|
||||
//
|
||||
// Definition of the SQLiteTestSuite class.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef SQLiteTestSuite_INCLUDED
|
||||
#define SQLiteTestSuite_INCLUDED
|
||||
|
||||
|
||||
#include "CppUnit/TestSuite.h"
|
||||
|
||||
|
||||
class SQLiteTestSuite
|
||||
{
|
||||
public:
|
||||
static CppUnit::Test* suite();
|
||||
};
|
||||
|
||||
|
||||
#endif // SQLiteTestSuite_INCLUDED
|
@ -1,32 +0,0 @@
|
||||
//
|
||||
// WinCEDriver.cpp
|
||||
//
|
||||
// $Id: //poco/1.3-WinCE/Net/testsuite/src/WinCEDriver.cpp#2 $
|
||||
//
|
||||
// Console-based test driver for Windows CE.
|
||||
//
|
||||
// Copyright (c) 2004-2010, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "CppUnit/TestRunner.h"
|
||||
#include "SQLiteTestSuite.h"
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
int wmain(int argc, wchar_t* argv[])
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
for (int i = 0; i < argc; ++i)
|
||||
{
|
||||
char buffer[1024];
|
||||
std::wcstombs(buffer, argv[i], sizeof(buffer));
|
||||
args.push_back(std::string(buffer));
|
||||
}
|
||||
CppUnit::TestRunner runner;
|
||||
runner.addTest("SQLiteTestSuite", SQLiteTestSuite::suite());
|
||||
return runner.run(args) ? 0 : 1;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
//
|
||||
// WinDriver.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Data/SQLite/testsuite/src/WinDriver.cpp#2 $
|
||||
//
|
||||
// Windows test driver for Poco SQLite.
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "WinTestRunner/WinTestRunner.h"
|
||||
#include "SQLiteTestSuite.h"
|
||||
|
||||
|
||||
class TestDriver: public CppUnit::WinTestRunnerApp
|
||||
{
|
||||
void TestMain()
|
||||
{
|
||||
CppUnit::WinTestRunner runner;
|
||||
runner.addTest(SQLiteTestSuite::suite());
|
||||
runner.run();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TestDriver theDriver;
|
@ -9,7 +9,7 @@ if ($ENV{DISABLE_MONGODB})
|
||||
set (DISABLE_MONGODB TRUE)
|
||||
endif()
|
||||
|
||||
if (${DISABLE_MONGODB})
|
||||
if (DISABLE_MONGODB)
|
||||
add_definitions(-D DISABLE_MONGODB)
|
||||
else()
|
||||
set (LINK_MONGOCLIENT libmongoclient.a libssl.a libcrypto.a libboost_thread.a)
|
||||
|
@ -14,7 +14,7 @@ namespace DB
|
||||
class JSONCompactRowOutputStream : public JSONRowOutputStream
|
||||
{
|
||||
public:
|
||||
JSONCompactRowOutputStream(WriteBuffer & ostr_, const Block & sample_, bool write_statistics_);
|
||||
JSONCompactRowOutputStream(WriteBuffer & ostr_, const Block & sample_, bool write_statistics_, bool force_quoting_64bit_integers_ = true);
|
||||
|
||||
void writeField(const IColumn & column, const IDataType & type, size_t row_num) override;
|
||||
void writeFieldDelimiter() override;
|
||||
|
@ -14,7 +14,7 @@ namespace DB
|
||||
class JSONEachRowRowOutputStream : public IRowOutputStream
|
||||
{
|
||||
public:
|
||||
JSONEachRowRowOutputStream(WriteBuffer & ostr_, const Block & sample);
|
||||
JSONEachRowRowOutputStream(WriteBuffer & ostr_, const Block & sample, bool force_quoting_64bit_integers_ = true);
|
||||
|
||||
void writeField(const IColumn & column, const IDataType & type, size_t row_num) override;
|
||||
void writeFieldDelimiter() override;
|
||||
@ -30,6 +30,7 @@ private:
|
||||
WriteBuffer & ostr;
|
||||
size_t field_number = 0;
|
||||
Names fields;
|
||||
bool force_quoting_64bit_integers;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class JSONRowOutputStream : public IRowOutputStream
|
||||
{
|
||||
public:
|
||||
JSONRowOutputStream(WriteBuffer & ostr_, const Block & sample_,
|
||||
bool write_statistics_);
|
||||
bool write_statistics_, bool force_quoting_64bit_integers_ = true);
|
||||
|
||||
void writeField(const IColumn & column, const IDataType & type, size_t row_num) override;
|
||||
void writeFieldDelimiter() override;
|
||||
@ -68,6 +68,7 @@ protected:
|
||||
Progress progress;
|
||||
Stopwatch watch;
|
||||
bool write_statistics;
|
||||
bool force_quoting_64bit_integers;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
void deserializeTextEscaped(IColumn & column, ReadBuffer & istr) const override;
|
||||
void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override;
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override;
|
||||
void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override;
|
||||
void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override;
|
||||
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override;
|
||||
void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override;
|
||||
|
||||
void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
static_cast<ColumnType &>(column).getData().push_back(x); /// Важно делать это в конце - для exception safety.
|
||||
}
|
||||
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override
|
||||
{
|
||||
writeChar('"', ostr);
|
||||
serializeText(column, row_num, ostr);
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
static_cast<ColumnType &>(column).getData().push_back(x); /// Важно делать это в конце - для exception safety.
|
||||
}
|
||||
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override
|
||||
{
|
||||
writeChar('"', ostr);
|
||||
serializeText(column, row_num, ostr);
|
||||
|
@ -81,7 +81,7 @@ public:
|
||||
void deserializeTextEscaped(IColumn & column, ReadBuffer & istr) const override;
|
||||
void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override;
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override;
|
||||
void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override;
|
||||
void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override;
|
||||
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override;
|
||||
void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override;
|
||||
|
||||
void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override;
|
||||
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override;
|
||||
void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override;
|
||||
|
||||
void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
void deserializeTextEscaped(IColumn & column, ReadBuffer & istr) const override;
|
||||
void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override;
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override;
|
||||
void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override;
|
||||
void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
|
||||
|
@ -87,9 +87,10 @@ public:
|
||||
*/
|
||||
virtual void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr) const = 0;
|
||||
|
||||
/** Текстовая сериализация в виде литерала для использования в формате JSON.
|
||||
/** Text serialization intended for using in JSON format.
|
||||
* force_quoting_64bit_integers parameter forces to brace UInt64 and Int64 types into quotes.
|
||||
*/
|
||||
virtual void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const = 0;
|
||||
virtual void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool force_quoting_64bit_integers) const = 0;
|
||||
virtual void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const = 0;
|
||||
|
||||
/** Текстовая сериализация для подстановки в формат XML.
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); }
|
||||
void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override { throwNoSerialization(); }
|
||||
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); }
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override { throwNoSerialization(); }
|
||||
void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override { throwNoSerialization(); }
|
||||
|
||||
void serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); }
|
||||
|
@ -56,7 +56,7 @@ public:
|
||||
deserializeText(column, istr);
|
||||
}
|
||||
|
||||
inline void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
|
||||
inline void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override;
|
||||
|
||||
void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override
|
||||
{
|
||||
@ -121,7 +121,7 @@ public:
|
||||
void deserializeTextEscaped(IColumn & column, ReadBuffer & istr) const override {}
|
||||
void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override {}
|
||||
void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override {}
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override {}
|
||||
void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override {}
|
||||
void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override {}
|
||||
void serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override {}
|
||||
void deserializeTextCSV(IColumn & column, ReadBuffer & istr, const char delimiter) const override {}
|
||||
@ -129,26 +129,30 @@ public:
|
||||
Field getDefault() const override { return {}; }
|
||||
};
|
||||
|
||||
template <typename FType> inline void IDataTypeNumber<FType>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
template <typename FType> inline void IDataTypeNumber<FType>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const
|
||||
{
|
||||
serializeText(column, row_num, ostr);
|
||||
}
|
||||
|
||||
template <> inline void IDataTypeNumber<Int64>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
template <> inline void IDataTypeNumber<Int64>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool force_quoting_64bit_integers) const
|
||||
{
|
||||
writeChar('"', ostr);
|
||||
if (force_quoting_64bit_integers)
|
||||
writeChar('"', ostr);
|
||||
serializeText(column, row_num, ostr);
|
||||
writeChar('"', ostr);
|
||||
if (force_quoting_64bit_integers)
|
||||
writeChar('"', ostr);
|
||||
}
|
||||
|
||||
template <> inline void IDataTypeNumber<UInt64>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
template <> inline void IDataTypeNumber<UInt64>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool force_quoting_64bit_integers) const
|
||||
{
|
||||
writeChar('"', ostr);
|
||||
if (force_quoting_64bit_integers)
|
||||
writeChar('"', ostr);
|
||||
serializeText(column, row_num, ostr);
|
||||
writeChar('"', ostr);
|
||||
if (force_quoting_64bit_integers)
|
||||
writeChar('"', ostr);
|
||||
}
|
||||
|
||||
template <> inline void IDataTypeNumber<Float32>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
template <> inline void IDataTypeNumber<Float32>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const
|
||||
{
|
||||
auto x = static_cast<const ColumnType &>(column).getData()[row_num];
|
||||
if (likely(std::isfinite(x)))
|
||||
@ -157,7 +161,7 @@ template <> inline void IDataTypeNumber<Float32>::serializeTextJSON(const IColum
|
||||
writeCString("null", ostr);
|
||||
}
|
||||
|
||||
template <> inline void IDataTypeNumber<Float64>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
template <> inline void IDataTypeNumber<Float64>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const
|
||||
{
|
||||
auto x = static_cast<const ColumnType &>(column).getData()[row_num];
|
||||
if (likely(std::isfinite(x)))
|
||||
|
@ -80,8 +80,9 @@ private:
|
||||
using Shared = std::shared_ptr<ContextShared>;
|
||||
Shared shared;
|
||||
|
||||
String user; /// Текущий пользователь.
|
||||
Poco::Net::IPAddress ip_address; /// IP-адрес, с которого задан запрос.
|
||||
String user; /// Current user
|
||||
Poco::Net::IPAddress ip_address; /// IP address
|
||||
UInt16 port; /// and port, from which current query was recieved
|
||||
Interface interface = Interface::TCP;
|
||||
HTTPMethod http_method = HTTPMethod::UNKNOWN; /// NOTE Возможно, перенести это в отдельный struct ClientInfo.
|
||||
|
||||
@ -121,9 +122,10 @@ public:
|
||||
|
||||
ConfigurationPtr getUsersConfig();
|
||||
|
||||
void setUser(const String & name, const String & password, const Poco::Net::IPAddress & address, const String & quota_key);
|
||||
void setUser(const String & name, const String & password, const Poco::Net::IPAddress & address, UInt16 port, const String & quota_key);
|
||||
String getUser() const { return user; }
|
||||
Poco::Net::IPAddress getIPAddress() const { return ip_address; }
|
||||
UInt16 getPort() const { return port; }
|
||||
|
||||
Interface getInterface() const { return interface; }
|
||||
void setInterface(Interface interface_) { interface = interface_; }
|
||||
|
@ -33,6 +33,7 @@ struct ProcessInfo
|
||||
String user;
|
||||
String query_id;
|
||||
Poco::Net::IPAddress ip_address;
|
||||
UInt16 port;
|
||||
double elapsed_seconds;
|
||||
size_t rows;
|
||||
size_t bytes;
|
||||
@ -48,6 +49,7 @@ struct ProcessListElement
|
||||
String user;
|
||||
String query_id;
|
||||
Poco::Net::IPAddress ip_address;
|
||||
UInt16 port;
|
||||
|
||||
Stopwatch watch;
|
||||
|
||||
@ -67,9 +69,9 @@ struct ProcessListElement
|
||||
|
||||
ProcessListElement(const String & query_, const String & user_,
|
||||
const String & query_id_, const Poco::Net::IPAddress & ip_address_,
|
||||
size_t max_memory_usage, double memory_tracker_fault_probability,
|
||||
UInt16 port_, size_t max_memory_usage, double memory_tracker_fault_probability,
|
||||
QueryPriorities::Handle && priority_handle_)
|
||||
: query(query_), user(user_), query_id(query_id_), ip_address(ip_address_), memory_tracker(max_memory_usage),
|
||||
: query(query_), user(user_), query_id(query_id_), ip_address(ip_address_), port(port_), memory_tracker(max_memory_usage),
|
||||
priority_handle(std::move(priority_handle_))
|
||||
{
|
||||
memory_tracker.setDescription("(for query)");
|
||||
@ -101,6 +103,7 @@ struct ProcessListElement
|
||||
.user = user,
|
||||
.query_id = query_id,
|
||||
.ip_address = ip_address,
|
||||
.port = port,
|
||||
.elapsed_seconds = watch.elapsedSeconds(),
|
||||
.rows = progress.rows,
|
||||
.bytes = progress.bytes,
|
||||
@ -184,7 +187,7 @@ public:
|
||||
* Если времени не хватило - кинуть исключение.
|
||||
*/
|
||||
EntryPtr insert(const String & query_, const String & user_, const String & query_id_, const Poco::Net::IPAddress & ip_address_,
|
||||
const Settings & settings);
|
||||
UInt16 port_, const Settings & settings);
|
||||
|
||||
/// Количество одновременно выполняющихся запросов.
|
||||
size_t size() const { return cur_size; }
|
||||
|
@ -225,7 +225,10 @@ struct Settings
|
||||
M(SettingBool, add_http_cors_header, false) \
|
||||
\
|
||||
/** Skip columns with unknown names from input data (it works for JSONEachRow and TSKV formats). */ \
|
||||
M(SettingBool, input_format_skip_unknown_fields, false)
|
||||
M(SettingBool, input_format_skip_unknown_fields, false) \
|
||||
\
|
||||
/** Controls quoting of 64-bit integers in JSON output format. */ \
|
||||
M(SettingBool, output_format_json_quote_64bit_integers, true)
|
||||
|
||||
/// Всевозможные ограничения на выполнение запроса.
|
||||
Limits limits;
|
||||
|
@ -26,8 +26,10 @@
|
||||
|
||||
#include <DB/IO/ReadBufferFromFileDescriptor.h>
|
||||
#include <DB/IO/WriteBufferFromFileDescriptor.h>
|
||||
#include <DB/IO/WriteBufferFromFile.h>
|
||||
#include <DB/IO/ReadHelpers.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
#include <DB/IO/Operators.h>
|
||||
|
||||
#include <DB/DataStreams/RemoteBlockInputStream.h>
|
||||
|
||||
@ -38,8 +40,8 @@
|
||||
#include "InterruptListener.h"
|
||||
|
||||
|
||||
/** Инструмент для измерения производительности ClickHouse
|
||||
* при выполнении запросов с фиксированным количеством одновременных запросов.
|
||||
/** A tool for evaluating ClickHouse performance.
|
||||
* The tool emulates a case with fixed amount of simultaneously executing queries.
|
||||
*/
|
||||
|
||||
namespace DB
|
||||
@ -58,12 +60,13 @@ public:
|
||||
Benchmark(unsigned concurrency_, double delay_,
|
||||
const String & host_, UInt16 port_, const String & default_database_,
|
||||
const String & user_, const String & password_, const String & stage,
|
||||
bool randomize_,
|
||||
const Settings & settings_)
|
||||
: concurrency(concurrency_), delay(delay_), queue(concurrency),
|
||||
bool randomize_, size_t max_iterations_, double max_time_,
|
||||
const String & json_path_, const Settings & settings_)
|
||||
:
|
||||
concurrency(concurrency_), delay(delay_), queue(concurrency),
|
||||
connections(concurrency, host_, port_, default_database_, user_, password_),
|
||||
randomize(randomize_),
|
||||
settings(settings_), pool(concurrency)
|
||||
randomize(randomize_), max_iterations(max_iterations_), max_time(max_time_),
|
||||
json_path(json_path_), settings(settings_), pool(concurrency)
|
||||
{
|
||||
std::cerr << std::fixed << std::setprecision(3);
|
||||
|
||||
@ -76,6 +79,11 @@ public:
|
||||
else
|
||||
throw Exception("Unknown query processing stage: " + stage, ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
if (!json_path.empty() && Poco::File(json_path).exists()) /// Clear file with previous results
|
||||
{
|
||||
Poco::File(json_path).remove();
|
||||
}
|
||||
|
||||
readQueries();
|
||||
run();
|
||||
}
|
||||
@ -94,6 +102,9 @@ private:
|
||||
|
||||
ConnectionPool connections;
|
||||
bool randomize;
|
||||
size_t max_iterations;
|
||||
double max_time;
|
||||
String json_path;
|
||||
Settings settings;
|
||||
QueryProcessingStage::Enum query_processing_stage;
|
||||
|
||||
@ -183,18 +194,13 @@ private:
|
||||
Stopwatch watch;
|
||||
|
||||
/// В цикле, кладём все запросы в очередь.
|
||||
for (size_t i = 0; !interrupt_listener.check(); ++i)
|
||||
for (size_t i = 0; !max_iterations || i < max_iterations; ++i)
|
||||
{
|
||||
if (i >= queries.size())
|
||||
i = 0;
|
||||
|
||||
size_t query_index = randomize
|
||||
? distribution(generator)
|
||||
: i;
|
||||
size_t query_index = randomize ? distribution(generator) : i % queries.size();
|
||||
|
||||
queue.push(queries[query_index]);
|
||||
|
||||
if (watch.elapsedSeconds() > delay)
|
||||
if (delay > 0 && watch.elapsedSeconds() > delay)
|
||||
{
|
||||
auto total_queries = 0;
|
||||
{
|
||||
@ -206,6 +212,18 @@ private:
|
||||
report(info_per_interval);
|
||||
watch.restart();
|
||||
}
|
||||
|
||||
if (max_time > 0 && info_total.watch.elapsedSeconds() >= max_time)
|
||||
{
|
||||
std::cout << "Stopping launch of queries. Requested time limit is exhausted.\n";
|
||||
break;
|
||||
}
|
||||
|
||||
if (interrupt_listener.check())
|
||||
{
|
||||
std::cout << "Stopping launch of queries. SIGINT recieved.\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Попросим потоки завершиться.
|
||||
@ -214,6 +232,9 @@ private:
|
||||
|
||||
pool.wait();
|
||||
|
||||
info_total.watch.stop();
|
||||
if (!json_path.empty())
|
||||
reportJSON(info_total, json_path);
|
||||
printNumberOfQueriesExecuted(info_total.queries);
|
||||
report(info_total);
|
||||
}
|
||||
@ -320,17 +341,67 @@ private:
|
||||
<< "result MiB/s: " << (info.result_bytes / seconds / 1048576) << "."
|
||||
<< "\n";
|
||||
|
||||
for (size_t percent = 0; percent <= 90; percent += 10)
|
||||
auto print_percentile = [&](double percent)
|
||||
{
|
||||
std::cerr << percent << "%\t" << info.sampler.quantileInterpolated(percent / 100.0) << " sec." << std::endl;
|
||||
};
|
||||
|
||||
std::cerr << "95%\t" << info.sampler.quantileInterpolated(0.95) << " sec.\n";
|
||||
std::cerr << "99%\t" << info.sampler.quantileInterpolated(0.99) << " sec.\n";
|
||||
std::cerr << "99.9%\t" << info.sampler.quantileInterpolated(0.999) << " sec.\n";
|
||||
std::cerr << "99.99%\t" << info.sampler.quantileInterpolated(0.9999) << " sec.\n";
|
||||
std::cerr << "100%\t" << info.sampler.quantileInterpolated(1) << " sec.\n";
|
||||
for (int percent = 0; percent <= 90; percent += 10)
|
||||
print_percentile(percent);
|
||||
|
||||
print_percentile(95);
|
||||
print_percentile(99);
|
||||
print_percentile(99.9);
|
||||
print_percentile(99.99);
|
||||
|
||||
info.clear();
|
||||
}
|
||||
|
||||
void reportJSON(Stats & info, const std::string & filename)
|
||||
{
|
||||
WriteBufferFromFile json_out(filename);
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
auto print_key_value = [&](auto key, auto value, bool with_comma = true)
|
||||
{
|
||||
json_out << double_quote << key << ": " << value << (with_comma ? ",\n" : "\n");
|
||||
};
|
||||
|
||||
auto print_percentile = [&](auto percent, bool with_comma = true)
|
||||
{
|
||||
json_out << "\"" << percent << "\"" << ": " << info.sampler.quantileInterpolated(percent / 100.0) << (with_comma ? ",\n" : "\n");
|
||||
};
|
||||
|
||||
json_out << "{\n";
|
||||
|
||||
json_out << double_quote << "statistics" << ": {\n";
|
||||
|
||||
double seconds = info.watch.elapsedSeconds();
|
||||
print_key_value("QPS", info.queries / seconds);
|
||||
print_key_value("RPS", info.queries / seconds);
|
||||
print_key_value("MiBPS", info.queries / seconds);
|
||||
print_key_value("RPS_result", info.queries / seconds);
|
||||
print_key_value("MiBPS_result", info.queries / seconds);
|
||||
print_key_value("num_queries", info.queries / seconds, false);
|
||||
|
||||
json_out << "},\n";
|
||||
|
||||
|
||||
json_out << double_quote << "query_time_percentiles" << ": {\n";
|
||||
|
||||
for (int percent = 0; percent <= 90; percent += 10)
|
||||
print_percentile(percent);
|
||||
|
||||
print_percentile(95);
|
||||
print_percentile(99);
|
||||
print_percentile(99.9);
|
||||
print_percentile(99.99, false);
|
||||
|
||||
json_out << "}\n";
|
||||
|
||||
json_out << "}\n";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@ -342,18 +413,24 @@ int main(int argc, char ** argv)
|
||||
|
||||
try
|
||||
{
|
||||
using boost::program_options::value;
|
||||
|
||||
boost::program_options::options_description desc("Allowed options");
|
||||
desc.add_options()
|
||||
("help", "produce help message")
|
||||
("concurrency,c", boost::program_options::value<unsigned>()->default_value(1), "number of parallel queries")
|
||||
("delay,d", boost::program_options::value<double>()->default_value(1), "delay between reports in seconds")
|
||||
("host,h", boost::program_options::value<std::string>()->default_value("localhost"), "")
|
||||
("port", boost::program_options::value<UInt16>()->default_value(9000), "")
|
||||
("user", boost::program_options::value<std::string>()->default_value("default"), "")
|
||||
("password", boost::program_options::value<std::string>()->default_value(""), "")
|
||||
("database", boost::program_options::value<std::string>()->default_value("default"), "")
|
||||
("stage", boost::program_options::value<std::string>()->default_value("complete"), "request query processing up to specified stage")
|
||||
("randomize,r", boost::program_options::value<bool>()->default_value(false), "randomize order of execution")
|
||||
("help", "produce help message")
|
||||
("concurrency,c", value<unsigned>()->default_value(1), "number of parallel queries")
|
||||
("delay,d", value<double>()->default_value(1), "delay between intermediate reports in seconds (set 0 to disable reports)")
|
||||
("stage", value<std::string>()->default_value("complete"), "request query processing up to specified stage")
|
||||
("iterations,i", value<size_t>()->default_value(0), "amount of queries to be executed")
|
||||
("timelimit,t", value<double>()->default_value(0.), "stop launch of queries after specified time limit")
|
||||
("randomize,r", value<bool>()->default_value(false), "randomize order of execution")
|
||||
("json", value<std::string>()->default_value(""), "write final report to specified file in JSON format")
|
||||
("host,h", value<std::string>()->default_value("localhost"), "")
|
||||
("port", value<UInt16>()->default_value(9000), "")
|
||||
("user", value<std::string>()->default_value("default"), "")
|
||||
("password", value<std::string>()->default_value(""), "")
|
||||
("database", value<std::string>()->default_value("default"), "")
|
||||
|
||||
#define DECLARE_SETTING(TYPE, NAME, DEFAULT) (#NAME, boost::program_options::value<std::string> (), "Settings.h")
|
||||
#define DECLARE_LIMIT(TYPE, NAME, DEFAULT) (#NAME, boost::program_options::value<std::string> (), "Limits.h")
|
||||
APPLY_FOR_SETTINGS(DECLARE_SETTING)
|
||||
@ -392,6 +469,9 @@ int main(int argc, char ** argv)
|
||||
options["password"].as<std::string>(),
|
||||
options["stage"].as<std::string>(),
|
||||
options["randomize"].as<bool>(),
|
||||
options["iterations"].as<size_t>(),
|
||||
options["timelimit"].as<double>(),
|
||||
options["json"].as<std::string>(),
|
||||
settings);
|
||||
}
|
||||
catch (const Exception & e)
|
||||
|
@ -135,12 +135,13 @@ static BlockOutputStreamPtr getOutputImpl(const String & name, WriteBuffer & buf
|
||||
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<ValuesRowOutputStream>(buf));
|
||||
else if (name == "JSON")
|
||||
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<JSONRowOutputStream>(buf, sample,
|
||||
context.getSettingsRef().output_format_write_statistics));
|
||||
context.getSettingsRef().output_format_write_statistics, context.getSettingsRef().output_format_json_quote_64bit_integers));
|
||||
else if (name == "JSONCompact")
|
||||
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<JSONCompactRowOutputStream>(buf, sample,
|
||||
context.getSettingsRef().output_format_write_statistics));
|
||||
context.getSettingsRef().output_format_write_statistics, context.getSettingsRef().output_format_json_quote_64bit_integers));
|
||||
else if (name == "JSONEachRow")
|
||||
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<JSONEachRowRowOutputStream>(buf, sample));
|
||||
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<JSONEachRowRowOutputStream>(buf, sample,
|
||||
context.getSettingsRef().output_format_json_quote_64bit_integers));
|
||||
else if (name == "XML")
|
||||
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<XMLRowOutputStream>(buf, sample,
|
||||
context.getSettingsRef().output_format_write_statistics));
|
||||
|
@ -6,15 +6,15 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
JSONCompactRowOutputStream::JSONCompactRowOutputStream(WriteBuffer & ostr_, const Block & sample_, bool write_statistics_)
|
||||
: JSONRowOutputStream(ostr_, sample_, write_statistics_)
|
||||
JSONCompactRowOutputStream::JSONCompactRowOutputStream(WriteBuffer & ostr_, const Block & sample_, bool write_statistics_, bool force_quoting_64bit_integers_)
|
||||
: JSONRowOutputStream(ostr_, sample_, write_statistics_, force_quoting_64bit_integers_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void JSONCompactRowOutputStream::writeField(const IColumn & column, const IDataType & type, size_t row_num)
|
||||
{
|
||||
type.serializeTextJSON(column, row_num, *ostr);
|
||||
type.serializeTextJSON(column, row_num, *ostr, force_quoting_64bit_integers);
|
||||
++field_number;
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ void JSONCompactRowOutputStream::writeTotals()
|
||||
writeChar(',', *ostr);
|
||||
|
||||
const ColumnWithTypeAndName & column = totals.getByPosition(i);
|
||||
column.type->serializeTextJSON(*column.column.get(), 0, *ostr);
|
||||
column.type->serializeTextJSON(*column.column.get(), 0, *ostr, force_quoting_64bit_integers);
|
||||
}
|
||||
|
||||
writeChar(']', *ostr);
|
||||
@ -64,7 +64,7 @@ void JSONCompactRowOutputStream::writeTotals()
|
||||
}
|
||||
|
||||
|
||||
static void writeExtremesElement(const char * title, const Block & extremes, size_t row_num, WriteBuffer & ostr)
|
||||
static void writeExtremesElement(const char * title, const Block & extremes, size_t row_num, WriteBuffer & ostr, bool force_quoting_64bit_integers)
|
||||
{
|
||||
writeCString("\t\t\"", ostr);
|
||||
writeCString(title, ostr);
|
||||
@ -77,7 +77,7 @@ static void writeExtremesElement(const char * title, const Block & extremes, siz
|
||||
writeChar(',', ostr);
|
||||
|
||||
const ColumnWithTypeAndName & column = extremes.getByPosition(i);
|
||||
column.type->serializeTextJSON(*column.column.get(), row_num, ostr);
|
||||
column.type->serializeTextJSON(*column.column.get(), row_num, ostr, force_quoting_64bit_integers);
|
||||
}
|
||||
|
||||
writeChar(']', ostr);
|
||||
@ -92,9 +92,9 @@ void JSONCompactRowOutputStream::writeExtremes()
|
||||
writeCString("\t\"extremes\":\n", *ostr);
|
||||
writeCString("\t{\n", *ostr);
|
||||
|
||||
writeExtremesElement("min", extremes, 0, *ostr);
|
||||
writeExtremesElement("min", extremes, 0, *ostr, force_quoting_64bit_integers);
|
||||
writeCString(",\n", *ostr);
|
||||
writeExtremesElement("max", extremes, 1, *ostr);
|
||||
writeExtremesElement("max", extremes, 1, *ostr, force_quoting_64bit_integers);
|
||||
|
||||
writeChar('\n', *ostr);
|
||||
writeCString("\t}", *ostr);
|
||||
|
@ -7,8 +7,8 @@ namespace DB
|
||||
{
|
||||
|
||||
|
||||
JSONEachRowRowOutputStream::JSONEachRowRowOutputStream(WriteBuffer & ostr_, const Block & sample)
|
||||
: ostr(ostr_)
|
||||
JSONEachRowRowOutputStream::JSONEachRowRowOutputStream(WriteBuffer & ostr_, const Block & sample, bool force_quoting_64bit_integers_)
|
||||
: ostr(ostr_), force_quoting_64bit_integers(force_quoting_64bit_integers_)
|
||||
{
|
||||
size_t columns = sample.columns();
|
||||
fields.resize(columns);
|
||||
@ -25,7 +25,7 @@ void JSONEachRowRowOutputStream::writeField(const IColumn & column, const IDataT
|
||||
{
|
||||
writeString(fields[field_number], ostr);
|
||||
writeChar(':', ostr);
|
||||
type.serializeTextJSON(column, row_num, ostr);
|
||||
type.serializeTextJSON(column, row_num, ostr, force_quoting_64bit_integers);
|
||||
++field_number;
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,8 @@ namespace DB
|
||||
{
|
||||
|
||||
|
||||
JSONRowOutputStream::JSONRowOutputStream(WriteBuffer & ostr_, const Block & sample_, bool write_statistics_)
|
||||
: dst_ostr(ostr_), write_statistics(write_statistics_)
|
||||
JSONRowOutputStream::JSONRowOutputStream(WriteBuffer & ostr_, const Block & sample_, bool write_statistics_, bool force_quoting_64bit_integers_)
|
||||
: dst_ostr(ostr_), write_statistics(write_statistics_), force_quoting_64bit_integers(force_quoting_64bit_integers_)
|
||||
{
|
||||
NamesAndTypesList columns(sample_.getColumnsList());
|
||||
fields.assign(columns.begin(), columns.end());
|
||||
@ -72,7 +72,7 @@ void JSONRowOutputStream::writeField(const IColumn & column, const IDataType & t
|
||||
writeCString("\t\t\t", *ostr);
|
||||
writeString(fields[field_number].name, *ostr);
|
||||
writeCString(": ", *ostr);
|
||||
type.serializeTextJSON(column, row_num, *ostr);
|
||||
type.serializeTextJSON(column, row_num, *ostr, force_quoting_64bit_integers);
|
||||
++field_number;
|
||||
}
|
||||
|
||||
@ -152,7 +152,7 @@ void JSONRowOutputStream::writeTotals()
|
||||
writeCString("\t\t", *ostr);
|
||||
writeJSONString(column.name, *ostr);
|
||||
writeCString(": ", *ostr);
|
||||
column.type->serializeTextJSON(*column.column.get(), 0, *ostr);
|
||||
column.type->serializeTextJSON(*column.column.get(), 0, *ostr, force_quoting_64bit_integers);
|
||||
}
|
||||
|
||||
writeChar('\n', *ostr);
|
||||
@ -161,7 +161,7 @@ void JSONRowOutputStream::writeTotals()
|
||||
}
|
||||
|
||||
|
||||
static void writeExtremesElement(const char * title, const Block & extremes, size_t row_num, WriteBuffer & ostr)
|
||||
static void writeExtremesElement(const char * title, const Block & extremes, size_t row_num, WriteBuffer & ostr, bool force_quoting_64bit_integers)
|
||||
{
|
||||
writeCString("\t\t\"", ostr);
|
||||
writeCString(title, ostr);
|
||||
@ -179,7 +179,7 @@ static void writeExtremesElement(const char * title, const Block & extremes, siz
|
||||
writeCString("\t\t\t", ostr);
|
||||
writeJSONString(column.name, ostr);
|
||||
writeCString(": ", ostr);
|
||||
column.type->serializeTextJSON(*column.column.get(), row_num, ostr);
|
||||
column.type->serializeTextJSON(*column.column.get(), row_num, ostr, force_quoting_64bit_integers);
|
||||
}
|
||||
|
||||
writeChar('\n', ostr);
|
||||
@ -195,9 +195,9 @@ void JSONRowOutputStream::writeExtremes()
|
||||
writeCString("\t\"extremes\":\n", *ostr);
|
||||
writeCString("\t{\n", *ostr);
|
||||
|
||||
writeExtremesElement("min", extremes, 0, *ostr);
|
||||
writeExtremesElement("min", extremes, 0, *ostr, force_quoting_64bit_integers);
|
||||
writeCString(",\n", *ostr);
|
||||
writeExtremesElement("max", extremes, 1, *ostr);
|
||||
writeExtremesElement("max", extremes, 1, *ostr, force_quoting_64bit_integers);
|
||||
|
||||
writeChar('\n', *ostr);
|
||||
writeCString("\t}", *ostr);
|
||||
|
@ -62,7 +62,7 @@ try
|
||||
//copyData(row_input, row_output);
|
||||
|
||||
BlockInputStreamFromRowInputStream in(std::make_shared<TabSeparatedRowInputStream>(in_buf, sample, true, true), sample);
|
||||
BlockOutputStreamFromRowOutputStream out(std::make_shared<JSONRowOutputStream>(out_buf, sample, false));
|
||||
BlockOutputStreamFromRowOutputStream out(std::make_shared<JSONRowOutputStream>(out_buf, sample, false, true));
|
||||
copyData(in, out);
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ void DataTypeAggregateFunction::deserializeTextQuoted(IColumn & column, ReadBuff
|
||||
}
|
||||
|
||||
|
||||
void DataTypeAggregateFunction::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
void DataTypeAggregateFunction::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const
|
||||
{
|
||||
writeJSONString(serializeToString(function, column, row_num), ostr);
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ void DataTypeArray::deserializeTextQuoted(IColumn & column, ReadBuffer & istr) c
|
||||
}
|
||||
|
||||
|
||||
void DataTypeArray::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
void DataTypeArray::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool force_quoting_64bit_integers) const
|
||||
{
|
||||
const ColumnArray & column_array = static_cast<const ColumnArray &>(column);
|
||||
const ColumnArray::Offsets_t & offsets = column_array.getOffsets();
|
||||
@ -303,7 +303,7 @@ void DataTypeArray::serializeTextJSON(const IColumn & column, size_t row_num, Wr
|
||||
{
|
||||
if (i != offset)
|
||||
writeChar(',', ostr);
|
||||
nested->serializeTextJSON(nested_column, i, ostr);
|
||||
nested->serializeTextJSON(nested_column, i, ostr, force_quoting_64bit_integers);
|
||||
}
|
||||
writeChar(']', ostr);
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ void DataTypeEnum<Type>::deserializeTextQuoted(IColumn & column, ReadBuffer & is
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void DataTypeEnum<Type>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
void DataTypeEnum<Type>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const
|
||||
{
|
||||
writeJSONString(getNameForValue(static_cast<const ColumnType &>(column).getData()[row_num]), ostr);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ void DataTypeFixedString::deserializeTextQuoted(IColumn & column, ReadBuffer & i
|
||||
}
|
||||
|
||||
|
||||
void DataTypeFixedString::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
void DataTypeFixedString::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const
|
||||
{
|
||||
const char * pos = reinterpret_cast<const char *>(&static_cast<const ColumnFixedString &>(column).getChars()[n * row_num]);
|
||||
writeJSONString(pos, pos + n, ostr);
|
||||
|
@ -266,7 +266,7 @@ void DataTypeString::deserializeTextQuoted(IColumn & column, ReadBuffer & istr)
|
||||
}
|
||||
|
||||
|
||||
void DataTypeString::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
void DataTypeString::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const
|
||||
{
|
||||
writeJSONString(static_cast<const ColumnString &>(column).getDataAt(row_num), ostr);
|
||||
}
|
||||
|
@ -144,14 +144,14 @@ void DataTypeTuple::deserializeTextQuoted(IColumn & column, ReadBuffer & istr) c
|
||||
deserializeText(column, istr);
|
||||
}
|
||||
|
||||
void DataTypeTuple::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
|
||||
void DataTypeTuple::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool force_quoting_64bit_integers) const
|
||||
{
|
||||
writeChar('[', ostr);
|
||||
for (const auto i : ext::range(0, ext::size(elems)))
|
||||
{
|
||||
if (i != 0)
|
||||
writeChar(',', ostr);
|
||||
elems[i]->serializeTextJSON(extractElementColumn(column, i), row_num, ostr);
|
||||
elems[i]->serializeTextJSON(extractElementColumn(column, i), row_num, ostr, force_quoting_64bit_integers);
|
||||
}
|
||||
writeChar(']', ostr);
|
||||
}
|
||||
|
@ -283,7 +283,7 @@ ConfigurationPtr Context::getUsersConfig()
|
||||
}
|
||||
|
||||
|
||||
void Context::setUser(const String & name, const String & password, const Poco::Net::IPAddress & address, const String & quota_key)
|
||||
void Context::setUser(const String & name, const String & password, const Poco::Net::IPAddress & address, UInt16 port, const String & quota_key)
|
||||
{
|
||||
auto lock = getLock();
|
||||
|
||||
@ -291,8 +291,9 @@ void Context::setUser(const String & name, const String & password, const Poco::
|
||||
setSetting("profile", user_props.profile);
|
||||
setQuota(user_props.quota, quota_key, name, address);
|
||||
|
||||
user = name;
|
||||
ip_address = address;
|
||||
this->user = name;
|
||||
this->ip_address = address;
|
||||
this->port = port;
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@ namespace ErrorCodes
|
||||
|
||||
ProcessList::EntryPtr ProcessList::insert(
|
||||
const String & query_, const String & user_, const String & query_id_, const Poco::Net::IPAddress & ip_address_,
|
||||
const Settings & settings)
|
||||
UInt16 port_, const Settings & settings)
|
||||
{
|
||||
EntryPtr res;
|
||||
|
||||
@ -54,7 +54,7 @@ ProcessList::EntryPtr ProcessList::insert(
|
||||
++cur_size;
|
||||
|
||||
res = std::make_shared<Entry>(*this, cont.emplace(cont.end(),
|
||||
query_, user_, query_id_, ip_address_,
|
||||
query_, user_, query_id_, ip_address_, port_,
|
||||
settings.limits.max_memory_usage, settings.memory_tracker_fault_probability,
|
||||
priorities.insert(settings.priority)));
|
||||
|
||||
|
@ -184,6 +184,7 @@ static std::tuple<ASTPtr, BlockIO> executeQueryImpl(
|
||||
context.getUser(),
|
||||
context.getCurrentQueryId(),
|
||||
context.getIPAddress(),
|
||||
context.getPort(),
|
||||
settings);
|
||||
|
||||
context.setProcessListElement(&process_list_entry->get());
|
||||
|
@ -108,7 +108,7 @@ void HTTPHandler::processQuery(
|
||||
Context context = *server.global_context;
|
||||
context.setGlobalContext(*server.global_context);
|
||||
|
||||
context.setUser(user, password, request.clientAddress().host(), quota_key);
|
||||
context.setUser(user, password, request.clientAddress().host(), request.clientAddress().port(), quota_key);
|
||||
context.setCurrentQueryId(query_id);
|
||||
|
||||
std::unique_ptr<ReadBuffer> in_param = std::make_unique<ReadBufferFromString>(query_param);
|
||||
|
@ -464,7 +464,7 @@ void TCPHandler::receiveHello()
|
||||
<< (!user.empty() ? ", user: " + user : "")
|
||||
<< ".");
|
||||
|
||||
connection_context.setUser(user, password, socket().peerAddress().host(), "");
|
||||
connection_context.setUser(user, password, socket().peerAddress().host(), socket().peerAddress().port(), "");
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,6 +15,7 @@ StorageSystemProcesses::StorageSystemProcesses(const std::string & name_)
|
||||
, columns{
|
||||
{ "user", std::make_shared<DataTypeString>() },
|
||||
{ "address", std::make_shared<DataTypeString>() },
|
||||
{ "port", std::make_shared<DataTypeUInt16>() },
|
||||
{ "elapsed", std::make_shared<DataTypeFloat64>() },
|
||||
{ "rows_read", std::make_shared<DataTypeUInt64>() },
|
||||
{ "bytes_read", std::make_shared<DataTypeUInt64>() },
|
||||
@ -46,6 +47,7 @@ BlockInputStreams StorageSystemProcesses::read(
|
||||
|
||||
ColumnWithTypeAndName col_user{std::make_shared<ColumnString>(), std::make_shared<DataTypeString>(), "user"};
|
||||
ColumnWithTypeAndName col_address{std::make_shared<ColumnString>(), std::make_shared<DataTypeString>(), "address"};
|
||||
ColumnWithTypeAndName col_port{std::make_shared<ColumnUInt16>(), std::make_shared<DataTypeUInt16>(), "port"};
|
||||
ColumnWithTypeAndName col_elapsed{std::make_shared<ColumnFloat64>(), std::make_shared<DataTypeFloat64>(), "elapsed"};
|
||||
ColumnWithTypeAndName col_rows_read{std::make_shared<ColumnUInt64>(), std::make_shared<DataTypeUInt64>(), "rows_read"};
|
||||
ColumnWithTypeAndName col_bytes_read{std::make_shared<ColumnUInt64>(), std::make_shared<DataTypeUInt64>(), "bytes_read"};
|
||||
@ -60,6 +62,7 @@ BlockInputStreams StorageSystemProcesses::read(
|
||||
{
|
||||
col_user.column->insert(process.user);
|
||||
col_address.column->insert(process.ip_address.toString());
|
||||
col_port.column->insert(static_cast<UInt64>(process.port));
|
||||
col_elapsed.column->insert(process.elapsed_seconds);
|
||||
col_rows_read.column->insert(process.rows);
|
||||
col_bytes_read.column->insert(process.bytes);
|
||||
@ -72,6 +75,7 @@ BlockInputStreams StorageSystemProcesses::read(
|
||||
Block block{
|
||||
col_user,
|
||||
col_address,
|
||||
col_port,
|
||||
col_elapsed,
|
||||
col_rows_read,
|
||||
col_bytes_read,
|
||||
|
@ -1,4 +1,5 @@
|
||||
clickhouse-client -n --query "DROP TABLE IF EXISTS test.json_noisy; CREATE TABLE test.json_noisy (d1 UInt8, d2 String) ENGINE = Memory"
|
||||
#!/bin/bash
|
||||
clickhouse-client -n --query "DROP TABLE IF EXISTS test.json_noisy; CREATE TABLE test.json_noisy (d1 UInt8, d2 String) ENGINE = Memory"
|
||||
|
||||
echo '{"d1" : 1, "d2" : "ok"}
|
||||
{ }
|
||||
@ -7,4 +8,4 @@ echo '{"d1" : 1, "d2" : "ok"}
|
||||
{"d2":"ok","t1":[[[]],true, null, false, "1","2", 0.03, 1], "d1":"1", "t2":["1","2"]}' \
|
||||
| clickhouse-client -n --query "SET input_format_skip_unknown_fields = 1; INSERT INTO test.json_noisy FORMAT JSONEachRow"
|
||||
|
||||
clickhouse-client -n --query "SELECT * FROM test.json_noisy; DROP TABLE IF EXISTS test.json_noisy;"
|
||||
clickhouse-client -n --query "SELECT * FROM test.json_noisy; DROP TABLE IF EXISTS test.json_noisy;"
|
||||
|
@ -4,8 +4,7 @@ CREATE TABLE test.group_uniq_str ENGINE = Memory AS SELECT number % 10 as id, to
|
||||
INSERT INTO test.group_uniq_str SELECT 2 as id, toString(number % 100) as v FROM system.numbers LIMIT 1000000;
|
||||
INSERT INTO test.group_uniq_str SELECT 5 as id, toString(number % 100) as v FROM system.numbers LIMIT 10000000;
|
||||
|
||||
SELECT length(groupUniqArray(v)) FROM test.group_uniq_str GROUP BY id ORDER BY id
|
||||
UNION ALL
|
||||
SELECT length(groupUniqArray(v)) FROM test.group_uniq_str GROUP BY id ORDER BY id;
|
||||
SELECT length(groupUniqArray(v)) FROM remote('127.0.0.{1,2,3,4}', 'test', 'group_uniq_str') GROUP BY id ORDER BY id;
|
||||
|
||||
DROP TABLE IF EXISTS test.group_uniq_str;
|
||||
|
@ -3,8 +3,7 @@ CREATE TABLE test.group_uniq_arr_int ENGINE = Memory AS
|
||||
SELECT g as id, if(c == 0, [v], if(c == 1, emptyArrayInt64(), [v, v])) as v FROM
|
||||
(SELECT intDiv(number%1000000, 100) as v, intDiv(number%100, 10) as g, number%10 as c FROM system.numbers WHERE c < 3 LIMIT 10000000);
|
||||
|
||||
SELECT length(groupUniqArray(v)) FROM test.group_uniq_arr_int GROUP BY id ORDER BY id
|
||||
UNION ALL
|
||||
SELECT length(groupUniqArray(v)) FROM test.group_uniq_arr_int GROUP BY id ORDER BY id;
|
||||
SELECT length(groupUniqArray(v)) FROM remote('127.0.0.{1,2,3,4}', 'test', 'group_uniq_arr_int') GROUP BY id ORDER BY id;
|
||||
|
||||
DROP TABLE IF EXISTS test.group_uniq_arr_int;
|
||||
|
@ -3,8 +3,7 @@ CREATE TABLE test.group_uniq_arr_str ENGINE = Memory AS
|
||||
SELECT hex(intHash32(g)) as id, if(c == 0, [hex(v)], if(c == 1, emptyArrayString(), [hex(v), hex(v)])) as v FROM
|
||||
(SELECT intDiv(number%1000000, 100) as v, intDiv(number%100, 10) as g, number%10 as c FROM system.numbers WHERE c < 3 LIMIT 10000000);
|
||||
|
||||
SELECT length(groupUniqArray(v)) FROM test.group_uniq_arr_str GROUP BY id ORDER BY id
|
||||
UNION ALL
|
||||
SELECT length(groupUniqArray(v)) FROM test.group_uniq_arr_str GROUP BY id ORDER BY id;
|
||||
SELECT length(groupUniqArray(v)) FROM remote('127.0.0.{1,2,3,4}', 'test', 'group_uniq_arr_str') GROUP BY id ORDER BY id;
|
||||
|
||||
DROP TABLE IF EXISTS test.group_uniq_arr_str;
|
||||
|
@ -0,0 +1,264 @@
|
||||
{
|
||||
"meta":
|
||||
[
|
||||
{
|
||||
"name": "i0",
|
||||
"type": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "u0",
|
||||
"type": "UInt64"
|
||||
},
|
||||
{
|
||||
"name": "ip",
|
||||
"type": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "in",
|
||||
"type": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "up",
|
||||
"type": "UInt64"
|
||||
},
|
||||
{
|
||||
"name": "arr",
|
||||
"type": "Array(Int64)"
|
||||
},
|
||||
{
|
||||
"name": "tuple",
|
||||
"type": "Tuple(UInt64, UInt64)"
|
||||
}
|
||||
],
|
||||
|
||||
"data":
|
||||
[
|
||||
{
|
||||
"i0": "0",
|
||||
"u0": "0",
|
||||
"ip": "9223372036854775807",
|
||||
"in": "-9223372036854775808",
|
||||
"up": "18446744073709551615",
|
||||
"arr": ["0"],
|
||||
"tuple": ["0","0"]
|
||||
}
|
||||
],
|
||||
|
||||
"totals":
|
||||
{
|
||||
"i0": "0",
|
||||
"u0": "0",
|
||||
"ip": "0",
|
||||
"in": "0",
|
||||
"up": "0",
|
||||
"arr": [],
|
||||
"tuple": ["0","0"]
|
||||
},
|
||||
|
||||
"extremes":
|
||||
{
|
||||
"min":
|
||||
{
|
||||
"i0": "0",
|
||||
"u0": "0",
|
||||
"ip": "9223372036854775807",
|
||||
"in": "-9223372036854775808",
|
||||
"up": "18446744073709551615",
|
||||
"arr": [],
|
||||
"tuple": ["0","0"]
|
||||
},
|
||||
"max":
|
||||
{
|
||||
"i0": "0",
|
||||
"u0": "0",
|
||||
"ip": "9223372036854775807",
|
||||
"in": "-9223372036854775808",
|
||||
"up": "18446744073709551615",
|
||||
"arr": [],
|
||||
"tuple": ["0","0"]
|
||||
}
|
||||
},
|
||||
|
||||
"rows": 1
|
||||
}
|
||||
{
|
||||
"meta":
|
||||
[
|
||||
{
|
||||
"name": "i0",
|
||||
"type": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "u0",
|
||||
"type": "UInt64"
|
||||
},
|
||||
{
|
||||
"name": "ip",
|
||||
"type": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "in",
|
||||
"type": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "up",
|
||||
"type": "UInt64"
|
||||
},
|
||||
{
|
||||
"name": "arr",
|
||||
"type": "Array(Int64)"
|
||||
},
|
||||
{
|
||||
"name": "tuple",
|
||||
"type": "Tuple(UInt64, UInt64)"
|
||||
}
|
||||
],
|
||||
|
||||
"data":
|
||||
[
|
||||
["0", "0", "9223372036854775807", "-9223372036854775808", "18446744073709551615", ["0"], ["0","0"]]
|
||||
],
|
||||
|
||||
"totals": ["0","0","0","0","0",[],["0","0"]],
|
||||
|
||||
"extremes":
|
||||
{
|
||||
"min": ["0","0","9223372036854775807","-9223372036854775808","18446744073709551615",[],["0","0"]],
|
||||
"max": ["0","0","9223372036854775807","-9223372036854775808","18446744073709551615",[],["0","0"]]
|
||||
},
|
||||
|
||||
"rows": 1
|
||||
}
|
||||
{"i0":"0","u0":"0","ip":"9223372036854775807","in":"-9223372036854775808","up":"18446744073709551615","arr":["0"],"tuple":["0","0"]}
|
||||
{
|
||||
"meta":
|
||||
[
|
||||
{
|
||||
"name": "i0",
|
||||
"type": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "u0",
|
||||
"type": "UInt64"
|
||||
},
|
||||
{
|
||||
"name": "ip",
|
||||
"type": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "in",
|
||||
"type": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "up",
|
||||
"type": "UInt64"
|
||||
},
|
||||
{
|
||||
"name": "arr",
|
||||
"type": "Array(Int64)"
|
||||
},
|
||||
{
|
||||
"name": "tuple",
|
||||
"type": "Tuple(UInt64, UInt64)"
|
||||
}
|
||||
],
|
||||
|
||||
"data":
|
||||
[
|
||||
{
|
||||
"i0": 0,
|
||||
"u0": 0,
|
||||
"ip": 9223372036854775807,
|
||||
"in": -9223372036854775808,
|
||||
"up": 18446744073709551615,
|
||||
"arr": [0],
|
||||
"tuple": [0,0]
|
||||
}
|
||||
],
|
||||
|
||||
"totals":
|
||||
{
|
||||
"i0": 0,
|
||||
"u0": 0,
|
||||
"ip": 0,
|
||||
"in": 0,
|
||||
"up": 0,
|
||||
"arr": [],
|
||||
"tuple": [0,0]
|
||||
},
|
||||
|
||||
"extremes":
|
||||
{
|
||||
"min":
|
||||
{
|
||||
"i0": 0,
|
||||
"u0": 0,
|
||||
"ip": 9223372036854775807,
|
||||
"in": -9223372036854775808,
|
||||
"up": 18446744073709551615,
|
||||
"arr": [],
|
||||
"tuple": [0,0]
|
||||
},
|
||||
"max":
|
||||
{
|
||||
"i0": 0,
|
||||
"u0": 0,
|
||||
"ip": 9223372036854775807,
|
||||
"in": -9223372036854775808,
|
||||
"up": 18446744073709551615,
|
||||
"arr": [],
|
||||
"tuple": [0,0]
|
||||
}
|
||||
},
|
||||
|
||||
"rows": 1
|
||||
}
|
||||
{
|
||||
"meta":
|
||||
[
|
||||
{
|
||||
"name": "i0",
|
||||
"type": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "u0",
|
||||
"type": "UInt64"
|
||||
},
|
||||
{
|
||||
"name": "ip",
|
||||
"type": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "in",
|
||||
"type": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "up",
|
||||
"type": "UInt64"
|
||||
},
|
||||
{
|
||||
"name": "arr",
|
||||
"type": "Array(Int64)"
|
||||
},
|
||||
{
|
||||
"name": "tuple",
|
||||
"type": "Tuple(UInt64, UInt64)"
|
||||
}
|
||||
],
|
||||
|
||||
"data":
|
||||
[
|
||||
[0, 0, 9223372036854775807, -9223372036854775808, 18446744073709551615, [0], [0,0]]
|
||||
],
|
||||
|
||||
"totals": [0,0,0,0,0,[],[0,0]],
|
||||
|
||||
"extremes":
|
||||
{
|
||||
"min": [0,0,9223372036854775807,-9223372036854775808,18446744073709551615,[],[0,0]],
|
||||
"max": [0,0,9223372036854775807,-9223372036854775808,18446744073709551615,[],[0,0]]
|
||||
},
|
||||
|
||||
"rows": 1
|
||||
}
|
||||
{"i0":0,"u0":0,"ip":9223372036854775807,"in":-9223372036854775808,"up":18446744073709551615,"arr":[0],"tuple":[0,0]}
|
@ -0,0 +1,12 @@
|
||||
SET output_format_write_statistics = 0;
|
||||
SET extremes = 1;
|
||||
|
||||
SET output_format_json_quote_64bit_integers = 1;
|
||||
SELECT toInt64(0) as i0, toUInt64(0) as u0, toInt64(9223372036854775807) as ip, toInt64(-9223372036854775808) as in, toUInt64(18446744073709551615) as up, [toInt64(0)] as arr, (toUInt64(0), toUInt64(0)) as tuple WITH TOTALS FORMAT JSON;
|
||||
SELECT toInt64(0) as i0, toUInt64(0) as u0, toInt64(9223372036854775807) as ip, toInt64(-9223372036854775808) as in, toUInt64(18446744073709551615) as up, [toInt64(0)] as arr, (toUInt64(0), toUInt64(0)) as tuple WITH TOTALS FORMAT JSONCompact;
|
||||
SELECT toInt64(0) as i0, toUInt64(0) as u0, toInt64(9223372036854775807) as ip, toInt64(-9223372036854775808) as in, toUInt64(18446744073709551615) as up, [toInt64(0)] as arr, (toUInt64(0), toUInt64(0)) as tuple WITH TOTALS FORMAT JSONEachRow;
|
||||
|
||||
SET output_format_json_quote_64bit_integers = 0;
|
||||
SELECT toInt64(0) as i0, toUInt64(0) as u0, toInt64(9223372036854775807) as ip, toInt64(-9223372036854775808) as in, toUInt64(18446744073709551615) as up, [toInt64(0)] as arr, (toUInt64(0), toUInt64(0)) as tuple WITH TOTALS FORMAT JSON;
|
||||
SELECT toInt64(0) as i0, toUInt64(0) as u0, toInt64(9223372036854775807) as ip, toInt64(-9223372036854775808) as in, toUInt64(18446744073709551615) as up, [toInt64(0)] as arr, (toUInt64(0), toUInt64(0)) as tuple WITH TOTALS FORMAT JSONCompact;
|
||||
SELECT toInt64(0) as i0, toUInt64(0) as u0, toInt64(9223372036854775807) as ip, toInt64(-9223372036854775808) as in, toUInt64(18446744073709551615) as up, [toInt64(0)] as arr, (toUInt64(0), toUInt64(0)) as tuple WITH TOTALS FORMAT JSONEachRow;
|
@ -0,0 +1 @@
|
||||
1390
|
4
dbms/tests/queries/0_stateless/00379_system_processes_port.sh
Executable file
4
dbms/tests/queries/0_stateless/00379_system_processes_port.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
curl --local-port 1390 'http://localhost:8123?query=SELECT%20port%20FROM%20system.processes%20ORDER%20BY%20elapsed%20LIMIT%201'
|
@ -6616,12 +6616,17 @@ Allows setting a default sampling coefficient for all SELECT queries.
|
||||
(For tables that don't support sampling, an exception will be thrown.)
|
||||
If set to 1, default sampling is not performed.
|
||||
|
||||
====input_format_skip_unknown_fields==
|
||||
==input_format_skip_unknown_fields==
|
||||
|
||||
If the parameter is true, INSERT operation will skip columns with unknown names from input.
|
||||
Otherwise, an exception will be generated.
|
||||
Otherwise, an exception will be generated, it is default behavior.
|
||||
The parameter works only for JSONEachRow and TSKV input formats.
|
||||
|
||||
==output_format_json_quote_64bit_integers==
|
||||
|
||||
If the parameter is true (default value), UInt64 and Int64 numbers are printed as quoted strings in all JSON output formats.
|
||||
Such behavior is compatible with most JavaScript interpreters that stores all numbers as double-precision floating point numbers.
|
||||
Otherwise, they are printed as regular numbers.
|
||||
|
||||
==Restrictions on query complexity==
|
||||
|
||||
|
@ -3881,7 +3881,7 @@ Extremes:
|
||||
}
|
||||
%%
|
||||
|
||||
JSON совместим с JavaScript. Для этого, дополнительно эскейпятся некоторые символы: символ прямого слеша %%/%% экранируется в виде %%\/%%; альтернативные переводы строк %%U+2028%%, %%U+2029%%, на которых ломаются некоторые браузеры, экранируются в виде <span class="inline-example">\u<i>XXXX</i></span>-последовательностей. Эскейпятся ASCII control characters: backspace, form feed, line feed, carriage return, horizontal tab в виде %%\b%%, %%\f%%, %%\n%%, %%\r%%, %%\t%% соответственно, а также остальные байты из диапазона 00-1F с помощью <span class="inline-example">\u<i>XXXX</i></span>-последовательностей. Невалидные UTF-8 последовательности заменяются на replacement character %%<25>%% и, таким образом, выводимый текст будет состоять из валидных UTF-8 последовательностей. Числа типа UInt64 и Int64, для совместимости с JavaScript, выводятся в двойных кавычках.
|
||||
JSON совместим с JavaScript. Для этого, дополнительно эскейпятся некоторые символы: символ прямого слеша %%/%% экранируется в виде %%\/%%; альтернативные переводы строк %%U+2028%%, %%U+2029%%, на которых ломаются некоторые браузеры, экранируются в виде <span class="inline-example">\u<i>XXXX</i></span>-последовательностей. Эскейпятся ASCII control characters: backspace, form feed, line feed, carriage return, horizontal tab в виде %%\b%%, %%\f%%, %%\n%%, %%\r%%, %%\t%% соответственно, а также остальные байты из диапазона 00-1F с помощью <span class="inline-example">\u<i>XXXX</i></span>-последовательностей. Невалидные UTF-8 последовательности заменяются на replacement character %%<25>%% и, таким образом, выводимый текст будет состоять из валидных UTF-8 последовательностей. Числа типа UInt64 и Int64, для совместимости с JavaScript, по-умолчанию выводятся в двойных кавычках, чтобы они выводились без кавычек можно установить конфигурационный параметр output_format_json_quote_64bit_integers равным 0.
|
||||
|
||||
%%rows%% - общее количество выведенных строчек.
|
||||
%%rows_before_limit_at_least%% - не менее скольких строчек получилось бы, если бы не было LIMIT-а. Выводится только если запрос содержит LIMIT.
|
||||
@ -6775,6 +6775,10 @@ regions_names_*.txt: TabSeparated (без заголовка), столбцы:
|
||||
Если значение истино, то при выполнении INSERT из входных данных пропускаются (не рассматриваются) колонки с неизвестными именами, иначе в данной ситуации будет сгенерировано исключение.
|
||||
Работает для форматов JSONEachRow и TSKV.
|
||||
|
||||
==output_format_json_quote_64bit_integers==
|
||||
|
||||
Если значение истино, то при использовании JSON* форматов UInt64 и Int64 числа выводятся в кавычках (из соображений совместимости с большинством реализаций JavaScript), иначе - без кавычек.
|
||||
|
||||
|
||||
==Ограничения на сложность запроса==
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user