identity generator progress
This commit is contained in:
parent
881e93e0f6
commit
4c63322024
|
|
@ -4,8 +4,7 @@
|
||||||
|
|
||||||
#include "matador/utils/basic_types.hpp"
|
#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;
|
using namespace matador::sql;
|
||||||
const static dialect d = dialect_builder::builder()
|
const static dialect d = dialect_builder::builder()
|
||||||
.create()
|
.create()
|
||||||
|
|
@ -13,7 +12,8 @@
|
||||||
return "$" + std::to_string(index);
|
return "$" + std::to_string(index);
|
||||||
})
|
})
|
||||||
.with_token_replace_map({
|
.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({
|
.with_data_type_replace_map({
|
||||||
{matador::utils::basic_type::Int8, "SMALLINT"},
|
{matador::utils::basic_type::Int8, "SMALLINT"},
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ public:
|
||||||
column_builder& not_null();
|
column_builder& not_null();
|
||||||
column_builder& primary_key();
|
column_builder& primary_key();
|
||||||
column_builder& unique();
|
column_builder& unique();
|
||||||
|
column_builder& identity();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string column_name_;
|
std::string column_name_;
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,17 @@ public:
|
||||||
query_create_table_columns_intermediate columns(const std::vector<table_column> &columns);
|
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 {
|
class query_create_intermediate : public query_intermediate {
|
||||||
public:
|
public:
|
||||||
query_create_intermediate();
|
query_create_intermediate();
|
||||||
|
|
||||||
query_create_table_intermediate table(const table &tab);
|
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);
|
executable_query schema(const std::string &schema_name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,6 @@ private:
|
||||||
std::vector<table_column> columns_;
|
std::vector<table_column> columns_;
|
||||||
};
|
};
|
||||||
|
|
||||||
table operator ""_tab(const char *name, size_t len);
|
|
||||||
|
|
||||||
template<typename Type = table>
|
template<typename Type = table>
|
||||||
class typed_table : public table {
|
class typed_table : public table {
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,7 @@ public:
|
||||||
[[nodiscard]] const std::string& foreign_key() const;
|
[[nodiscard]] const std::string& foreign_key() const;
|
||||||
[[nodiscard]] const std::string& from() const;
|
[[nodiscard]] const std::string& from() const;
|
||||||
[[nodiscard]] const std::string& group_by() const;
|
[[nodiscard]] const std::string& group_by() const;
|
||||||
|
[[nodiscard]] const std::string& identity() const;
|
||||||
[[nodiscard]] const std::string& in() const;
|
[[nodiscard]] const std::string& in() const;
|
||||||
[[nodiscard]] const std::string& insert() const;
|
[[nodiscard]] const std::string& insert() const;
|
||||||
[[nodiscard]] const std::string& into() const;
|
[[nodiscard]] const std::string& into() const;
|
||||||
|
|
@ -216,6 +217,7 @@ private:
|
||||||
{dialect_token::ForeignKey, "FOREIGN KEY"},
|
{dialect_token::ForeignKey, "FOREIGN KEY"},
|
||||||
{dialect_token::From, "FROM"},
|
{dialect_token::From, "FROM"},
|
||||||
{dialect_token::GroupBy, "GROUP BY"},
|
{dialect_token::GroupBy, "GROUP BY"},
|
||||||
|
{dialect_token::Identity, "AUTO INCREMENT"},
|
||||||
{dialect_token::In, "IN"},
|
{dialect_token::In, "IN"},
|
||||||
{dialect_token::Insert, "INSERT"},
|
{dialect_token::Insert, "INSERT"},
|
||||||
{dialect_token::Into, "INTO"},
|
{dialect_token::Into, "INTO"},
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ enum class dialect_token : uint8_t {
|
||||||
ForeignKey,
|
ForeignKey,
|
||||||
From,
|
From,
|
||||||
GroupBy,
|
GroupBy,
|
||||||
|
Identity,
|
||||||
In,
|
In,
|
||||||
Insert,
|
Insert,
|
||||||
Into,
|
Into,
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,9 @@ enum class constraints : unsigned char {
|
||||||
Unique = 1 << 1,
|
Unique = 1 << 1,
|
||||||
PrimaryKey = 1 << 2,
|
PrimaryKey = 1 << 2,
|
||||||
ForeignKey = 1 << 3,
|
ForeignKey = 1 << 3,
|
||||||
Default = 1 << 4,
|
Identity = 1 << 4,
|
||||||
NotNull = 1 << 5
|
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)); }
|
inline constraints operator|(constraints a, constraints b) { return static_cast<constraints>(static_cast<unsigned int>(a) | static_cast<unsigned int>(b)); }
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,11 @@ column_builder & column_builder::unique() {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
column_builder& column_builder::identity() {
|
||||||
|
constraints_ |= utils::constraints::Identity;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
table_builder::table_builder(std::string name)
|
table_builder::table_builder(std::string name)
|
||||||
: table_name( std::move(name) ) {}
|
: table_name( std::move(name) ) {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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));
|
context_->parts.push_back(std::make_unique<internal::query_create_table_part>(tab));
|
||||||
return {context_};
|
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 ) {
|
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));
|
context_->parts.push_back(std::make_unique<internal::query_create_schema_part>(schema_name));
|
||||||
|
|
|
||||||
|
|
@ -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)) {
|
if (is_constraint_set(col.attributes().options(), utils::constraints::Unique)) {
|
||||||
out.append(" ").append(d.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)) {
|
if (is_constraint_set(col.attributes().options(), utils::constraints::PrimaryKey)) {
|
||||||
out.append(" ").append(d.primary_key());
|
out.append(" ").append(d.primary_key());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,35 +13,6 @@
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
|
|
||||||
utils::result<void, utils::error> schema::create(const sql::connection &conn) const {
|
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;
|
std::vector<std::string> fk_sql_commands;
|
||||||
|
|
||||||
const auto q = query::create().schema(repo_.name()).compile(conn);
|
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()
|
auto ctx = query::query::create()
|
||||||
.table(node.name())
|
.table(node.name())
|
||||||
.columns(node.info().attributes())
|
.columns(node.info().attributes())
|
||||||
// .constraints(node->info().constraints())
|
|
||||||
.compile(conn);
|
.compile(conn);
|
||||||
|
|
||||||
std::cout << ctx.sql << std::endl;
|
std::cout << ctx.sql << std::endl;
|
||||||
|
|
|
||||||
|
|
@ -103,10 +103,4 @@ const table_column& table::create_column(class table &tab, const std::string &na
|
||||||
tab.columns_.back().table(&tab);
|
tab.columns_.back().table(&tab);
|
||||||
return tab.columns_.back();
|
return tab.columns_.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
table operator ""_tab(const char *name, size_t len) {
|
|
||||||
return {{name, len}};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,10 @@ const std::string &dialect::from() const {
|
||||||
return token_at(dialect_token::From);
|
return token_at(dialect_token::From);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string &dialect::identity() const {
|
||||||
|
return token_at(dialect_token::Identity);
|
||||||
|
}
|
||||||
|
|
||||||
const std::string &dialect::in() const {
|
const std::string &dialect::in() const {
|
||||||
return token_at(dialect_token::In);
|
return token_at(dialect_token::In);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,8 @@ TEST_CASE_METHOD(SchemaFixture, "Test schema one-two-many", "[schema][one-to-man
|
||||||
using namespace matador::test;
|
using namespace matador::test;
|
||||||
query::schema repo;
|
query::schema repo;
|
||||||
|
|
||||||
// auto result = repo.attach<department>("departments")
|
auto result = repo.attach<department>("departments")
|
||||||
// .and_then([&repo] { return repo.attach<employee>("employees"); });
|
.and_then([&repo] { return repo.attach<employee>("employees"); });
|
||||||
auto result = repo.attach<employee>("employees")
|
|
||||||
.and_then([&repo] { return repo.attach<department>("departments"); });
|
|
||||||
REQUIRE(result);
|
REQUIRE(result);
|
||||||
|
|
||||||
auto conn = pool.acquire();
|
auto conn = pool.acquire();
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,8 @@ utils::result<utils::version, utils::error> test_connection::server_version() co
|
||||||
return utils::ok(utils::version{3, 2, 1});
|
return utils::ok(utils::version{3, 2, 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::result<size_t, utils::error> test_connection::execute(const std::string &/*stmt*/) {
|
utils::result<sql::execute_result, utils::error> test_connection::execute(const sql::query_context &/*context*/) {
|
||||||
return utils::ok(static_cast<size_t>(4));
|
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) {
|
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> test_connection::fetch(const sql::query_context &context) {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define QUERY_NOOP_CONNECTION_HPP
|
#define QUERY_NOOP_CONNECTION_HPP
|
||||||
|
|
||||||
#include "matador/sql/interface/connection_impl.hpp"
|
#include "matador/sql/interface/connection_impl.hpp"
|
||||||
|
#include "matador/sql/execute_result.hpp"
|
||||||
|
|
||||||
namespace matador::test::orm {
|
namespace matador::test::orm {
|
||||||
|
|
||||||
|
|
@ -16,7 +17,7 @@ public:
|
||||||
[[nodiscard]] utils::result<bool, utils::error> is_valid() const override;
|
[[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> client_version() const override;
|
||||||
[[nodiscard]] utils::result<utils::version, utils::error> server_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::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::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;
|
utils::result<std::vector<object::attribute>, utils::error> describe(const std::string &table) override;
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,12 @@ namespace matador::test::orm {
|
||||||
test_statement::test_statement(const sql::query_context &query)
|
test_statement::test_statement(const sql::query_context &query)
|
||||||
: statement_impl(query, 0) {}
|
: 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;
|
using namespace std::chrono_literals;
|
||||||
std::mt19937 rng(query_.sql.size());
|
std::mt19937 rng(query_.sql.size());
|
||||||
std::uniform_int_distribution dist(10, 50);
|
std::uniform_int_distribution dist(10, 50);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(dist(rng)));
|
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*/) {
|
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> test_statement::fetch(const sql::parameter_binder &/*bindings*/) {
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,14 @@
|
||||||
#define TEST_STATEMENT_HPP
|
#define TEST_STATEMENT_HPP
|
||||||
|
|
||||||
#include "matador/sql/interface/statement_impl.hpp"
|
#include "matador/sql/interface/statement_impl.hpp"
|
||||||
|
#include "matador/sql/execute_result.hpp"
|
||||||
|
|
||||||
namespace matador::test::orm {
|
namespace matador::test::orm {
|
||||||
|
|
||||||
class test_statement final : public sql::statement_impl {
|
class test_statement final : public sql::statement_impl {
|
||||||
public:
|
public:
|
||||||
explicit test_statement(const sql::query_context &query);
|
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;
|
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetch(const sql::parameter_binder &bindings) override;
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)))##");
|
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()
|
auto ctx = query::create()
|
||||||
.table("person")
|
.table("person")
|
||||||
.columns({
|
.columns({
|
||||||
|
|
|
||||||
|
|
@ -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,
|
// If it's a varchar/string and has a defined size, use it if it's reasonable,
|
||||||
// otherwise fall back to type defaults.
|
// otherwise fall back to type defaults.
|
||||||
if ((f.is_varchar() || f.is_string()) && f.size() > 0 && f.size() < 100) {
|
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
|
// Find the default width for type
|
||||||
// Note: field class doesn't expose basic_type directly but we can use value().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.
|
// if we had access. For now we use name length as a minimum.
|
||||||
constexpr size_t w = 15;
|
constexpr size_t w = 15;
|
||||||
// In a real implementation we would probe the field's underlying type.
|
// 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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue