mirror of https://github.com/layters/testshop
parent
40c5c4fe44
commit
3ff1925055
@ -0,0 +1,139 @@
|
||||
##=============================================================================
|
||||
##
|
||||
## Copyright (c) Kitware, Inc.
|
||||
## All rights reserved.
|
||||
## See LICENSE.txt for details.
|
||||
##
|
||||
## This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
## PURPOSE. See the above copyright notice for more information.
|
||||
##
|
||||
##=============================================================================
|
||||
# - Try to find ZeroMQ headers and libraries
|
||||
#
|
||||
# Usage of this module as follows:
|
||||
#
|
||||
# find_package(ZeroMQ)
|
||||
#
|
||||
# Variables used by this module, they can change the default behaviour and need
|
||||
# to be set before calling find_package:
|
||||
#
|
||||
# ZeroMQ_ROOT_DIR Set this variable to the root installation of
|
||||
# ZeroMQ if the module has problems finding
|
||||
# the proper installation path.
|
||||
#
|
||||
# Variables defined by this module:
|
||||
#
|
||||
# ZeroMQ_FOUND System has ZeroMQ libs/headers
|
||||
# ZeroMQ_LIBRARIES The ZeroMQ libraries
|
||||
# ZeroMQ_INCLUDE_DIR The location of ZeroMQ headers
|
||||
# ZeroMQ_VERSION The version of ZeroMQ
|
||||
|
||||
find_path(ZeroMQ_ROOT_DIR
|
||||
NAMES include/zmq.h
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
#add in all the names it can have on windows
|
||||
if(CMAKE_GENERATOR_TOOLSET MATCHES "v140" OR MSVC14)
|
||||
set(_zmq_TOOLSET "-v140")
|
||||
elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v120" OR MSVC12)
|
||||
set(_zmq_TOOLSET "-v120")
|
||||
elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v110_xp")
|
||||
set(_zmq_TOOLSET "-v110_xp")
|
||||
elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v110" OR MSVC11)
|
||||
set(_zmq_TOOLSET "-v110")
|
||||
elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v100" OR MSVC10)
|
||||
set(_zmq_TOOLSET "-v100")
|
||||
elseif(CMAKE_GENERATOR_TOOLSET MATCHES "v90" OR MSVC90)
|
||||
set(_zmq_TOOLSET "-v90")
|
||||
endif()
|
||||
|
||||
set(_zmq_versions
|
||||
"4_1_5" "4_1_4" "4_1_3" "4_1_2" "4_1_1" "4_1_0"
|
||||
"4_0_8" "4_0_7" "4_0_6" "4_0_5" "4_0_4" "4_0_3" "4_0_2" "4_0_1" "4_0_0"
|
||||
"3_2_5" "3_2_4" "3_2_3" "3_2_2" "3_2_1" "3_2_0" "3_1_0")
|
||||
|
||||
set(_zmq_release_names)
|
||||
set(_zmq_debug_names)
|
||||
foreach( ver ${_zmq_versions})
|
||||
list(APPEND _zmq_release_names "libzmq${_zmq_TOOLSET}-mt-${ver}")
|
||||
endforeach()
|
||||
foreach( ver ${_zmq_versions})
|
||||
list(APPEND _zmq_debug_names "libzmq${_zmq_TOOLSET}-mt-gd-${ver}")
|
||||
endforeach()
|
||||
|
||||
#now try to find the release and debug version
|
||||
find_library(ZeroMQ_LIBRARY_RELEASE
|
||||
NAMES ${_zmq_release_names} zmq libzmq
|
||||
HINTS ${ZeroMQ_ROOT_DIR}/bin
|
||||
${ZeroMQ_ROOT_DIR}/lib
|
||||
)
|
||||
|
||||
find_library(ZeroMQ_LIBRARY_DEBUG
|
||||
NAMES ${_zmq_debug_names} zmq libzmq
|
||||
HINTS ${ZeroMQ_ROOT_DIR}/bin
|
||||
${ZeroMQ_ROOT_DIR}/lib
|
||||
)
|
||||
|
||||
if(ZeroMQ_LIBRARY_RELEASE AND ZeroMQ_LIBRARY_DEBUG)
|
||||
set(ZeroMQ_LIBRARY
|
||||
debug ${ZeroMQ_LIBRARY_DEBUG}
|
||||
optimized ${ZeroMQ_LIBRARY_RELEASE}
|
||||
)
|
||||
elseif(ZeroMQ_LIBRARY_RELEASE)
|
||||
set(ZeroMQ_LIBRARY ${ZeroMQ_LIBRARY_RELEASE})
|
||||
elseif(ZeroMQ_LIBRARY_DEBUG)
|
||||
set(ZeroMQ_LIBRARY ${ZeroMQ_LIBRARY_DEBUG})
|
||||
endif()
|
||||
|
||||
else()
|
||||
find_library(ZeroMQ_LIBRARY
|
||||
NAMES zmq libzmq
|
||||
HINTS ${ZeroMQ_ROOT_DIR}/lib
|
||||
)
|
||||
endif()
|
||||
|
||||
find_path(ZeroMQ_INCLUDE_DIR
|
||||
NAMES zmq.h
|
||||
HINTS ${ZeroMQ_ROOT_DIR}/include
|
||||
)
|
||||
|
||||
function(extract_version_value value_name file_name value)
|
||||
file(STRINGS ${file_name} val REGEX "${value_name} .")
|
||||
string(FIND ${val} " " last REVERSE)
|
||||
string(SUBSTRING ${val} ${last} -1 val)
|
||||
string(STRIP ${val} val)
|
||||
set(${value} ${val} PARENT_SCOPE)
|
||||
endfunction(extract_version_value)
|
||||
|
||||
extract_version_value("ZMQ_VERSION_MAJOR" ${ZeroMQ_INCLUDE_DIR}/zmq.h MAJOR)
|
||||
extract_version_value("ZMQ_VERSION_MINOR" ${ZeroMQ_INCLUDE_DIR}/zmq.h MINOR)
|
||||
extract_version_value("ZMQ_VERSION_PATCH" ${ZeroMQ_INCLUDE_DIR}/zmq.h PATCH)
|
||||
|
||||
set(ZeroMQ_VER "${MAJOR}.${MINOR}.${PATCH}")
|
||||
|
||||
#We are using the 2.8.10 signature of find_package_handle_standard_args,
|
||||
#as that is the version that ParaView 5.1 && VTK 6/7 ship, and inject
|
||||
#into the CMake module path. This allows our FindModule to work with
|
||||
#projects that include VTK/ParaView before searching for Remus
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(
|
||||
ZeroMQ
|
||||
REQUIRED_VARS ZeroMQ_LIBRARY ZeroMQ_INCLUDE_DIR
|
||||
VERSION_VAR ZeroMQ_VER
|
||||
)
|
||||
|
||||
set(ZeroMQ_FOUND ${ZEROMQ_FOUND})
|
||||
set(ZeroMQ_INCLUDE_DIRS ${ZeroMQ_INCLUDE_DIR})
|
||||
set(ZeroMQ_LIBRARIES ${ZeroMQ_LIBRARY})
|
||||
set(ZeroMQ_VERSION ${ZeroMQ_VER})
|
||||
|
||||
mark_as_advanced(
|
||||
ZeroMQ_ROOT_DIR
|
||||
ZeroMQ_LIBRARY
|
||||
ZeroMQ_LIBRARY_DEBUG
|
||||
ZeroMQ_LIBRARY_RELEASE
|
||||
ZeroMQ_INCLUDE_DIR
|
||||
ZeroMQ_VERSION
|
||||
)
|
Before Width: | Height: | Size: 1013 B After Width: | Height: | Size: 744 B |
@ -0,0 +1,439 @@
|
||||
#include "sqlite.hpp"
|
||||
|
||||
|
||||
neroshop::db::Sqlite3::Sqlite3() : handle(nullptr), opened(false) {}
|
||||
////////////////////
|
||||
neroshop::db::Sqlite3::Sqlite3(const std::string& filename) : Sqlite3()
|
||||
{
|
||||
if(!open(filename)) {
|
||||
throw std::runtime_error(std::string("sqlite3_open: ") + std::string(sqlite3_errmsg(handle)));
|
||||
}
|
||||
}
|
||||
////////////////////
|
||||
neroshop::db::Sqlite3::~Sqlite3() {
|
||||
close();
|
||||
}
|
||||
////////////////////
|
||||
// SQLite database should only need to be opened once per application session and closed once when the application is terminated
|
||||
bool neroshop::db::Sqlite3::open(const std::string& filename)
|
||||
{
|
||||
if(opened) {
|
||||
neroshop::print("database is already opened", 2);
|
||||
return true;
|
||||
}
|
||||
if(sqlite3_open(filename.c_str(), &handle) != SQLITE_OK) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
// Enable Write-Ahead Log. This will prevent the database from being locked
|
||||
if(get_text("PRAGMA journal_mode;") != "wal") {
|
||||
execute("PRAGMA journal_mode = WAL;"); // requires version 3.7.0 (2010-07-21)
|
||||
}
|
||||
// Enable Foreign keys
|
||||
if(get_integer("PRAGMA foreign_keys;") != 1) {
|
||||
execute("PRAGMA foreign_keys = ON;"); // requires version 3.6.19 (2009-10-14)
|
||||
}
|
||||
opened = true;
|
||||
return true;
|
||||
}
|
||||
////////////////////
|
||||
void neroshop::db::Sqlite3::close() {
|
||||
if(!handle) {
|
||||
return;
|
||||
}
|
||||
sqlite3_close(handle);
|
||||
handle = nullptr;
|
||||
opened = false;
|
||||
neroshop::print("database is now closed");
|
||||
}
|
||||
////////////////////
|
||||
void neroshop::db::Sqlite3::execute(const std::string& command)
|
||||
{
|
||||
if(!handle) throw std::runtime_error("database is not connected");
|
||||
char * error_message = 0;
|
||||
int result = sqlite3_exec(handle, command.c_str(), neroshop::db::Sqlite3::callback, 0, &error_message);
|
||||
if (result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_exec: " + std::string(error_message), 1);
|
||||
sqlite3_free(error_message);
|
||||
}
|
||||
}
|
||||
////////////////////
|
||||
void neroshop::db::Sqlite3::execute_params(const std::string& command, const std::vector<std::string>& args) {
|
||||
if(!handle) throw std::runtime_error("database is not connected");
|
||||
// Prepare statement
|
||||
sqlite3_stmt * statement = nullptr;
|
||||
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &statement, nullptr);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_prepare_v2: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
// Since we don't prepare a statement here, there is no need to finalise it
|
||||
return;
|
||||
}
|
||||
// Bind user-defined parameter arguments
|
||||
for(int i = 0; i < args.size()/*sqlite3_bind_parameter_count(statement)*/; i++) {
|
||||
result = sqlite3_bind_text(statement, i + 1, args[i].c_str(), args[i].length(), SQLITE_STATIC);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_bind_*: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
sqlite3_finalize(statement);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Evaluate the statement
|
||||
result = sqlite3_step(statement);
|
||||
if(result != SQLITE_DONE) {
|
||||
neroshop::print("sqlite3_step: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
sqlite3_finalize(statement);
|
||||
return;
|
||||
}
|
||||
// Finalize (destroy) the prepared statement
|
||||
result = sqlite3_finalize(statement);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_finalize: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
sqlite3_finalize(statement);
|
||||
return;
|
||||
}
|
||||
// We are not returning anything, just setting executing queries
|
||||
}
|
||||
////////////////////
|
||||
////////////////////
|
||||
////////////////////
|
||||
std::string neroshop::db::Sqlite3::get_sqlite_version() {
|
||||
return sqlite3_libversion();
|
||||
}
|
||||
////////////////////
|
||||
sqlite3 * neroshop::db::Sqlite3::get_handle() const {
|
||||
return handle;
|
||||
}
|
||||
////////////////////
|
||||
void * neroshop::db::Sqlite3::get_blob(const std::string& command) {
|
||||
if(!handle) throw std::runtime_error("database is not connected");
|
||||
sqlite3_stmt * statement = nullptr;
|
||||
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &statement, nullptr);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_prepare_v2: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
return nullptr;
|
||||
}
|
||||
result = sqlite3_step(statement);
|
||||
if (result != SQLITE_ROW) {
|
||||
neroshop::print("sqlite3_step: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
sqlite3_finalize(statement);
|
||||
return nullptr;
|
||||
}
|
||||
int column_type = sqlite3_column_type(statement, 0);
|
||||
if(column_type == SQLITE_NULL) {
|
||||
sqlite3_finalize(statement);
|
||||
return nullptr;
|
||||
}
|
||||
if(column_type != SQLITE_BLOB) { // NULL is the only other acceptable return type
|
||||
neroshop::print("sqlite3_column_type: invalid column return type\ncommand: " + command, 1);
|
||||
sqlite3_finalize(statement);
|
||||
return nullptr;
|
||||
}
|
||||
void * blob = const_cast<void *>(sqlite3_column_blob(statement, 0));//reinterpret_cast<const char *>(sqlite3_column_text16(stmt, 0)); // utf-16
|
||||
sqlite3_finalize(statement);
|
||||
return blob;
|
||||
}
|
||||
////////////////////
|
||||
void * neroshop::db::Sqlite3::get_blob_params(const std::string& command, const std::vector<std::string>& args) {
|
||||
if(!handle) throw std::runtime_error("database is not connected");
|
||||
sqlite3_stmt * statement = nullptr;
|
||||
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &statement, nullptr);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_prepare_v2: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
return nullptr;
|
||||
}
|
||||
// Bind user-defined parameter arguments
|
||||
for(int i = 0; i < args.size()/*sqlite3_bind_parameter_count(statement)*/; i++) {
|
||||
result = sqlite3_bind_text(statement, i + 1, args[i].c_str(), args[i].length(), SQLITE_STATIC);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_bind_*: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
sqlite3_finalize(statement);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
sqlite3_step(statement); // Don't check for error or it'll keep saying: "another row available" or "no more rows available"
|
||||
int column_type = sqlite3_column_type(statement, 0);
|
||||
if(column_type == SQLITE_NULL) {
|
||||
sqlite3_finalize(statement);
|
||||
return nullptr;
|
||||
}
|
||||
if(column_type != SQLITE_BLOB) {
|
||||
neroshop::print("sqlite3_column_type: invalid column return type\ncommand: " + command, 1);
|
||||
sqlite3_finalize(statement);
|
||||
return nullptr;
|
||||
}
|
||||
void * blob = const_cast<void *>(sqlite3_column_blob(statement, 0));//reinterpret_cast<const char *>(sqlite3_column_text16(stmt, 0)); // utf-16
|
||||
sqlite3_finalize(statement);
|
||||
return blob;
|
||||
}
|
||||
////////////////////
|
||||
std::string neroshop::db::Sqlite3::get_text(const std::string& command) {//const {
|
||||
if(!handle) throw std::runtime_error("database is not connected");
|
||||
sqlite3_stmt * stmt = nullptr;
|
||||
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &stmt, nullptr);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_prepare_v2: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
return "";
|
||||
}
|
||||
result = sqlite3_step(stmt);
|
||||
if (result != SQLITE_ROW) {
|
||||
neroshop::print("sqlite3_step: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
sqlite3_finalize(stmt);
|
||||
return "";
|
||||
}
|
||||
int column_type = sqlite3_column_type(stmt, 0);
|
||||
if(column_type == SQLITE_NULL) {
|
||||
sqlite3_finalize(stmt);
|
||||
return "";
|
||||
}
|
||||
if(column_type != SQLITE_TEXT) {
|
||||
neroshop::print("sqlite3_column_type: invalid column return type\ncommand: " + command, 1);
|
||||
sqlite3_finalize(stmt);
|
||||
return "";
|
||||
}
|
||||
std::string text = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0));//reinterpret_cast<const char *>(sqlite3_column_text16(stmt, 0)); // utf-16
|
||||
sqlite3_finalize(stmt);
|
||||
return text;
|
||||
}
|
||||
////////////////////
|
||||
std::string neroshop::db::Sqlite3::get_text_params(const std::string& command, const std::vector<std::string>& args) {//const {
|
||||
if(!handle) throw std::runtime_error("database is not connected");
|
||||
// Prepare statement
|
||||
sqlite3_stmt * statement = nullptr;
|
||||
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &statement, nullptr);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_prepare_v2: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
return "";
|
||||
}
|
||||
// Bind user-defined parameter arguments
|
||||
for(int i = 0; i < args.size()/*sqlite3_bind_parameter_count(statement)*/; i++) {
|
||||
result = sqlite3_bind_text(statement, i + 1, args[i].c_str(), args[i].length(), SQLITE_STATIC);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_bind_*: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
sqlite3_finalize(statement);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
// Evaluate statement
|
||||
sqlite3_step(statement); // Don't check for error or it'll keep saying: "another row available" or "no more rows available"
|
||||
// Check the type of the statement's return value
|
||||
int column_type = sqlite3_column_type(statement, 0);
|
||||
if(column_type == SQLITE_NULL) {
|
||||
sqlite3_finalize(statement);
|
||||
return "";
|
||||
}
|
||||
if(column_type != SQLITE_TEXT) {
|
||||
neroshop::print("sqlite3_column_type: invalid column return type\ncommand: " + command, 1);
|
||||
sqlite3_finalize(statement);
|
||||
return "";
|
||||
}
|
||||
// Finalize (destroy) the prepared statement
|
||||
std::string text = reinterpret_cast<const char *>(sqlite3_column_text(statement, 0));//reinterpret_cast<const char *>(sqlite3_column_text16(stmt, 0)); // utf-16
|
||||
sqlite3_finalize(statement);
|
||||
return text;
|
||||
}
|
||||
////////////////////
|
||||
int neroshop::db::Sqlite3::get_integer(const std::string& command) {
|
||||
if(!handle) throw std::runtime_error("database is not connected");
|
||||
sqlite3_stmt * statement = nullptr;
|
||||
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &statement, nullptr);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_prepare_v2: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
return 0;
|
||||
}
|
||||
result = sqlite3_step(statement);
|
||||
if (result != SQLITE_ROW) {
|
||||
neroshop::print("sqlite3_step: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
sqlite3_finalize(statement);
|
||||
return 0;
|
||||
}
|
||||
int column_type = sqlite3_column_type(statement, 0);
|
||||
if(column_type == SQLITE_NULL) {
|
||||
sqlite3_finalize(statement);
|
||||
return 0;
|
||||
}
|
||||
if(column_type != SQLITE_INTEGER) {
|
||||
neroshop::print("sqlite3_column_type: invalid column return type\ncommand: " + command, 1);
|
||||
sqlite3_finalize(statement);
|
||||
return 0;
|
||||
}
|
||||
int number = sqlite3_column_int64(statement, 0);//sqlite3_column_int(statement, 0);
|
||||
sqlite3_finalize(statement);
|
||||
return number;
|
||||
}
|
||||
////////////////////
|
||||
int neroshop::db::Sqlite3::get_integer_params(const std::string& command, const std::vector<std::string>& args) {
|
||||
if(!handle) throw std::runtime_error("database is not connected");
|
||||
// Prepare statement
|
||||
sqlite3_stmt * statement = nullptr;
|
||||
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &statement, nullptr);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_prepare_v2: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
return 0;
|
||||
}
|
||||
// Bind user-defined parameter arguments
|
||||
for(int i = 0; i < args.size()/*sqlite3_bind_parameter_count(statement)*/; i++) {
|
||||
result = sqlite3_bind_text(statement, i + 1, args[i].c_str(), args[i].length(), SQLITE_STATIC);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_bind_*: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
sqlite3_finalize(statement);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// Evaluate statement
|
||||
sqlite3_step(statement); // Don't check for error or it'll keep saying: "another row available" or "no more rows available"
|
||||
// Check the type of the statement's return value
|
||||
int column_type = sqlite3_column_type(statement, 0);
|
||||
if(column_type == SQLITE_NULL) {
|
||||
sqlite3_finalize(statement);
|
||||
return 0;
|
||||
}
|
||||
if(column_type != SQLITE_INTEGER) {
|
||||
neroshop::print("sqlite3_column_type: invalid column return type\ncommand: " + command, 1);
|
||||
sqlite3_finalize(statement);
|
||||
return 0;
|
||||
}
|
||||
// Finalize (destroy) the prepared statement
|
||||
int number = sqlite3_column_int64(statement, 0);//sqlite3_column_int(statement, 0);
|
||||
sqlite3_finalize(statement);
|
||||
return number;
|
||||
}
|
||||
////////////////////
|
||||
double neroshop::db::Sqlite3::get_real(const std::string& command) {
|
||||
if(!handle) throw std::runtime_error("database is not connected");
|
||||
sqlite3_stmt * stmt = nullptr;
|
||||
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &stmt, nullptr);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_prepare_v2: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
return 0.0;
|
||||
}
|
||||
result = sqlite3_step(stmt);
|
||||
if (result != SQLITE_ROW) {
|
||||
neroshop::print("sqlite3_step: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
sqlite3_finalize(stmt);
|
||||
return 0.0;
|
||||
}
|
||||
int column_type = sqlite3_column_type(stmt, 0);
|
||||
if(column_type == SQLITE_NULL) {
|
||||
sqlite3_finalize(stmt);
|
||||
return 0.0;
|
||||
}
|
||||
if(column_type != SQLITE_FLOAT) {
|
||||
neroshop::print("sqlite3_column_type: invalid column return type\ncommand: " + command, 1);
|
||||
sqlite3_finalize(stmt);
|
||||
return 0.0;
|
||||
}
|
||||
double number = sqlite3_column_double(stmt, 0);
|
||||
sqlite3_finalize(stmt);
|
||||
return number;
|
||||
}
|
||||
////////////////////
|
||||
double neroshop::db::Sqlite3::get_real_params(const std::string& command, const std::vector<std::string>& args) {
|
||||
if(!handle) throw std::runtime_error("database is not connected");
|
||||
// Prepare statement
|
||||
sqlite3_stmt * statement = nullptr;
|
||||
int result = sqlite3_prepare_v2(handle, command.c_str(), -1, &statement, nullptr);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_prepare_v2: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
return 0.0;
|
||||
}
|
||||
// Bind user-defined parameter arguments
|
||||
for(int i = 0; i < args.size()/*sqlite3_bind_parameter_count(statement)*/; i++) {
|
||||
result = sqlite3_bind_text(statement, i + 1, args[i].c_str(), args[i].length(), SQLITE_STATIC);
|
||||
if(result != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_bind_*: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
sqlite3_finalize(statement);
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
// Evaluate statement
|
||||
sqlite3_step(statement); // Don't check for error or it'll keep saying: "another row available" or "no more rows available"
|
||||
// Check the type of the statement's return value
|
||||
int column_type = sqlite3_column_type(statement, 0);
|
||||
if(column_type == SQLITE_NULL) {
|
||||
sqlite3_finalize(statement);
|
||||
return 0.0;
|
||||
}
|
||||
if(column_type != SQLITE_FLOAT) {
|
||||
neroshop::print("sqlite3_column_type: invalid column return type\ncommand: " + command, 1);
|
||||
sqlite3_finalize(statement);
|
||||
return 0.0;
|
||||
}
|
||||
// Finalize (destroy) the prepared statement
|
||||
double number = sqlite3_column_double(statement, 0);
|
||||
sqlite3_finalize(statement);
|
||||
return number;
|
||||
}
|
||||
////////////////////
|
||||
std::vector<std::string> neroshop::db::Sqlite3::get_rows(const std::string& command) {
|
||||
if(!handle) throw std::runtime_error("database is not connected");
|
||||
sqlite3_stmt * stmt = nullptr;
|
||||
std::vector<std::string> row_values = {};
|
||||
// Prepare (compile) statement
|
||||
if(sqlite3_prepare_v2(handle, command.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
neroshop::print("sqlite3_prepare_v2: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
return {};
|
||||
}
|
||||
// Check whether the prepared statement returns no data (for example an UPDATE)
|
||||
// "SELECT name FROM users ORDER BY id;" = 1 column
|
||||
// "SELECT name, age FROM users ORDER BY id;" = 2 columns
|
||||
// "SELECT * FROM users ORDER BY id;" = all column(s) including the id
|
||||
if(sqlite3_column_count(stmt) == 0) {
|
||||
neroshop::print("No data found. Be sure to use an appropriate SELECT statement", 1);
|
||||
return {};
|
||||
}
|
||||
// Get all table values row by row instead of column by column
|
||||
int result = 0;
|
||||
while((result = sqlite3_step(stmt)) == SQLITE_ROW) {
|
||||
for(int i = 0; i < sqlite3_column_count(stmt); i++) {
|
||||
std::string column_value = (sqlite3_column_text(stmt, i) == nullptr) ? "" : reinterpret_cast<const char *>(sqlite3_column_text(stmt, i));////if(sqlite3_column_text(stmt, i) == nullptr) {throw std::runtime_error("column is NULL");}
|
||||
row_values.push_back(column_value); //std::cout << sqlite3_column_text(stmt, i) << std::endl;//std::cout << sqlite3_column_name(stmt, i) << std::endl;
|
||||
// To get a specific column use: if(i == 0) {} or any number
|
||||
// or call sqlite3_column_name for each column
|
||||
}
|
||||
}
|
||||
|
||||
if(result != SQLITE_DONE) {
|
||||
neroshop::print("sqlite3_step: " + std::string(sqlite3_errmsg(handle)), 1);
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return row_values;
|
||||
}
|
||||
////////////////////
|
||||
////////////////////
|
||||
////////////////////
|
||||
////////////////////
|
||||
bool neroshop::db::Sqlite3::is_open() const {
|
||||
return (opened == true);
|
||||
}
|
||||
////////////////////
|
||||
bool neroshop::db::Sqlite3::table_exists(const std::string& table_name) {
|
||||
std::string command = "SELECT count(*) FROM sqlite_master WHERE type = 'table' AND name = $1;";
|
||||
return get_integer_params(command, { table_name });
|
||||
}
|
||||
////////////////////
|
||||
/*bool neroshop::db::Sqlite3::rowid_exists(const std::string& table_name, int rowid) {
|
||||
int rowid = database->get_integer_params("SELECT id FROM $1 WHERE id = $2", { table_name, rowid });
|
||||
return (rowid != 0);
|
||||
}*/
|
||||
////////////////////
|
||||
////////////////////
|
||||
////////////////////
|
||||
int neroshop::db::Sqlite3::callback(void *not_used, int argc, char **argv, char **az_col_name)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < argc; i++) {
|
||||
std::cout << SQLITE3_TAG << az_col_name[i] << " = " << (argv[i] ? argv[i] : "NULL") << std::endl; // printf("%s = %s\n", azcolname[i], argv[i] ? argv[i] : "nullptr");
|
||||
}
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
||||
////////////////////
|
||||
////////////////////
|
||||
////////////////////
|
||||
////////////////////
|
||||
////////////////////
|
||||
////////////////////
|
||||
////////////////////
|
||||
////////////////////
|
@ -0,0 +1,140 @@
|
||||
#include "rpc.hpp"
|
||||
|
||||
std::string neroshop::rpc::translate(const std::string& sql) {
|
||||
std::string request = "";
|
||||
#if defined(NEROSHOP_USE_QT)
|
||||
QJsonObject request_object; // JSON-RPC Request object
|
||||
|
||||
request_object.insert(QString("jsonrpc"), QJsonValue("2.0"));
|
||||
request_object.insert(QString("method"), QJsonValue("query"));////QJsonValue(QString::fromStdString(method_type)));
|
||||
QJsonObject params_object;////QJsonArray params_array; // can be an array or object
|
||||
params_object.insert(QString("sql"), QJsonValue(QString::fromStdString(sql)));////params_array.insert(params_array.size(), QJsonValue("arg1")); // based on the number of parameter args
|
||||
request_object.insert(QString("params"), QJsonValue(params_object));
|
||||
// Generate random number for id (id can be either a string or an integer or null which is not recommended)
|
||||
std::random_device rd; // obtain a random number from hardware
|
||||
std::mt19937 gen(rd()); // seed the generator
|
||||
std::uniform_int_distribution<> distr(1, 9); // define the range
|
||||
std::string random_id;
|
||||
for(int n = 0; n < 10; ++n) {
|
||||
int random_integer = distr(gen); // generate numbers
|
||||
random_id = random_id + std::to_string(random_integer); // append 10 different numbers to generate a unique id
|
||||
}
|
||||
request_object.insert(QString("id"), QJsonValue(QString::fromStdString(random_id))); // https://stackoverflow.com/questions/2210791/json-rpc-what-is-the-id-for
|
||||
// Convert JSON to string then display it (for debugging purposes)
|
||||
QJsonDocument json_doc(request_object);
|
||||
QString json_str = json_doc.toJson();////(QJsonDocument::Compact); // https://doc.qt.io/qt-6/qjsondocument.html#JsonFormat-enum
|
||||
request = json_str.toStdString();
|
||||
#else
|
||||
nlohmann::json json;
|
||||
json["jsonrpc"] = "2.0";
|
||||
json["method"] = "query";////get_method(sql);
|
||||
json["params"]["sql"] = sql;
|
||||
// Generate random number for id (id can be either a string or an integer or null which is not recommended)
|
||||
std::random_device rd; // obtain a random number from hardware
|
||||
std::mt19937 gen(rd()); // seed the generator
|
||||
std::uniform_int_distribution<> distr(1, 9); // define the range
|
||||
std::string random_id;
|
||||
for(int n = 0; n < 10; ++n) {
|
||||
int random_integer = distr(gen); // generate numbers
|
||||
random_id = random_id + std::to_string(random_integer); // append 10 different numbers to generate a unique id
|
||||
}
|
||||
json["id"] = random_id;
|
||||
// Dump JSON to string
|
||||
request = json.dump(4);////json.dump();
|
||||
#endif
|
||||
#ifdef NEROSHOP_DEBUG
|
||||
std::cout << "\"" << sql << "\" has been translated to: \n" << request << std::endl;
|
||||
#endif
|
||||
return request;
|
||||
}
|
||||
|
||||
std::string neroshop::rpc::translate(const std::string& sql, const std::vector<std::string>& args) {
|
||||
std::string request = "";
|
||||
#if defined(NEROSHOP_USE_QT)
|
||||
QJsonObject request_object; // JSON-RPC Request object
|
||||
|
||||
request_object.insert(QString("jsonrpc"), QJsonValue("2.0"));
|
||||
request_object.insert(QString("method"), QJsonValue("query"));
|
||||
QJsonObject params_object;
|
||||
params_object.insert(QString("sql"), QJsonValue(QString::fromStdString(sql))); // eg. "SELECT * FROM products WHERE condition = $1;"
|
||||
params_object.insert(QString("count"), static_cast<int>(args.size()));
|
||||
for(int index = 0; index < args.size(); index++) {
|
||||
std::string arg_key = /*"" + */std::to_string(index + 1);
|
||||
std::string arg_value = args[index];
|
||||
params_object.insert(QString::fromStdString(arg_key), QJsonValue(QString::fromStdString(arg_value)));
|
||||
std::cout << "" << (index + 1) << "= " << arg_value << "\n";
|
||||
}
|
||||
request_object.insert(QString("params"), QJsonValue(params_object));
|
||||
// Generate random number for id (id can be either a string or an integer or null which is not recommended)
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_int_distribution<> distr(1, 9);
|
||||
std::string random_id;
|
||||
for(int n = 0; n < 10; ++n) {
|
||||
int random_integer = distr(gen);
|
||||
random_id = random_id + std::to_string(random_integer);
|
||||
}
|
||||
request_object.insert(QString("id"), QJsonValue(QString::fromStdString(random_id)));
|
||||
// Convert JSON to string
|
||||
QJsonDocument json_doc(request_object);
|
||||
QString json_str = json_doc.toJson();
|
||||
request = json_str.toStdString();
|
||||
#else
|
||||
nlohmann::json json;
|
||||
json["jsonrpc"] = "2.0";
|
||||
json["method"] = "query";////get_method(sql);
|
||||
json["params"]["sql"] = sql;
|
||||
json["params"]["count"] = args.size();
|
||||
for(int index = 0; index < args.size(); index++) {
|
||||
std::string arg_key = std::to_string(index + 1);
|
||||
std::string arg_value = args[index];
|
||||
json["params"][arg_key] = arg_value;
|
||||
}
|
||||
// Generate random number for id (id can be either a string or an integer or null which is not recommended)
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_int_distribution<> distr(1, 9);
|
||||
std::string random_id;
|
||||
for(int n = 0; n < 10; ++n) {
|
||||
int random_integer = distr(gen);
|
||||
random_id = random_id + std::to_string(random_integer);
|
||||
}
|
||||
json["id"] = random_id;
|
||||
// Dump JSON to string
|
||||
request = json.dump(4);////json.dump();
|
||||
#endif
|
||||
#ifdef NEROSHOP_DEBUG
|
||||
std::cout << "\"" << sql << "\" has been translated to: \n" << request << std::endl;
|
||||
#endif
|
||||
return request;
|
||||
}
|
||||
|
||||
void neroshop::rpc::request(const std::string& json) { // TODO: this function should return a json_rpc response from the server
|
||||
// Get the json which is basically a translated sqlite query or a translate method string + args
|
||||
// Passing the data onto the server
|
||||
////zmq_send (requester, request.c_str(), request.size(), 0);
|
||||
// The server will then execute the data
|
||||
// Lastly, the server will return any results
|
||||
} // Usage: neroshop::rpc::request(neroshop::rpc::translate("SELECT * FROM users;"));
|
||||
|
||||
void request_batch(const std::vector<std::string>& json_batch) {
|
||||
}
|
||||
|
||||
void neroshop::rpc::respond(const std::string& json) {
|
||||
std::string response = "";
|
||||
#if defined(NEROSHOP_USE_QT)
|
||||
#endif
|
||||
}
|
||||
|
||||
void neroshop::rpc::respond_batch(const std::vector<std::string>& json_batch) {
|
||||
}
|
||||
|
||||
std::string neroshop::rpc::get_method(const std::string& sql) {
|
||||
std::string first_word = sql.substr(0, sql.find_first_of(" "));
|
||||
if(is_valid_method(first_word)) return first_word;
|
||||
return "";
|
||||
}
|
||||
|
||||
bool neroshop::rpc::is_valid_method(const std::string& method) {
|
||||
return ((std::find(sql_methods.begin(), sql_methods.end(), method) != sql_methods.end()) || (std::find(methods.begin(), methods.end(), method) != methods.end()));
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(NEROSHOP_USE_QT)
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonParseError>
|
||||
#else
|
||||
#include <nlohmann/json.hpp>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
// uncomment to disable assert()
|
||||
// #define NDEBUG
|
||||
////#include <cassert>
|
||||
// neroshop JSON-RPC API // TODO: translate method names like get_product_ratings (along with the args) into json request strings via command line
|
||||
namespace neroshop {
|
||||
|
||||
namespace rpc {
|
||||
static std::vector<std::string> methods = {};//static std::unordered_map<std::string, std::function<void(int)>> methods_cmd
|
||||
static std::vector<std::string> sql_methods = { // TODO: rename to query_type?
|
||||
"SELECT", // extracts data from a database
|
||||
"UPDATE", // updates data in a database
|
||||
"DELETE", // deletes data from a database
|
||||
"INSERT", // "INSERT INTO" - inserts new data into a database
|
||||
"CREATE", // "CREATE DATABASE" - creates a new database // "CREATE TABLE" - creates a new table // "CREATE INDEX" - creates an index (search key)
|
||||
"ALTER", // "ALTER DATABASE" - modifies a database // "ALTER TABLE" - modifies a table
|
||||
"DROP", // "DROP TABLE" - deletes a table // "DROP INDEX" - deletes an index
|
||||
};
|
||||
static std::string get_method(const std::string& sql);
|
||||
static bool is_valid_method(const std::string& method);
|
||||
static std::string translate(const std::string& sql); // converts an sqlite query to a json_rpc request message
|
||||
static std::string translate(const std::string& sql, const std::vector<std::string>& args);
|
||||
template <typename... Args>
|
||||
static std::string translate_cmd(const std::string& method, Args&&... args) { // converts a method (string) and its argument(s) into a json_rpc response message via the command line
|
||||
// accessing the number of args: static const size_t arg_count = sizeof...(Args);
|
||||
//if(method == "get_whatever") { ...
|
||||
// accessing the arguments: functions[name](std::forward<Args>(args)...);
|
||||
return ""; // TEMPORARY
|
||||
}
|
||||
static void request(const std::string& json); // for client - to send requests
|
||||
static void request_batch(const std::vector<std::string>& json_batch); // sends a batch of json_rpc requests to the server and expects a batch of json_rpc responses
|
||||
static void respond(const std::string& json); // for server - to respond to requests
|
||||
static void respond_batch(const std::vector<std::string>& json_batch);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in new issue