diff --git a/libs/libcore/src/column.cpp b/libs/libcore/src/column.cpp index 892510402..0c112bd81 100644 --- a/libs/libcore/src/column.cpp +++ b/libs/libcore/src/column.cpp @@ -40,7 +40,7 @@ Column::Column() attributes[Attributes::Cache]=""; attributes[Attributes::Cycle]=""; - parent_rel=sequence=nullptr; + sequence=nullptr; identity_type = IdentityType::Null; } @@ -168,19 +168,6 @@ QString Column::getOldName(bool format) return old_name; } -void Column::setParentRelationship(BaseObject *parent_rel) -{ - if(parent_rel && parent_rel->getObjectType()!=ObjectType::Relationship) - throw Exception(ErrorCode::AsgObjectInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__); - - this->parent_rel=parent_rel; -} - -BaseObject *Column::getParentRelationship() -{ - return parent_rel; -} - void Column::setSequence(BaseObject *seq) { if(seq) @@ -429,7 +416,6 @@ void Column::operator = (Column &col) this->not_null=col.not_null; this->generated=col.generated; - this->parent_rel=col.parent_rel; this->sequence=col.sequence; this->identity_type=col.identity_type; @@ -445,6 +431,7 @@ void Column::operator = (Column &col) this->setAddedByGeneralization(false); this->setAddedByLinking(false); this->setCodeInvalidated(true); + this->setParentRelationship(col.getParentRelationship()); } QString Column::getDataDictionary(const attribs_map &extra_attribs) diff --git a/libs/libcore/src/column.h b/libs/libcore/src/column.h index 4e94e4177..b1884577a 100644 --- a/libs/libcore/src/column.h +++ b/libs/libcore/src/column.h @@ -53,11 +53,8 @@ class __libcore Column: public TableObject{ for a date the defaul value should be '2006-09-12 ' and so on. */ QString default_value; - //! \brief Stores a reference to the relationship that generates the column - BaseObject *parent_rel; - /*! \brief Stores a reference to the sequence used to generate the default value. - This attribute is used only the data type is integer, smallint or bigint */ + * This attribute is used only the data type is integer, smallint or bigint */ BaseObject *sequence; //! \brief Identity type of the column (GENERATED BY DEFAULT | ALWAYS) @@ -143,10 +140,6 @@ class __libcore Column: public TableObject{ //! \brief Returns the reference to the column type in the form [schema].table.column_name%TYPE QString getTypeReference(); - void setParentRelationship(BaseObject *parent_rel); - - BaseObject *getParentRelationship(); - //! \brief Set the sequence that will generate the default value for the column void setSequence(BaseObject *seq); diff --git a/libs/libcore/src/constraint.cpp b/libs/libcore/src/constraint.cpp index fb4874640..9f9fdf7d4 100644 --- a/libs/libcore/src/constraint.cpp +++ b/libs/libcore/src/constraint.cpp @@ -429,70 +429,61 @@ bool Constraint::isNoInherit() return no_inherit; } -bool Constraint::isReferRelationshipAddedColumn() +bool Constraint::isReferRelationshipAddedColumns(const std::vector &cols) { - std::vector::iterator itr, itr_end; - std::vector::iterator itr1, itr1_end; - Column *col=nullptr; - bool found=false; + std::vector rel_cols = getRelationshipAddedColumns(cols.empty()); - //First iterates over the source columns list - itr=columns.begin(); - itr_end=columns.end(); - - while(itr!=itr_end && !found) + if(!cols.empty()) { - col=(*itr); - //Check if the current column were added by relationship - found=col->isAddedByRelationship(); - itr++; - - /* Case the source column list is completely iterated steps to - the referenced columns list iteration */ - if(itr==itr_end && itr_end!=ref_columns.end() && !found) - { - itr=ref_columns.begin(); - itr_end=ref_columns.end(); - } - } + auto find_cols = [&rel_cols, &cols]() { + for(auto &col : cols) + { + if(std::find(rel_cols.begin(), rel_cols.end(), col) != rel_cols.end()) + return true; + } - //Iterates over the exclude elements - itr1=excl_elements.begin(); - itr1_end=excl_elements.end(); + return false; + }; - while(itr1!=itr1_end && !found) - { - col=(*itr1).getColumn(); - found=(col && col->isAddedByRelationship()); - itr1++; + return find_cols(); } - return found; + return !rel_cols.empty(); } -std::vector Constraint::getRelationshipAddedColumns() +std::vector Constraint::getRelationshipAddedColumns(bool first_col_only) { - Column *column=nullptr; - std::vector cols; - std::vector *> lists = { &columns, &ref_columns }; + std::vector rel_cols; + Column *col = nullptr; + + std::for_each(columns.begin(), columns.end(), [&rel_cols](auto &col) { + if(col->isAddedByRelationship()) + rel_cols.push_back(col); + }); - for(auto &p_lst : lists) + if(!first_col_only || (first_col_only && rel_cols.empty())) { - for(auto &col : (*p_lst)) - { + std::for_each(ref_columns.begin(), ref_columns.end(), [&rel_cols](auto &col) { if(col->isAddedByRelationship()) - cols.push_back(col); - } + rel_cols.push_back(col); + }); } - for(auto &excl_elem : excl_elements) + if(!first_col_only || (first_col_only && rel_cols.empty())) { - column=excl_elem.getColumn(); - if(column && column->isAddedByRelationship()) - cols.push_back(column); + std::for_each(excl_elements.begin(), excl_elements.end(), [&rel_cols, &col](auto &elem) { + col = elem.getColumn(); + if(col && col->isAddedByRelationship()) + rel_cols.push_back(col); + }); } - return cols; + return rel_cols; +} + +std::vector Constraint::getRelationshipAddedColumns() +{ + return getRelationshipAddedColumns(false); } MatchType Constraint::getMatchType() @@ -500,7 +491,6 @@ MatchType Constraint::getMatchType() return match_type; } - int Constraint::getExcludeElementIndex(ExcludeElement elem) { int idx=0; @@ -627,7 +617,7 @@ void Constraint::setDeclInTableAttribute() { if(!isDeclaredInTable() || (constr_type==ConstraintType::ForeignKey && !isAddedByLinking())) attributes[Attributes::DeclInTable]=""; - else if(!isReferRelationshipAddedColumn() || constr_type==ConstraintType::PrimaryKey) + else if(!isReferRelationshipAddedColumns() || constr_type==ConstraintType::PrimaryKey) attributes[Attributes::DeclInTable]=Attributes::True; } diff --git a/libs/libcore/src/constraint.h b/libs/libcore/src/constraint.h index 01803b33d..e35812289 100644 --- a/libs/libcore/src/constraint.h +++ b/libs/libcore/src/constraint.h @@ -105,6 +105,11 @@ class __libcore Constraint: public TableObject{ void setDeclInTableAttribute(); + /*! \brief Returns the list of all columns that is created by relationships. + * The parameter first_col_only will return as soon as the first column added + * by a relationship is found. */ + std::vector getRelationshipAddedColumns(bool first_col_only); + protected: virtual void configureSearchAttributes() override; @@ -212,16 +217,16 @@ class __libcore Constraint: public TableObject{ bool isNoInherit(); /*! \brief Returns whether the constraint references columns added - by relationship. This method is used as auxiliary - to control which constraints reference columns added by the - relationship in order to avoid referece breaking due constants - connections and disconnections of relationships */ - bool isReferRelationshipAddedColumn(); + * by relationship. This method is used as auxiliary to control which + * constraints reference columns added by the relationship in order to + * avoid referece breaking due constants connections and disconnections + * of relationships */ + bool isReferRelationshipAddedColumns(const std::vector &cols = {}); /*! \brief Returns the list of all columns that is created by relationships. - This method is slower than isReferRelationshipAddedColumn() so it's not - recommended to use it only check if the object is referencing columns - added by relationship */ + * this method is slower than isReferRelationshipAddedColumn() so it's not + * recommended to use it only to check if the object is referencing columns + * added by relationship. */ std::vector getRelationshipAddedColumns(); //! \brief Returns the matching type adopted by the constraint diff --git a/libs/libcore/src/databasemodel.cpp b/libs/libcore/src/databasemodel.cpp index 7b5b8d674..4faaf34e0 100644 --- a/libs/libcore/src/databasemodel.cpp +++ b/libs/libcore/src/databasemodel.cpp @@ -2101,7 +2101,7 @@ void DatabaseModel::storeSpecialObjectsXML() relationship added column and the constraint itself was not added by relationship (created manually by the user) */ found=(!constr->isAddedByRelationship() && - constr->isReferRelationshipAddedColumn() && + constr->isReferRelationshipAddedColumns() && constr->getConstraintType()!=ConstraintType::PrimaryKey); //When found some special object, stores is xml definition @@ -7885,7 +7885,7 @@ std::map DatabaseModel::getCreationOrder(SchemaParser::C configuration, foreign keys are discarded in this iteration because on the end of the method they have the definition generated */ if(constr->getConstraintType()!=ConstraintType::ForeignKey && !constr->isAddedByLinking() && - ((constr->getConstraintType()!=ConstraintType::PrimaryKey && constr->isReferRelationshipAddedColumn()))) + ((constr->getConstraintType()!=ConstraintType::PrimaryKey && constr->isReferRelationshipAddedColumns()))) objects_map[constr->getObjectId()]=constr; else if(constr->getConstraintType()==ConstraintType::ForeignKey && !constr->isAddedByLinking()) fkeys.push_back(constr); @@ -8071,7 +8071,7 @@ std::map DatabaseModel::getCreationOrder(SchemaParser::C ((constr->getConstraintType()==ConstraintType::ForeignKey) || (constr->getConstraintType()!=ConstraintType::ForeignKey && constr->getConstraintType()!=ConstraintType::PrimaryKey && - constr->isReferRelationshipAddedColumn())))) + constr->isReferRelationshipAddedColumns())))) { __getObjectDependencies(child, objs); @@ -8158,7 +8158,7 @@ std::vector DatabaseModel::getCreationOrder(BaseObject *object, bo ((constr->getConstraintType()==ConstraintType::ForeignKey) || (constr->getConstraintType()!=ConstraintType::ForeignKey && constr->getConstraintType()!=ConstraintType::PrimaryKey && - constr->isReferRelationshipAddedColumn())))) + constr->isReferRelationshipAddedColumns())))) { objs_aux.push_back(child); } diff --git a/libs/libcore/src/operationlist.cpp b/libs/libcore/src/operationlist.cpp index e0bd3cad8..c1e76b831 100644 --- a/libs/libcore/src/operationlist.cpp +++ b/libs/libcore/src/operationlist.cpp @@ -422,7 +422,7 @@ int OperationList::registerObject(BaseObject *object, Operation::OperType op_typ if(((obj_type==ObjectType::Trigger && dynamic_cast(tab_obj)->isReferRelationshipAddedColumn()) || (obj_type==ObjectType::Index && dynamic_cast(tab_obj)->isReferRelationshipAddedColumn()) || - (obj_type==ObjectType::Constraint && dynamic_cast(tab_obj)->isReferRelationshipAddedColumn()))) + (obj_type==ObjectType::Constraint && dynamic_cast(tab_obj)->isReferRelationshipAddedColumns()))) { if(op_type==Operation::ObjRemoved) tab_obj->setParentTable(parent_tab); diff --git a/libs/libcore/src/physicaltable.cpp b/libs/libcore/src/physicaltable.cpp index e810a725e..6f2d04d73 100644 --- a/libs/libcore/src/physicaltable.cpp +++ b/libs/libcore/src/physicaltable.cpp @@ -293,12 +293,12 @@ void PhysicalTable::setConstraintsAttribute(SchemaParser::CodeType def_type) if(constr->getConstraintType()!=ConstraintType::ForeignKey && ((def_type==SchemaParser::SqlCode && - ((!constr->isReferRelationshipAddedColumn() && constr->getConstraintType()!=ConstraintType::Check) || + ((!constr->isReferRelationshipAddedColumns() && constr->getConstraintType()!=ConstraintType::Check) || (constr->getConstraintType()==ConstraintType::Check && !constr->isAddedByGeneralization()) || constr->getConstraintType()==ConstraintType::PrimaryKey)) || (def_type==SchemaParser::XmlCode && !constr->isAddedByRelationship() && - ((constr->getConstraintType()!=ConstraintType::PrimaryKey && !constr->isReferRelationshipAddedColumn()) || + ((constr->getConstraintType()!=ConstraintType::PrimaryKey && !constr->isReferRelationshipAddedColumns()) || (constr->getConstraintType()==ConstraintType::PrimaryKey))))) { inc_added_by_rel=(def_type==SchemaParser::SqlCode); diff --git a/libs/libcore/src/relationship.cpp b/libs/libcore/src/relationship.cpp index 8f4f08387..10e509465 100644 --- a/libs/libcore/src/relationship.cpp +++ b/libs/libcore/src/relationship.cpp @@ -352,6 +352,7 @@ void Relationship::createSpecialPrimaryKey() pk_special->setAlias(generateObjectName(PkPattern, nullptr, true)); pk_special->setConstraintType(ConstraintType::PrimaryKey); pk_special->setAddedByLinking(true); + pk_special->setParentRelationship(this); pk_special->setProtected(true); pk_special->setTablespace(dynamic_cast(getReceiverTable()->getTablespace())); @@ -594,6 +595,7 @@ void Relationship::addObject(TableObject *tab_obj, int obj_idx) //Defines the parent table for the object only for validation tab_obj->setParentTable(src_table); + tab_obj->setParentRelationship(this); //Generates the code for the object only for validation if(obj_type==ObjectType::Column) @@ -909,6 +911,7 @@ void Relationship::addConstraints(PhysicalTable *recv_tab) { constr=dynamic_cast(rel_constraints[constr_id]); constr->setAddedByLinking(true); + constr->setParentRelationship(this); //Breaks the iteration if the constraist has a parent if(constr->getParentTable()) @@ -1280,6 +1283,7 @@ void Relationship::addCheckConstrsRelGenPart() ck_constr = createObject(); (*ck_constr)=(*constr); ck_constr->setParentTable(nullptr); + ck_constr->setParentRelationship(this); ck_constr->setAddedByGeneralization(true); child_tab->addConstraint(ck_constr); ck_constraints.push_back(ck_constr); @@ -1485,6 +1489,7 @@ void Relationship::configureIndentifierRel(PhysicalTable *recv_tab) pk = createObject(); pk->setConstraintType(ConstraintType::PrimaryKey); pk->setAddedByLinking(true); + pk->setParentRelationship(this); pk->setDeferrable(this->deferrable); pk->setDeferralType(this->deferral_type); this->pk_relident=pk; @@ -1547,6 +1552,7 @@ void Relationship::addUniqueKey(PhysicalTable *recv_tab) uq->setDeferralType(this->deferral_type); uq->setConstraintType(ConstraintType::Unique); uq->setAddedByLinking(true); + uq->setParentRelationship(this); uq_rel11=uq; } @@ -1608,6 +1614,7 @@ void Relationship::addForeignKey(PhysicalTable *ref_tab, PhysicalTable *recv_tab fk->setDeferralType(this->deferral_type); fk->setConstraintType(ConstraintType::ForeignKey); fk->setAddedByLinking(true); + fk->setParentRelationship(this); //The reference table is the table referenced by the foreign key fk->setReferencedTable(ref_tab); @@ -2075,6 +2082,7 @@ void Relationship::addColumnsRelNn() pk_col->setAlias(generateObjectName(PkColPattern, nullptr, true)); pk_col->setType(PgSqlType("serial")); pk_col->setAddedByLinking(true); + pk_col->setParentRelationship(this); table_relnn->addColumn(pk_col); } @@ -2085,6 +2093,7 @@ void Relationship::addColumnsRelNn() pk_tabnn->setAlias(generateObjectName(PkPattern, nullptr, true)); pk_tabnn->setConstraintType(ConstraintType::PrimaryKey); pk_tabnn->setAddedByLinking(true); + pk_tabnn->setParentRelationship(this); if(!single_pk_column) { @@ -2237,7 +2246,7 @@ void Relationship::removeTableObjectsRefCols(PhysicalTable *table) constr=table->getConstraint(i); if(!constr->isAddedByRelationship() && constr->getConstraintType()!=ConstraintType::PrimaryKey && - constr->isReferRelationshipAddedColumn()) + constr->isReferRelationshipAddedColumns()) { table->removeObject(constr); delete constr; diff --git a/libs/libcore/src/tableobject.cpp b/libs/libcore/src/tableobject.cpp index cd74a34dd..fb1a4cc3f 100644 --- a/libs/libcore/src/tableobject.cpp +++ b/libs/libcore/src/tableobject.cpp @@ -21,6 +21,7 @@ TableObject::TableObject() { + parent_rel=nullptr; parent_table=nullptr; decl_in_table=true; add_by_linking=add_by_generalization=add_by_copy=false; @@ -29,7 +30,7 @@ TableObject::TableObject() void TableObject::setParentTable(BaseTable *table) { setCodeInvalidated(table != parent_table); - parent_table=table; + parent_table = table; } BaseTable *TableObject::getParentTable() @@ -144,3 +145,16 @@ QString TableObject::getSignature(bool format) return QString("%1.%2").arg(parent_table->getSignature(format)).arg(this->getName(format)); } + +void TableObject::setParentRelationship(BaseObject *parent_rel) +{ + if(parent_rel && parent_rel->getObjectType()!=ObjectType::Relationship) + throw Exception(ErrorCode::AsgObjectInvalidType,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + this->parent_rel = parent_rel; +} + +BaseObject *TableObject::getParentRelationship() +{ + return parent_rel; +} diff --git a/libs/libcore/src/tableobject.h b/libs/libcore/src/tableobject.h index f85974f90..a05239dcf 100644 --- a/libs/libcore/src/tableobject.h +++ b/libs/libcore/src/tableobject.h @@ -34,6 +34,9 @@ class __libcore TableObject: public BaseObject { //! \brief Stores the table that owns this object BaseTable *parent_table; + //! \brief Stores a reference to the relationship that generates the object + BaseObject *parent_rel; + /*! \brief Indicates that the object was included automaticaly by "one to many", "one to many", "many to many" relationships */ bool add_by_linking; @@ -77,6 +80,10 @@ class __libcore TableObject: public BaseObject { //! \brief Returns the object parent table BaseTable *getParentTable(); + virtual void setParentRelationship(BaseObject *parent_rel); + + BaseObject *getParentRelationship(); + /*! \brief This method is purely virtual to force the derived classes * overload this method. This also makes class TableObject * not instantiable */ diff --git a/libs/libgui/src/dbobjects/constraintwidget.cpp b/libs/libgui/src/dbobjects/constraintwidget.cpp index c6dfa8fdb..bd7ffb34d 100644 --- a/libs/libgui/src/dbobjects/constraintwidget.cpp +++ b/libs/libgui/src/dbobjects/constraintwidget.cpp @@ -229,7 +229,7 @@ void ConstraintWidget::applyConfiguration() //Raises an error if the user try to create a primary key that has columns added by relationship (not supported) if(constr->getConstraintType()==ConstraintType::PrimaryKey && - constr->isReferRelationshipAddedColumn()) + constr->isReferRelationshipAddedColumns()) throw Exception(ErrorCode::UnsupportedPKColsAddedByRel,__PRETTY_FUNCTION__,__FILE__,__LINE__); BaseObjectWidget::applyConfiguration(); diff --git a/libs/libgui/src/tools/modelsdiffhelper.cpp b/libs/libgui/src/tools/modelsdiffhelper.cpp index 380c7cb97..54829469c 100644 --- a/libs/libgui/src/tools/modelsdiffhelper.cpp +++ b/libs/libgui/src/tools/modelsdiffhelper.cpp @@ -945,7 +945,7 @@ void ModelsDiffHelper::processDiffInfos() * these objects are not created in the parent table's definition, instead, the are created via separated * ALTER TABLE command. */ (create_objs.count(constr->getParentTable()->getObjectId()) && - constr->isReferRelationshipAddedColumn() && constr->getConstraintType() == ConstraintType::Unique)) + constr->isReferRelationshipAddedColumns() && constr->getConstraintType() == ConstraintType::Unique)) create_constrs[constr->getObjectId()]=getSourceCode(constr, false); } else diff --git a/libs/libgui/src/widgets/modelwidget.cpp b/libs/libgui/src/widgets/modelwidget.cpp index c78c2293f..1347bc98e 100644 --- a/libs/libgui/src/widgets/modelwidget.cpp +++ b/libs/libgui/src/widgets/modelwidget.cpp @@ -1620,12 +1620,16 @@ void ModelWidget::convertRelationship1N() Column *column = nullptr; Constraint *constr = nullptr, *pk = recv_tab->getPrimaryKey(); std::vector columns; - QString pk_name, orig_name, rel_name = rel->getName(); + QString pk_name, rel_name = rel->getName(); bool register_pk = false; QColor rel_color = rel->getCustomColor(); + QList layers = rel->getLayers(); - // Storing the XML definition of table's PK - if(pk && (pk->isReferRelationshipAddedColumn() || pk->isAddedByRelationship())) + /* Storing the XML definition of table's PK if it was added by the relationship being converted + * or the PK wasn't created by a relationship but references columns that were added by the relationship */ + if(pk && + ((!pk->isAddedByRelationship() && pk->isReferRelationshipAddedColumns(rel->getGeneratedColumns())) || + (pk->isAddedByRelationship() && pk->getParentRelationship() == rel))) { /* This flag indicates that the pk removal (further in this method) should be registered in the operations list * This will happen only if the pk wasn't added by the relationship */ @@ -1722,6 +1726,7 @@ void ModelWidget::convertRelationship1N() BaseRelationship *fk_rel = db_model->getRelationship(recv_tab, ref_tab); fk_rel->setName(rel_name); fk_rel->setCustomColor(rel_color); + fk_rel->setLayers(layers); fk_rel->setModified(true); op_list->registerObject(fk_rel, Operation::ObjModified); @@ -2772,7 +2777,7 @@ void ModelWidget::copyObjects(bool duplicate_mode, bool copy_deps) (!constr || (((constr && (constr->getConstraintType()==ConstraintType::ForeignKey || (constr->getConstraintType()==ConstraintType::Unique && - constr->isReferRelationshipAddedColumn())))))))) + constr->isReferRelationshipAddedColumns())))))))) { sel_obj_deps.push_back(tab_obj); } @@ -4493,21 +4498,23 @@ void ModelWidget::configureBasicActions(BaseObject *obj) action_deps_refs->setData(QVariant::fromValue(obj)); TableObject *tab_obj = dynamic_cast(obj); - if(tab_obj && tab_obj->getObjectType()==ObjectType::Column) + if(tab_obj && + (tab_obj->getObjectType() == ObjectType::Column || + tab_obj->getObjectType() == ObjectType::Constraint)) { - Column *col=dynamic_cast(tab_obj); + Column *col = dynamic_cast(tab_obj); if(tab_obj->isAddedByRelationship()) { - action_parent_rel->setData(QVariant::fromValue(dynamic_cast(tab_obj)->getParentRelationship())); + action_parent_rel->setData(QVariant::fromValue(tab_obj->getParentRelationship())); popup_menu.addAction(action_parent_rel); } - else if(col->getType().isSerialType()) + else if(col && col->getType().isSerialType()) { action_create_seq_col->setData(QVariant::fromValue(col)); popup_menu.addAction(action_create_seq_col); } - else if(col->getType().isIntegerType()) + else if(col && col->getType().isIntegerType()) { action_conv_int_serial->setData(QVariant::fromValue(col)); popup_menu.addAction(action_conv_int_serial);