added returning to update statement and added error code implementation for query

This commit is contained in:
sascha 2026-02-27 16:29:49 +01:00
parent 626eae1ac8
commit 1e78430855
17 changed files with 172 additions and 26 deletions

View File

@ -88,6 +88,7 @@ int main() {
.and_then([&admin_schema] { return admin_schema.attach<jobs::IdPayload, jobs::Payload>("id_list_payloads"); })
.and_then([&admin_schema] { return admin_schema.attach<jobs::IdListPayload, jobs::Payload>("id_payloads"); })
.and_then([&admin_schema] { return admin_schema.attach<jobs::Task>("tasks"); })
.and_then([&admin_schema, &pool] { return admin_schema.create( *pool.acquire() ); })
;
admin_schema.dump(std::cout);
@ -109,7 +110,7 @@ int main() {
// }
/*
* const auto statement = QString( "SELECT %5.%6, %1.%2 FROM %3 %1, %4 %5 WHERE %1.%2=%5.%6 AND %7" )
const auto statement = QString( "SELECT %5.%6, %1.%2 FROM %3 %1, %4 %5 WHERE %1.%2=%5.%6 AND %7" )
.arg( payloadTableAliasName,
payloadSqlMetaInfo.columnName( Payload::Attributes::idAttributeId() ),
Payload::staticSqlMetaInfo().tableName(),

View File

@ -0,0 +1,35 @@
#ifndef MATADOR_ERROR_CODE_HPP
#define MATADOR_ERROR_CODE_HPP
#include <cstdint>
#include <system_error>
namespace matador::query {
enum class error_code {
Success,
Failure,
InvalidQuery,
InvalidSchema,
InvalidTable,
InvalidColumn,
InvalidConstraint,
InvalidDataType,
InvalidValue
};
class query_category_impl final : public std::error_category
{
public:
[[nodiscard]] const char* name() const noexcept override;
[[nodiscard]] std::string message(int ev) const override;
};
const std::error_category& query_category();
std::error_code make_error_code(error_code e);
std::error_condition make_error_condition(error_code e);
}
template <>
struct std::is_error_code_enum<matador::query::error_code> : true_type {};
#endif //MATADOR_ERROR_CODE_HPP

View File

@ -2,6 +2,7 @@
#define QUERY_EXECUTE_WHERE_INTERMEDIATE_HPP
#include "matador/query/intermediates/executable_query.hpp"
#include "matador/query/intermediates/fetchable_query.hpp"
namespace matador::query {
@ -14,9 +15,18 @@ class query_execute_where_intermediate : public executable_query
public:
using executable_query::executable_query;
template<typename... TableColumns>
fetchable_query returning(const TableColumns&... table_columns) {
const std::vector<table_column> tcv { table_columns... };
return returning(tcv);
}
query_execute_limit_intermediate limit(size_t limit);
query_execute_order_by_intermediate order_by(const table_column &col);
query_execute_order_by_intermediate order_by(std::initializer_list<table_column> columns);
private:
fetchable_query returning(const std::vector<table_column>& tables);
};
}

View File

@ -2,22 +2,13 @@
#define QUERY_INTO_INTERMEDIATE_HPP
#include "matador/query/intermediates/executable_query.hpp"
#include "matador/query/intermediates/fetchable_query.hpp"
#include "matador/query/intermediates/query_values_intermediate.hpp"
#include "matador/query/value_extractor.hpp"
#include "matador/utils/placeholder.hpp"
namespace matador::query {
class table_column;
class query_values_intermediate : public executable_query {
public:
using executable_query::executable_query;
fetchable_query returning(const table_column &col);
};
class query_into_intermediate : public query_intermediate {
public:
using query_intermediate::query_intermediate;

View File

@ -9,14 +9,11 @@
namespace matador::query {
class query_set_intermediate : public executable_query
{
class query_set_intermediate : public executable_query {
public:
using executable_query::executable_query;
query_execute_where_intermediate where(std::unique_ptr<abstract_criteria> cond) {
return where_clause(std::move(cond));
}
query_execute_where_intermediate where(std::unique_ptr<abstract_criteria> cond);
private:
query_execute_where_intermediate where_clause(std::unique_ptr<abstract_criteria> &&cond);

View File

@ -0,0 +1,24 @@
#ifndef MATADOR_QUERY_VALUES_INTERMEDIATE_H
#define MATADOR_QUERY_VALUES_INTERMEDIATE_H
#include "matador/query/intermediates/executable_query.hpp"
#include "matador/query/intermediates/fetchable_query.hpp"
namespace matador::query {
class table_column;
class query_values_intermediate : public executable_query {
public:
using executable_query::executable_query;
template<typename... TableColumns>
fetchable_query returning(const TableColumns&... table_columns) {
const std::vector<table_column> tcv { table_columns... };
return returning(tcv);
}
private:
fetchable_query returning(const std::vector<table_column>& tables);
};
}
#endif //MATADOR_QUERY_VALUES_INTERMEDIATE_H

View File

@ -198,6 +198,10 @@ add_library(matador-orm STATIC
query/manual_pk_generator.cpp
../../include/matador/query/table_pk_generator.hpp
query/table_pk_generator.cpp
../../include/matador/query/intermediates/query_values_intermediate.hpp
query/intermediates/query_values_intermediate.cpp
../../include/matador/query/error_code.hpp
query/error_code.cpp
)
target_include_directories(matador-orm

View File

@ -0,0 +1,45 @@
#include "matador/query/error_code.hpp"
namespace matador::query {
const char* query_category_impl::name() const noexcept {
return "query";
}
std::string query_category_impl::message(int ev) const {
switch (static_cast<error_code>(ev)) {
case error_code::Success:
return "Success";
case error_code::Failure:
return "Failure";
case error_code::InvalidQuery:
return "Invalid query";
case error_code::InvalidSchema:
return "Invalid schema";
case error_code::InvalidTable:
return "Invalid table";
case error_code::InvalidColumn:
return "Invalid column";
case error_code::InvalidConstraint:
return "Invalid constraint";
case error_code::InvalidDataType:
return "Invalid data type";
case error_code::InvalidValue:
return "Invalid value";
default:
return "Unknown error";
}
}
const std::error_category& query_category() {
static query_category_impl instance;
return instance;
}
std::error_code make_error_code(error_code e) {
return {static_cast<int>(e), query_category()};
}
std::error_condition make_error_condition(error_code e) {
return {static_cast<int>(e), query_category()};
}
}

View File

@ -8,6 +8,10 @@
#include "matador/query/query_data.hpp"
namespace matador::query {
fetchable_query query_execute_where_intermediate::returning(const std::vector<table_column>& table_columns) {
context_->parts.push_back(std::make_unique<internal::query_returning_part>(table_columns));
return {context_};
}
query_execute_limit_intermediate query_execute_where_intermediate::limit(size_t limit) {
context_->parts.push_back(std::make_unique<internal::query_limit_part>(limit));

View File

@ -4,11 +4,6 @@
#include "matador/query/query_data.hpp"
namespace matador::query {
fetchable_query query_values_intermediate::returning(const table_column &col) {
context_->parts.push_back(std::make_unique<internal::query_returning_part>(std::vector{col}));
return {context_};
}
query_values_intermediate query_into_intermediate::values(const std::initializer_list<std::variant<utils::placeholder, utils::database_type>> values) {
return this->values(std::vector(values));
}

View File

@ -4,6 +4,9 @@
#include "matador/query/query_data.hpp"
namespace matador::query {
query_execute_where_intermediate query_set_intermediate::where(std::unique_ptr<abstract_criteria> cond) {
return where_clause(std::move(cond));
}
query_execute_where_intermediate query_set_intermediate::where_clause(std::unique_ptr<abstract_criteria> &&cond)
{

View File

@ -0,0 +1,11 @@
#include "matador/query/intermediates/query_values_intermediate.hpp"
#include "matador/query/internal/query_parts.hpp"
#include "matador/query/query_data.hpp"
namespace matador::query {
fetchable_query query_values_intermediate::returning(const std::vector<table_column>& table_columns) {
context_->parts.push_back(std::make_unique<internal::query_returning_part>(table_columns));
return {context_};
}
}

View File

@ -3,6 +3,7 @@
#include "matador/query/schema.hpp"
#include "matador/query/query.hpp"
#include "matador/query/manual_pk_generator.hpp"
#include "matador/object/repository_node.hpp"
@ -164,6 +165,6 @@ schema::iterator schema::insert_table(const std::type_index &ti, const object::r
for (const auto &attr: node.info().attributes()) {
columns.emplace_back(nullptr, attr.name(), attr.type(), attr.attributes());
}
return schema_nodes_.insert({ti, schema_node{table(node.name(), columns), generator_type, node}}).first;
return schema_nodes_.insert({ti, schema_node{table(node.name(), columns), std::make_unique<manual_pk_generator>(), node}}).first;
}
} // namespace matador::query

View File

@ -1,5 +1,6 @@
#include "matador/query/table_pk_generator.hpp"
#include "matador/query/query.hpp"
#include "matador/query/error_code.hpp"
namespace matador::query {
table_pk_generator::table_pk_generator(const std::string& table_name, const std::string &sequence_name)
@ -18,5 +19,6 @@ table_pk_generator::table_pk_generator(const std::string& table_name, const std:
}
utils::result<int64_t, utils::error> table_pk_generator::next_id(const sql::executor &exec) {
return utils::failure(utils::error{error_code::Failure});
}
}

View File

@ -142,9 +142,9 @@ TEST_CASE("Create sql query data for entity with eager belongs to", "[query][ent
query_context qc;
size_t index{0};
criteria_evaluator evaluator(db.dialect(), qc);
for (const auto & [join_table, clause] : data.joins) {
REQUIRE(join_table->table_name() == expected_join_data[index].first);
REQUIRE(evaluator.evaluate(*clause) == expected_join_data[index].second);
for (const auto &join : data.joins) {
REQUIRE(join.join_table->table_name() == expected_join_data[index].first);
REQUIRE(evaluator.evaluate(*join.condition) == expected_join_data[index].second);
++index;
}

View File

@ -39,6 +39,9 @@ TEST_CASE("insert query builder test", "[query][insert_query_builder]") {
const auto& stmts = *build_result;
REQUIRE(stmts.size() == 1);
const auto sql = stmts.front().str(db);
const auto step = stmts.front();
REQUIRE(std::holds_alternative<executable_query>(step.query));
const auto sql = std::get<executable_query>(step.query).str(db);
REQUIRE(sql == R"(INSERT INTO "airplanes" ("id", "brand", "model") VALUES (1, 'Boeing', 'A380'))");
}

View File

@ -139,6 +139,16 @@ TEST_CASE_METHOD(QueryFixture, "Test update sql statement string", "[query]") {
REQUIRE(result == R"(UPDATE "person" SET "id"=7, "name"='george', "age"=65 WHERE "id" > 9 ORDER BY "id" ASC LIMIT 3 OFFSET 2)");
}
TEST_CASE_METHOD(QueryFixture, "Test update returning statement", "[query][update][returning]") {
const auto result = query::update("person")
.set({{"id", 7U}, {"name", "george"}, {"age", 65U}})
.where("name"_col == "george")
.returning("id"_col, "name"_col, "age"_col)
.str(*db);
REQUIRE(result == R"(UPDATE "person" SET "id"=7, "name"='george', "age"=65 WHERE "name" = 'george' RETURNING "id", "name", "age")");
}
TEST_CASE_METHOD(QueryFixture, "Test update limit sql statement", "[query][update][limit]") {
const auto result = query::update("person")
.set({{"id", 7U}, {"name", "george"}, {"age", 65U}})
@ -199,6 +209,16 @@ TEST_CASE_METHOD(QueryFixture, "Test insert sql statement with placeholder", "[q
REQUIRE(result == R"(INSERT INTO "person" ("id", "name", "age") VALUES (9, 'george', ?))");
}
TEST_CASE_METHOD(QueryFixture, "Test insert sql statement with returning", "[query][insert][returning]") {
const auto result = query::insert()
.into("person", {"id", "name", "age"})
.values({9, "george", _})
.returning("id"_col, "name"_col, "age"_col)
.str(*db);
REQUIRE(result == R"(INSERT INTO "person" ("id", "name", "age") VALUES (9, 'george', ?) RETURNING "id", "name", "age")");
}
TEST_CASE_METHOD(QueryFixture, "Test select sql statement string with order by", "[query]") {
const auto result = query::select({"id", "name", "age"})
.from("person")