From 715f4dff8f678e06c514922a3dfb64c67d5867e4 Mon Sep 17 00:00:00 2001 From: Sascha Kuehl Date: Tue, 7 Nov 2023 23:07:49 +0100 Subject: [PATCH] added sqlite connection class (progress) --- CMakeLists.txt | 19 +++- backends/CMakeLists.txt | 1 + backends/sqlite/CMakeLists.txt | 17 +++ backends/sqlite/include/sqlite_connection.hpp | 26 +++++ backends/sqlite/include/sqlite_error.hpp | 15 +++ backends/sqlite/src/sqlite_connection.cpp | 46 ++++++++ backends/sqlite/src/sqlite_error.cpp | 28 +++++ include/matador/sql/connection.hpp | 21 ++-- include/matador/sql/connection_pool.hpp | 107 ++++++++++++++++++ ...ermediates.hpp => query_intermediates.hpp} | 14 +-- include/matador/sql/session.hpp | 31 +++++ include/matador/utils/library.hpp | 107 ++++++++++++++++++ src/CMakeLists.txt | 20 ++-- src/sql/connection.cpp | 33 ++---- ...ermediates.cpp => query_intermediates.cpp} | 8 +- src/sql/session.cpp | 56 +++++++++ src/utils/library.cpp | 70 ++++++++++++ test/CMakeLists.txt | 6 +- test/connection_pool.cpp | 42 +++++++ test/query.cpp | 9 ++ test/{connection.cpp => session.cpp} | 42 ++++--- 21 files changed, 645 insertions(+), 73 deletions(-) create mode 100644 backends/CMakeLists.txt create mode 100644 backends/sqlite/CMakeLists.txt create mode 100644 backends/sqlite/include/sqlite_connection.hpp create mode 100644 backends/sqlite/include/sqlite_error.hpp create mode 100644 backends/sqlite/src/sqlite_connection.cpp create mode 100644 backends/sqlite/src/sqlite_error.cpp create mode 100644 include/matador/sql/connection_pool.hpp rename include/matador/sql/{connection_intermediates.hpp => query_intermediates.hpp} (94%) create mode 100644 include/matador/sql/session.hpp create mode 100644 include/matador/utils/library.hpp rename src/sql/{connection_intermediates.cpp => query_intermediates.cpp} (94%) create mode 100644 src/sql/session.cpp create mode 100644 src/utils/library.cpp create mode 100644 test/connection_pool.cpp create mode 100644 test/query.cpp rename test/{connection.cpp => session.cpp} (75%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5238d80..6afa9e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/backends/CMakeLists.txt b/backends/CMakeLists.txt new file mode 100644 index 0000000..d1d6ca8 --- /dev/null +++ b/backends/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(sqlite) \ No newline at end of file diff --git a/backends/sqlite/CMakeLists.txt b/backends/sqlite/CMakeLists.txt new file mode 100644 index 0000000..ce8aaa3 --- /dev/null +++ b/backends/sqlite/CMakeLists.txt @@ -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}) diff --git a/backends/sqlite/include/sqlite_connection.hpp b/backends/sqlite/include/sqlite_connection.hpp new file mode 100644 index 0000000..2b3fde5 --- /dev/null +++ b/backends/sqlite/include/sqlite_connection.hpp @@ -0,0 +1,26 @@ +#ifndef QUERY_SQLITE_CONNECTION_HPP +#define QUERY_SQLITE_CONNECTION_HPP + +#include "matador/sql/connection_impl.hpp" + +#include + +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 diff --git a/backends/sqlite/include/sqlite_error.hpp b/backends/sqlite/include/sqlite_error.hpp new file mode 100644 index 0000000..722bf6a --- /dev/null +++ b/backends/sqlite/include/sqlite_error.hpp @@ -0,0 +1,15 @@ +#ifndef QUERY_SQLITE_ERROR_HPP +#define QUERY_SQLITE_ERROR_HPP + +#include + +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 diff --git a/backends/sqlite/src/sqlite_connection.cpp b/backends/sqlite/src/sqlite_connection.cpp new file mode 100644 index 0000000..3509b4e --- /dev/null +++ b/backends/sqlite/src/sqlite_connection.cpp @@ -0,0 +1,46 @@ +#include "sqlite_connection.hpp" +#include "sqlite_error.hpp" + +#include + +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) +{ + +} + +} \ No newline at end of file diff --git a/backends/sqlite/src/sqlite_error.cpp b/backends/sqlite/src/sqlite_error.cpp new file mode 100644 index 0000000..ead0493 --- /dev/null +++ b/backends/sqlite/src/sqlite_error.cpp @@ -0,0 +1,28 @@ +#include "sqlite_error.hpp" + +#include +#include + +#include + +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()); + } +} + +} \ No newline at end of file diff --git a/include/matador/sql/connection.hpp b/include/matador/sql/connection.hpp index e5051cc..dc9c85e 100644 --- a/include/matador/sql/connection.hpp +++ b/include/matador/sql/connection.hpp @@ -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 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 fetch(const std::string &sql); std::pair execute(const std::string &sql); private: - dialect dialect_; - query_builder query_; + std::string dns_; + bool is_open_{false}; }; } diff --git a/include/matador/sql/connection_pool.hpp b/include/matador/sql/connection_pool.hpp new file mode 100644 index 0000000..78f44b7 --- /dev/null +++ b/include/matador/sql/connection_pool.hpp @@ -0,0 +1,107 @@ +#ifndef QUERY_CONNECTION_POOL_HPP +#define QUERY_CONNECTION_POOL_HPP + +#include +#include +#include +#include +#include + +namespace matador::sql { + +template < class Connection > +class connection_pool; + +template < class Connection > +class connection_ptr +{ +public: + connection_ptr(Connection *c, connection_pool &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_pool &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 acquire() { + std::lock_guard 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 guard(mutex_); + + if (inuse_connections_.erase(c) > 0) { + idle_connections_.push(c); + } + } + + void release(connection_ptr &c) { + release(c.connection_); + c.connection_ = nullptr; + } + + std::size_t size() const { return connection_repo_.size(); } + std::size_t idle() const { + std::lock_guard guard(mutex_); + return idle_connections_.size(); + } + std::size_t inuse() const { + std::lock_guard guard(mutex_); + return inuse_connections_.size(); + } + +private: + mutable std::mutex mutex_; + std::vector connection_repo_; + using pointer = Connection*; + using connections = std::queue; + using connection_set = std::unordered_set; + connections idle_connections_; + connection_set inuse_connections_; +}; + +template +connection_ptr::~connection_ptr() { + pool_.release(connection_); +} + +} + +#endif //QUERY_CONNECTION_POOL_HPP diff --git a/include/matador/sql/connection_intermediates.hpp b/include/matador/sql/query_intermediates.hpp similarity index 94% rename from include/matador/sql/connection_intermediates.hpp rename to include/matador/sql/query_intermediates.hpp index 0329851..46ec5c9 100644 --- a/include/matador/sql/connection_intermediates.hpp +++ b/include/matador/sql/query_intermediates.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 diff --git a/include/matador/sql/session.hpp b/include/matador/sql/session.hpp new file mode 100644 index 0000000..8031b17 --- /dev/null +++ b/include/matador/sql/session.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 &pool); + + query_create_intermediate create(); + query_drop_intermediate drop(); + query_select_intermediate select(std::initializer_list column_names); + query_insert_intermediate insert(); + query_update_intermediate update(const std::string &table); + query_delete_intermediate remove(); + + query_result fetch(const std::string &sql); + std::pair execute(const std::string &sql); + +private: + connection_pool &pool_; + dialect dialect_; + query_builder query_; +}; + +} +#endif //QUERY_SESSION_HPP diff --git a/include/matador/utils/library.hpp b/include/matador/utils/library.hpp new file mode 100644 index 0000000..b13e134 --- /dev/null +++ b/include/matador/utils/library.hpp @@ -0,0 +1,107 @@ +#ifndef QUERY_LIBRARY_HPP +#define QUERY_LIBRARY_HPP + +#include + +#if defined(_MSC_VER) || defined(__MINGW32__) +#define _WINSOCKAPI_ +#include +#else +#include +#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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9f7de44..c9d8316 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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) diff --git a/src/sql/connection.cpp b/src/sql/connection.cpp index 22eff71..2b0d3ed 100644 --- a/src/sql/connection.cpp +++ b/src/sql/connection.cpp @@ -1,39 +1,30 @@ +#include + #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 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 connection::fetch(const std::string &sql) diff --git a/src/sql/connection_intermediates.cpp b/src/sql/query_intermediates.cpp similarity index 94% rename from src/sql/connection_intermediates.cpp rename to src/sql/query_intermediates.cpp index 9ac2430..46ddfea 100644 --- a/src/sql/connection_intermediates.cpp +++ b/src/sql/query_intermediates.cpp @@ -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) diff --git a/src/sql/session.cpp b/src/sql/session.cpp new file mode 100644 index 0000000..e906c91 --- /dev/null +++ b/src/sql/session.cpp @@ -0,0 +1,56 @@ +#include "matador/sql/session.hpp" + +#include + +namespace matador::sql { + +session::session(connection_pool &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 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 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 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); +} +} \ No newline at end of file diff --git a/src/utils/library.cpp b/src/utils/library.cpp new file mode 100644 index 0000000..785ddda --- /dev/null +++ b/src/utils/library.cpp @@ -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 +} + +} \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b7ff137..4d5bf8e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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 $/include) \ No newline at end of file diff --git a/test/connection_pool.cpp b/test/connection_pool.cpp new file mode 100644 index 0000000..97d9ce5 --- /dev/null +++ b/test/connection_pool.cpp @@ -0,0 +1,42 @@ +#include + +#include +#include + +using namespace matador::sql; + +TEST_CASE("Create connection pool", "[connection pool]") { + using pool_t = connection_pool; + + 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); +} diff --git a/test/query.cpp b/test/query.cpp new file mode 100644 index 0000000..0def8a3 --- /dev/null +++ b/test/query.cpp @@ -0,0 +1,9 @@ +#include +#include "catch2/generators/catch_generators.hpp" + +TEST_CASE("Query test", "[query]") { + auto dns = GENERATE(as{}, "mssql", "sqlite", "postgres" ); + + INFO(dns); + REQUIRE(!dns.empty()); +} diff --git a/test/connection.cpp b/test/session.cpp similarity index 75% rename from test/connection.cpp rename to test/session.cpp index 105d30e..fea04d8 100644 --- a/test/connection.cpp +++ b/test/session.cpp @@ -2,14 +2,15 @@ #include #include -#include +#include using namespace matador::sql; TEST_CASE("Execute create table statement", "[connection]") { - connection c; + connection_pool pool("dns", 4); + session s(pool); - const auto res = c.create() + const auto res = s.create() .table("person", { make_pk_column("id"), make_column("name", 255), @@ -21,9 +22,10 @@ TEST_CASE("Execute create table statement", "[connection]") { } TEST_CASE("Execute drop table statement", "[connection]") { - connection c; + connection_pool 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 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 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 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 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 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 pool("dns", 4); + session s(pool); - auto res = c.remove() + auto res = s.remove() .from("person", "p") .where("id"_col == 9) .execute();