added noop_connection for testing
This commit is contained in:
parent
b1f2d94c7a
commit
2d9a4f3866
|
|
@ -6,6 +6,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
|
|
@ -26,28 +27,50 @@ public:
|
||||||
const dialect& connection_dialect(const std::string &connection_type);
|
const dialect& connection_dialect(const std::string &connection_type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct backend_context {
|
struct basic_backend_context {
|
||||||
backend_context(const std::string &connection_type,
|
virtual ~basic_backend_context() = default;
|
||||||
const std::string &backends_path);
|
[[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(const backend_context&) = delete;
|
||||||
backend_context& operator=(const backend_context&) = delete;
|
backend_context& operator=(const backend_context&) = delete;
|
||||||
backend_context(backend_context&&) noexcept = default;
|
backend_context(backend_context&&) noexcept = default;
|
||||||
backend_context& operator=(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 connection_impl*(*create_func)(const connection_info&);
|
||||||
typedef void (*destroy_func)(connection_impl*);
|
typedef void (*destroy_func)(connection_impl*);
|
||||||
typedef const dialect*(*dialect_func)();
|
typedef const class dialect*(*dialect_func)();
|
||||||
|
|
||||||
create_func create_connection{};
|
create_func create_connection{};
|
||||||
destroy_func destroy_connection{};
|
destroy_func destroy_connection{};
|
||||||
dialect_func get_dialect{};
|
dialect_func get_dialect{};
|
||||||
utils::library lib;
|
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<std::unique_ptr<connection_impl>> noop_connections_;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using backends_t = std::unordered_map<std::string, std::unique_ptr<backend_context>>;
|
using backends_t = std::unordered_map<std::string, std::unique_ptr<basic_backend_context>>;
|
||||||
backends_t backends_;
|
backends_t backends_;
|
||||||
std::string backends_path_;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif //QUERY_BACKEND_PROVIDER_HPP
|
#endif //QUERY_BACKEND_PROVIDER_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<query_result_impl> fetch(const std::string &stmt) override;
|
||||||
|
std::unique_ptr<statement_impl> 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
|
||||||
|
|
@ -9,14 +9,13 @@
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
|
class query_part;
|
||||||
|
|
||||||
struct query_data
|
struct query_data
|
||||||
{
|
{
|
||||||
// SqlCommands command;
|
// SqlCommands command;
|
||||||
std::vector<std::unique_ptr<query_part>> parts;
|
std::vector<std::unique_ptr<query_part>> parts;
|
||||||
std::vector<column_definition> columns;
|
std::vector<column_definition> columns;
|
||||||
std::unordered_map<std::type_index, table> table_map_by_index;
|
|
||||||
using table_ref = std::reference_wrapper<table>;
|
|
||||||
std::unordered_map<std::string, table_ref> table_map_by_name;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -240,8 +240,7 @@ public:
|
||||||
if (!schema_->exists<Type>()) {
|
if (!schema_->exists<Type>()) {
|
||||||
schema_->attach<Type>(table.name);
|
schema_->attach<Type>(table.name);
|
||||||
}
|
}
|
||||||
data_.parts.push_back(std::make_unique<query_create_table_part>(table, column_generator::generate<Type>(*schema_)));
|
return this->table(table, column_generator::generate<Type>(*schema_));
|
||||||
return {connection_, schema_, data_};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -261,7 +260,7 @@ public:
|
||||||
query_into_intermediate into(const sql::table &table, std::initializer_list<column> column_names);
|
query_into_intermediate into(const sql::table &table, std::initializer_list<column> column_names);
|
||||||
template<class Type>
|
template<class Type>
|
||||||
query_into_intermediate into(const sql::table &table)
|
query_into_intermediate into(const sql::table &table)
|
||||||
{;
|
{
|
||||||
data_.parts.push_back(std::make_unique<query_into_part>(table, column_name_generator::generate<Type>(*schema_)));
|
data_.parts.push_back(std::make_unique<query_into_part>(table, column_name_generator::generate<Type>(*schema_)));
|
||||||
return {connection_, schema_, data_};
|
return {connection_, schema_, data_};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ set(SQL_SOURCES
|
||||||
sql/query.cpp
|
sql/query.cpp
|
||||||
sql/query_parts.cpp
|
sql/query_parts.cpp
|
||||||
sql/query_compiler.cpp
|
sql/query_compiler.cpp
|
||||||
|
sql/noop_connection.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SQL_HEADER
|
set(SQL_HEADER
|
||||||
|
|
@ -79,6 +80,7 @@ set(SQL_HEADER
|
||||||
../include/matador/sql/query_compiler.hpp
|
../include/matador/sql/query_compiler.hpp
|
||||||
../include/matador/sql/query_data.hpp
|
../include/matador/sql/query_data.hpp
|
||||||
../include/matador/sql/table.hpp
|
../include/matador/sql/table.hpp
|
||||||
|
../include/matador/sql/noop_connection.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(QUERY_SOURCES
|
set(QUERY_SOURCES
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
#include "matador/sql/backend_provider.hpp"
|
#include "matador/sql/backend_provider.hpp"
|
||||||
|
#include "matador/sql/noop_connection.hpp"
|
||||||
|
#include "matador/sql/dialect_builder.hpp"
|
||||||
|
|
||||||
#include "matador/utils/os.hpp"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
backend_provider::backend_provider()
|
backend_provider::backend_provider()
|
||||||
: backends_path_(utils::os::getenv("MATADOR_BACKENDS_PATH"))
|
{
|
||||||
{}
|
backends_.emplace("noop", std::make_unique<noop_backend_context>());
|
||||||
|
}
|
||||||
|
|
||||||
backend_provider &backend_provider::instance() {
|
backend_provider &backend_provider::instance() {
|
||||||
static backend_provider provider;
|
static backend_provider provider;
|
||||||
|
|
@ -19,31 +19,30 @@ connection_impl *backend_provider::create_connection(const std::string &connecti
|
||||||
{
|
{
|
||||||
auto it = backends_.find(connection_type);
|
auto it = backends_.find(connection_type);
|
||||||
if (it == backends_.end()) {
|
if (it == backends_.end()) {
|
||||||
it = backends_.emplace(connection_type, std::make_unique<backend_context>(connection_type, backends_path_)).first;
|
it = backends_.emplace(connection_type, std::make_unique<backend_context>(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)
|
void backend_provider::destroy_connection(const std::string &connection_type, connection_impl *c)
|
||||||
{
|
{
|
||||||
auto it = backends_.find(connection_type);
|
auto it = backends_.find(connection_type);
|
||||||
if (it == backends_.end()) {
|
if (it == backends_.end()) {
|
||||||
it = backends_.emplace(connection_type, std::make_unique<backend_context>(connection_type, backends_path_)).first;
|
it = backends_.emplace(connection_type, std::make_unique<backend_context>(connection_type)).first;
|
||||||
}
|
}
|
||||||
(*it->second->destroy_connection)(c);
|
return it->second->destroy(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dialect &backend_provider::connection_dialect(const std::string &connection_type)
|
const dialect &backend_provider::connection_dialect(const std::string &connection_type)
|
||||||
{
|
{
|
||||||
auto it = backends_.find(connection_type);
|
auto it = backends_.find(connection_type);
|
||||||
if (it == backends_.end()) {
|
if (it == backends_.end()) {
|
||||||
it = backends_.emplace(connection_type, std::make_unique<backend_context>(connection_type, backends_path_)).first;
|
it = backends_.emplace(connection_type, std::make_unique<backend_context>(connection_type)).first;
|
||||||
}
|
}
|
||||||
return *(*it->second->get_dialect)();
|
return *it->second->dialect();
|
||||||
}
|
}
|
||||||
|
|
||||||
backend_provider::backend_context::backend_context(const std::string &connection_type,
|
backend_provider::backend_context::backend_context(const std::string &connection_type)
|
||||||
const std::string &backends_path)
|
|
||||||
{
|
{
|
||||||
if (!lib.load("matador-" + connection_type)) {
|
if (!lib.load("matador-" + connection_type)) {
|
||||||
throw std::runtime_error("couldn't load library '" + 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<dialect_func >(reinterpret_cast<std::uintptr_t>(lib.function("get_dialect")));
|
get_dialect = reinterpret_cast<dialect_func >(reinterpret_cast<std::uintptr_t>(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()
|
backend_provider::backend_context::~backend_context()
|
||||||
{
|
{
|
||||||
lib.unload();
|
lib.unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connection_impl *backend_provider::noop_backend_context::create(const connection_info &info)
|
||||||
|
{
|
||||||
|
return noop_connections_.insert(std::make_unique<noop_connection>(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_;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
#include "matador/sql/noop_connection.hpp"
|
||||||
|
#include "matador/sql/query_context.hpp"
|
||||||
|
#include "matador/sql/record.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
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<query_result_impl> noop_connection::fetch(const std::string &stmt)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<statement_impl> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,13 +2,24 @@
|
||||||
|
|
||||||
#include <matador/sql/column_definition.hpp>
|
#include <matador/sql/column_definition.hpp>
|
||||||
#include <matador/sql/condition.hpp>
|
#include <matador/sql/condition.hpp>
|
||||||
|
#include <matador/sql/connection.hpp>
|
||||||
#include <matador/sql/dialect_builder.hpp>
|
#include <matador/sql/dialect_builder.hpp>
|
||||||
#include <matador/sql/query_builder.hpp>
|
#include <matador/sql/query_builder.hpp>
|
||||||
|
#include <matador/sql/query.hpp>
|
||||||
|
|
||||||
using namespace matador::sql;
|
using namespace matador::sql;
|
||||||
using namespace matador::utils;
|
using namespace matador::utils;
|
||||||
|
|
||||||
TEST_CASE("Create table sql statement string", "[query]") {
|
TEST_CASE("Create table sql statement string", "[query]") {
|
||||||
|
connection noop("noop://noop.db");
|
||||||
|
auto scm = std::make_shared<schema>("noop");
|
||||||
|
query qu(noop, scm);
|
||||||
|
auto s = qu.create().table({"person"}, {
|
||||||
|
make_pk_column<unsigned long>("id"),
|
||||||
|
make_column<std::string>("name", 255),
|
||||||
|
make_column<unsigned short>("age")
|
||||||
|
}).str();
|
||||||
|
|
||||||
dialect d = dialect_builder::builder().create().build();
|
dialect d = dialect_builder::builder().create().build();
|
||||||
query_builder query(d);
|
query_builder query(d);
|
||||||
auto q = query.create().table("person", {
|
auto q = query.create().table("person", {
|
||||||
|
|
@ -17,7 +28,8 @@ TEST_CASE("Create table sql statement string", "[query]") {
|
||||||
make_column<unsigned short>("age")
|
make_column<unsigned short>("age")
|
||||||
}).compile();
|
}).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");
|
REQUIRE(q.table_name == "person");
|
||||||
|
|
||||||
q = query.create().table("person", {
|
q = query.create().table("person", {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue