QString SchemaParser::getCodeDefinition(const QString & obj_name, map<QString, QString> &attributes, unsigned def_type) { if(obj_name!="") { QString filename; if(def_type==SQL_DEFINITION) { try { //Formats the filename filename=GlobalAttributes::SCHEMAS_ROOT_DIR + GlobalAttributes::DIR_SEPARATOR + GlobalAttributes::SQL_SCHEMA_DIR + GlobalAttributes::DIR_SEPARATOR + pgsql_version + GlobalAttributes::DIR_SEPARATOR + obj_name + GlobalAttributes::SCHEMA_EXT; //Try to get the object definitin from the specified path return(getCodeDefinition(filename, attributes)); } catch(Exception &e) { /* If detected the error that the file was not found, the parser try to fetch the file in the common schema for all versions postgresql */ //If the exception is of another type than 'file not loaded' redirects error if(e.getErrorType()!=ERR_FILE_DIR_NOT_ACCESSED) throw Exception(e.getErrorMessage(),e.getErrorType(), __PRETTY_FUNCTION__,__FILE__,__LINE__,&e); //Reconfigure the name of the file to point to the default directory filename=GlobalAttributes::SCHEMAS_ROOT_DIR + GlobalAttributes::DIR_SEPARATOR + GlobalAttributes::SQL_SCHEMA_DIR + GlobalAttributes::DIR_SEPARATOR + GlobalAttributes::COMMON_SCHEMA_DIR + GlobalAttributes::DIR_SEPARATOR + obj_name + GlobalAttributes::SCHEMA_EXT; return(getCodeDefinition(filename, attributes)); } } else { filename=GlobalAttributes::SCHEMAS_ROOT_DIR + GlobalAttributes::DIR_SEPARATOR + GlobalAttributes::XML_SCHEMA_DIR + GlobalAttributes::DIR_SEPARATOR + obj_name + GlobalAttributes::SCHEMA_EXT; return(getCodeDefinition(filename, attributes)); } } else return(""); }
void ModelsDiffHelper::processDiffInfos(void) { BaseObject *object=nullptr; Relationship *rel=nullptr; map<unsigned, QString> drop_objs, create_objs, alter_objs, truncate_tabs; vector<BaseObject *> drop_vect, create_vect, drop_cols; unsigned diff_type, schema_id=0, idx=0; ObjectType obj_type; map<unsigned, QString>::reverse_iterator ritr, ritr_end; attribs_map attribs; QString alter_def, no_inherit_def, inherit_def, set_perms, unset_perms, fk_defs, col_drop_def; SchemaParser schparser; Type *type=nullptr; vector<Type *> types; Constraint *constr=nullptr; Column *col=nullptr, *aux_col=nullptr; Table *parent_tab=nullptr; bool skip_obj=false; QStringList sch_names; try { if(!diff_infos.empty()) emit s_progressUpdated(0, trUtf8("Processing diff infos...")); //Reuniting the schema names to inject a SET search_path command for(auto &schema : *imported_model->getObjectList(OBJ_SCHEMA)) sch_names.push_back(schema->getName(true)); //Separating the base types for(ObjectsDiffInfo diff : diff_infos) { type=dynamic_cast<Type *>(diff.getObject()); if(type && type->getConfiguration()==Type::BASE_TYPE) { type->convertFunctionParameters(); types.push_back(type); } } for(ObjectsDiffInfo diff : diff_infos) { diff_type=diff.getDiffType(); object=diff.getObject(); obj_type=object->getObjectType(); rel=dynamic_cast<Relationship *>(object); constr=dynamic_cast<Constraint *>(object); col=dynamic_cast<Column *>(object); emit s_progressUpdated((idx++/static_cast<float>(diff_infos.size())) * 100, trUtf8("Processing `%1' info for object `%2' (%3)...") .arg(diff.getDiffTypeString()).arg(object->getSignature()).arg(object->getTypeName()), obj_type); /* Preliminary verification for check constraints: there is the need to check if the constraint is added by generalization or if this is not the case if it already exists in a ancestor table of its parent, this avoid the generation of commands to create or drop an inherited constraint raising errors when export the diff */ if(constr && constr->getConstraintType()==ConstraintType::check) { parent_tab=dynamic_cast<Table *>(constr->getParentTable()); skip_obj=constr->isAddedByGeneralization(); for(unsigned i=0; i < parent_tab->getAncestorTableCount() && !skip_obj; i++) skip_obj=(parent_tab->getAncestorTable(i)->getConstraint(constr->getName())!=nullptr); if(skip_obj) continue; } //Igoring any operation done over inherited columns else if(col) { parent_tab=dynamic_cast<Table *>(col->getParentTable()); skip_obj=col->isAddedByGeneralization(); for(unsigned i=0; i < parent_tab->getAncestorTableCount() && !skip_obj; i++) { aux_col=parent_tab->getAncestorTable(i)->getColumn(col->getName()); skip_obj=(aux_col && aux_col->getType().getAliasType()==col->getType()); } if(skip_obj) continue; } //Generating the DROP commands if(diff_type==ObjectsDiffInfo::DROP_OBJECT) { if(rel) //Undoing inheritances no_inherit_def+=rel->getInheritDefinition(true); else if(obj_type==OBJ_PERMISSION) //Unsetting permissions unset_perms+=object->getDropDefinition(diff_opts[OPT_CASCADE_MODE]); else { //Ordinary drop commands for any object except columns if(obj_type!=OBJ_COLUMN) drop_objs[object->getObjectId()]=getCodeDefinition(object, true); else { /* Special case for columns: due to cases like inheritance there is the the need to drop the columns in the normal order of creation to avoid error like 'drop inherited column' or wrong propagation of drop on all child tables. */ drop_cols.push_back(object); } } } //Generating the CREATE commands else if(diff_type==ObjectsDiffInfo::CREATE_OBJECT) { if(rel) //Creating inheritances inherit_def+=rel->getInheritDefinition(false); else if(obj_type==OBJ_PERMISSION) //Setting permissions set_perms+=object->getCodeDefinition(SchemaParser::SQL_DEFINITION); else { //Generating fks definitions in a separated variable in order to append them at create commands maps if(object->getObjectType()==OBJ_CONSTRAINT && dynamic_cast<Constraint *>(object)->getConstraintType()==ConstraintType::foreign_key) fk_defs+=getCodeDefinition(object, false); else { create_objs[object->getObjectId()]=getCodeDefinition(object, false); if(obj_type==OBJ_SCHEMA) sch_names.push_back(object->getName(true)); } } } //Generating the ALTER commands else if(diff_type==ObjectsDiffInfo::ALTER_OBJECT) { //Recreating the object instead of generating an ALTER command for it if((diff_opts[OPT_FORCE_RECREATION] && obj_type!=OBJ_DATABASE) && (!diff_opts[OPT_RECREATE_UNCHANGEBLE] || (diff_opts[OPT_RECREATE_UNCHANGEBLE] && !object->acceptsAlterCommand()))) { recreateObject(object, drop_vect, create_vect); //Generating the drop for the object's reference for(auto &obj : drop_vect) drop_objs[obj->getObjectId()]=getCodeDefinition(obj, true); //Generating the create for the object's reference for(auto &obj : create_vect) { //The there is no ALTER info registered for an object's reference if(!isDiffInfoExists(ObjectsDiffInfo::ALTER_OBJECT, nullptr, obj, false)) create_objs[obj->getObjectId()]=getCodeDefinition(obj, false); } drop_vect.clear(); create_vect.clear(); } else { if(diff.getOldObject()) alter_def=diff.getOldObject()->getAlterDefinition(object); if(!alter_def.isEmpty()) { //Commenting out the ALTER DATABASE ... RENAME TO ... command if user chooses to preserve the original name if(obj_type==OBJ_DATABASE && alter_def.contains("RENAME") && diff_opts[OPT_PRESERVE_DB_NAME]) alter_def.prepend(QString("-- ")); alter_objs[object->getObjectId()]=alter_def; /* If the object is a column checks if the types of the columns are differents, generating a TRUNCATE TABLE for the parent table */ if(obj_type==OBJ_COLUMN && diff_opts[OPT_TRUCANTE_TABLES]) { Column *src_col=dynamic_cast<Column *>(object), *imp_col=dynamic_cast<Column *>(diff.getOldObject()); Table *tab=dynamic_cast<Table *>(src_col->getParentTable()); //If the truncate was not generated previously if((*src_col->getType())!=(*imp_col->getType()) && truncate_tabs.count(tab->getObjectId())==0) truncate_tabs[tab->getObjectId()]=tab->getTruncateDefinition(diff_opts[OPT_CASCADE_MODE]); } } } } } //Creating the shell types declaration right below on the DDL that creates their schemas for(Type *type : types) { schema_id=type->getSchema()->getObjectId(); if(create_objs.count(schema_id)!=0) create_objs[schema_id]+=type->getCodeDefinition(SchemaParser::SQL_DEFINITION, true); else attribs[ParsersAttributes::CREATE_CMDS]+=type->getCodeDefinition(SchemaParser::SQL_DEFINITION, true); type->convertFunctionParameters(true); } //Generating the drop command for columns for(BaseObject *col : drop_cols) col_drop_def+=getCodeDefinition(col, true); diff_def.clear(); if(!drop_objs.empty() || !create_objs.empty() || !alter_objs.empty() || !inherit_def.isEmpty() || !no_inherit_def.isEmpty() || !set_perms.isEmpty() || !fk_defs.isEmpty() || !col_drop_def.isEmpty()) { sch_names.removeDuplicates(); //Attributes used on the diff schema file attribs[ParsersAttributes::HAS_CHANGES]=ParsersAttributes::_TRUE_; attribs[ParsersAttributes::PGMODELER_VERSION]=GlobalAttributes::PGMODELER_VERSION; attribs[ParsersAttributes::CHANGE]=QString::number(alter_objs.size()); attribs[ParsersAttributes::CREATE]=QString::number(create_objs.size()); attribs[ParsersAttributes::DROP]=QString::number(drop_objs.size()); attribs[ParsersAttributes::TRUNCATE]=QString::number(truncate_tabs.size()); attribs[ParsersAttributes::SEARCH_PATH]=sch_names.join(','); attribs[ParsersAttributes::ALTER_CMDS]=QString(); attribs[ParsersAttributes::DROP_CMDS]=QString(); attribs[ParsersAttributes::CREATE_CMDS]=QString(); attribs[ParsersAttributes::TRUNCATE_CMDS]=QString(); attribs[ParsersAttributes::UNSET_PERMS]=unset_perms; attribs[ParsersAttributes::SET_PERMS]=set_perms; attribs[ParsersAttributes::FUNCTION]=(source_model->getObjectCount(OBJ_FUNCTION)!=0 ? ParsersAttributes::_TRUE_ : QString()); ritr=drop_objs.rbegin(); ritr_end=drop_objs.rend(); attribs[ParsersAttributes::DROP_CMDS]+=no_inherit_def; while(ritr!=ritr_end) { attribs[ParsersAttributes::DROP_CMDS]+=ritr->second; ritr++; } attribs[ParsersAttributes::DROP_CMDS]+=col_drop_def; for(auto &itr : create_objs) attribs[ParsersAttributes::CREATE_CMDS]+=itr.second; attribs[ParsersAttributes::CREATE_CMDS]+=fk_defs; attribs[ParsersAttributes::CREATE_CMDS]+=inherit_def; for(auto &itr : truncate_tabs) attribs[ParsersAttributes::TRUNCATE_CMDS]+=itr.second; for(auto &itr : alter_objs) attribs[ParsersAttributes::ALTER_CMDS]+=itr.second; //Generating the whole diff buffer schparser.setPgSQLVersion(pgsql_version); diff_def=schparser.getCodeDefinition(GlobalAttributes::SCHEMAS_ROOT_DIR + GlobalAttributes::DIR_SEPARATOR + GlobalAttributes::ALTER_SCHEMA_DIR + GlobalAttributes::DIR_SEPARATOR + ParsersAttributes::DIFF + GlobalAttributes::SCHEMA_EXT, attribs); } emit s_progressUpdated(100, trUtf8("Comparison between model and database finished.")); } catch(Exception &e) { for(Type *type : types) type->convertFunctionParameters(true); throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e); } }
QString Constraint::getCodeDefinition(unsigned def_type) { return(getCodeDefinition(def_type, false)); }
QString Collation::getCodeDefinition(unsigned def_type) { return(getCodeDefinition(def_type, false)); }