ensure proper table creation in session::create_schema including foreign key constraints

This commit is contained in:
Sascha Kühl 2025-07-17 15:56:15 +02:00
parent 581b93c5ea
commit fa393a1e30
16 changed files with 186 additions and 221 deletions

View File

@ -131,14 +131,14 @@ int main() {
// logger::default_min_log_level(logger::log_level::LVL_DEBUG);
// logger::add_log_sink(logger::create_stdout_sink());
// {
// // has_many with builtin-type
// object::schema schema;
//
// auto result = schema.attach<names>("names");
//
// schema.dump(std::cout);
// }
{
// has_many with builtin-type
object::schema schema;
auto result = schema.attach<names>("names");
schema.dump(std::cout);
}
{
// has_many with foreign without belongs_to
object::schema schema;
@ -157,58 +157,58 @@ int main() {
schema.dump(std::cout);
}
// {
// // has_many to belongs_to
// object::schema schema;
//
// auto result = schema.attach<author>("authors")
// .and_then([&schema] { return schema.attach<book>("books"); });
//
// schema.dump(std::cout);
// }
// {
// // belongs_to to has_many
// object::schema schema;
//
// auto result = schema.attach<book>("books")
// .and_then([&schema] { return schema.attach<author>("authors"); });
//
// schema.dump(std::cout);
// }
// {
// // has_many_to_many (with join columns first)
// object::schema schema;
//
// auto result = schema.attach<demo::ingredient>("ingredients")
// .and_then([&schema] { return schema.attach<recipe>("recipes"); });
//
// schema.dump(std::cout);
// }
// {
// // has_many_to_many (with join columns last)
// object::schema schema;
//
// auto result = schema.attach<demo::recipe>("recipes")
// .and_then([&schema] { return schema.attach<ingredient>("ingredients"); });
//
// schema.dump(std::cout);
// }
// {
// // belongs_to to has_one
// object::schema schema;
//
// auto result = schema.attach<profile>("profiles")
// .and_then([&schema] { return schema.attach<user>("users"); });
//
// schema.dump(std::cout);
// }
// {
// // has_one to belongs_to
// object::schema schema;
//
// auto result = schema.attach<user>("users")
// .and_then([&schema] { return schema.attach<profile>("profiles"); });
//
// schema.dump(std::cout);
// }
{
// has_many to belongs_to
object::schema schema;
auto result = schema.attach<author>("authors")
.and_then([&schema] { return schema.attach<book>("books"); });
schema.dump(std::cout);
}
{
// belongs_to to has_many
object::schema schema;
auto result = schema.attach<book>("books")
.and_then([&schema] { return schema.attach<author>("authors"); });
schema.dump(std::cout);
}
{
// has_many_to_many (with join columns first)
object::schema schema;
auto result = schema.attach<demo::ingredient>("ingredients")
.and_then([&schema] { return schema.attach<recipe>("recipes"); });
schema.dump(std::cout);
}
{
// has_many_to_many (with join columns last)
object::schema schema;
auto result = schema.attach<demo::recipe>("recipes")
.and_then([&schema] { return schema.attach<ingredient>("ingredients"); });
schema.dump(std::cout);
}
{
// belongs_to to has_one
object::schema schema;
auto result = schema.attach<profile>("profiles")
.and_then([&schema] { return schema.attach<user>("users"); });
schema.dump(std::cout);
}
{
// has_one to belongs_to
object::schema schema;
auto result = schema.attach<user>("users")
.and_then([&schema] { return schema.attach<profile>("profiles"); });
schema.dump(std::cout);
}
}

View File

@ -75,8 +75,8 @@ int main() {
const object::schema schema("Administration");
// sql::connection_pool<sql::connection> pool("postgres://news:news@127.0.0.1:15432/matador", 4);
sql::connection_pool<sql::connection> pool("postgres://test:test123!@127.0.0.1:5432/matador", 4);
sql::connection_pool<sql::connection> pool("postgres://news:news@127.0.0.1:15432/matador", 4);
// sql::connection_pool<sql::connection> pool("postgres://test:test123!@127.0.0.1:5432/matador", 4);
orm::session ses(pool);

View File

@ -54,13 +54,13 @@ private:
class attribute_definition_generator final {
private:
attribute_definition_generator(std::vector<attribute_definition> &columns, schema &repo);
attribute_definition_generator(std::vector<attribute_definition> &columns, const schema &repo);
public:
~attribute_definition_generator() = default;
template < class Type >
static std::vector<attribute_definition> generate(schema &repo)
static std::vector<attribute_definition> generate(const schema &repo)
{
std::vector<attribute_definition> columns;
attribute_definition_generator gen(columns, repo);
@ -70,7 +70,7 @@ public:
}
template < class Type >
static std::vector<attribute_definition> generate(const Type& obj, schema &repo) {
static std::vector<attribute_definition> generate(const Type& obj, const schema &repo) {
std::vector<attribute_definition> columns;
attribute_definition_generator gen(columns, repo);
access::process(gen, obj);
@ -128,7 +128,7 @@ private:
private:
size_t index_ = 0;
std::vector<attribute_definition> &columns_;
schema &repo_;
const schema &repo_;
fk_attribute_generator fk_column_generator_;
};

View File

@ -9,6 +9,7 @@
namespace matador::sql {
class executor;
class statement;
struct query_context;
}
namespace matador::query {
@ -19,6 +20,7 @@ public:
[[nodiscard]] utils::result<size_t, utils::error> execute(const sql::executor &exec) const;
[[nodiscard]] utils::result<sql::statement, utils::error> prepare(const sql::executor &exec) const;
[[nodiscard]] sql::query_context compile(const sql::executor &exec) const;
[[nodiscard]] std::string str(const sql::executor &exec) const;
};

View File

@ -35,7 +35,7 @@ public:
virtual void on_close() = 0;
/**
* Is called when a sql statement is going to
* Is called when a SQL statement is going to
* be executed
*
* @param stmt SQL statement to be executed
@ -43,7 +43,15 @@ public:
virtual void on_execute(const std::string &stmt) = 0;
/**
* Is called when a sql statement is going to
* Is called when a SQL select statement is going to
* be executed
*
* @param stmt The SQL select-statement to be executed
*/
virtual void on_fetch(const std::string &stmt) = 0;
/**
* Is called when a SQL statement is going to
* be prepared
*
* @param stmt SQL statement to be prepared
@ -75,6 +83,11 @@ public:
*/
void on_execute(const std::string &) override { }
/**
* No logging on a select-statement.
*/
void on_fetch( const std::string& stmt ) override { }
/**
* No logging on preparing a statement.
*/

View File

@ -13,27 +13,28 @@
namespace matador::sql {
class connection_impl;
const auto null_logger = std::make_shared<null_sql_logger>();
/**
* @brief The connection class represents a connection to a database.
*/
class connection final : public executor {
public:
using logger_ptr = std::shared_ptr<abstract_sql_logger>;
/**
* @brief Creates a database connection from a connection info data.
* @brief Creates a database connection from connection info data.
*
* @param info The database connection info data
* @param sql_logger The logging handler
*/
explicit connection(connection_info info,
const std::shared_ptr<abstract_sql_logger> &sql_logger = std::make_shared<null_sql_logger>());
explicit connection(connection_info info, const logger_ptr &sql_logger = null_logger);
/**
* @brief Creates a database connection from a connection string.
*
* @param dns The database connection string
* @param sql_logger The logging handler
*/
explicit connection(const std::string &dns,
const std::shared_ptr<abstract_sql_logger> &sql_logger = std::make_shared<null_sql_logger>());
explicit connection(const std::string &dns, const logger_ptr &sql_logger = null_logger);
/**
* Copies a given connection
*
@ -66,8 +67,8 @@ public:
/**
* @brief Opens the database connection for the given dns.
*
* Opens the database connection. If database connection
* couldn't be opened an exception is thrown.
* Opens the database connection. If the database connection
* couldn't be opened, an exception is thrown.
*/
[[nodiscard]] utils::result<void, utils::error> open() const;
/**
@ -77,11 +78,11 @@ public:
*/
[[nodiscard]] utils::result<void, utils::error> close() const;
/**
* @brief Returns true if database connection is open.
* @brief Returns true if the database connection is open.
*
* Returns true if database connection is open
* Returns true if the database connection is open
*
* @return True on open database connection.
* @return True on an open database connection.
*/
[[nodiscard]] utils::result<bool, utils::error> is_open() const;
@ -95,7 +96,7 @@ public:
/**
* @brief Return the database type of the connection.
*
* Returns the database type of the connection which is
* Returns the database type of the connection, which is
* currently one of
* - mssql
* - mysql
@ -108,21 +109,21 @@ public:
/**
* @brief Starts a transaction by calling the
* underlying database backends transaction begin
* underlying database backends a transaction begin
* statement.
*/
[[nodiscard]] utils::result<void, utils::error> begin() const;
/**
* @brief Commits a transaction by calling the
* underlying database backends transaction commit
* underlying database backends a transaction commit
* statement.
*/
[[nodiscard]] utils::result<void, utils::error> commit() const;
/**
* @brief Roll back a transaction by calling the
* underlying database backends transaction rollback/abort
* underlying database backends transaction rollback or abort
* statement.
*/
[[nodiscard]] utils::result<void, utils::error> rollback() const;

View File

@ -5,14 +5,16 @@
namespace matador::sql {
enum class dialect_token : uint8_t
{
enum class dialect_token : uint8_t {
CREATE = 0,
DROP,
REMOVE,
INSERT,
UPDATE,
SELECT,
ALTER,
SCHEMA,
DATABASE,
TABLE,
VALUES,
INSERT_VALUES,

View File

@ -9,18 +9,26 @@
namespace matador::sql {
enum class sql_command {
SQL_CMD_UNKNOWN,
SQL_CMD_CREATE,
SQL_CMD_UPDATE,
SQL_CMD_INSERT,
SQL_CMD_DELETE,
SQL_CMD_SELECT,
SQL_CMD_DROP,
SQL_CMD_ALTER
SQL_UNKNOWN,
SQL_CREATE_TABLE,
SQL_CREATE_SCHEMA,
SQL_CREATE_DATABASE,
SQL_UPDATE,
SQL_INSERT,
SQL_DELETE,
SQL_SELECT,
SQL_DROP_TABLE,
SQL_DROP_SCHEMA,
SQL_DROP_DATABASE,
SQL_ALTER_TABLE
};
struct query_context
{
struct sql_command_info {
std::string sql;
sql_command command{};
};
struct query_context {
std::string sql;
sql_command command{};
std::string command_name;
@ -32,6 +40,8 @@ struct query_context
std::unordered_map<std::string, std::string> column_aliases;
std::unordered_map<std::string, std::string> table_aliases;
std::vector<sql_command_info> additional_commands;
};
}

View File

@ -3,7 +3,7 @@
namespace matador::object {
attribute_definition_generator::attribute_definition_generator(std::vector<object::attribute_definition> &columns, schema &repo)
attribute_definition_generator::attribute_definition_generator(std::vector<object::attribute_definition> &columns, const schema &repo)
: columns_(columns)
, repo_(repo)
{}
@ -23,7 +23,7 @@ utils::result<std::shared_ptr<attribute_definition>, utils::error> attribute_def
}
void attribute_definition_generator::insert_missing_reference_column(const std::type_index& ti, std::shared_ptr<attribute_definition> ref_column) const {
repo_.missing_references_.insert({ti, ref_column});
const_cast<schema&>(repo_).missing_references_.insert({ti, ref_column});
}
void fk_attribute_generator::on_primary_key(const char *, std::string &, const size_t size)

View File

@ -6,7 +6,7 @@
namespace matador::utils {
std::string error::message() const {
return error_message_;
return ec_.message();;
}
std::string error::category() const {

View File

@ -4,7 +4,6 @@ add_library(matador-orm STATIC
../../include/matador/query/condition.hpp
../../include/matador/query/fk_value_extractor.hpp
../../include/matador/query/intermediates/executable_query.hpp
../../include/matador/query/intermediates/executable_query.hpp
../../include/matador/query/intermediates/fetchable_query.hpp
../../include/matador/query/intermediates/query_create_intermediate.hpp
../../include/matador/query/intermediates/query_delete_from_intermediate.hpp

View File

@ -25,12 +25,8 @@ utils::result<void, utils::error> session::create_schema() const {
for (const auto &node: *schema_) {
for (auto it = node->info().endpoint_begin(); it != node->info().endpoint_end(); ++it) {
std::cout << "Dependency graph " << node->name() << " (" << node.get() << ")" << " -> " << it->second->node_ptr()->name() << " (" << it->second->node_ptr().get() << ")" << std::endl;
dependency_graph[node->name()].push_back(it->second->node().name());
// if (it->second->is_has_many()) {
// continue;
// }
if (const auto dit = in_degree.find(it->second->node().name()); dit == in_degree.end()) {
in_degree[it->second->node().name()] = std::make_pair(1, it->second->node_ptr());
} else {
@ -51,67 +47,29 @@ utils::result<void, utils::error> session::create_schema() const {
}
std::cout << std::endl;
}
// Step 2: Perform topological sorting (Kahn's Algorithm)
std::queue<object::schema::node_ptr> zero_in_degree;
std::vector<object::schema::node_ptr> sorted_order;
for (const auto &[table, degree]: in_degree) {
if (degree.first == 0) {
zero_in_degree.push(degree.second);
}
}
for (const auto &it : in_degree) {
std::cout << "In degree table " << it.second.second->name() << " (" << it.second.first << ")" << std::endl;
}
while (!zero_in_degree.empty()) {
auto current = zero_in_degree.front();
zero_in_degree.pop();
sorted_order.push_back(current);
for (const auto &neighbor: dependency_graph[current->name()]) {
in_degree[neighbor].first--;
if (in_degree[neighbor].first == 0) {
zero_in_degree.push(in_degree[neighbor].second);
}
}
}
// Step 3: Check for cycles
if (sorted_order.size() != in_degree.size()) {
std::cout << "Cycle detected in table dependencies (sorted order size: " << sorted_order.size() << ", in degree size: " << in_degree.size() << ")" << std::endl;
// throw std::logic_error("Cycle detected in table dependencies");
}
// Step 4: Create tables in the sorted order
std::vector<std::string> fk_sql_commands;
auto c = pool_.acquire();
for (const auto &node : sorted_order) {
std::cout << "Creating table " << node->name() << std::endl;
// auto result = query::query::create()
// .table(node->name(), node->info().definition().columns())
// .execute(*c);
// if (!result) {
// return utils::failure(result.err());
// }
for (const auto &node: *schema_) {
auto ctx = query::query::create()
.table(node->name(), node->info().definition().columns())
.compile(*c);
for ( const auto& [sql, command] : ctx.additional_commands ) {
fk_sql_commands.push_back( sql );
}
if (auto result = c->execute(ctx.sql); !result) {
return utils::failure(result.err());
}
}
// auto c = pool_.acquire();
// for (const auto &node: *schema_) {
// auto result = query::query::create()
// .table(node->name(), node->info().definition().columns())
// .execute(*c);
// if (!result) {
// return utils::failure(result.err());
// }
// }
// execute additional commands (e.g. ALTER TABLE ADD FK)
for (const auto &sql: fk_sql_commands) {
if (auto result = c->execute(sql); !result) {
return utils::failure(result.err());
}
}
return utils::ok<void>();
}
utils::result<void, utils::error> session::drop_table(const std::string &table_name) const {

View File

@ -6,22 +6,25 @@
namespace matador::query {
utils::result<size_t, utils::error> executable_query::execute(const sql::executor &exec) const
{
utils::result<size_t, utils::error> executable_query::execute(const sql::executor &exec) const {
query_compiler compiler;
context_->mode = query_mode::Direct;
return exec.execute(compiler.compile(*context_, exec.dialect(), std::nullopt));
}
utils::result<sql::statement, utils::error> executable_query::prepare(const sql::executor &exec) const
{
utils::result<sql::statement, utils::error> executable_query::prepare(const sql::executor &exec) const {
query_compiler compiler;
context_->mode = query_mode::Prepared;
return exec.prepare(compiler.compile(*context_, exec.dialect(), std::nullopt));
}
std::string executable_query::str(const sql::executor &exec) const
{
sql::query_context executable_query::compile( const sql::executor& exec ) const {
query_compiler compiler;
context_->mode = query_mode::Prepared;
return compiler.compile(*context_, exec.dialect(), std::nullopt);
}
std::string executable_query::str(const sql::executor &exec) const {
query_compiler compiler;
context_->mode = query_mode::Direct;
return exec.str(compiler.compile(*context_, exec.dialect(), std::nullopt));

View File

@ -5,8 +5,7 @@
namespace matador::query {
utils::result<sql::query_result<sql::record>, utils::error> fetchable_query::fetch_all(const sql::executor &exec) const
{
utils::result<sql::query_result<sql::record>, utils::error> fetchable_query::fetch_all(const sql::executor &exec) const {
query_compiler compiler;
context_->mode = query_mode::Direct;
return exec.fetch(compiler.compile(*context_, exec.dialect(), std::nullopt))
@ -15,8 +14,7 @@ utils::result<sql::query_result<sql::record>, utils::error> fetchable_query::fet
});
}
utils::result<std::optional<sql::record>, utils::error> fetchable_query::fetch_one(const sql::executor &exec) const
{
utils::result<std::optional<sql::record>, utils::error> fetchable_query::fetch_one(const sql::executor &exec) const {
query_compiler compiler;
context_->mode = query_mode::Direct;
auto result = exec.fetch(compiler.compile(*context_, exec.dialect(), std::nullopt));
@ -30,25 +28,22 @@ utils::result<std::optional<sql::record>, utils::error> fetchable_query::fetch_o
return utils::ok(std::optional<sql::record>{std::nullopt});
}
return utils::ok(std::optional<sql::record>{*first.get()});
return utils::ok(std::optional{*first.get()});
}
std::string fetchable_query::str(const sql::executor &exec) const
{
std::string fetchable_query::str(const sql::executor &exec) const {
query_compiler compiler;
context_->mode = query_mode::Direct;
return exec.str(compiler.compile(*context_, exec.dialect(), std::nullopt));
}
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetchable_query::fetch(const sql::executor &exec) const
{
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetchable_query::fetch(const sql::executor &exec) const {
query_compiler compiler;
context_->mode = query_mode::Direct;
return exec.fetch(compiler.compile(*context_, exec.dialect(), std::nullopt));
}
utils::result<sql::statement, utils::error> fetchable_query::prepare(const sql::executor &exec) const
{
utils::result<sql::statement, utils::error> fetchable_query::prepare(const sql::executor &exec) const {
query_compiler compiler;
context_->mode = query_mode::Prepared;
return exec.prepare(compiler.compile(*context_, exec.dialect(), std::nullopt));

View File

@ -29,7 +29,7 @@ sql::query_context query_compiler::compile(const query_data &data,
dialect_ = nullptr;
data_ = nullptr;
return query_;
return {query_};
}
std::string handle_column(sql::query_context &ctx, const sql::dialect *d, const query_data &data, const sql::column &col) {
@ -52,7 +52,7 @@ std::string handle_column(sql::query_context &ctx, const sql::dialect *d, const
void query_compiler::visit(internal::query_select_part &select_part)
{
query_.command = sql::sql_command::SQL_CMD_SELECT;
query_.command = sql::sql_command::SQL_SELECT;
query_.sql = dialect_->token_at(sql::dialect_token::SELECT) + " ";
query_.prototype.clear();
@ -131,7 +131,7 @@ void query_compiler::visit(internal::query_limit_part &limit_part)
void query_compiler::visit(internal::query_insert_part &/*insert_part*/)
{
query_.command = sql::sql_command::SQL_CMD_INSERT;
query_.command = sql::sql_command::SQL_INSERT;
query_.sql = dialect_->token_at(sql::dialect_token::INSERT);
}
@ -212,14 +212,14 @@ void query_compiler::visit(internal::query_values_part &values_part) {
void query_compiler::visit(internal::query_update_part &update_part)
{
query_.command = sql::sql_command::SQL_CMD_UPDATE;
query_.command = sql::sql_command::SQL_UPDATE;
query_.table = update_part.table();
query_.sql += query_compiler::build_table_name(update_part.token(), *dialect_, query_.table);
}
void query_compiler::visit(internal::query_delete_part &/*delete_part*/)
{
query_.command = sql::sql_command::SQL_CMD_DELETE;
query_.command = sql::sql_command::SQL_DELETE;
query_.sql = dialect_->token_at(sql::dialect_token::REMOVE);
}
@ -231,7 +231,7 @@ void query_compiler::visit(internal::query_delete_from_part &delete_from_part)
void query_compiler::visit(internal::query_create_part &/*create_part*/)
{
query_.command = sql::sql_command::SQL_CMD_CREATE;
query_.command = sql::sql_command::SQL_CREATE_TABLE;
query_.sql = dialect_->token_at(sql::dialect_token::CREATE);
}
@ -274,10 +274,13 @@ void query_compiler::visit(internal::query_create_table_part &create_table_part)
result.append(", CONSTRAINT PK_" + create_table_part.table().name + " PRIMARY KEY (" + utils::join(context.primary_keys, ", ") + ")");
}
for (const auto &[column, reference_column]: context.foreign_contexts) {
result += ", CONSTRAINT FK_" + create_table_part.table().name;
result += "_" + column;
result += " FOREIGN KEY (" + dialect_->prepare_identifier_string(column) + ")";
result += " REFERENCES " + reference_column->table_name() + "(" + reference_column->name() + ")";
// ALTER TABLE Orders ADD CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID) REFERENCES Persons(PersonID);
std::string fk_cmd = "ALTER TABLE " + query_.table.name + " ADD";
fk_cmd += " CONSTRAINT FK_" + create_table_part.table().name;
fk_cmd += "_" + column;
fk_cmd += " FOREIGN KEY (" + dialect_->prepare_identifier_string(column) + ")";
fk_cmd += " REFERENCES " + reference_column->table_name() + "(" + reference_column->name() + ")";
query_.additional_commands.push_back({fk_cmd, sql::sql_command::SQL_ALTER_TABLE});
}
result += ")";
@ -286,7 +289,7 @@ void query_compiler::visit(internal::query_create_table_part &create_table_part)
void query_compiler::visit(internal::query_drop_part &/*drop_part*/)
{
query_.command = sql::sql_command::SQL_CMD_DROP;
query_.command = sql::sql_command::SQL_DROP_TABLE;
query_.sql = dialect_->token_at(sql::dialect_token::DROP);
}
@ -311,24 +314,15 @@ void query_compiler::visit(internal::query_set_part &set_part)
for (const auto &col: set_part.key_values()) {
result.append(dialect_->prepare_identifier_string(col.name()) + "=");
result.append(determine_set_value(visitor, col.value()));
// auto var = col.value();
// std::visit(visitor, var);
// result.append(visitor.result);
}
} else {
auto it = set_part.key_values().begin();
result.append(dialect_->prepare_identifier_string(it->name()) + "=");
result.append(determine_set_value(visitor, (it++)->value()));
// auto var = (it++)->value();
// std::visit(visitor, var);
// result.append(visitor.result);
for (; it != set_part.key_values().end(); ++it) {
result.append(", ");
result.append(dialect_->prepare_identifier_string(it->name()) + "=");
result.append(determine_set_value(visitor, it->value()));
// var = it->value();
// std::visit(visitor, var);
// result.append(visitor.result);
}
}

View File

@ -3,8 +3,7 @@
#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/error_code.hpp"
#include "matador/sql/interface/connection_impl.hpp"
@ -127,24 +126,20 @@ utils::result<void, utils::error> connection::rollback() const {
return utils::ok<void>();
}
utils::result<std::vector<object::attribute_definition>, utils::error> connection::describe(const std::string &table_name) const
{
utils::result<std::vector<object::attribute_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
{
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
{
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);
utils::result<size_t, utils::error> connection::execute(const std::string &sql) const {
logger_->on_execute(sql);
return connection_->execute(sql);
}
@ -181,22 +176,18 @@ bool has_unknown_columns(const std::vector<object::attribute_definition> &column
// 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);
utils::result<std::unique_ptr<query_result_impl>, utils::error> connection::fetch(const query_context &ctx) const {
logger_->on_fetch(ctx.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
{
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 (ctx.command != sql_command::SQL_CREATE_TABLE && (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),
@ -210,9 +201,6 @@ utils::result<statement, utils::error> connection::prepare(const query_context &
}
}
// 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()));
}