added sqlite connection class (progress)
This commit is contained in:
parent
f4f5c00eec
commit
715f4dff8f
|
|
@ -2,15 +2,24 @@ cmake_minimum_required(VERSION 3.26)
|
|||
project(query)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
find_package(ODBC REQUIRED)
|
||||
find_package(SQLite3 REQUIRED)
|
||||
|
||||
message(STATUS "Found SQLite3 ${SQLite3_VERSION}")
|
||||
message(STATUS "Adding SQLite3 include directory: ${SQLite3_INCLUDE_DIRS}")
|
||||
message(STATUS "Adding SQLite3 libs: ${SQLite3_LIBRARIES}")
|
||||
|
||||
message(STATUS "Common flags ${CMAKE_CXX_FLAGS}")
|
||||
message(STATUS "Debug flags ${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
message(STATUS "Relase flags ${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
|
||||
message(STATUS "Linker flags ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(backends)
|
||||
|
||||
add_executable(query main.cpp
|
||||
include/matador/sql/connection_impl.hpp
|
||||
include/matador/sql/connection_info.hpp)
|
||||
add_executable(query main.cpp)
|
||||
target_link_libraries(query matador)
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
add_subdirectory(sqlite)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
set(HEADER
|
||||
include/sqlite_connection.hpp
|
||||
include/sqlite_error.hpp
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
src/sqlite_connection.cpp
|
||||
src/sqlite_error.cpp
|
||||
)
|
||||
|
||||
add_library(matador-sqlite SHARED ${SOURCES} ${HEADER})
|
||||
target_include_directories(matador-sqlite PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
${PROJECT_SOURCE_DIR}/backends/sqlite/include
|
||||
${SQLite3_INCLUDE_DIRS})
|
||||
|
||||
target_link_libraries(matador-sqlite matador ${SQLite3_LIBRARIES})
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef QUERY_SQLITE_CONNECTION_HPP
|
||||
#define QUERY_SQLITE_CONNECTION_HPP
|
||||
|
||||
#include "matador/sql/connection_impl.hpp"
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
namespace matador::backends::sqlite {
|
||||
|
||||
class sqlite_connection : public matador::sql::connection_impl
|
||||
{
|
||||
public:
|
||||
explicit sqlite_connection(sql::connection_info info);
|
||||
void open() override;
|
||||
void close() override;
|
||||
bool is_open() override;
|
||||
|
||||
void execute(const std::string &stmt) override;
|
||||
void prepare(const std::string &stmt) override;
|
||||
|
||||
private:
|
||||
sqlite3 *sqlite_db_{};
|
||||
};
|
||||
|
||||
}
|
||||
#endif //QUERY_SQLITE_CONNECTION_HPP
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef QUERY_SQLITE_ERROR_HPP
|
||||
#define QUERY_SQLITE_ERROR_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
struct sqlite3;
|
||||
|
||||
namespace matador::backends::sqlite {
|
||||
|
||||
void throw_sqlite_error(int ec, sqlite3 *db, const std::string &source);
|
||||
void throw_sqlite_error(int ec, sqlite3 *db, const std::string &source, const std::string &sql);
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_SQLITE_ERROR_HPP
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
#include "sqlite_connection.hpp"
|
||||
#include "sqlite_error.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace matador::backends::sqlite {
|
||||
|
||||
sqlite_connection::sqlite_connection(sql::connection_info info)
|
||||
: connection_impl(std::move(info)) {
|
||||
|
||||
}
|
||||
|
||||
void sqlite_connection::open()
|
||||
{
|
||||
const auto ret = sqlite3_open(info().database.c_str(), &sqlite_db_);
|
||||
|
||||
if (ret != SQLITE_OK) {
|
||||
throw_sqlite_error(ret, sqlite_db_, "open");
|
||||
}
|
||||
}
|
||||
|
||||
void sqlite_connection::close()
|
||||
{
|
||||
int ret = sqlite3_close(sqlite_db_);
|
||||
|
||||
throw_sqlite_error(ret, sqlite_db_, "close");
|
||||
|
||||
sqlite_db_ = nullptr;
|
||||
}
|
||||
|
||||
bool sqlite_connection::is_open()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void sqlite_connection::execute(const std::string &stmt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void sqlite_connection::prepare(const std::string &stmt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#include "sqlite_error.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
namespace matador::backends::sqlite {
|
||||
|
||||
void throw_sqlite_error(int ec, sqlite3 *db, const std::string &source)
|
||||
{
|
||||
if (ec != SQLITE_OK) {
|
||||
std::stringstream msg;
|
||||
msg << "sqlite error (" << source << "): " << sqlite3_errmsg(db);
|
||||
throw std::logic_error(msg.str());
|
||||
}
|
||||
}
|
||||
|
||||
void throw_sqlite_error(int ec, sqlite3 *db, const std::string &source, const std::string &sql)
|
||||
{
|
||||
if (ec != SQLITE_OK) {
|
||||
std::stringstream msg;
|
||||
msg << "sqlite error (" << source << ", sql: " << sql << "): " << sqlite3_errmsg(db);
|
||||
throw std::logic_error(msg.str());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef QUERY_CONNECTION_HPP
|
||||
#define QUERY_CONNECTION_HPP
|
||||
|
||||
#include "matador/sql/connection_intermediates.hpp"
|
||||
#include "matador/sql/query_intermediates.hpp"
|
||||
#include "matador/sql/dialect.hpp"
|
||||
#include "matador/sql/query_builder.hpp"
|
||||
|
||||
|
|
@ -12,20 +12,21 @@ namespace matador::sql {
|
|||
class connection
|
||||
{
|
||||
public:
|
||||
connection();
|
||||
query_create_intermediate create();
|
||||
query_drop_intermediate drop();
|
||||
query_select_intermediate select(std::initializer_list<std::string> column_names);
|
||||
query_insert_intermediate insert();
|
||||
query_update_intermediate update(const std::string &table);
|
||||
query_delete_intermediate remove();
|
||||
connection() = default;
|
||||
explicit connection(std::string dns);
|
||||
|
||||
void open();
|
||||
void close();
|
||||
[[nodiscard]] bool is_open() const;
|
||||
|
||||
[[nodiscard]] const std::string& dns() const;
|
||||
|
||||
query_result<record> fetch(const std::string &sql);
|
||||
std::pair<size_t, std::string> execute(const std::string &sql);
|
||||
|
||||
private:
|
||||
dialect dialect_;
|
||||
query_builder query_;
|
||||
std::string dns_;
|
||||
bool is_open_{false};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,107 @@
|
|||
#ifndef QUERY_CONNECTION_POOL_HPP
|
||||
#define QUERY_CONNECTION_POOL_HPP
|
||||
|
||||
#include <utility>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
template < class Connection >
|
||||
class connection_pool;
|
||||
|
||||
template < class Connection >
|
||||
class connection_ptr
|
||||
{
|
||||
public:
|
||||
connection_ptr(Connection *c, connection_pool<Connection> &pool)
|
||||
: connection_(c), pool_(pool) {}
|
||||
~connection_ptr();
|
||||
connection_ptr(const connection_ptr &) = delete;
|
||||
connection_ptr& operator=(const connection_ptr &) = delete;
|
||||
connection_ptr(connection_ptr &&) noexcept = default;
|
||||
connection_ptr& operator=(connection_ptr &&) noexcept = default;
|
||||
|
||||
Connection* operator->() { return connection_; }
|
||||
Connection& operator*() { return *connection_; }
|
||||
|
||||
[[nodiscard]] bool valid() const { return connection_ != nullptr; }
|
||||
|
||||
private:
|
||||
friend class connection_pool<Connection>;
|
||||
|
||||
Connection *connection_;
|
||||
connection_pool<Connection> &pool_;
|
||||
};
|
||||
|
||||
template < class Connection >
|
||||
class connection_pool
|
||||
{
|
||||
public:
|
||||
connection_pool(const std::string &db, unsigned int count) {
|
||||
connection_repo_.reserve(count);
|
||||
for (auto i = 0U; i < count; ++i) {
|
||||
connection_repo_.emplace_back(db + std::to_string(i+1));
|
||||
idle_connections_.push(&connection_repo_.back());
|
||||
idle_connections_.back()->open();
|
||||
}
|
||||
}
|
||||
|
||||
connection_ptr<Connection> acquire() {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
if (idle_connections_.empty()) {
|
||||
return {nullptr, *this};
|
||||
}
|
||||
|
||||
auto ptr = idle_connections_.front();
|
||||
idle_connections_.pop();
|
||||
inuse_connections_.insert(ptr);
|
||||
return { ptr, *this };
|
||||
}
|
||||
|
||||
void release(Connection *c) {
|
||||
if (c == nullptr) {
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
|
||||
if (inuse_connections_.erase(c) > 0) {
|
||||
idle_connections_.push(c);
|
||||
}
|
||||
}
|
||||
|
||||
void release(connection_ptr<Connection> &c) {
|
||||
release(c.connection_);
|
||||
c.connection_ = nullptr;
|
||||
}
|
||||
|
||||
std::size_t size() const { return connection_repo_.size(); }
|
||||
std::size_t idle() const {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
return idle_connections_.size();
|
||||
}
|
||||
std::size_t inuse() const {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
return inuse_connections_.size();
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::mutex mutex_;
|
||||
std::vector<Connection> connection_repo_;
|
||||
using pointer = Connection*;
|
||||
using connections = std::queue<pointer>;
|
||||
using connection_set = std::unordered_set<pointer>;
|
||||
connections idle_connections_;
|
||||
connection_set inuse_connections_;
|
||||
};
|
||||
|
||||
template<class Connection>
|
||||
connection_ptr<Connection>::~connection_ptr() {
|
||||
pool_.release(connection_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_CONNECTION_POOL_HPP
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef QUERY_CONNECTION_INTERMEDIATES_HPP
|
||||
#define QUERY_CONNECTION_INTERMEDIATES_HPP
|
||||
#ifndef QUERY_QUERY_INTERMEDIATES_HPP
|
||||
#define QUERY_QUERY_INTERMEDIATES_HPP
|
||||
|
||||
#include "matador/sql/column.hpp"
|
||||
#include "matador/sql/key_value_pair.hpp"
|
||||
|
|
@ -11,20 +11,20 @@
|
|||
namespace matador::sql {
|
||||
|
||||
class basic_condition;
|
||||
class connection;
|
||||
class session;
|
||||
class query_builder;
|
||||
|
||||
class query_intermediate
|
||||
{
|
||||
public:
|
||||
query_intermediate(connection &db, query_builder &query);
|
||||
query_intermediate(session &db, query_builder &query);
|
||||
|
||||
protected:
|
||||
connection& db();
|
||||
session& db();
|
||||
query_builder& query();
|
||||
|
||||
private:
|
||||
connection &db_;
|
||||
session &db_;
|
||||
query_builder &query_;
|
||||
};
|
||||
|
||||
|
|
@ -195,4 +195,4 @@ public:
|
|||
};
|
||||
|
||||
}
|
||||
#endif //QUERY_CONNECTION_INTERMEDIATES_HPP
|
||||
#endif //QUERY_QUERY_INTERMEDIATES_HPP
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef QUERY_SESSION_HPP
|
||||
#define QUERY_SESSION_HPP
|
||||
|
||||
#include "matador/sql/connection.hpp"
|
||||
#include "matador/sql/connection_pool.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
class session
|
||||
{
|
||||
public:
|
||||
explicit session(connection_pool<connection> &pool);
|
||||
|
||||
query_create_intermediate create();
|
||||
query_drop_intermediate drop();
|
||||
query_select_intermediate select(std::initializer_list<std::string> column_names);
|
||||
query_insert_intermediate insert();
|
||||
query_update_intermediate update(const std::string &table);
|
||||
query_delete_intermediate remove();
|
||||
|
||||
query_result<record> fetch(const std::string &sql);
|
||||
std::pair<size_t, std::string> execute(const std::string &sql);
|
||||
|
||||
private:
|
||||
connection_pool<connection> &pool_;
|
||||
dialect dialect_;
|
||||
query_builder query_;
|
||||
};
|
||||
|
||||
}
|
||||
#endif //QUERY_SESSION_HPP
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
#ifndef QUERY_LIBRARY_HPP
|
||||
#define QUERY_LIBRARY_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#define _WINSOCKAPI_
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
#ifndef MATADOR_DOXYGEN_DOC
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
typedef FARPROC func_ptr;
|
||||
#else
|
||||
typedef void *func_ptr;
|
||||
#endif
|
||||
#endif /* MATADOR_DOXYGEN_DOC */
|
||||
|
||||
/**
|
||||
* @class library
|
||||
* @brief Helps to load and unload
|
||||
* external libraries.
|
||||
*
|
||||
* This class represents a loader and un-loader
|
||||
* for an external library. The path to the library
|
||||
* is given by a string.
|
||||
* It can be loaded and unloaded. Furthermore it
|
||||
* provides a method to get a pointer to an function
|
||||
* exported by the library. The function is identified
|
||||
* by a name.
|
||||
*/
|
||||
class library
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create a unspecified library serializable
|
||||
*/
|
||||
library() = default;
|
||||
|
||||
/**
|
||||
* Create a library for the given lib path
|
||||
*
|
||||
* @param lib The path to the library to map.
|
||||
*/
|
||||
explicit library(std::string lib);
|
||||
|
||||
~library();
|
||||
|
||||
/**
|
||||
* Load the underlying library.
|
||||
* If the library path is invalid
|
||||
* or the library cannot be loaded
|
||||
* false is returned.
|
||||
*
|
||||
* @return True on successful library loading.
|
||||
*/
|
||||
bool load();
|
||||
|
||||
/**
|
||||
* Sets the library (and subsequently close and
|
||||
* overwrite an already instantiated library) and
|
||||
* load the underlying library. If the library
|
||||
* path is invalid or the library cannot be loaded
|
||||
* false is returned.
|
||||
*
|
||||
* @param lib The path to the library to load.
|
||||
* @return True on successful library loading.
|
||||
*/
|
||||
bool load(const std::string &lib);
|
||||
|
||||
/**
|
||||
* Unload an loaded library. If
|
||||
* the library isn't loaded or an
|
||||
* error occurred while unloading
|
||||
* false is returned.
|
||||
*
|
||||
* @return True on successful unloading.
|
||||
*/
|
||||
bool unload();
|
||||
|
||||
/**
|
||||
* Returns the pointer to the exported
|
||||
* function of the library identified
|
||||
* by the given name.
|
||||
*
|
||||
* @param f The name of the exported function.
|
||||
* @return The pointer to the function.
|
||||
*/
|
||||
[[nodiscard]] func_ptr function(const std::string &f) const;
|
||||
|
||||
private:
|
||||
std::string lib_;
|
||||
|
||||
#if defined(_WIN32) || defined(__MINGW32__)
|
||||
HMODULE handle_ = nullptr;
|
||||
#else
|
||||
void *handle_ = nullptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_LIBRARY_HPP
|
||||
|
|
@ -5,10 +5,11 @@ set(SQL_SOURCES
|
|||
sql/key_value_pair.cpp
|
||||
sql/basic_condition.cpp
|
||||
sql/connection.cpp
|
||||
sql/connection_intermediates.cpp
|
||||
sql/query_intermediates.cpp
|
||||
sql/record.cpp
|
||||
sql/connection_info.cpp
|
||||
sql/connection_impl.cpp)
|
||||
sql/connection_impl.cpp
|
||||
sql/session.cpp)
|
||||
|
||||
set(SQL_HEADER
|
||||
../include/matador/sql/dialect.hpp
|
||||
|
|
@ -19,22 +20,27 @@ set(SQL_HEADER
|
|||
../include/matador/sql/basic_condition.hpp
|
||||
../include/matador/sql/condition.hpp
|
||||
../include/matador/sql/connection.hpp
|
||||
../include/matador/sql/connection_intermediates.hpp
|
||||
../include/matador/sql/query_intermediates.hpp
|
||||
../include/matador/sql/result.hpp
|
||||
../include/matador/sql/record.hpp
|
||||
../include/matador/sql/query_result.hpp
|
||||
../include/matador/sql/connection_impl.hpp
|
||||
../include/matador/sql/connection_info.hpp)
|
||||
../include/matador/sql/connection_info.hpp
|
||||
../include/matador/sql/connection_pool.hpp
|
||||
../include/matador/sql/session.hpp)
|
||||
|
||||
set(UTILS_HEADER
|
||||
../include/matador/utils/field_attributes.hpp
|
||||
../include/matador/utils/string.hpp
|
||||
../include/matador/utils/constraints.hpp)
|
||||
../include/matador/utils/constraints.hpp
|
||||
../include/matador/utils/library.hpp)
|
||||
|
||||
set(UTILS_SOURCES
|
||||
utils/field_attributes.cpp
|
||||
utils/string.cpp
|
||||
sql/condition.cpp)
|
||||
sql/condition.cpp
|
||||
utils/library.cpp)
|
||||
|
||||
add_library(matador STATIC ${SQL_SOURCES} ${SQL_HEADER} ${UTILS_SOURCES} ${UTILS_HEADER})
|
||||
set_target_properties(matador PROPERTIES LINKER_LANGUAGE CXX)
|
||||
target_include_directories(matador PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
||||
#set_target_properties(matador PROPERTIES LINKER_LANGUAGE CXX)
|
||||
|
|
|
|||
|
|
@ -1,39 +1,30 @@
|
|||
#include <utility>
|
||||
|
||||
#include "matador/sql/connection.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
connection::connection(std::string dns)
|
||||
: dns_(std::move(dns)) {}
|
||||
|
||||
connection::connection()
|
||||
: query_(dialect_) {}
|
||||
|
||||
query_create_intermediate connection::create()
|
||||
void connection::open()
|
||||
{
|
||||
return query_create_intermediate{*this, query_.create()};
|
||||
is_open_ = true;
|
||||
}
|
||||
|
||||
query_drop_intermediate connection::drop()
|
||||
void connection::close()
|
||||
{
|
||||
return query_drop_intermediate{*this, query_.drop()};
|
||||
is_open_ = false;
|
||||
}
|
||||
|
||||
query_select_intermediate connection::select(std::initializer_list<std::string> column_names)
|
||||
bool connection::is_open() const
|
||||
{
|
||||
return query_select_intermediate{*this, query_.select(column_names)};
|
||||
return is_open_;
|
||||
}
|
||||
|
||||
query_insert_intermediate connection::insert()
|
||||
const std::string &connection::dns() const
|
||||
{
|
||||
return query_insert_intermediate{*this, query_.insert()};
|
||||
}
|
||||
|
||||
query_update_intermediate connection::update(const std::string &table)
|
||||
{
|
||||
return query_update_intermediate{*this, query_.update(table)};
|
||||
}
|
||||
|
||||
query_delete_intermediate connection::remove()
|
||||
{
|
||||
return query_delete_intermediate{*this, query_.remove()};
|
||||
return dns_;
|
||||
}
|
||||
|
||||
query_result<record> connection::fetch(const std::string &sql)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#include "matador/sql/connection_intermediates.hpp"
|
||||
#include "matador/sql/connection.hpp"
|
||||
#include "matador/sql/query_intermediates.hpp"
|
||||
#include "matador/sql/session.hpp"
|
||||
#include "matador/sql/query_builder.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
connection &query_intermediate::db()
|
||||
session &query_intermediate::db()
|
||||
{
|
||||
return db_;
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ record query_select_finish::fetch_one()
|
|||
return db().fetch(query().compile()).begin();
|
||||
}
|
||||
|
||||
query_intermediate::query_intermediate(connection &db, query_builder &query)
|
||||
query_intermediate::query_intermediate(session &db, query_builder &query)
|
||||
: db_(db), query_(query) {}
|
||||
|
||||
query_offset_intermediate query_order_direction_intermediate::offset(size_t offset)
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
#include "matador/sql/session.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
session::session(connection_pool<connection> &pool)
|
||||
: pool_(pool)
|
||||
, query_(dialect_) {}
|
||||
|
||||
query_create_intermediate session::create()
|
||||
{
|
||||
return query_create_intermediate{*this, query_.create()};
|
||||
}
|
||||
|
||||
query_drop_intermediate session::drop()
|
||||
{
|
||||
return query_drop_intermediate{*this, query_.drop()};
|
||||
}
|
||||
|
||||
query_select_intermediate session::select(std::initializer_list<std::string> column_names)
|
||||
{
|
||||
return query_select_intermediate{*this, query_.select(column_names)};
|
||||
}
|
||||
|
||||
query_insert_intermediate session::insert()
|
||||
{
|
||||
return query_insert_intermediate{*this, query_.insert()};
|
||||
}
|
||||
|
||||
query_update_intermediate session::update(const std::string &table)
|
||||
{
|
||||
return query_update_intermediate{*this, query_.update(table)};
|
||||
}
|
||||
|
||||
query_delete_intermediate session::remove()
|
||||
{
|
||||
return query_delete_intermediate{*this, query_.remove()};
|
||||
}
|
||||
|
||||
query_result<record> session::fetch(const std::string &sql) {
|
||||
auto c = pool_.acquire();
|
||||
if (!c.valid()) {
|
||||
throw std::logic_error("no database connection available");
|
||||
}
|
||||
return c->fetch(sql);
|
||||
}
|
||||
|
||||
std::pair<size_t, std::string> session::execute(const std::string &sql) {
|
||||
auto c = pool_.acquire();
|
||||
if (!c.valid()) {
|
||||
throw std::logic_error("no database connection available");
|
||||
}
|
||||
return c->execute(sql);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#include "matador/utils/library.hpp"
|
||||
|
||||
namespace matador::utils {
|
||||
|
||||
library::library(std::string lib)
|
||||
: lib_(std::move(lib))
|
||||
{}
|
||||
|
||||
library::~library()
|
||||
{
|
||||
unload();
|
||||
}
|
||||
|
||||
bool library::load()
|
||||
{
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
handle_ = LoadLibrary((lib_ + ".dll").c_str());
|
||||
#elif defined(__APPLE__)
|
||||
handle_ = dlopen(std::string("lib" + lib_ + ".dylib").c_str(), RTLD_LAZY);
|
||||
#else
|
||||
handle_ = dlopen(std::string("./lib" + lib_ + ".so").c_str(), RTLD_LAZY);
|
||||
#endif
|
||||
if (!handle_) {
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
DWORD errorMessageID = ::GetLastError();
|
||||
#else
|
||||
// TODO: handle win32 and linux error
|
||||
fprintf(stdout, "dlopen error: %s", dlerror());
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool library::load(const std::string &lib)
|
||||
{
|
||||
if (handle_) {
|
||||
return false;
|
||||
}
|
||||
lib_ = lib;
|
||||
return load();
|
||||
}
|
||||
|
||||
bool library::unload()
|
||||
{
|
||||
bool ret(true);
|
||||
if (handle_) {
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
ret = FreeLibrary(handle_) == TRUE;
|
||||
#else
|
||||
ret = dlclose(handle_) == 0;
|
||||
#endif
|
||||
if (!ret) {
|
||||
} else {
|
||||
handle_ = nullptr;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
func_ptr library::function(const std::string &f) const
|
||||
{
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
return GetProcAddress(handle_, f.c_str());
|
||||
#else
|
||||
return dlsym(handle_, f.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -9,7 +9,9 @@ FetchContent_Declare(
|
|||
FetchContent_MakeAvailable(Catch2)
|
||||
|
||||
add_executable(tests builder.cpp
|
||||
connection.cpp
|
||||
record.cpp)
|
||||
session.cpp
|
||||
record.cpp
|
||||
connection_pool.cpp
|
||||
query.cpp)
|
||||
target_link_libraries(tests PRIVATE Catch2::Catch2WithMain matador)
|
||||
target_include_directories(tests PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>/include)
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <matador/sql/connection.hpp>
|
||||
#include <matador/sql/connection_pool.hpp>
|
||||
|
||||
using namespace matador::sql;
|
||||
|
||||
TEST_CASE("Create connection pool", "[connection pool]") {
|
||||
using pool_t = connection_pool<connection>;
|
||||
|
||||
pool_t pool("db", 4);
|
||||
|
||||
REQUIRE(pool.size() == 4);
|
||||
REQUIRE(pool.idle() == 4);
|
||||
REQUIRE(pool.inuse() == 0);
|
||||
|
||||
auto ptr = pool.acquire();
|
||||
REQUIRE(ptr.valid());
|
||||
REQUIRE(ptr->is_open());
|
||||
REQUIRE(!ptr->dns().empty());
|
||||
|
||||
REQUIRE(pool.idle() == 3);
|
||||
REQUIRE(pool.inuse() == 1);
|
||||
|
||||
pool.release(ptr);
|
||||
REQUIRE(!ptr.valid());
|
||||
REQUIRE(pool.idle() == 4);
|
||||
REQUIRE(pool.inuse() == 0);
|
||||
|
||||
{
|
||||
auto ptr2 = pool.acquire();
|
||||
REQUIRE(ptr2.valid());
|
||||
REQUIRE(ptr2->is_open());
|
||||
REQUIRE(!ptr2->dns().empty());
|
||||
|
||||
REQUIRE(pool.idle() == 3);
|
||||
REQUIRE(pool.inuse() == 1);
|
||||
}
|
||||
|
||||
REQUIRE(pool.idle() == 4);
|
||||
REQUIRE(pool.inuse() == 0);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include "catch2/generators/catch_generators.hpp"
|
||||
|
||||
TEST_CASE("Query test", "[query]") {
|
||||
auto dns = GENERATE(as<std::string>{}, "mssql", "sqlite", "postgres" );
|
||||
|
||||
INFO(dns);
|
||||
REQUIRE(!dns.empty());
|
||||
}
|
||||
|
|
@ -2,14 +2,15 @@
|
|||
|
||||
#include <matador/sql/column.hpp>
|
||||
#include <matador/sql/condition.hpp>
|
||||
#include <matador/sql/connection.hpp>
|
||||
#include <matador/sql/session.hpp>
|
||||
|
||||
using namespace matador::sql;
|
||||
|
||||
TEST_CASE("Execute create table statement", "[connection]") {
|
||||
connection c;
|
||||
connection_pool<connection> pool("dns", 4);
|
||||
session s(pool);
|
||||
|
||||
const auto res = c.create()
|
||||
const auto res = s.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
|
|
@ -21,9 +22,10 @@ TEST_CASE("Execute create table statement", "[connection]") {
|
|||
}
|
||||
|
||||
TEST_CASE("Execute drop table statement", "[connection]") {
|
||||
connection c;
|
||||
connection_pool<connection> pool("dns", 4);
|
||||
session s(pool);
|
||||
|
||||
const auto res = c.drop()
|
||||
const auto res = s.drop()
|
||||
.table("person")
|
||||
.execute();
|
||||
|
||||
|
|
@ -31,9 +33,10 @@ TEST_CASE("Execute drop table statement", "[connection]") {
|
|||
}
|
||||
|
||||
TEST_CASE("Execute select statement with where clause", "[connection]") {
|
||||
connection c;
|
||||
connection_pool<connection> pool("dns", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = c.select({"id", "name", "color"})
|
||||
auto res = s.select({"id", "name", "color"})
|
||||
.from("person")
|
||||
.where("id"_col == 8)
|
||||
.fetch_all();
|
||||
|
|
@ -42,9 +45,10 @@ TEST_CASE("Execute select statement with where clause", "[connection]") {
|
|||
}
|
||||
|
||||
TEST_CASE("Execute select statement with order by", "[connection]") {
|
||||
connection c;
|
||||
connection_pool<connection> pool("dns", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = c.select({"id", "name", "color"})
|
||||
auto res = s.select({"id", "name", "color"})
|
||||
.from("person")
|
||||
.where("id"_col == 8)
|
||||
.order_by("name").desc()
|
||||
|
|
@ -54,9 +58,10 @@ TEST_CASE("Execute select statement with order by", "[connection]") {
|
|||
}
|
||||
|
||||
TEST_CASE("Execute select statement with group by and order by", "[connection]") {
|
||||
connection c;
|
||||
connection_pool<connection> pool("dns", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = c.select({"id", "name", "color"})
|
||||
auto res = s.select({"id", "name", "color"})
|
||||
.from("person")
|
||||
.where("id"_col == 8)
|
||||
.group_by("color")
|
||||
|
|
@ -67,9 +72,10 @@ TEST_CASE("Execute select statement with group by and order by", "[connection]")
|
|||
}
|
||||
|
||||
TEST_CASE("Execute insert statement", "[connection]") {
|
||||
connection c;
|
||||
connection_pool<connection> pool("dns", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = c.insert()
|
||||
auto res = s.insert()
|
||||
.into("person", {"id", "name", "color"})
|
||||
.values({7, "george", "green"})
|
||||
.execute();
|
||||
|
|
@ -78,9 +84,10 @@ TEST_CASE("Execute insert statement", "[connection]") {
|
|||
}
|
||||
|
||||
TEST_CASE("Execute update statement", "[connection]") {
|
||||
connection c;
|
||||
connection_pool<connection> pool("dns", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = c.update("person")
|
||||
auto res = s.update("person")
|
||||
.set({
|
||||
{"name", "george"},
|
||||
{"color", "green"}
|
||||
|
|
@ -92,9 +99,10 @@ TEST_CASE("Execute update statement", "[connection]") {
|
|||
}
|
||||
|
||||
TEST_CASE("Execute delete statement", "[connection]") {
|
||||
connection c;
|
||||
connection_pool<connection> pool("dns", 4);
|
||||
session s(pool);
|
||||
|
||||
auto res = c.remove()
|
||||
auto res = s.remove()
|
||||
.from("person", "p")
|
||||
.where("id"_col == 9)
|
||||
.execute();
|
||||
Loading…
Reference in New Issue