diff --git a/src/Learning/KWData/KWAttribute.cpp b/src/Learning/KWData/KWAttribute.cpp index 418db36a2..24c73763f 100644 --- a/src/Learning/KWData/KWAttribute.cpp +++ b/src/Learning/KWData/KWAttribute.cpp @@ -696,6 +696,35 @@ int KWAttributeCompareBlockName(const void* elem1, const void* elem2) return nDiff; } +int KWAttributeCompareClassAndAttributeName(const void* elem1, const void* elem2) +{ + KWAttribute* attribute1; + KWAttribute* attribute2; + int nDiff; + + require(elem1 != NULL); + require(elem2 != NULL); + + // Acces aux attributs + attribute1 = cast(KWAttribute*, *(Object**)elem1); + attribute2 = cast(KWAttribute*, *(Object**)elem2); + + // Comparaison d'abord sur la classe + if (attribute1->GetParentClass() == attribute2->GetParentClass()) + nDiff = 0; + else if (attribute1->GetParentClass() == NULL) + nDiff = -1; + else if (attribute2->GetParentClass() == NULL) + nDiff = 1; + else + nDiff = attribute1->GetParentClass()->GetName().Compare(attribute2->GetParentClass()->GetName()); + + // Difference + if (nDiff == 0) + nDiff = attribute1->GetName().Compare(attribute2->GetName()); + return nDiff; +} + int KWAttributeCompareVarKey(const void* elem1, const void* elem2) { KWAttribute* attribute1; diff --git a/src/Learning/KWData/KWAttribute.h b/src/Learning/KWData/KWAttribute.h index c72bf35e0..a7c9d5549 100644 --- a/src/Learning/KWData/KWAttribute.h +++ b/src/Learning/KWData/KWAttribute.h @@ -258,6 +258,9 @@ int KWAttributeCompareName(const void* elem1, const void* elem2); // Methode de comparaison base sur le nom du bloc de l'attribut, puis de son nom int KWAttributeCompareBlockName(const void* elem1, const void* elem2); +// Methode de comparaison base sur le nom de la classe contenant l'attribut puis celui de l'attribut +int KWAttributeCompareClassAndAttributeName(const void* elem1, const void* elem2); + // Methode de comparaison base sur la VarKey d'un attribut pour deux attribut d'un meme bloc int KWAttributeCompareVarKey(const void* elem1, const void* elem2); diff --git a/src/Learning/KWData/KWClass.cpp b/src/Learning/KWData/KWClass.cpp index c57a0f09c..a4fc6a60a 100644 --- a/src/Learning/KWData/KWClass.cpp +++ b/src/Learning/KWData/KWClass.cpp @@ -671,7 +671,7 @@ int KWClass::ComputeOverallNativeRelationAttributeNumber(boolean bIncludingRefer odAnalysedCreatedClasses.SetAt(kwcTargetClass->GetName(), kwcTargetClass); - // Recherche de toutes les classe utilisee recursivement + // Recherche de toutes les classe utilisees recursivement kwcTargetClass->BuildAllUsedClasses(&oaUsedClass); // Recherches des classes externes diff --git a/src/Learning/KWData/KWClass.h b/src/Learning/KWData/KWClass.h index cea58a238..2777f742d 100644 --- a/src/Learning/KWData/KWClass.h +++ b/src/Learning/KWData/KWClass.h @@ -322,14 +322,15 @@ class KWClass : public Object // Completion eventuelle des attributs avec les informations de type de leur regle de derivation void CompleteTypeInfo(); - // Calcul de l'ensemble des classes utilisees recursivement par les attributs de la classe courante (y compris - // la classe courante) Prerequis: la classe doit etre compilee Memoire: le tableau du code retour appartient a - // l'appelant, et contient des references aux classes utilisees + // Calcul de l'ensemble des classes utilisees recursivement par les attributs de la classe courante + // (y compris la classe courante) + // Prerequis: la classe doit etre compilee + // Memoire: le tableau du code retour appartient a l'appelant, et contient des references aux classes utilisees void BuildAllUsedClasses(ObjectArray* oaUsedClasses) const; // Export des noms des champs natifs (stockes et non calcules, utilises ou non), dans l'ordre du dictionnaire - // (utile pour constituer une ligne de header) Il peut s'agir d'attributs denses natifs ou de blocs d'attributs - // non calcules + // (utile pour constituer une ligne de header) + // Il peut s'agir d'attributs denses natifs ou de blocs d'attributs non calcules void ExportNativeFieldNames(StringVector* svNativeFieldNames) const; // Export des noms des champs stockes (et loades), dans l'ordre du dictionnaire (utile pour constituer une ligne diff --git a/src/Learning/KWData/KWDatabase.cpp b/src/Learning/KWData/KWDatabase.cpp index 34afa7dc1..9579e82b8 100644 --- a/src/Learning/KWData/KWDatabase.cpp +++ b/src/Learning/KWData/KWDatabase.cpp @@ -1410,7 +1410,8 @@ void KWDatabase::BuildPhysicalClass() NumericKeyDictionary nkdAllNeededAttributes; NumericKeyDictionary nkdLoadedAttributeBlocks; NumericKeyDictionary nkdAllNeededClasses; - NumericKeyDictionary nkdLogicalyNeededClasses; + NumericKeyDictionary nkdNeededUsedClasses; + NumericKeyDictionary nkdNeededLogicalClasses; ObjectArray oaAllNeededClasses; ObjectArray oaAttributesToDelete; ObjectArray oaNeededAttributes; @@ -1485,9 +1486,8 @@ void KWDatabase::BuildPhysicalClass() nkdAllNeededClasses.SetAt(kwcPhysicalClass, kwcPhysicalClass); oaAllNeededClasses.Add(kwcPhysicalClass); - // Initialisation des classes necessaires au niveau logique - // Les classes logiques sont celles dont l'utilisateur demande explicitement (Loaded) le chargement en memoire - nkdLogicalyNeededClasses.SetAt(kwcPhysicalClass, kwcPhysicalClass); + // Initialisation des classes necessaires dont l'utilisateur demande explicitement (Loaded) le chargement en memoire + nkdNeededUsedClasses.SetAt(kwcPhysicalClass, kwcPhysicalClass); // Calcul de tous les operandes terminaux intervenant dans une derivation d'un // attribut Loaded de la classe physique (ou d'une autre classe du domaine physique, @@ -1524,8 +1524,8 @@ void KWDatabase::BuildPhysicalClass() } // Ajout au niveau logique - if (nkdLogicalyNeededClasses.Lookup(kwcRefClass) == NULL) - nkdLogicalyNeededClasses.SetAt(kwcRefClass, kwcRefClass); + if (nkdNeededUsedClasses.Lookup(kwcRefClass) == NULL) + nkdNeededUsedClasses.SetAt(kwcRefClass, kwcRefClass); } } @@ -1595,16 +1595,26 @@ void KWDatabase::BuildPhysicalClass() oaClassNeededAttributes.RemoveAll(); } + // Collecte de toutes les logiques necessaires + for (nClass = 0; nClass < oaAllNeededClasses.GetSize(); nClass++) + { + kwcCurrentPhysicalClass = cast(KWClass*, oaAllNeededClasses.GetAt(nClass)); + kwcInitialClass = kwcClass->GetDomain()->LookupClass(kwcCurrentPhysicalClass->GetName()); + nkdNeededLogicalClasses.SetAt(kwcInitialClass, kwcInitialClass); + } + // Affichage des classes et attributs necessaires if (bTrace) { // Affichages des classes necessaires cout << "Needed classes\n"; + oaAllNeededClasses.SetCompareFunction(KWClassCompareName); + oaAllNeededClasses.Sort(); for (nClass = 0; nClass < oaAllNeededClasses.GetSize(); nClass++) { kwcCurrentPhysicalClass = cast(KWClass*, oaAllNeededClasses.GetAt(nClass)); cout << "\t" << kwcCurrentPhysicalClass->GetName(); - if (nkdLogicalyNeededClasses.Lookup(kwcCurrentPhysicalClass)) + if (nkdNeededUsedClasses.Lookup(kwcCurrentPhysicalClass)) cout << "\tLogical"; else cout << "\tPhysical"; @@ -1614,7 +1624,7 @@ void KWDatabase::BuildPhysicalClass() // Affichage des attributs necessaires cout << "Needed attributes\t" << nkdAllNeededAttributes.GetCount() << endl; nkdAllNeededAttributes.ExportObjectArray(&oaNeededAttributes); - oaNeededAttributes.SetCompareFunction(KWAttributeCompareName); + oaNeededAttributes.SetCompareFunction(KWAttributeCompareClassAndAttributeName); oaNeededAttributes.Sort(); for (nAttribute = 0; nAttribute < oaNeededAttributes.GetSize(); nAttribute++) { @@ -1632,7 +1642,7 @@ void KWDatabase::BuildPhysicalClass() for (nAttribute = 0; nAttribute < oaNeededAttributes.GetSize(); nAttribute++) { attribute = cast(KWAttribute*, oaNeededAttributes.GetAt(nAttribute)); - if (not attribute->GetLoaded() or nkdLogicalyNeededClasses.Lookup(attribute->GetParentClass()) == NULL) + if (not attribute->GetLoaded() or nkdNeededUsedClasses.Lookup(attribute->GetParentClass()) == NULL) { bPhysicalDomainNeeded = true; break; @@ -1658,6 +1668,10 @@ void KWDatabase::BuildPhysicalClass() { kwcCurrentPhysicalClass = cast(KWClass*, oaAllNeededClasses.GetAt(nClass)); + // Recherche de la classe initiale correspondante + kwcInitialClass = + KWClassDomain::GetCurrentDomain()->LookupClass(kwcCurrentPhysicalClass->GetName()); + // Identification des blocs d'attributs charges en memoire // Ces blocs initialement charges en memoire ne sont ni a supprimer, ni a deplacer en fin de // classe @@ -1673,7 +1687,7 @@ void KWDatabase::BuildPhysicalClass() // Si la classe n'est pas necessaire au niveau logique, // ses attributs de base ne sont pas a charger - if (nkdLogicalyNeededClasses.Lookup(kwcCurrentPhysicalClass) == NULL) + if (nkdNeededUsedClasses.Lookup(kwcCurrentPhysicalClass) == NULL) kwcCurrentPhysicalClass->SetAllAttributesLoaded(false); //////////////////////////////////////////////////////////////////////// @@ -1743,7 +1757,7 @@ void KWDatabase::BuildPhysicalClass() // Passage a l'attribut suivant kwcCurrentPhysicalClass->GetNextAttribute(attribute); } - assert(nkdLogicalyNeededClasses.Lookup(kwcCurrentPhysicalClass) != NULL or + assert(nkdNeededUsedClasses.Lookup(kwcCurrentPhysicalClass) != NULL or kwcCurrentPhysicalClass->GetAttributeNumber() >= oaAttributesToDelete.GetSize() + oaNeededAttributes.GetSize()); @@ -1763,15 +1777,20 @@ void KWDatabase::BuildPhysicalClass() for (nAttribute = 0; nAttribute < oaNeededAttributes.GetSize(); nAttribute++) { attribute = cast(KWAttribute*, oaNeededAttributes.GetAt(nAttribute)); + assert(attribute->GetParentClass() == kwcCurrentPhysicalClass); + + // Recherche de l'attribut initial correspondant + initialAttribute = kwcInitialClass->LookupAttribute(attribute->GetName()); + assert(initialAttribute != NULL); // On passe l'attribut en Used et Loaded attribute->SetUsed(true); attribute->SetLoaded(true); - // Deplacement en fin de classe - // Dans le cas des blocs, le calcul des reindexation des variables du bloc se fera a la - // fin de la methode - if (not attribute->IsInBlock()) + // Deplacement en fin de classe, sauf si l'attribut est utilise dans la classe initiale + // Dans le cas des blocs, le calcul des reindexation des variables du bloc + // se fera a la fin de la methode + if (not attribute->IsInBlock() and not initialAttribute->GetLoaded()) kwcCurrentPhysicalClass->MoveAttributeToClassTail(attribute); } @@ -1789,7 +1808,7 @@ void KWDatabase::BuildPhysicalClass() // Indexation de la classe kwcCurrentPhysicalClass->IndexClass(); - assert(nkdLogicalyNeededClasses.Lookup(kwcCurrentPhysicalClass) == NULL or + assert(nkdNeededUsedClasses.Lookup(kwcCurrentPhysicalClass) == NULL or kwcCurrentPhysicalClass->GetAttributeNumber() == KWClassDomain::GetCurrentDomain() ->LookupClass(kwcCurrentPhysicalClass->GetName()) @@ -1843,7 +1862,7 @@ void KWDatabase::BuildPhysicalClass() KWClassDomain::GetCurrentDomain()->LookupClass(kwcCurrentPhysicalClass->GetName()); // Verification de la coherence entre classes initiales et classes physiques - if (nkdLogicalyNeededClasses.Lookup(kwcCurrentPhysicalClass) != NULL) + if (nkdNeededUsedClasses.Lookup(kwcCurrentPhysicalClass) != NULL) { // Les attributs initiaux Loaded doivent avoir meme index pour les classes // necessaires logiquement saif s'il sont dans des blocs @@ -2069,7 +2088,7 @@ void KWDatabase::BuildPhysicalClass() } // Calcul des attributs natifs non utilises a garder pour gerer correctement la mutation des objets - ComputeUnusedNativeAttributesToKeep(&nkdUnusedNativeAttributesToKeep); + ComputeUnusedNativeAttributesToKeep(&nkdNeededLogicalClasses, &nkdUnusedNativeAttributesToKeep); ensure(kwcPhysicalClass != NULL); ensure(kwcPhysicalClass->GetName() == GetClassName()); @@ -2077,7 +2096,8 @@ void KWDatabase::BuildPhysicalClass() ensure(kwcPhysicalClass->GetLoadedAttributeNumber() >= kwcClass->GetLoadedAttributeNumber()); } -void KWDatabase::ComputeUnusedNativeAttributesToKeep(NumericKeyDictionary* nkdAttributes) +void KWDatabase::ComputeUnusedNativeAttributesToKeep(const NumericKeyDictionary* nkdNeededClasses, + NumericKeyDictionary* nkdAttributes) { const boolean bTrace = false; ObjectArray oaImpactedClasses; @@ -2087,9 +2107,11 @@ void KWDatabase::ComputeUnusedNativeAttributesToKeep(NumericKeyDictionary* nkdAt KWAttribute* attribute; int nAttribute; ObjectArray oaAttributesToKeep; + ObjectArray oaNeededClasses; NumericKeyDictionary nkdAnalysedRules; require(kwcClass != NULL); + require(nkdNeededClasses != NULL); require(nkdAttributes != NULL); require(nkdAttributes->GetCount() == 0); @@ -2117,7 +2139,8 @@ void KWDatabase::ComputeUnusedNativeAttributesToKeep(NumericKeyDictionary* nkdAt // Analyse si retourne par une regle de derivation // On identifie ainsi les attributs Object natifs potentiellement references if (attribute->GetAnyDerivationRule() != NULL) - ComputeUnusedNativeAttributesToKeepForRule(nkdAttributes, &nkdAnalysedRules, + ComputeUnusedNativeAttributesToKeepForRule(nkdNeededClasses, nkdAttributes, + &nkdAnalysedRules, attribute->GetAnyDerivationRule()); // Ajout de la classe parmi les classes a analyser @@ -2133,13 +2156,28 @@ void KWDatabase::ComputeUnusedNativeAttributesToKeep(NumericKeyDictionary* nkdAt // Affichage des attributs a garder if (bTrace) { - // Export des attrribut a garder + // Export des classes necessaires + nkdNeededClasses->ExportObjectArray(&oaNeededClasses); + oaNeededClasses.SetCompareFunction(KWClassCompareName); + oaNeededClasses.Sort(); + + // Affichagges des classe necessaires + cout << "ComputeUnusedNativeAttributesToKeep\n"; + cout << " Necessary classes\t" << nkdNeededClasses->GetCount() << "\n"; + for (nClass = 0; nClass < oaNeededClasses.GetSize(); nClass++) + { + kwcCurrentClass = cast(KWClass*, oaNeededClasses.GetAt(nClass)); + cout << "\t" << kwcCurrentClass->GetDomain()->GetName() << "\t" << kwcCurrentClass->GetName() + << "\n"; + } + + // Export des attributs a garder nkdAttributes->ExportObjectArray(&oaAttributesToKeep); - oaAttributesToKeep.SetCompareFunction(KWAttributeCompareName); + oaAttributesToKeep.SetCompareFunction(KWAttributeCompareClassAndAttributeName); oaAttributesToKeep.Sort(); - // Affichage - cout << "Unused native attributes to keep\n"; + // Affichage des attributs + cout << " Unused native attributes to keep\t" << nkdAttributes->GetCount() << "\n"; for (nAttribute = 0; nAttribute < oaAttributesToKeep.GetSize(); nAttribute++) { attribute = cast(KWAttribute*, oaAttributesToKeep.GetAt(nAttribute)); @@ -2148,7 +2186,8 @@ void KWDatabase::ComputeUnusedNativeAttributesToKeep(NumericKeyDictionary* nkdAt } } -void KWDatabase::ComputeUnusedNativeAttributesToKeepForRule(NumericKeyDictionary* nkdAttributes, +void KWDatabase::ComputeUnusedNativeAttributesToKeepForRule(const NumericKeyDictionary* nkdNeededClasses, + NumericKeyDictionary* nkdAttributes, NumericKeyDictionary* nkdAnalysedRules, KWDerivationRule* rule) { @@ -2158,6 +2197,7 @@ void KWDatabase::ComputeUnusedNativeAttributesToKeepForRule(NumericKeyDictionary KWAttributeBlock* attributeBlock; require(kwcClass != NULL); + require(nkdNeededClasses != NULL); require(nkdAttributes != NULL); require(nkdAnalysedRules != NULL); require(rule != NULL); @@ -2178,17 +2218,19 @@ void KWDatabase::ComputeUnusedNativeAttributesToKeepForRule(NumericKeyDictionary // Cas d'un type non bloc if (not KWType::IsValueBlock(operand->GetType())) { - // On considere l'operande s'il s'agit d'un objet du meme type que celui de la regle - // Il n'est pas utile de poursuivre l'analyse recursive des operandes si l'on a pas le bon type - // de relation - if (KWType::IsRelation(operand->GetType()) and - operand->GetObjectClassName() == rule->GetObjectClassName()) + // On considere l'operande s'il s'agit d'un objet de type relation + // Il faut propager l'analyse meme si le type d'objet de l'operande n'est pas le meme + // que celui de la regle. En effet, dans le cas de regles de creation de table, on peut + // creer des tables intermediaires en unused pour alimenter le contenu d'autres tables + // de type differents + if (KWType::IsRelation(operand->GetType())) { // Propagation si regle if (operand->GetDerivationRule() != NULL) { assert(not KWType::IsValueBlock(operand->GetType())); - ComputeUnusedNativeAttributesToKeepForRule(nkdAttributes, nkdAnalysedRules, + ComputeUnusedNativeAttributesToKeepForRule(nkdNeededClasses, nkdAttributes, + nkdAnalysedRules, operand->GetDerivationRule()); } // Traitement de l'attribut sinon @@ -2200,11 +2242,15 @@ void KWDatabase::ComputeUnusedNativeAttributesToKeepForRule(NumericKeyDictionary // Propagation si regle if (attribute->GetAnyDerivationRule() != NULL) ComputeUnusedNativeAttributesToKeepForRule( - nkdAttributes, nkdAnalysedRules, attribute->GetAnyDerivationRule()); + nkdNeededClasses, nkdAttributes, nkdAnalysedRules, + attribute->GetAnyDerivationRule()); // Memorisation de l'attribut natif ou cree sinon, s'il n'est pas utilise + //DDD On prend en fait en compte toutes les classes, sinon cela fait planter z_TableCreationRules\BugDeleteSubTableOfView + //DDD le parametre nkdNeededClasses est donc a ignorer et inutile!!! if (not attribute->IsInBlock() and not attribute->GetReference() and - not attribute->GetUsed()) + not attribute->GetUsed() and + nkdNeededClasses->Lookup(attribute->GetClass()) != NULL) nkdAttributes->SetAt(attribute, attribute); } } @@ -2215,9 +2261,8 @@ void KWDatabase::ComputeUnusedNativeAttributesToKeepForRule(NumericKeyDictionary // On verifie qu'un operande de type block ne peut etre renvoye par une regle assert(not(operand->GetOrigin() == KWDerivationRuleOperand::OriginRule)); - // On considere l'operande s'il s'agit d'un bloc d'objets du meme type que celui de la regle - if (operand->GetType() == KWType::ObjectArrayValueBlock and - operand->GetObjectClassName() == rule->GetObjectClassName()) + // On considere l'operande s'il s'agit d'un bloc d'objets + if (operand->GetType() == KWType::ObjectArrayValueBlock) { // Traitement du bloc d'attributs attributeBlock = operand->GetOriginAttributeBlock(); @@ -2225,7 +2270,8 @@ void KWDatabase::ComputeUnusedNativeAttributesToKeepForRule(NumericKeyDictionary // Propagation a la regle: un bloc d'attributs de type relation ne peut qu'etre calcule assert(attributeBlock->GetDerivationRule() != NULL); - ComputeUnusedNativeAttributesToKeepForRule(nkdAttributes, nkdAnalysedRules, + ComputeUnusedNativeAttributesToKeepForRule(nkdNeededClasses, nkdAttributes, + nkdAnalysedRules, attributeBlock->GetDerivationRule()); } } @@ -2256,6 +2302,7 @@ void KWDatabase::DeletePhysicalClass() void KWDatabase::MutatePhysicalObject(KWObject* kwoPhysicalObject) const { + const boolean bTrace = false; KWObjectKey objectKey; require(kwcPhysicalClass != NULL); @@ -2284,9 +2331,23 @@ void KWDatabase::MutatePhysicalObject(KWObject* kwoPhysicalObject) const kwoPhysicalObject->GetObjectLabel(); } + // Trace avant mutation + if (bTrace) + { + if (kwcPhysicalClass != kwcClass) + cout << "Before mutation\n" << *kwoPhysicalObject << "\n"; + } + // Mutation si necessaire if (kwcPhysicalClass != kwcClass) kwoPhysicalObject->Mutate(kwcClass, &nkdUnusedNativeAttributesToKeep); + + // Trace apres mutation + if (bTrace) + { + if (kwcPhysicalClass != kwcClass) + cout << "After mutation\n" << *kwoPhysicalObject << "\n"; + } ensure(kwoPhysicalObject->GetClass() == kwcClass); ensure(kwoPhysicalObject->Check()); } diff --git a/src/Learning/KWData/KWDatabase.h b/src/Learning/KWData/KWDatabase.h index 1a3f1ba50..63dc49f15 100644 --- a/src/Learning/KWData/KWDatabase.h +++ b/src/Learning/KWData/KWDatabase.h @@ -437,9 +437,11 @@ class KWDatabase : public Object // pour piloter efficacement la methode de mutation des object physiques virtual void BuildPhysicalClass(); - // Calcul du dictionnaire des attributs natifs inutilises a garder - void ComputeUnusedNativeAttributesToKeep(NumericKeyDictionary* nkdAttributes); - void ComputeUnusedNativeAttributesToKeepForRule(NumericKeyDictionary* nkdAttributes, + // Calcul du dictionnaire des attributs natifs inutilises a garder, en precisant les classes qui sont necessaires + void ComputeUnusedNativeAttributesToKeep(const NumericKeyDictionary* nkdNeededClasses, + NumericKeyDictionary* nkdAttributes); + void ComputeUnusedNativeAttributesToKeepForRule(const NumericKeyDictionary* nkdClassesToKeep, + NumericKeyDictionary* nkdAttributes, NumericKeyDictionary* nkdAnalysedRules, KWDerivationRule* rule); // Destruction de la classe physique diff --git a/src/Learning/KWData/KWMTDatabase.cpp b/src/Learning/KWData/KWMTDatabase.cpp index 218f2e7e4..2e681da50 100644 --- a/src/Learning/KWData/KWMTDatabase.cpp +++ b/src/Learning/KWData/KWMTDatabase.cpp @@ -251,6 +251,7 @@ int KWMTDatabaseCompareMappingMainClass(const void* first, const void* second) void KWMTDatabase::UpdateMultiTableMappings() { + const boolean bTrace = false; KWClass* mainClass; ObjectArray oaPreviousMultiTableMappings; ObjectDictionary odReferenceClasses; @@ -361,6 +362,18 @@ void KWMTDatabase::UpdateMultiTableMappings() // Destruction des anciens mappings oaPreviousMultiTableMappings.DeleteAll(); } + + // Affichage des mappings + if (bTrace) + { + cout << "Database " << GetDatabaseName() << " " << GetClassName() << " mappings\n"; + for (i = 0; i < oaMultiTableMappings.GetSize(); i++) + { + mapping = cast(KWMTDatabaseMapping*, oaMultiTableMappings.GetAt(i)); + cout << "\t" << i + 1 << "\t" << mapping->GetDataPath() << "\t" << mapping->GetClassName() + << "\t" << mapping->GetDataTableName() << "\n"; + } + } ensure(mainClass == NULL or mainClass->ComputeOverallNativeRelationAttributeNumber(true) == oaMultiTableMappings.GetSize() - 1); ensure(oaMultiTableMappings.GetAt(0) == rootMultiTableMapping); @@ -1402,6 +1415,7 @@ KWMTDatabaseMapping* KWMTDatabase::CreateMapping(ObjectDictionary* odReferenceCl { // Memorisation de la classe cible odAnalysedCreatedClasses->SetAt(kwcTargetClass->GetName(), kwcTargetClass); + // Recherche de toutes les classe utilisee recursivement kwcTargetClass->BuildAllUsedClasses(&oaUsedClass); diff --git a/src/Learning/KWData/KWMTDatabaseMapping.cpp b/src/Learning/KWData/KWMTDatabaseMapping.cpp index 0d73e5e01..6c5515136 100644 --- a/src/Learning/KWData/KWMTDatabaseMapping.cpp +++ b/src/Learning/KWData/KWMTDatabaseMapping.cpp @@ -263,7 +263,7 @@ boolean KWMTDatabaseMapping::CheckDataPath() const if (n == sDataPathAttributeNames.GetLength() - 1) { nAttributeNumber++; - if (n <= nLastAttributeBegin) + if (n < nLastAttributeBegin) { AddError(sTmp + "Missing name for variable " + IntToString(nAttributeNumber + 1) + " in data path"); diff --git a/src/Learning/KWData/KWMTDatabaseMapping.h b/src/Learning/KWData/KWMTDatabaseMapping.h index eb42abfd1..9b81bf89f 100644 --- a/src/Learning/KWData/KWMTDatabaseMapping.h +++ b/src/Learning/KWData/KWMTDatabaseMapping.h @@ -65,9 +65,9 @@ class KWMTDatabaseMapping : public Object // (caractere interdit dans les identifiant de nom de classe et d'attribut) // Exemples de DataPath pour differents types de mapping: // classe principale: Customer - // sous-objet: Customer.Address - // tableau de sous-objets: Customer.Log - // Sous-objet de second niveau: Customer.Address.City + // sous-objet: Customer`Address + // tableau de sous-objets: Customer`Log + // Sous-objet de second niveau: Customer`Address`City // Attributs du DataPath int GetDataPathAttributeNumber() const; diff --git a/src/Learning/KWData/KWObject.cpp b/src/Learning/KWData/KWObject.cpp index edb3aad0b..3ab5aecb3 100644 --- a/src/Learning/KWData/KWObject.cpp +++ b/src/Learning/KWData/KWObject.cpp @@ -29,6 +29,7 @@ KWObject::~KWObject() void KWObject::ComputeAllValues(KWDatabaseMemoryGuard* memoryGuard) { + const boolean bTrace = false; int nAttribute; KWDataItem* dataItem; KWAttribute* attribute; @@ -43,6 +44,11 @@ void KWObject::ComputeAllValues(KWDatabaseMemoryGuard* memoryGuard) debug(require(nObjectLoadedDataItemNumber == kwcClass->GetTotalInternallyLoadedDataItemNumber())); debug(require(nFreshness == kwcClass->GetFreshness())); + // Trace de debut + if (bTrace) + cout << "Begin KWObject::ComputeAllValues " << GetClass()->GetName() << " " << GetCreationIndex() + << "\n"; + // Calcul de toutes les valeurs a transferer for (nAttribute = 0; nAttribute < kwcClass->GetConstDatabaseDataItemsToCompute()->GetSize(); nAttribute++) { @@ -173,10 +179,15 @@ void KWObject::ComputeAllValues(KWDatabaseMemoryGuard* memoryGuard) CleanAllNonNativeAttributes(); CleanNativeRelationAttributes(); } + + // Trace de fin + if (bTrace) + cout << "End KWObject::ComputeAllValues " << GetClass()->GetName() << " " << GetCreationIndex() << "\n"; } void KWObject::DeleteAttributes() { + boolean bTrace = false; int i; KWAttribute* attribute; SymbolVector* svTextList; @@ -192,6 +203,11 @@ void KWObject::DeleteAttributes() debug(require(nFreshness == kwcClass->GetFreshness())); require(kwcClass->IsCompiled()); + // Trace de debut + if (bTrace) + cout << " Begin KWObject::DeleteAttributes " << GetClass()->GetName() << " " << GetCreationIndex() + << "\n"; + // Recherche si usage de type view bIsViewTypeUse = GetViewTypeUse(); @@ -298,7 +314,15 @@ void KWObject::DeleteAttributes() { kwoUsedObject = value.GetObject(); if (kwoUsedObject != NULL) + { + // Trace + if (bTrace) + cout << " delete object " << attribute->GetName() + << kwoUsedObject << "\n"; + + // Destruction delete kwoUsedObject; + } } } } @@ -314,6 +338,13 @@ void KWObject::DeleteAttributes() oaUsedObjectArray = value.GetObjectArray(); if (oaUsedObjectArray != NULL) { + // Trace + if (bTrace) + cout << " delete ObjectArray content " << attribute->GetName() + << " " + << "(size=" << oaUsedObjectArray->GetSize() << ") " + << oaUsedObjectArray << "\n"; + // Destruction des objets contenus si necessaire if (bIsDeletionNeeded) oaUsedObjectArray->DeleteAll(); @@ -393,6 +424,11 @@ void KWObject::DeleteAttributes() // Destruction du tableau d'attributs de base DeleteValueVector(values, kwcClass->GetTotalInternallyLoadedDataItemNumber()); } + + // Trace de fin + if (bTrace) + cout << " End KWObject::DeleteAttributes " << GetClass()->GetName() << " " << GetCreationIndex() + << "\n"; } void KWObject::CleanTemporayDataItemsToComputeAndClean() @@ -885,6 +921,12 @@ boolean KWObject::Check() const void KWObject::Write(ostream& ost) const { + PrettyWrite(ost, ""); +} + +void KWObject::PrettyWrite(ostream& ost, const ALString& sIndent) const +{ + const ALString sBasicIndent = " "; KWDataItem* dataItem; KWAttribute* attribute; KWAttributeBlock* attributeBlock; @@ -900,11 +942,12 @@ void KWObject::Write(ostream& ost) const debug(require(nObjectLoadedDataItemNumber == kwcClass->GetTotalInternallyLoadedDataItemNumber())); debug(require(nFreshness == kwcClass->GetFreshness())); require(GetClass()->Check()); + require(sIndent.SpanIncluding(" ") == sIndent); // Impression de l'entete de l'objet if (GetClass()->GetRoot()) ost << GetClass()->GetName() << "\n"; - ost << "{[" << GetCreationIndex() << "]\n"; + ost << sIndent << "{" << GetClass()->GetName() << "[" << GetCreationIndex() << "]\n"; // Impression des attributs charges en memoire for (i = 0; i < GetClass()->GetLoadedDataItemNumber(); i++) @@ -916,6 +959,9 @@ void KWObject::Write(ostream& ost) const { attribute = cast(KWAttribute*, dataItem); + // Indentation + ost << sIndent; + // Nom de l'attribut ost << attribute->GetName() << ": "; @@ -963,9 +1009,14 @@ void KWObject::Write(ostream& ost) const ost << "[NULL]\n"; else { - ost << "[" << kwoUsedObject->GetCreationIndex() << "]\n"; if (not attribute->GetReference()) - ost << *kwoUsedObject; + { + ost << "\n"; + kwoUsedObject->PrettyWrite(ost, sIndent + sBasicIndent); + } + else + ost << kwoUsedObject->GetClass()->GetName() << "[" + << kwoUsedObject->GetCreationIndex() << "]\n"; } break; // Valeur ObjectArray @@ -976,26 +1027,27 @@ void KWObject::Write(ostream& ost) const else { // Parcours des elements du tableau - ost << "\n{\n"; + ost << "\n" << sIndent + sBasicIndent << "{\n"; for (j = 0; j < oaUsedObjectArray->GetSize(); j++) { kwoUsedObject = cast(KWObject*, oaUsedObjectArray->GetAt(j)); // Test si objet multi inclu ou multi reference if (kwoUsedObject == NULL) - ost << "[NULL]\n"; + ost << sIndent + sBasicIndent << "[NULL]\n"; else { - ost << "[" << kwoUsedObject->GetCreationIndex() << "] "; if (not attribute->GetReference()) - ost << *kwoUsedObject; + kwoUsedObject->PrettyWrite(ost, sIndent + sBasicIndent + + sBasicIndent); else - ost << "\n"; + ost << sIndent + sBasicIndent << "[" + << kwoUsedObject->GetCreationIndex() << "]\n"; } } - ost << "}\n"; - break; + ost << sIndent + sBasicIndent << "}\n"; } + break; // Valeur Structure case KWType::Structure: oUsedStructure = ComputeStructureValueAt(attribute->GetLoadIndex()); @@ -1004,7 +1056,7 @@ void KWObject::Write(ostream& ost) const else { ost << "[" << oUsedStructure << "]\n"; - ost << *oUsedStructure; + ost << sIndent << *oUsedStructure; } break; } @@ -1020,17 +1072,17 @@ void KWObject::Write(ostream& ost) const continuousValueBlock = ComputeContinuousValueBlockAt(attributeBlock->GetLoadIndex()); if (continuousValueBlock->GetValueNumber() > 0) { - ost << "{\n"; + ost << sIndent << "{\n"; for (j = 0; j < continuousValueBlock->GetValueNumber(); j++) { attribute = attributeBlock->GetLoadedAttributeAt( continuousValueBlock->GetAttributeSparseIndexAt(j)); - ost << attribute->GetName() << ": "; + ost << sIndent << attribute->GetName() << ": "; ost << KWContinuous::ContinuousToString( continuousValueBlock->GetValueAt(j)) << "\n"; } - ost << "}\n"; + ost << sIndent << "}\n"; } } // Bloc de valeurs Symbol @@ -1039,15 +1091,15 @@ void KWObject::Write(ostream& ost) const symbolValueBlock = ComputeSymbolValueBlockAt(attributeBlock->GetLoadIndex()); if (symbolValueBlock->GetValueNumber() > 0) { - ost << "{\n"; + ost << sIndent << "{\n"; for (j = 0; j < symbolValueBlock->GetValueNumber(); j++) { attribute = attributeBlock->GetLoadedAttributeAt( symbolValueBlock->GetAttributeSparseIndexAt(j)); - ost << attribute->GetName() << ": "; + ost << sIndent << attribute->GetName() << ": "; ost << symbolValueBlock->GetValueAt(j) << "\n"; } - ost << "}\n"; + ost << sIndent << "}\n"; } } // Bloc de valeurs ObjectArray @@ -1056,12 +1108,12 @@ void KWObject::Write(ostream& ost) const objectArrayValueBlock = ComputeObjectArrayValueBlockAt(attributeBlock->GetLoadIndex()); if (objectArrayValueBlock->GetValueNumber() > 0) { - ost << "{\n"; + ost << sIndent << "{\n"; for (j = 0; j < objectArrayValueBlock->GetValueNumber(); j++) { attribute = attributeBlock->GetLoadedAttributeAt( objectArrayValueBlock->GetAttributeSparseIndexAt(j)); - ost << attribute->GetName() << ": "; + ost << sIndent << attribute->GetName() << ": "; // Ecriture du tableau d'objet oaUsedObjectArray = objectArrayValueBlock->GetValueAt(j); @@ -1070,7 +1122,7 @@ void KWObject::Write(ostream& ost) const else { // Parcours des elements du tableau - ost << "\n{\n"; + ost << "\n" << sIndent + sBasicIndent << "{\n"; for (j = 0; j < oaUsedObjectArray->GetSize(); j++) { kwoUsedObject = @@ -1078,28 +1130,33 @@ void KWObject::Write(ostream& ost) const // Test si objet multi inclu ou multi reference if (kwoUsedObject == NULL) - ost << "[NULL]\n"; + ost << sIndent + sBasicIndent << "[NULL]\n"; else { - ost << "[" << kwoUsedObject->GetCreationIndex() - << "] "; if (not attribute->GetReference()) - ost << *kwoUsedObject; + kwoUsedObject->PrettyWrite( + ost, sIndent + sBasicIndent + + sBasicIndent); else - ost << "\n"; + ost << sIndent + sBasicIndent + << kwoUsedObject->GetClass() + ->GetName() + << "[" + << kwoUsedObject->GetCreationIndex() + << "]\n"; } } - ost << "}\n"; + ost << sIndent + sBasicIndent << "}\n"; } } - ost << "}\n"; + ost << sIndent << "}\n"; } } } } // Impression de la fin de l'objet - ost << "}\n"; + ost << sIndent << "}\n"; } longint KWObject::GetUsedMemory() const @@ -1430,6 +1487,7 @@ void KWObject::Test() void KWObject::Mutate(const KWClass* kwcNewClass, const NumericKeyDictionary* nkdUnusedNativeAttributesToKeep) { + const boolean bTrace = false; const KWClass* previousClass; const KWAttribute* previousAttribute; ObjectValues previousValues; @@ -1472,6 +1530,10 @@ void KWObject::Mutate(const KWClass* kwcNewClass, const NumericKeyDictionary* nk if (kwcNewClass == kwcClass) return; + // Trace de debut + if (bTrace) + cout << "Begin Object::Mutate " << GetClass()->GetName() << " " << GetCreationIndex() << "\n"; + // Recherche si usage de type view bIsViewTypeUse = GetViewTypeUse(); @@ -1558,7 +1620,16 @@ void KWObject::Mutate(const KWClass* kwcNewClass, const NumericKeyDictionary* nk // Les containers appartiennent a l'objet, qu'ils soient natifs ou // proviennent d'une regle, auquel cas ils ont ete dupliques if (attribute->GetReference()) + { + // Trace + if (bTrace) + cout << " delete ref ObjectArray " + << attribute->GetName() << " " << oaUsedObjectArray + << "\n"; + + // Destruction delete oaUsedObjectArray; + } } } } @@ -1691,6 +1762,11 @@ void KWObject::Mutate(const KWClass* kwcNewClass, const NumericKeyDictionary* nk nLoadedDataItemNumber = kwcClass->GetLoadedDataItemNumber(); if (nTotalInternallyLoadedDataItemNumber > 0) { + // Trace + if (bTrace) + cout << " new ValueVector (size=" << nLoadedDataItemNumber + << " , internal size=" << nTotalInternallyLoadedDataItemNumber << ")\n"; + // Creation du vecteur de valeur et memorisation de son type de taille values = NewValueVector(nTotalInternallyLoadedDataItemNumber); SetSmallSize(nTotalInternallyLoadedDataItemNumber <= nBlockSize); @@ -1758,7 +1834,16 @@ void KWObject::Mutate(const KWClass* kwcNewClass, const NumericKeyDictionary* nk } // Destruction sinon else + { + // Trace + if (bTrace) + cout << " delete Object " + << attribute->GetName() << " " + << kwoUsedObject << "\n"; + + // Destruction delete kwoUsedObject; + } } } // Cas des ObjectArray @@ -1807,6 +1892,14 @@ void KWObject::Mutate(const KWClass* kwcNewClass, const NumericKeyDictionary* nk // Destruction sinon else { + // Trace + if (bTrace) + cout << " delete ObjectArray content " + << attribute->GetName() << " " + << "(size=" << oaUsedObjectArray->GetSize() + << ") " << oaUsedObjectArray << "\n"; + + // Destruction oaUsedObjectArray->DeleteAll(); delete oaUsedObjectArray; } @@ -1850,6 +1943,13 @@ void KWObject::Mutate(const KWClass* kwcNewClass, const NumericKeyDictionary* nk // Si non trouve, supression if (kwcMutationClass == NULL) { + // Trace + if (bTrace) + cout << " delete unmutated Object " + << attribute->GetName() << " " + << kwoUsedObject << "\n"; + + // Supression delete kwoUsedObject; GetAt(liLoadIndex.GetDenseIndex()).SetObject(NULL); } @@ -1892,6 +1992,15 @@ void KWObject::Mutate(const KWClass* kwcNewClass, const NumericKeyDictionary* nk // Si non trouve, supression if (kwcMutationClass == NULL) { + // Trace + if (bTrace) + cout << " delete unmutated " + "Object in ObjectArray " + << attribute->GetName() + << " " << kwoUsedObject + << "\n"; + + // Supression delete kwoUsedObject; oaUsedObjectArray->SetAt(nObject, NULL); } @@ -1911,7 +2020,19 @@ void KWObject::Mutate(const KWClass* kwcNewClass, const NumericKeyDictionary* nk // Destruction des valeurs precedentes, geree par la destruction de l'objet precedent memorise if (previousValues.attributeValues != NULL) + { + // Trace + if (bTrace) + cout << " delete previous ValueVector (size=" + << previousClass->GetTotalInternallyLoadedDataItemNumber() << ")\n"; + + // Destruction DeleteValueVector(previousValues, previousClass->GetTotalInternallyLoadedDataItemNumber()); + } + + // Trace de fin + if (bTrace) + cout << "End Object::Mutate " << GetClass()->GetName() << " " << GetCreationIndex() << "\n"; // Memorisation des informations de coherence debug(nObjectLoadedDataItemNumber = kwcClass->GetTotalInternallyLoadedDataItemNumber()); diff --git a/src/Learning/KWData/KWObject.h b/src/Learning/KWData/KWObject.h index 4eff5beef..50121494c 100644 --- a/src/Learning/KWData/KWObject.h +++ b/src/Learning/KWData/KWObject.h @@ -178,8 +178,9 @@ class KWObject : public Object // Verification de coherence boolean Check() const override; - // Affichage, ecriture dans un fichier, de facon structuree + // Affichage, ecriture dans un fichier, de facon structuree, avec indentation void Write(ostream& ost) const override; + void PrettyWrite(ostream& ost, const ALString& sIndent) const; // Estimation de la memoire utilisee par l'objet, et de tous ses sous-objets longint GetUsedMemory() const override; diff --git a/src/Learning/KWData/KWRelationCreationRule.cpp b/src/Learning/KWData/KWRelationCreationRule.cpp index 76f29c392..2e0672f57 100644 --- a/src/Learning/KWData/KWRelationCreationRule.cpp +++ b/src/Learning/KWData/KWRelationCreationRule.cpp @@ -963,7 +963,9 @@ void KWDRRelationCreationRule::BuildAllUsedAttributes(const KWAttribute* derived { // On ne traite que les attributs natifs utilises non deja prise en compte // par une alimentation de type calcul - //DDD if (targetAttribute->GetUsed() and targetAttribute->GetDerivationRule() == NULL) + //DDD On doit integrer meme les attribut en Unused (BUG EN COURS) + //DDD if (targetAttribute->GetUsed() and targetAttribute->GetDerivationRule() == NULL and + //DDD odOutputAttributeNames.Lookup(targetAttribute->GetName()) == NULL) if (targetAttribute->GetDerivationRule() == NULL and odOutputAttributeNames.Lookup(targetAttribute->GetName()) == NULL) { @@ -991,6 +993,33 @@ void KWDRRelationCreationRule::BuildAllUsedAttributes(const KWAttribute* derived // Attribut suivant kwcTargetClass->GetNextAttribute(targetAttribute); } + + //DDD On doit integrer tous les attribut Used de la classe source (BUG EN COURS) + //DDD Sinon, on a des incoherences entre la classe source et cible lors des calculs + //DDD de classe phyisuqe dans les Database + // Parcours des attributs utilises de la classe source + sourceAttribute = kwcSourceClass->GetHeadAttribute(); + while (sourceAttribute != NULL) + { + if (sourceAttribute->GetUsed()) + { + // Analyse de l'attribut si necessaire + if (nkdAllUsedAttributes->Lookup(sourceAttribute) == NULL) + { + // Memorisation de l'attribut dans le dictionnaire + nkdAllUsedAttributes->SetAt(sourceAttribute, sourceAttribute); + + // Acces a la regle d'attribut ou de bloc + sourceAttributeRule = sourceAttribute->GetAnyDerivationRule(); + if (sourceAttributeRule != NULL) + sourceAttributeRule->BuildAllUsedAttributes(sourceAttribute, + nkdAllUsedAttributes); + } + } + + // Attribut suivant + kwcSourceClass->GetNextAttribute(sourceAttribute); + } } } diff --git a/src/Learning/MODL/MODL.cpp b/src/Learning/MODL/MODL.cpp index 5fce36b63..7ff7308c9 100644 --- a/src/Learning/MODL/MODL.cpp +++ b/src/Learning/MODL/MODL.cpp @@ -38,8 +38,7 @@ int main(int argc, char** argv) // Choix du repertoire de lancement pour le debugage sous Windows (a commenter apres fin du debug) // SetWindowsDebugDir("Standard", "IrisLight"); // SetWindowsDebugDir("Standard", "IrisU2D"); - // SetWindowsDebugDir("z_TableCreationRules", "NoKeyInCreatedSnowflake"); - SetWindowsDebugDir("z_TableCreationRules", "TableNoKey"); + SetWindowsDebugDir("z_TableCreationRules", "TableViewBasic"); // Parametrage des logs memoires depuis les variables d'environnement, pris en compte dans KWLearningProject // KhiopsMemStatsLogFileName, KhiopsMemStatsLogFrequency, KhiopsMemStatsLogToCollect