identity generator progress

This commit is contained in:
Sascha Kühl 2026-02-11 16:01:44 +01:00
parent 881e93e0f6
commit 4c63322024
20 changed files with 68 additions and 69 deletions

View File

@ -4,8 +4,7 @@
#include "matador/utils/basic_types.hpp"
[[maybe_unused]] const matador::sql::dialect *get_dialect()
{
[[maybe_unused]] const matador::sql::dialect *get_dialect() {
using namespace matador::sql;
const static dialect d = dialect_builder::builder()
.create()
@ -13,7 +12,8 @@
return "$" + std::to_string(index);
})
.with_token_replace_map({
{dialect_token::BeginBinaryData, "'\\x"}
{dialect_token::BeginBinaryData, "'\\x"},
{dialect_token::Identity, "GENERATED BY DEFAULT AS IDENTITY"}
})
.with_data_type_replace_map({
{matador::utils::basic_type::Int8, "SMALLINT"},

View File

@ -70,6 +70,7 @@ public:
column_builder& not_null();
column_builder& primary_key();
column_builder& unique();
column_builder& identity();
private:
std::string column_name_;

View File

@ -36,11 +36,17 @@ public:
query_create_table_columns_intermediate columns(const std::vector<table_column> &columns);
};
class query_create_sequence_intermediate : public executable_query {
public:
using executable_query::executable_query;
};
class query_create_intermediate : public query_intermediate {
public:
query_create_intermediate();
query_create_table_intermediate table(const table &tab);
query_create_sequence_intermediate sequence(const std::string &sequence_name);
executable_query schema(const std::string &schema_name);
};

View File

@ -52,8 +52,6 @@ private:
std::vector<table_column> columns_;
};
table operator ""_tab(const char *name, size_t len);
template<typename Type = table>
class typed_table : public table {
public:

View File

@ -148,6 +148,7 @@ public:
[[nodiscard]] const std::string& foreign_key() const;
[[nodiscard]] const std::string& from() const;
[[nodiscard]] const std::string& group_by() const;
[[nodiscard]] const std::string& identity() const;
[[nodiscard]] const std::string& in() const;
[[nodiscard]] const std::string& insert() const;
[[nodiscard]] const std::string& into() const;
@ -216,6 +217,7 @@ private:
{dialect_token::ForeignKey, "FOREIGN KEY"},
{dialect_token::From, "FROM"},
{dialect_token::GroupBy, "GROUP BY"},
{dialect_token::Identity, "AUTO INCREMENT"},
{dialect_token::In, "IN"},
{dialect_token::Insert, "INSERT"},
{dialect_token::Into, "INTO"},

View File

@ -32,6 +32,7 @@ enum class dialect_token : uint8_t {
ForeignKey,
From,
GroupBy,
Identity,
In,
Insert,
Into,

View File

@ -9,8 +9,9 @@ enum class constraints : unsigned char {
Unique = 1 << 1,
PrimaryKey = 1 << 2,
ForeignKey = 1 << 3,
Default = 1 << 4,
NotNull = 1 << 5
Identity = 1 << 4,
Default = 1 << 5,
NotNull = 1 << 6
};
inline constraints operator|(constraints a, constraints b) { return static_cast<constraints>(static_cast<unsigned int>(a) | static_cast<unsigned int>(b)); }

View File

@ -26,6 +26,11 @@ column_builder & column_builder::unique() {
return *this;
}
column_builder& column_builder::identity() {
constraints_ |= utils::constraints::Identity;
return *this;
}
table_builder::table_builder(std::string name)
: table_name( std::move(name) ) {}

View File

@ -18,6 +18,9 @@ query_create_table_intermediate query_create_intermediate::table(const class tab
context_->parts.push_back(std::make_unique<internal::query_create_table_part>(tab));
return {context_};
}
query_create_sequence_intermediate query_create_intermediate::sequence(const std::string& sequence_name) {
return {context_};
}
executable_query query_create_intermediate::schema( const std::string& schema_name ) {
context_->parts.push_back(std::make_unique<internal::query_create_schema_part>(schema_name));

View File

@ -378,6 +378,9 @@ void build_create_column(std::string &out, const table_column &col, const sql::d
if (is_constraint_set(col.attributes().options(), utils::constraints::Unique)) {
out.append(" ").append(d.unique());
}
if (is_constraint_set(col.attributes().options(), utils::constraints::Identity)) {
out.append(" ").append(d.identity());
}
if (is_constraint_set(col.attributes().options(), utils::constraints::PrimaryKey)) {
out.append(" ").append(d.primary_key());
}

View File

@ -13,35 +13,6 @@
namespace matador::query {
utils::result<void, utils::error> schema::create(const sql::connection &conn) const {
// Step 1: Build dependency graph
// std::unordered_map<std::string, std::vector<std::string> > dependency_graph;
// std::unordered_map<std::string, std::pair<int,object::repository::node_ptr>> in_degree;
//
// for (const auto &node: repo_) {
// for (auto it = node->info().endpoint_begin(); it != node->info().endpoint_end(); ++it) {
// dependency_graph[node->name()].push_back(it->second->node().name());
//
// 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 {
// in_degree[it->second->node().name()].first++;
// }
// }
//
// // Ensure the current node exists in the graph representation
// if (in_degree.find(node->name()) == in_degree.end()) {
// in_degree[node->name()] = std::make_pair(0, node);
// }
// }
//
// for (const auto &it : dependency_graph) {
// std::cout << "Dependency graph " << it.first << std::endl;
// for (const auto &neighbor: it.second) {
// std::cout << " " << neighbor << std::endl;
// }
// std::cout << std::endl;
// }
std::vector<std::string> fk_sql_commands;
const auto q = query::create().schema(repo_.name()).compile(conn);
@ -52,7 +23,6 @@ utils::result<void, utils::error> schema::create(const sql::connection &conn) co
auto ctx = query::query::create()
.table(node.name())
.columns(node.info().attributes())
// .constraints(node->info().constraints())
.compile(conn);
std::cout << ctx.sql << std::endl;

View File

@ -103,10 +103,4 @@ const table_column& table::create_column(class table &tab, const std::string &na
tab.columns_.back().table(&tab);
return tab.columns_.back();
}
table operator ""_tab(const char *name, size_t len) {
return {{name, len}};
}
}

View File

@ -175,6 +175,10 @@ const std::string &dialect::from() const {
return token_at(dialect_token::From);
}
const std::string &dialect::identity() const {
return token_at(dialect_token::Identity);
}
const std::string &dialect::in() const {
return token_at(dialect_token::In);
}

View File

@ -17,10 +17,8 @@ TEST_CASE_METHOD(SchemaFixture, "Test schema one-two-many", "[schema][one-to-man
using namespace matador::test;
query::schema repo;
// auto result = repo.attach<department>("departments")
// .and_then([&repo] { return repo.attach<employee>("employees"); });
auto result = repo.attach<employee>("employees")
.and_then([&repo] { return repo.attach<department>("departments"); });
auto result = repo.attach<department>("departments")
.and_then([&repo] { return repo.attach<employee>("employees"); });
REQUIRE(result);
auto conn = pool.acquire();

View File

@ -44,8 +44,8 @@ utils::result<utils::version, utils::error> test_connection::server_version() co
return utils::ok(utils::version{3, 2, 1});
}
utils::result<size_t, utils::error> test_connection::execute(const std::string &/*stmt*/) {
return utils::ok(static_cast<size_t>(4));
utils::result<sql::execute_result, utils::error> test_connection::execute(const sql::query_context &/*context*/) {
return utils::ok(sql::execute_result{4});
}
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> test_connection::fetch(const sql::query_context &context) {

View File

@ -2,6 +2,7 @@
#define QUERY_NOOP_CONNECTION_HPP
#include "matador/sql/interface/connection_impl.hpp"
#include "matador/sql/execute_result.hpp"
namespace matador::test::orm {
@ -16,7 +17,7 @@ public:
[[nodiscard]] utils::result<bool, utils::error> is_valid() const override;
[[nodiscard]] utils::result<utils::version, utils::error> client_version() const override;
[[nodiscard]] utils::result<utils::version, utils::error> server_version() const override;
utils::result<size_t, utils::error> execute(const std::string &stmt) override;
utils::result<sql::execute_result, utils::error> execute(const sql::query_context &context) override;
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetch(const sql::query_context &context) override;
utils::result<std::unique_ptr<sql::statement_impl>, utils::error> prepare(const sql::query_context &context) override;
utils::result<std::vector<object::attribute>, utils::error> describe(const std::string &table) override;

View File

@ -10,12 +10,12 @@ namespace matador::test::orm {
test_statement::test_statement(const sql::query_context &query)
: statement_impl(query, 0) {}
utils::result<size_t, utils::error> test_statement::execute(const sql::parameter_binder &/*bindings*/) {
utils::result<sql::execute_result, utils::error> test_statement::execute(const sql::parameter_binder &/*bindings*/) {
using namespace std::chrono_literals;
std::mt19937 rng(query_.sql.size());
std::uniform_int_distribution dist(10, 50);
std::this_thread::sleep_for(std::chrono::milliseconds(dist(rng)));
return utils::ok(static_cast<size_t>(8));
return utils::ok(sql::execute_result{8});
}
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> test_statement::fetch(const sql::parameter_binder &/*bindings*/) {

View File

@ -2,13 +2,14 @@
#define TEST_STATEMENT_HPP
#include "matador/sql/interface/statement_impl.hpp"
#include "matador/sql/execute_result.hpp"
namespace matador::test::orm {
class test_statement final : public sql::statement_impl {
public:
explicit test_statement(const sql::query_context &query);
utils::result<size_t, utils::error> execute(const sql::parameter_binder &bindings) override;
utils::result<sql::execute_result, utils::error> execute(const sql::parameter_binder &bindings) override;
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetch(const sql::parameter_binder &bindings) override;
void reset() override;

View File

@ -50,6 +50,17 @@ TEST_CASE_METHOD(QueryFixture, "Test create table sql statement string", "[query
REQUIRE(result == R"##(CREATE TABLE "person" ("id" BIGINT NOT NULL, "name" VARCHAR(255) NOT NULL, "age" INTEGER NOT NULL, CONSTRAINT PK_person PRIMARY KEY (id)))##");
result = query::create()
.table({"person"})
.columns({
column("id", basic_type::UInt32).primary_key().identity(),
column("name", basic_type::Varchar, 255),
column("age", basic_type::UInt16)
})
.str(*db);
REQUIRE(result == R"##(CREATE TABLE "person" ("id" BIGINT NOT NULL AUTO INCREMENT PRIMARY KEY, "name" VARCHAR(255) NOT NULL, "age" INTEGER NOT NULL))##");
auto ctx = query::create()
.table("person")
.columns({

View File

@ -58,15 +58,15 @@ int record_printer::width(const sql::field &f) {
// If it's a varchar/string and has a defined size, use it if it's reasonable,
// otherwise fall back to type defaults.
if ((f.is_varchar() || f.is_string()) && f.size() > 0 && f.size() < 100) {
return std::max(f.name().length(), f.size());
return static_cast<int>(std::max(f.name().length(), f.size()));
}
// Find the default width for type
// Note: field class doesn't expose basic_type directly but we can use value().type()
// if we had access. For now we use name length as minimum.
// Note: field class doesn't expose basic_type directly, but we can use value().type()
// if we had access. For now we use name length as a minimum.
constexpr size_t w = 15;
// In a real implementation we would probe the field's underlying type.
return std::max(f.name().length(), w);
return static_cast<int>(std::max(f.name().length(), w));
}
}