diff --git a/include/matador/sql/backend_provider.hpp b/include/matador/sql/backend_provider.hpp index b1cf12b..af2fdeb 100644 --- a/include/matador/sql/backend_provider.hpp +++ b/include/matador/sql/backend_provider.hpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace matador::sql { @@ -26,28 +27,50 @@ public: const dialect& connection_dialect(const std::string &connection_type); private: - struct backend_context { - backend_context(const std::string &connection_type, - const std::string &backends_path); + struct basic_backend_context { + virtual ~basic_backend_context() = default; + [[nodiscard]] virtual connection_impl* create(const connection_info&) = 0; + virtual void destroy(connection_impl*) = 0; + [[nodiscard]] virtual const sql::dialect* dialect() const = 0; + }; + + class backend_context final : public basic_backend_context { + public: + explicit backend_context(const std::string &connection_type); backend_context(const backend_context&) = delete; backend_context& operator=(const backend_context&) = delete; backend_context(backend_context&&) noexcept = default; backend_context& operator=(backend_context&&) noexcept = default; - ~backend_context(); + ~backend_context() override; + [[nodiscard]] connection_impl* create(const connection_info&) override; + void destroy(connection_impl *conn) override; + [[nodiscard]] const class dialect* dialect() const override; + + private: typedef connection_impl*(*create_func)(const connection_info&); typedef void (*destroy_func)(connection_impl*); - typedef const dialect*(*dialect_func)(); + typedef const class dialect*(*dialect_func)(); create_func create_connection{}; destroy_func destroy_connection{}; dialect_func get_dialect{}; utils::library lib; }; + + class noop_backend_context final : public basic_backend_context { + public: + connection_impl *create(const connection_info &info) override; + void destroy(connection_impl *impl) override; + [[nodiscard]] const sql::dialect *dialect() const override; + + private: + std::unordered_set> noop_connections_; + }; + private: - using backends_t = std::unordered_map>; + using backends_t = std::unordered_map>; backends_t backends_; - std::string backends_path_; }; } #endif //QUERY_BACKEND_PROVIDER_HPP diff --git a/include/matador/sql/noop_connection.hpp b/include/matador/sql/noop_connection.hpp new file mode 100644 index 0000000..2598eaf --- /dev/null +++ b/include/matador/sql/noop_connection.hpp @@ -0,0 +1,26 @@ +#ifndef QUERY_NOOP_CONNECTION_HPP +#define QUERY_NOOP_CONNECTION_HPP + +#include "matador/sql/connection_impl.hpp" + +namespace matador::sql { + +class noop_connection final : public connection_impl +{ +public: + explicit noop_connection(const connection_info &info); + + void open() override; + void close() override; + bool is_open() override; + size_t execute(const std::string &stmt) override; + std::unique_ptr fetch(const std::string &stmt) override; + std::unique_ptr prepare(query_context context) override; + record describe(const std::string &table) override; + bool exists(const std::string &schema_name, const std::string &table_name) override; + +private: + bool is_open_{false}; +}; +} +#endif //QUERY_NOOP_CONNECTION_HPP diff --git a/include/matador/sql/query_data.hpp b/include/matador/sql/query_data.hpp index 918fc95..ee9d8f2 100644 --- a/include/matador/sql/query_data.hpp +++ b/include/matador/sql/query_data.hpp @@ -9,14 +9,13 @@ namespace matador::sql { +class query_part; + struct query_data { // SqlCommands command; std::vector> parts; std::vector columns; - std::unordered_map table_map_by_index; - using table_ref = std::reference_wrapper; - std::unordered_map table_map_by_name; }; } diff --git a/include/matador/sql/query_intermediates.hpp b/include/matador/sql/query_intermediates.hpp index cf0215b..b927347 100644 --- a/include/matador/sql/query_intermediates.hpp +++ b/include/matador/sql/query_intermediates.hpp @@ -240,8 +240,7 @@ public: if (!schema_->exists()) { schema_->attach(table.name); } - data_.parts.push_back(std::make_unique(table, column_generator::generate(*schema_))); - return {connection_, schema_, data_}; + return this->table(table, column_generator::generate(*schema_)); } }; @@ -261,7 +260,7 @@ public: query_into_intermediate into(const sql::table &table, std::initializer_list column_names); template query_into_intermediate into(const sql::table &table) - {; + { data_.parts.push_back(std::make_unique(table, column_name_generator::generate(*schema_))); return {connection_, schema_, data_}; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 128bc0d..fce3a70 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,6 +32,7 @@ set(SQL_SOURCES sql/query.cpp sql/query_parts.cpp sql/query_compiler.cpp + sql/noop_connection.cpp ) set(SQL_HEADER @@ -79,6 +80,7 @@ set(SQL_HEADER ../include/matador/sql/query_compiler.hpp ../include/matador/sql/query_data.hpp ../include/matador/sql/table.hpp + ../include/matador/sql/noop_connection.hpp ) set(QUERY_SOURCES diff --git a/src/sql/backend_provider.cpp b/src/sql/backend_provider.cpp index a6727fa..00f2af1 100644 --- a/src/sql/backend_provider.cpp +++ b/src/sql/backend_provider.cpp @@ -1,14 +1,14 @@ #include "matador/sql/backend_provider.hpp" +#include "matador/sql/noop_connection.hpp" +#include "matador/sql/dialect_builder.hpp" -#include "matador/utils/os.hpp" - -#include #include namespace matador::sql { backend_provider::backend_provider() -: backends_path_(utils::os::getenv("MATADOR_BACKENDS_PATH")) -{} +{ + backends_.emplace("noop", std::make_unique()); +} backend_provider &backend_provider::instance() { static backend_provider provider; @@ -19,31 +19,30 @@ connection_impl *backend_provider::create_connection(const std::string &connecti { auto it = backends_.find(connection_type); if (it == backends_.end()) { - it = backends_.emplace(connection_type, std::make_unique(connection_type, backends_path_)).first; + it = backends_.emplace(connection_type, std::make_unique(connection_type)).first; } - return (*it->second->create_connection)(info); + return it->second->create(info); } void backend_provider::destroy_connection(const std::string &connection_type, connection_impl *c) { auto it = backends_.find(connection_type); if (it == backends_.end()) { - it = backends_.emplace(connection_type, std::make_unique(connection_type, backends_path_)).first; + it = backends_.emplace(connection_type, std::make_unique(connection_type)).first; } - (*it->second->destroy_connection)(c); + return it->second->destroy(c); } const dialect &backend_provider::connection_dialect(const std::string &connection_type) { auto it = backends_.find(connection_type); if (it == backends_.end()) { - it = backends_.emplace(connection_type, std::make_unique(connection_type, backends_path_)).first; + it = backends_.emplace(connection_type, std::make_unique(connection_type)).first; } - return *(*it->second->get_dialect)(); + return *it->second->dialect(); } -backend_provider::backend_context::backend_context(const std::string &connection_type, - const std::string &backends_path) +backend_provider::backend_context::backend_context(const std::string &connection_type) { if (!lib.load("matador-" + connection_type)) { throw std::runtime_error("couldn't load library '" + connection_type + "'"); @@ -54,9 +53,45 @@ backend_provider::backend_context::backend_context(const std::string &connection get_dialect = reinterpret_cast(reinterpret_cast(lib.function("get_dialect"))); } +connection_impl *backend_provider::backend_context::create(const connection_info &info) +{ + return (create_connection)(info); +} + +void backend_provider::backend_context::destroy(connection_impl *conn) +{ + (destroy_connection)(conn); +} + +const class dialect *backend_provider::backend_context::dialect() const +{ + return (get_dialect)(); +} + backend_provider::backend_context::~backend_context() { lib.unload(); } +connection_impl *backend_provider::noop_backend_context::create(const connection_info &info) +{ + return noop_connections_.insert(std::make_unique(info)).first->get(); +} + +void backend_provider::noop_backend_context::destroy(connection_impl *impl) +{ + auto it = std::find_if(noop_connections_.begin(), noop_connections_.end(), [impl](const auto &item) { + return impl == item.get(); + }); + if (it != noop_connections_.end()) { + noop_connections_.erase(it); + } +} + +const dialect *backend_provider::noop_backend_context::dialect() const +{ + static sql::dialect dialect_ = dialect_builder::builder().create().build(); + return &dialect_; +} + } \ No newline at end of file diff --git a/src/sql/noop_connection.cpp b/src/sql/noop_connection.cpp new file mode 100644 index 0000000..1c40e21 --- /dev/null +++ b/src/sql/noop_connection.cpp @@ -0,0 +1,52 @@ +#include "matador/sql/noop_connection.hpp" +#include "matador/sql/query_context.hpp" +#include "matador/sql/record.hpp" + +#include +#include + +namespace matador::sql { +noop_connection::noop_connection(const connection_info &info) +: connection_impl(info) {} + +void noop_connection::open() +{ + is_open_ = true; +} + +void noop_connection::close() +{ + is_open_ = false; +} + +bool noop_connection::is_open() +{ + return is_open_; +} + +size_t noop_connection::execute(const std::string &stmt) +{ + return 0; +} + +std::unique_ptr noop_connection::fetch(const std::string &stmt) +{ + return {}; +} + +std::unique_ptr noop_connection::prepare(query_context context) +{ + return {}; +} + +record noop_connection::describe(const std::string &table) +{ + return {}; +} + +bool noop_connection::exists(const std::string &schema_name, const std::string &table_name) +{ + return false; +} + +} \ No newline at end of file diff --git a/test/QueryBuilderTest.cpp b/test/QueryBuilderTest.cpp index cfb788e..db87278 100644 --- a/test/QueryBuilderTest.cpp +++ b/test/QueryBuilderTest.cpp @@ -2,13 +2,24 @@ #include #include +#include #include #include +#include using namespace matador::sql; using namespace matador::utils; TEST_CASE("Create table sql statement string", "[query]") { + connection noop("noop://noop.db"); + auto scm = std::make_shared("noop"); + query qu(noop, scm); + auto s = qu.create().table({"person"}, { + make_pk_column("id"), + make_column("name", 255), + make_column("age") + }).str(); + dialect d = dialect_builder::builder().create().build(); query_builder query(d); auto q = query.create().table("person", { @@ -17,7 +28,8 @@ TEST_CASE("Create table sql statement string", "[query]") { make_column("age") }).compile(); - REQUIRE(q.sql == R"##(CREATE TABLE "person" ("id" BIGINT NOT NULL, "name" VARCHAR(255) NOT NULL, "age" INTEGER NOT NULL, CONSTRAINT PK_person PRIMARY KEY (id)))##"); + REQUIRE(s == R"##(CREATE TABLE "person" ("id" BIGINT NOT NULL, "name" VARCHAR(255) NOT NULL, "age" INTEGER NOT NULL, CONSTRAINT PK_person PRIMARY KEY (id)))##"); +// REQUIRE(q.sql == R"##(CREATE TABLE "person" ("id" BIGINT NOT NULL, "name" VARCHAR(255) NOT NULL, "age" INTEGER NOT NULL, CONSTRAINT PK_person PRIMARY KEY (id)))##"); REQUIRE(q.table_name == "person"); q = query.create().table("person", {