initial matador ng commit
This commit is contained in:
@@ -0,0 +1,228 @@
|
||||
#include "matador/sql/connection.hpp"
|
||||
|
||||
#include "matador/sql/backend_provider.hpp"
|
||||
#include "matador/sql/dialect.hpp"
|
||||
#include "matador/sql/dialect_token.hpp"
|
||||
// #include "matador/sql/schema.hpp"
|
||||
// #include "matador/sql/query_compile_context.hpp"
|
||||
#include "matador/sql/interface/connection_impl.hpp"
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
connection::connection(connection_info info, const std::shared_ptr<abstract_sql_logger> &sql_logger)
|
||||
: connection_info_(std::move(info))
|
||||
, logger_(sql_logger)
|
||||
{
|
||||
connection_.reset(backend_provider::instance().create_connection(connection_info_.type, connection_info_));
|
||||
}
|
||||
|
||||
connection::connection(const std::string& dns, const std::shared_ptr<abstract_sql_logger> &sql_logger)
|
||||
: connection(connection_info::parse(dns), sql_logger)
|
||||
{}
|
||||
|
||||
connection::connection(const connection &x)
|
||||
: connection_info_(x.connection_info_)
|
||||
{
|
||||
if (x.connection_) {
|
||||
throw std::runtime_error("couldn't copy connection with valid connection impl");
|
||||
}
|
||||
}
|
||||
|
||||
connection &connection::operator=(const connection &x) {
|
||||
if (this == &x) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
connection_info_ = x.connection_info_;
|
||||
if (x.connection_) {
|
||||
throw std::runtime_error("couldn't copy connection with valid connection impl");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
connection & connection::operator=(connection &&x) noexcept {
|
||||
connection_info_ = std::move(x.connection_info_);
|
||||
connection_ = std::move(x.connection_);
|
||||
logger_ = std::move(x.logger_);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
connection::~connection()
|
||||
{
|
||||
if (connection_->is_open()) {
|
||||
connection_->close();
|
||||
}
|
||||
backend_provider::instance().destroy_connection(connection_info_.type, connection_.release());
|
||||
connection_ = nullptr;
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> connection::open() const
|
||||
{
|
||||
const auto res = is_open();
|
||||
if (res.is_error()) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
if (*res) {
|
||||
logger_->on_connect();
|
||||
return connection_->open();
|
||||
}
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> connection::close() const
|
||||
{
|
||||
logger_->on_close();
|
||||
return connection_->close();
|
||||
}
|
||||
|
||||
utils::result<bool, utils::error> connection::is_open() const
|
||||
{
|
||||
return connection_->is_open();
|
||||
}
|
||||
|
||||
const connection_info &connection::info() const
|
||||
{
|
||||
return connection_info_;
|
||||
}
|
||||
|
||||
std::string connection::type() const {
|
||||
return connection_info_.type;
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> connection::begin() const {
|
||||
const auto res = connection_->execute(dialect().token_at(dialect_token::BEGIN));
|
||||
if (res.is_error()) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> connection::commit() const {
|
||||
const auto res = connection_->execute(dialect().token_at(dialect_token::COMMIT));
|
||||
if (res.is_error()) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
utils::result<void, utils::error> connection::rollback() const {
|
||||
const auto res = connection_->execute(dialect().token_at(dialect_token::ROLLBACK));
|
||||
if (res.is_error()) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
|
||||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
utils::result<std::vector<column_definition>, utils::error> connection::describe(const std::string &table_name) const
|
||||
{
|
||||
return connection_->describe(table_name);
|
||||
}
|
||||
|
||||
utils::result<bool, utils::error> connection::exists(const std::string &schema_name, const std::string &table_name) const
|
||||
{
|
||||
return connection_->exists(schema_name, table_name);
|
||||
}
|
||||
|
||||
utils::result<bool, utils::error> connection::exists(const std::string &table_name) const
|
||||
{
|
||||
return connection_->exists(dialect().default_schema_name(), table_name);
|
||||
}
|
||||
|
||||
utils::result<size_t, utils::error> connection::execute(const std::string &sql) const
|
||||
{
|
||||
// logger_.debug(sql);
|
||||
return connection_->execute(sql);
|
||||
}
|
||||
|
||||
bool has_unknown_columns(const std::vector<sql::column_definition> &columns) {
|
||||
return std::any_of(std::begin(columns), std::end(columns), [](const auto &col) {
|
||||
return col.type() == utils::basic_type::type_null;
|
||||
});
|
||||
}
|
||||
|
||||
// query_result<record> connection::fetch(const query_context &ctx) const
|
||||
// {
|
||||
// if (ctx.prototype.empty() || is_unknown(ctx.prototype)) {
|
||||
// const auto table_prototype = describe(ctx.table.name);
|
||||
// for (auto &col : ctx.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::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(ctx.sql);
|
||||
// return query_result<record>{std::move(res), ctx.prototype};
|
||||
// }
|
||||
|
||||
utils::result<std::unique_ptr<query_result_impl>, utils::error> connection::fetch(const query_context &ctx) const
|
||||
{
|
||||
// logger_.debug(sql);
|
||||
return connection_->fetch(ctx);
|
||||
// return connection_->fetch(dialect().compile(ctx, *connection_));
|
||||
}
|
||||
|
||||
utils::result<size_t, utils::error> connection::execute(const query_context& ctx) const
|
||||
{
|
||||
return execute(ctx.sql);
|
||||
// return execute(dialect().compile(ctx, *connection_).sql);
|
||||
}
|
||||
|
||||
utils::result<statement, utils::error> connection::prepare(const query_context &ctx) const
|
||||
{
|
||||
if (ctx.command != sql_command::SQL_CMD_CREATE && (ctx.prototype.empty() || has_unknown_columns(ctx.prototype))) {
|
||||
if (const auto result = describe(ctx.table.name); result.is_ok()) {
|
||||
for (auto &col: ctx.prototype) {
|
||||
const auto rit = std::find_if(std::begin(*result), std::end(*result),
|
||||
[&col](const auto &value) {
|
||||
return value.name() == col.name();
|
||||
});
|
||||
if (col.type() == utils::basic_type::type_null && rit != result->end()) {
|
||||
const_cast<column_definition &>(col).type(rit->type());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return connection_->prepare(qry).and_then([](auto &&res) {
|
||||
// return statement(std::forward<decltype(res)>(res));
|
||||
// });
|
||||
if (auto result = connection_->prepare(ctx); result.is_ok()) {
|
||||
return utils::ok(statement(result.release()));
|
||||
}
|
||||
|
||||
return utils::ok(statement(std::unique_ptr<statement_impl>{}));
|
||||
}
|
||||
|
||||
std::string connection::str( const query_context& ctx ) const
|
||||
{
|
||||
return ctx.sql;
|
||||
}
|
||||
|
||||
const class dialect &connection::dialect() const
|
||||
{
|
||||
return connection_->dialect();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user