#include "matador/sql/connection.hpp" #include "matador/sql/backend_provider.hpp" #include "matador/sql/connection_impl.hpp" #include #include namespace matador::sql { connection::connection(connection_info info, const std::shared_ptr &repo) : connection_info_(std::move(info)) , logger_(stdout, "SQL") , dialect_(backend_provider::instance().connection_dialect(connection_info_.type)) , schema_(repo) { connection_.reset(backend_provider::instance().create_connection(connection_info_.type, connection_info_)); } connection::connection(const std::string& dns, const std::shared_ptr &repo) : connection(connection_info::parse(dns), repo) {} connection::connection(const connection &x) : connection_info_(x.connection_info_) , logger_(x.logger_) , dialect_(x.dialect_) { if (x.connection_) { throw std::runtime_error("couldn't copy connection with valid connection impl"); } } connection &connection::operator=(const connection &x) { connection_info_ = x.connection_info_; logger_ = x.logger_; if (x.connection_) { throw std::runtime_error("couldn't copy connection with valid connection impl"); } return *this; } connection::~connection() { if (connection_->is_open()) { connection_->close(); } backend_provider::instance().destroy_connection(connection_info_.type, connection_.release()); connection_ = nullptr; } void connection::open() { connection_->open(); } void connection::close() { connection_->close(); } bool connection::is_open() const { return connection_->is_open(); } const connection_info &connection::info() const { return connection_info_; } query_create_intermediate connection::create() { return query_create_intermediate(*this); } query_drop_intermediate connection::drop() { return query_drop_intermediate{*this}; } query_select_intermediate connection::select(std::initializer_list columns) { return {*this, columns}; } query_insert_intermediate connection::insert() { return query_insert_intermediate{*this}; } query_update_intermediate connection::update(const std::string &table) { return query_update_intermediate{*this, table}; } query_delete_intermediate connection::remove() { return query_delete_intermediate{*this}; } record connection::describe(const std::string &table_name) const { return std::move(connection_->describe(table_name)); } bool connection::exists(const std::string &schema_name, const std::string &table_name) const { return connection_->exists(schema_name, table_name); } bool connection::exists(const std::string &table_name) const { return connection_->exists(dialect_.default_schema_name(), table_name); } size_t connection::execute(const std::string &sql) const { logger_.debug(sql); return connection_->execute(sql); } query_result connection::fetch(const query_context &q) const { if (q.prototype.empty() || q.prototype.unknown()) { const auto table_prototype = describe(q.table_name); for (auto &col : q.prototype) { if (const auto rit = table_prototype.find(col.name()); col.type() == data_type_t::type_unknown && rit != table_prototype.end()) { const_cast(col).type(rit->type()); } } } // auto it = prototypes_.find(q.table_name); // if (it == prototypes_.end()) { // it = prototypes_.emplace(q.table_name, describe(q.table_name)).first; // } // // adjust columns from given query // for (auto &col : q.prototype) { // if (const auto rit = it->second.find(col.name()); col.type() == data_type_t::type_unknown && rit != it->second.end()) { // const_cast(col).type(rit->type()); // } // } auto res = fetch(q.sql); return query_result{std::move(res), q.prototype}; } std::unique_ptr connection::fetch(const std::string &sql) const { logger_.debug(sql); return connection_->fetch(sql); } statement connection::prepare(query_context &&query) const { return statement(connection_->prepare(std::move(query)), logger_); } const class dialect &connection::dialect() const { return dialect_; } std::shared_ptr connection::tables() const { return schema_; } }