149 lines
3.9 KiB
C++
149 lines
3.9 KiB
C++
#include "matador/sql/connection.hpp"
|
|
|
|
#include "matador/sql/backend_provider.hpp"
|
|
#include "matador/sql/connection_impl.hpp"
|
|
#include "matador/sql/schema.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <stdexcept>
|
|
#include <utility>
|
|
|
|
namespace matador::sql {
|
|
|
|
connection::connection(connection_info info)
|
|
: connection_info_(std::move(info))
|
|
, logger_(stdout, "SQL")
|
|
, dialect_(backend_provider::instance().connection_dialect(connection_info_.type))
|
|
{
|
|
connection_.reset(backend_provider::instance().create_connection(connection_info_.type, connection_info_));
|
|
}
|
|
|
|
connection::connection(const std::string& dns)
|
|
: connection(connection_info::parse(dns))
|
|
{}
|
|
|
|
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_;
|
|
}
|
|
|
|
std::vector<sql::column_definition> 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);
|
|
}
|
|
|
|
sql::query connection::query(const schema &schema) const
|
|
{
|
|
return sql::query(*const_cast<connection*>(this), schema);
|
|
}
|
|
|
|
bool is_unknown(const std::vector<sql::column_definition> &columns) {
|
|
return std::all_of(std::begin(columns), std::end(columns), [](const auto &col) {
|
|
return col.type() == data_type_t::type_unknown;
|
|
});
|
|
}
|
|
|
|
query_result<record> connection::fetch(const query_context &q) const
|
|
{
|
|
if (q.prototype.empty() || is_unknown(q.prototype)) {
|
|
const auto table_prototype = describe(q.table.name);
|
|
for (auto &col : q.prototype) {
|
|
const auto rit = std::find_if(std::begin(table_prototype), std::end(table_prototype), [&col](const auto &value) {
|
|
return value.name() == col.name();
|
|
});
|
|
if (col.type() == data_type_t::type_unknown && rit != table_prototype.end()) {
|
|
const_cast<column_definition&>(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<column&>(col).type(rit->type());
|
|
// }
|
|
// }
|
|
auto res = fetch(q.sql);
|
|
return query_result<record>{std::move(res), q.prototype};
|
|
}
|
|
|
|
std::unique_ptr<query_result_impl> 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_;
|
|
}
|
|
|
|
}
|