|
- #include <cppcore/misc/indent.h>
-
- #include <cpphibernate/types.inl>
- #include <cpphibernate/driver/mariadb/classes/tables/table.inl>
- #include <cpphibernate/driver/mariadb/classes/schema/schema.inl>
- #include <cpphibernate/driver/mariadb/context/init_context.inl>
-
- using namespace ::cpphibernate;
- using namespace ::cpphibernate::mariadb;
-
- static std::string build_init_stage1_query(const table_t& table);
- static std::string build_init_stage2_query(const table_t& table);
-
- void table_t::init(const init_context& context, init_stage stage) const
- {
- switch (stage)
- {
- case init_stage::stage1:
- {
- auto& statement = get_statement_init_stage1();
- auto& connection = context.connection;
- cpphibernate_log_debug("execute CREATE TABLE query: " << std::endl << statement.query(connection) << std::endl);
- connection.execute(statement);
- }
- break;
-
- case init_stage::stage2:
- {
- auto* statement = get_statement_init_stage2();
- auto& connection = context.connection;
- if (!statement)
- return;
- cpphibernate_log_debug("execute ALTER TABLE query: " << std::endl << statement->query(connection) << std::endl);
- connection.execute(*statement);
- }
- break;
-
- case init_stage::unknown:
- throw exception("Unkown or invalid init stage!");
- break;
- }
- }
-
- ::cppmariadb::statement& table_t::get_statement_init_stage1() const
- {
- if (!_statement_init_stage1)
- _statement_init_stage1.reset(new ::cppmariadb::statement(build_init_stage1_query(*this)));
- return *_statement_init_stage1;
- }
-
- ::cppmariadb::statement* table_t::get_statement_init_stage2() const
- {
- if (!_statement_init_stage2)
- _statement_init_stage2.reset(new ::cppmariadb::statement(build_init_stage2_query(*this)));
-
- return _statement_init_stage2->empty()
- ? nullptr
- : _statement_init_stage2.get();
- }
-
- std::string build_init_stage1_query(const table_t& table)
- {
- using namespace ::cppcore;
-
- std::ostringstream os;
-
- /* CREATE TABLE */
- os << "CREATE TABLE IF NOT EXISTS `"
- << table.name
- << "`"
- << indent
- << "("
- << incindent;
-
- /* primary key */
- {
- assert(table.primary_key_field);
- auto& key_info = *table.primary_key_field;
- auto args = key_info.create_arguments;
-
- os << indent
- << "`"
- << key_info.name
- << "` "
- << key_info.type
- << " NOT NULL"
- << (args.empty() ? "" : " ")
- << args
- << ",";
- }
-
- /* base table key fields */
- if (static_cast<bool>(table.base_table))
- {
- auto& base_table_info = *table.base_table;
-
- assert(base_table_info.primary_key_field);
- auto& key_info = *base_table_info.primary_key_field;
-
- os << indent
- << "`"
- << key_info.name
- << "` "
- << key_info.type
- << " NOT NULL,";
- }
-
- /* foreign table one fields */
- for (auto& ptr : table.foreign_table_one_fields)
- {
- assert(static_cast<bool>(ptr));
- auto& field_info = *ptr;
-
- assert(field_info.referenced_table);
- auto& referenced_table = *field_info.referenced_table;
- if (referenced_table.is_used_in_container)
- continue;
-
- assert(referenced_table.primary_key_field);
- auto& ref_key_info = *referenced_table.primary_key_field;
-
- os << indent
- << "`"
- << ref_key_info.table.name
- << "_id_"
- << field_info.name
- << "` "
- << ref_key_info.type
- << (field_info.value_is_nullable
- ? " NULL DEFAULT NULL,"
- : " NOT NULL,");
- }
-
- /* foreign fields */
- for (auto& ptr : table.foreign_key_fields)
- {
- assert(static_cast<bool>(ptr));
- auto& field_info = *ptr;
-
- assert(field_info.table.primary_key_field);
- auto& ref_key_info = *field_info.table.primary_key_field;
-
- os << indent
- << "`"
- << field_info.table.name
- << "_id_"
- << field_info.name
- << "` "
- << ref_key_info.type
- << " NULL DEFAULT NULL,";
- if (field_info.value_is_ordered)
- {
- os << indent
- << "`"
- << field_info.table.name
- << "_index_"
- << field_info.name
- << "` INT UNSIGNED NOT NULL,";
- }
- }
-
- /* data fields */
- for (auto& ptr : table.data_fields)
- {
- assert(static_cast<bool>(ptr));
- auto& field_info = *ptr;
-
- os << indent
- << "`"
- << field_info.name
- << "` "
- << field_info.type
- << (field_info.value_is_nullable
- ? " NULL DEFAULT NULL,"
- : " NOT NULL,");
- }
-
- /* type field for derived tables */
- if (!table.derived_tables.empty() &&
- !table.base_table)
- {
- os << indent
- << "`__type` INT UNSIGNED NOT NULL,";
- }
-
- /* PRIMARY KEY */
- {
- assert(table.primary_key_field);
- auto& key_info = *table.primary_key_field;
-
- os << indent
- << "PRIMARY KEY ( `"
- << key_info.name
- << "` )";
- }
-
- /* UNIQUE INDEX primary key */
- {
- assert(table.primary_key_field);
- auto& key_info = *table.primary_key_field;
-
- os << ','
- << indent
- << "UNIQUE INDEX `index_"
- << key_info.name
- << "` ( `"
- << key_info.name
- << "` ASC )";
- }
-
- /* UNIQUE INDEX base table keys */
- if (table.base_table)
- {
- auto& table_info = *table.base_table;
-
- assert(table_info.primary_key_field);
- auto& key_info = *table_info.primary_key_field;
-
- os << ','
- << indent
- << "UNIQUE INDEX `index_"
- << key_info.name
- << "` ( `"
- << key_info.name
- << "` ASC )";
- }
-
- /* INDEX foreign table one fields */
- for (auto& ptr : table.foreign_table_one_fields)
- {
- assert(static_cast<bool>(ptr));
- auto& field_info = *ptr;
-
- assert(field_info.referenced_table);
- auto& referenced_table = *field_info.referenced_table;
- if (referenced_table.is_used_in_container)
- continue;
-
- assert(referenced_table.primary_key_field);
- auto& ref_key_info = *referenced_table.primary_key_field;
-
- os << ","
- << indent
- << "INDEX `index_"
- << ref_key_info.table.name
- << "_id_"
- << field_info.name
- << "` ( `"
- << ref_key_info.table.name
- << "_id_"
- << field_info.name
- << "` ASC )";
- }
-
- /* INDEX foreign fields */
- for (auto& ptr : table.foreign_key_fields)
- {
- assert(static_cast<bool>(ptr));
- auto& field_info = *ptr;
-
- os << ","
- << indent
- << "INDEX `index_"
- << field_info.table.name
- << "_id_"
- << field_info.name
- << "` ( `"
- << field_info.table.name
- << "_id_"
- << field_info.name
- << "` ASC )";
- }
-
- /* CREATE TABLE end */
- os << decindent
- << indent
- << ")"
- << indent
- << "ENGINE = InnoDB"
- << indent
- << "DEFAULT CHARACTER SET = utf8";
-
- return os.str();
- }
-
- std::string build_init_stage2_query(const table_t& table)
- {
- using namespace ::cppcore;
-
- std::ostringstream os;
-
- /* ALTER TABLE */
- os << "ALTER TABLE `"
- << table.name
- << "`"
- << incindent;
-
- size_t index = 0;
-
- /* CONSTRAINT base table */
- if (table.base_table)
- {
- assert(table.base_table->primary_key_field);
- auto& ref_key_info = *table.base_table->primary_key_field;
-
- if (index++) os << ",";
- os << indent
- << "ADD CONSTRAINT `fk_"
- << table.name
- << "_"
- << ref_key_info.name
- << "`"
- << incindent
- << indent
- << "FOREIGN KEY IF NOT EXISTS (`"
- << ref_key_info.name
- << "`)"
- << indent
- << "REFERENCES `"
- << ref_key_info.table.schema.name
- << "`.`"
- << ref_key_info.table.name
- << "` (`"
- << ref_key_info.name
- << "`)"
- << indent
- << "ON DELETE CASCADE"
- << indent
- << "ON UPDATE CASCADE"
- << decindent;
- }
-
- /* CONSTRAINT foreign table one fields */
- for (auto& ptr : table.foreign_table_one_fields)
- {
- assert(static_cast<bool>(ptr));
- auto& field_info = *ptr;
-
- assert(field_info.referenced_table);
- auto& referenced_table = *field_info.referenced_table;
- if (referenced_table.is_used_in_container)
- continue;
-
- assert(referenced_table.primary_key_field);
- auto& ref_key_info = *referenced_table.primary_key_field;
-
- if (index++) os << ",";
- os << indent
- << "ADD CONSTRAINT `fk_"
- << table.name
- << "_"
- << ref_key_info.table.name
- << "_"
- << field_info.name
- << "`"
- << incindent
- << indent
- << "FOREIGN KEY IF NOT EXISTS (`"
- << ref_key_info.table.name
- << "_id_"
- << field_info.name
- << "`)"
- << indent
- << "REFERENCES `"
- << ref_key_info.table.schema.name
- << "`.`"
- << ref_key_info.table.name
- << "` (`"
- << ref_key_info.name
- << "`)"
- << indent;
- if (field_info.value_is_nullable)
- os << "ON DELETE SET NULL";
- else
- os << "ON DELETE CASCADE";
- os << indent
- << "ON UPDATE NO ACTION"
- << decindent;
- }
-
- /* CONSTRAINT foreign fields */
- for (auto& ptr : table.foreign_key_fields)
- {
- assert(static_cast<bool>(ptr));
- auto& field_info = *ptr;
-
- assert(field_info.table.primary_key_field);
- auto& ref_key_info = *field_info.table.primary_key_field;
-
- if (index++) os << ",";
- os << indent
- << "ADD CONSTRAINT `fk_"
- << table.name
- << "_"
- << field_info.table.name
- << "_"
- << field_info.name
- << "`"
- << incindent
- << indent
- << "FOREIGN KEY IF NOT EXISTS (`"
- << field_info.table.name
- << "_id_"
- << field_info.name
- << "`)"
- << indent
- << "REFERENCES `"
- << ref_key_info.table.schema.name
- << "`.`"
- << ref_key_info.table.name
- << "` (`"
- << ref_key_info.name
- << "`)"
- << indent
- << "ON DELETE SET NULL"
- << indent
- << "ON UPDATE NO ACTION"
- << decindent;
- }
-
- return index == 0
- ? std::string { }
- : os.str();
- }
|