diff --git a/core/dbobjectsearch.class.php b/core/dbobjectsearch.class.php index 26acfa5af..7a3d4294a 100644 --- a/core/dbobjectsearch.class.php +++ b/core/dbobjectsearch.class.php @@ -1,5 +1,5 @@ m_aReferencedBy[$this->GetClass()][$sExtKeyAttCode][$iOperatorCode])) { - // Optimization - fold sibling query - $oRemoteFilter = $oFilter->m_aReferencedBy[$this->GetClass()][$sExtKeyAttCode][$iOperatorCode][0]; - $aAliasTranslation = array(); - $this->MergeWith_InNamespace($oRemoteFilter, $this->m_aClasses, $aAliasTranslation); - unset($oFilter->m_aReferencedBy[$this->GetClass()][$sExtKeyAttCode][$iOperatorCode]); - $this->m_oSearchCondition = $this->m_oSearchCondition->Translate($aAliasTranslation, false, false); - $this->UpdateRealiasingMap($aRealiasingMap, $aAliasTranslation); + foreach ($oFilter->m_aReferencedBy[$this->GetClass()][$sExtKeyAttCode][$iOperatorCode] as $oRemoteFilter) + { + if ($this->GetClass() == $oRemoteFilter->GetClass()) + { + // Optimization - fold sibling query + $aAliasTranslation = array(); + $this->MergeWith_InNamespace($oRemoteFilter, $this->m_aClasses, $aAliasTranslation); + unset($oFilter->m_aReferencedBy[$this->GetClass()][$sExtKeyAttCode][$iOperatorCode]); + $this->m_oSearchCondition = $this->m_oSearchCondition->Translate($aAliasTranslation, false, false); + $this->UpdateRealiasingMap($aRealiasingMap, $aAliasTranslation); + } + } } } $this->RecomputeClassList($this->m_aClasses); @@ -767,12 +772,20 @@ class DBObjectSearch extends DBSearch // Find the node on which the new tree must be attached (most of the time it is "this") $oReceivingFilter = $this->GetNode($this->GetClassAlias()); + $bMerged = false; if (ENABLE_OPT && isset($oReceivingFilter->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode])) { - $oExisting = $oReceivingFilter->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode][0]; - $oExisting->MergeWith_InNamespace($oFilter, $oExisting->m_aClasses, $aAliasTranslation); + foreach ($oReceivingFilter->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode] as $oExisting) + { + if ($oExisting->GetClass() == $oFilter->GetClass()) + { + $oExisting->MergeWith_InNamespace($oFilter, $oExisting->m_aClasses, $aAliasTranslation); + $bMerged = true; + break; + } + } } - else + if (!$bMerged) { $oFilter->AddToNamespace($aClassAliases, $aAliasTranslation); $oReceivingFilter->m_aPointingTo[$sExtKeyAttCode][$iOperatorCode][] = $oFilter; @@ -814,13 +827,18 @@ class DBObjectSearch extends DBSearch { if (isset($oFilter->m_aPointingTo[$sForeignExtKeyAttCode][$iOperatorCode])) { - // Optimization - fold sibling query - $oRemoteFilter = $oFilter->m_aPointingTo[$sForeignExtKeyAttCode][$iOperatorCode][0]; - $aAliasTranslation = array(); - $this->MergeWith_InNamespace($oRemoteFilter, $this->m_aClasses, $aAliasTranslation); - unset($oFilter->m_aPointingTo[$sForeignExtKeyAttCode][$iOperatorCode]); - $this->m_oSearchCondition = $this->m_oSearchCondition->Translate($aAliasTranslation, false, false); - $this->UpdateRealiasingMap($aRealiasingMap, $aAliasTranslation); + foreach ($oFilter->m_aPointingTo[$sForeignExtKeyAttCode][$iOperatorCode] as $oRemoteFilter) + { + if ($this->GetClass() == $oRemoteFilter->GetClass()) + { + // Optimization - fold sibling query + $aAliasTranslation = array(); + $this->MergeWith_InNamespace($oRemoteFilter, $this->m_aClasses, $aAliasTranslation); + unset($oFilter->m_aPointingTo[$sForeignExtKeyAttCode][$iOperatorCode]); + $this->m_oSearchCondition = $this->m_oSearchCondition->Translate($aAliasTranslation, false, false); + $this->UpdateRealiasingMap($aRealiasingMap, $aAliasTranslation); + } + } } } $this->RecomputeClassList($this->m_aClasses); @@ -834,12 +852,20 @@ class DBObjectSearch extends DBSearch // Find the node on which the new tree must be attached (most of the time it is "this") $oReceivingFilter = $this->GetNode($this->GetClassAlias()); + $bMerged = false; if (ENABLE_OPT && isset($oReceivingFilter->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode][$iOperatorCode])) { - $oExisting = $oReceivingFilter->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode][$iOperatorCode][0]; - $oExisting->MergeWith_InNamespace($oFilter, $oExisting->m_aClasses, $aAliasTranslation); + foreach ($oReceivingFilter->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode][$iOperatorCode] as $oExisting) + { + if ($oExisting->GetClass() == $oFilter->GetClass()) + { + $oExisting->MergeWith_InNamespace($oFilter, $oExisting->m_aClasses, $aAliasTranslation); + $bMerged = true; + break; + } + } } - else + if (!$bMerged) { $oFilter->AddToNamespace($aClassAliases, $aAliasTranslation); $oReceivingFilter->m_aReferencedBy[$sForeignClass][$sForeignExtKeyAttCode][$iOperatorCode][] = $oFilter; diff --git a/test/testlist.inc.php b/test/testlist.inc.php index 8fa08ca55..20694f37c 100644 --- a/test/testlist.inc.php +++ b/test/testlist.inc.php @@ -5309,7 +5309,7 @@ class TestIntersectOptimization5 extends TestBizModel protected function DoExecute() { - echo "
Referenced by...: ".htmlentities($oSearchB->ToOQL(), ENT_QUOTES, 'UTF-8')."
\n"; + echo "Pointing to...: ".htmlentities($oSearchB->ToOQL(), ENT_QUOTES, 'UTF-8')."
\n"; CMDBSource::TestQuery($oSearchB->MakeSelectQuery()); echo "Successfully tested the SQL query.
\n"; } @@ -5454,3 +5454,67 @@ class TestImplicitAlias extends TestBizModel } } } + +class TestIntersectNotOptimized extends TestBizModel +{ + static public function GetName() + { + return 'Internal query NOT optimized'; + } + + static public function GetDescription() + { + return '(N.718) Sometimes, the optimization CANNOT be performed because merging two different classes (same branch) is not implemented'; + } + + protected function DoExecute() + { + echo "Intersect: ".htmlentities($oIntersect->ToOQL(), ENT_QUOTES, 'UTF-8')."
\n"; + CMDBSource::TestQuery($oIntersect->MakeSelectQuery()); + echo "Successfully tested the SQL query.
\n"; + + echo "Intersect: ".htmlentities($oIntersect->ToOQL(), ENT_QUOTES, 'UTF-8')."
\n"; + CMDBSource::TestQuery($oIntersect->MakeSelectQuery()); + echo "Successfully tested the SQL query.
\n"; + + echo "Pointing to...: ".htmlentities($oSearchB->ToOQL(), ENT_QUOTES, 'UTF-8')."
\n"; + CMDBSource::TestQuery($oSearchB->MakeSelectQuery()); + echo "Successfully tested the SQL query.
\n"; + + echo "Referenced by...: ".htmlentities($oSearchA->ToOQL(), ENT_QUOTES, 'UTF-8')."
\n"; + CMDBSource::TestQuery($oSearchA->MakeSelectQuery()); + echo "Successfully tested the SQL query.
\n"; + } +}