query builder progress

This commit is contained in:
Sascha Kühl
2025-12-02 16:19:13 +01:00
parent c156ab5e74
commit bfbbd4c589
31 changed files with 348 additions and 164 deletions
+3 -1
View File
@@ -57,7 +57,9 @@ matador::utils::result<void, matador::utils::error> matador::orm::schema::create
// std::cout << result.sql << std::endl;
for (const auto &node: repo_) {
auto ctx = query::query::create()
.table(node->name(), node->info().attributes())
.table(node->name())
.columns(node->info().attributes())
.constraints(node->info().constraints())
.compile(*c);
for ( const auto& [sql, command] : ctx.additional_commands ) {
+3 -1
View File
@@ -52,7 +52,9 @@ utils::result<void, utils::error> session::create_schema() const {
auto c = cache_.pool().acquire();
for (const auto &node: *schema_) {
auto ctx = query::query::create()
.table(node->name(), node->info().attributes())
.table(node->name())
.columns(node->info().attributes())
.constraints(node->info().constraints())
.compile(*c);
for ( const auto& [sql, command] : ctx.additional_commands ) {
@@ -9,13 +9,14 @@ namespace matador::query {
namespace detail {
sql::record *create_prototype(const std::vector<object::attribute> &prototype) {
auto result = std::make_unique<sql::record>();
int index{0};
for (const auto &col: prototype) {
result->append({
col.name(),
col.type(),
col.attributes().options(),
col.attributes().size(),
col.index()
index++
});
}
return result.release();
@@ -8,12 +8,8 @@ query_create_intermediate::query_create_intermediate() {
context_->parts.push_back(std::make_unique<internal::query_create_part>());
}
executable_query query_create_intermediate::table(const class table &tab, const std::initializer_list<object::attribute> columns) {
return this->table(tab, std::vector<object::attribute>{columns});
}
executable_query query_create_intermediate::table(const class table &tab, const std::vector<object::attribute> &columns) {
context_->parts.push_back(std::make_unique<internal::query_create_table_part>(tab, columns));
query_create_table_intermediate query_create_intermediate::table(const class table &tab) {
context_->parts.push_back(std::make_unique<internal::query_create_table_part>(tab));
return {context_};
}
@@ -21,4 +17,24 @@ executable_query query_create_intermediate::schema( const std::string& schema_na
context_->parts.push_back(std::make_unique<internal::query_create_schema_part>(schema_name));
return {context_};
}
executable_query query_create_table_columns_intermediate::constraints( std::initializer_list<class object::constraint> constraints ) {
return this->constraints(std::list(constraints));
}
executable_query query_create_table_columns_intermediate::constraints( const std::list<class object::constraint>& constraints ) {
context_->parts.push_back(std::make_unique<internal::query_create_table_constraints_part>(constraints));
return {context_};
}
query_create_table_columns_intermediate query_create_table_intermediate::columns( std::initializer_list<object::attribute> columns ) {
context_->parts.push_back(std::make_unique<internal::query_create_table_columns_part>(columns));
return {context_};
}
query_create_table_columns_intermediate query_create_table_intermediate::columns( const std::list<object::attribute>& columns ) {
context_->parts.push_back(std::make_unique<internal::query_create_table_columns_part>(columns));
return {context_};
}
}
+24 -6
View File
@@ -344,23 +344,41 @@ void query_create_part::accept(query_part_visitor &visitor)
visitor.visit(*this);
}
query_create_table_part::query_create_table_part(class table tab, std::vector<object::attribute> columns)
query_create_table_part::query_create_table_part(class table tab)
: query_part(sql::dialect_token::Table)
, table_(std::move(tab))
, columns_(std::move(columns)) {}
, table_(std::move(tab)) {}
const table &query_create_table_part::table() const
{
return table_;
}
const std::vector<object::attribute> &query_create_table_part::columns() const
void query_create_table_part::accept(query_part_visitor &visitor)
{
visitor.visit(*this);
}
query_create_table_columns_part::query_create_table_columns_part(const std::list<object::attribute>& columns)
: query_part( sql::dialect_token::Columns )
, columns_(columns){}
const std::list<object::attribute>& query_create_table_columns_part::columns() const {
return columns_;
}
void query_create_table_part::accept(query_part_visitor &visitor)
{
void query_create_table_columns_part::accept(query_part_visitor& visitor) {
visitor.visit(*this);
}
query_create_table_constraints_part::query_create_table_constraints_part(const std::list<class object::constraint>& constraints)
: query_part( sql::dialect_token::Constraint )
, constraints_(constraints) {}
const std::list<class object::constraint>& query_create_table_constraints_part::constraints() const {
return constraints_;
}
void query_create_table_constraints_part::accept( query_part_visitor& visitor ) {
visitor.visit(*this);
}
+49 -38
View File
@@ -27,6 +27,7 @@ sql::query_context query_compiler::compile(const query_data &data,
for (const auto &part: data.parts) {
part->accept(*this);
}
finisher_(query_);
connection_ = std::nullopt;
dialect_ = nullptr;
data_ = nullptr;
@@ -289,55 +290,55 @@ void query_compiler::visit(internal::query_create_part &/*create_part*/)
query_.sql = dialect_->token_at(sql::dialect_token::Create);
}
struct fk_context {
std::string column;
std::shared_ptr<object::attribute> reference_column;
};
struct column_context
{
std::vector<std::string> primary_keys;
std::vector<fk_context> foreign_contexts;
};
std::string build_create_column(const object::attribute &col, const sql::dialect &d, column_context &context);
std::string build_create_column(const object::attribute &col, const sql::dialect &d);
std::string build_constraint(const class object::constraint &cons, const sql::dialect &d);
void query_compiler::visit(internal::query_create_table_part &part)
{
query_.sql += " " + dialect_->token_at(sql::dialect_token::Table) + " " + dialect_->prepare_identifier_string(part.table().name()) + " ";
query_.sql += " " + dialect_->token_at(sql::dialect_token::Table) + " " + dialect_->prepare_identifier_string(part.table().name()) + " (";
query_.table_name = part.table().name();
std::string result = "(";
// if (!context.primary_keys.empty()) {
// result.append(", CONSTRAINT PK_" + part.table().name() + " PRIMARY KEY (" + utils::join(context.primary_keys, ", ") + ")");
// }
// for (const auto &[column, reference_column]: context.foreign_contexts) {
// // ALTER TABLE Orders ADD CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID) REFERENCES Persons(PersonID);
// std::string fk_cmd = "ALTER TABLE " + dialect_->prepare_identifier_string(query_.table_name) + " ADD";
// fk_cmd += " CONSTRAINT FK_" + query_.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});
// }
column_context context;
finisher_ = [](sql::query_context &ctx) { ctx.sql += ")"; };
}
void query_compiler::visit(internal::query_create_table_columns_part& part) {
std::string result = "(";
if (part.columns().size() < 2) {
for (const auto &col: part.columns()) {
result.append(build_create_column(col, *dialect_, context));
result.append(build_create_column(col, *dialect_));
}
} else {
auto it = part.columns().begin();
result.append(build_create_column(*it++, *dialect_, context));
result.append(build_create_column(*it++, *dialect_));
for (; it != part.columns().end(); ++it) {
result.append(", ");
result.append(build_create_column(*it, *dialect_, context));
result.append(build_create_column(*it, *dialect_));
}
}
if (!context.primary_keys.empty()) {
result.append(", CONSTRAINT PK_" + part.table().name() + " PRIMARY KEY (" + utils::join(context.primary_keys, ", ") + ")");
}
for (const auto &[column, reference_column]: context.foreign_contexts) {
// ALTER TABLE Orders ADD CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID) REFERENCES Persons(PersonID);
std::string fk_cmd = "ALTER TABLE " + dialect_->prepare_identifier_string(query_.table_name) + " ADD";
fk_cmd += " CONSTRAINT FK_" + query_.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});
}
query_.sql += result;
}
result += ")";
void query_compiler::visit(internal::query_create_table_constraints_part& part) {
std::string result;
for (const auto& c : part.constraints()) {
result.append(", ");
result.append(build_constraint(c, *dialect_));
}
query_.sql += result;
}
@@ -387,7 +388,7 @@ void query_compiler::visit(internal::query_drop_table_part &part)
query_.sql += " " + build_table_name(part.token(), *dialect_, query_.table_name);
}
std::string build_create_column(const object::attribute &col, const sql::dialect &d, column_context &context)
std::string build_create_column(const object::attribute &col, const sql::dialect &d)
{
std::string result = d.prepare_identifier_string(col.name()) + " " + d.data_type_at(col.type());
if (col.attributes().size() > 0) {
@@ -399,16 +400,26 @@ std::string build_create_column(const object::attribute &col, const sql::dialect
if (is_constraint_set(col.attributes().options(), utils::constraints::Unique)) {
result.append(" UNIQUE");
}
if (is_constraint_set(col.attributes().options(), utils::constraints::PrimaryKey)) {
context.primary_keys.emplace_back(col.name());
}
if (is_constraint_set(col.attributes().options(), utils::constraints::ForeignKey)) {
context.foreign_contexts.push_back({col.name(), col.reference_column()});
}
return result;
}
std::string build_constraint(const class object::constraint& cons, const sql::dialect& d) {
std::string result;
if (!cons.name().empty()) {
result.append(d.constraint()).append(" ").append(d.prepare_identifier_string(cons.name())).append(" ");
}
if (cons.is_primary_key_constraint()) {
result.append(d.primary_key());
} else if (cons.is_foreign_key_constraint()) {
result.append(d.foreign_key());
} else {
// handle error
}
result.append("(").append(cons.attribute()->full_name()).append(")");
return result;
}
std::string query_compiler::build_table_name(const sql::dialect_token token, const sql::dialect &d, const table& t)
{
return d.token_at(token) + " " +
+4
View File
@@ -172,6 +172,10 @@ const std::string& dialect::commit() const {
return token_at(dialect_token::Commit);
}
const std::string& dialect::constraint() const {
return token_at(dialect_token::Constraint);
}
const std::string& dialect::create() const {
return token_at(dialect_token::Create);
}
+2 -1
View File
@@ -8,13 +8,14 @@ namespace matador::sql::detail {
template<>
record *create_prototype<record>(const std::vector<object::attribute> &prototype) {
auto result = std::make_unique<record>();
int index{0};
for (const auto &col: prototype) {
result->append({
col.name(),
col.type(),
col.attributes().options(),
col.attributes().size(),
col.index()
index++
});
}
return result.release();