query builder progress
This commit is contained in:
@@ -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_};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) + " " +
|
||||
|
||||
Reference in New Issue
Block a user