mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-12 23:14:18 +01:00
Optimization of SQL queries: fixed two issues (SELECT to track object linked to... and SELECT ExternalUser)
SVN:trunk[2496]
This commit is contained in:
@@ -1121,13 +1121,20 @@ class QueryBuilderExpressions
|
||||
protected $m_aSelectExpr;
|
||||
protected $m_aGroupByExpr;
|
||||
protected $m_aJoinFields;
|
||||
protected $m_aClassIds;
|
||||
|
||||
public function __construct($oCondition, $aGroupByExpr = null)
|
||||
public function __construct($oSearch, $aGroupByExpr = null)
|
||||
{
|
||||
$this->m_oConditionExpr = $oCondition;
|
||||
$this->m_oConditionExpr = $oSearch->GetCriteria();
|
||||
$this->m_aSelectExpr = array();
|
||||
$this->m_aGroupByExpr = $aGroupByExpr;
|
||||
$this->m_aJoinFields = array();
|
||||
|
||||
$this->m_aClassIds = array();
|
||||
foreach($oSearch->GetJoinedClasses() as $sClassAlias => $sClass)
|
||||
{
|
||||
$this->m_aClassIds[$sClassAlias] = new FieldExpression('id', $sClassAlias);
|
||||
}
|
||||
}
|
||||
|
||||
public function GetSelect()
|
||||
@@ -1166,6 +1173,20 @@ class QueryBuilderExpressions
|
||||
array_push($this->m_aJoinFields, $oExpression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tables representing the queried objects
|
||||
* Could be further optimized: when the first join is an outer join, then the rest can be omitted
|
||||
*/
|
||||
public function GetMandatoryTables(&$aTables = null)
|
||||
{
|
||||
if (is_null($aTables)) $aTables = array();
|
||||
|
||||
foreach($this->m_aClassIds as $sClass => $oExpression)
|
||||
{
|
||||
$oExpression->CollectUsedParents($aTables);
|
||||
}
|
||||
}
|
||||
|
||||
public function GetUnresolvedFields($sAlias, &$aUnresolved)
|
||||
{
|
||||
$this->m_oConditionExpr->GetUnresolvedFields($sAlias, $aUnresolved);
|
||||
@@ -1204,6 +1225,11 @@ class QueryBuilderExpressions
|
||||
{
|
||||
$this->m_aJoinFields[$index] = $oExpression->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
|
||||
}
|
||||
|
||||
foreach($this->m_aClassIds as $sClass => $oExpression)
|
||||
{
|
||||
$this->m_aClassIds[$sClass] = $oExpression->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
|
||||
}
|
||||
}
|
||||
|
||||
public function RenameParam($sOldName, $sNewName)
|
||||
|
||||
@@ -2290,7 +2290,8 @@ abstract class MetaModel
|
||||
// Simplify the query if just getting the count
|
||||
$oSelect->SetSelect(array());
|
||||
}
|
||||
$oSelect->OptimizeJoins();
|
||||
$oBuild->m_oQBExpressions->GetMandatoryTables($aMandatoryTables);
|
||||
$oSelect->OptimizeJoins($aMandatoryTables);
|
||||
}
|
||||
|
||||
$oKPI->ComputeStats('MakeQuery (select)', $sOqlQuery);
|
||||
@@ -2504,7 +2505,6 @@ abstract class MetaModel
|
||||
{
|
||||
// default to the whole list of attributes + the very std id/finalclass
|
||||
$oBuild->m_oQBExpressions->AddSelect($sClassAlias.'id', new FieldExpression('id', $sClassAlias));
|
||||
|
||||
if (is_null($aAttToLoad) || !array_key_exists($sClassAlias, $aAttToLoad))
|
||||
{
|
||||
$aAttList = self::ListAttributeDefs($sClass);
|
||||
@@ -2798,19 +2798,15 @@ abstract class MetaModel
|
||||
|
||||
// 1/a - Get the key and friendly name
|
||||
//
|
||||
// We need one pkey to be the key, let's take the one corresponding to the root class
|
||||
// (used to be based on the leaf, then moved to the root class... now back to the leaf for optimization concerns)
|
||||
// We need one pkey to be the key, let's take the first one available
|
||||
$oSelectedIdField = null;
|
||||
if ($sTableClass == $sTargetClass)
|
||||
{
|
||||
$oIdField = new FieldExpressionResolved(self::DBGetKey($sTableClass), $sTableAlias);
|
||||
$aTranslation[$sTargetAlias]['id'] = $oIdField;
|
||||
$oIdField = new FieldExpressionResolved(self::DBGetKey($sTableClass), $sTableAlias);
|
||||
$aTranslation[$sTargetAlias]['id'] = $oIdField;
|
||||
|
||||
if ($bIsOnQueriedClass)
|
||||
{
|
||||
// Add this field to the list of queried fields (required for the COUNT to work fine)
|
||||
$oSelectedIdField = $oIdField;
|
||||
}
|
||||
if ($bIsOnQueriedClass)
|
||||
{
|
||||
// Add this field to the list of queried fields (required for the COUNT to work fine)
|
||||
$oSelectedIdField = $oIdField;
|
||||
}
|
||||
|
||||
// 1/b - Get the other attributes
|
||||
|
||||
@@ -35,7 +35,7 @@ class QueryBuilderContext
|
||||
public function __construct($oFilter, $aModifierProperties, $aGroupByExpr = null)
|
||||
{
|
||||
$this->m_oRootFilter = $oFilter;
|
||||
$this->m_oQBExpressions = new QueryBuilderExpressions($oFilter->GetCriteria(), $aGroupByExpr);
|
||||
$this->m_oQBExpressions = new QueryBuilderExpressions($oFilter, $aGroupByExpr);
|
||||
|
||||
$this->m_aClassAliases = $oFilter->GetJoinedClasses();
|
||||
$this->m_aTableAliases = array();
|
||||
|
||||
@@ -597,12 +597,12 @@ class SQLQuery
|
||||
return $this->m_sTableAlias;
|
||||
}
|
||||
|
||||
public function OptimizeJoins($aUsedTables = null)
|
||||
public function OptimizeJoins($aUsedTables, $bTopCall = true)
|
||||
{
|
||||
if (is_null($aUsedTables))
|
||||
if ($bTopCall)
|
||||
{
|
||||
// Top call: build the list of tables absolutely required to perform the query
|
||||
$aUsedTables = $this->CollectUsedTables();
|
||||
// Top call: complete the list of tables absolutely required to perform the right query
|
||||
$this->CollectUsedTables($aUsedTables);
|
||||
}
|
||||
|
||||
$aToDiscard = array();
|
||||
@@ -610,7 +610,7 @@ class SQLQuery
|
||||
{
|
||||
$oSQLQuery = $aJoinInfo["select"];
|
||||
$sTableAlias = $oSQLQuery->GetTableAlias();
|
||||
if ($oSQLQuery->OptimizeJoins($aUsedTables) && !array_key_exists($sTableAlias, $aUsedTables))
|
||||
if ($oSQLQuery->OptimizeJoins($aUsedTables, false) && !array_key_exists($sTableAlias, $aUsedTables))
|
||||
{
|
||||
$aToDiscard[] = $i;
|
||||
}
|
||||
@@ -623,29 +623,24 @@ class SQLQuery
|
||||
return (count($this->m_aJoinSelects) == 0);
|
||||
}
|
||||
|
||||
protected function CollectUsedTables(&$aTables = null)
|
||||
protected function CollectUsedTables(&$aTables)
|
||||
{
|
||||
if (is_null($aTables))
|
||||
$this->m_oConditionExpr->CollectUsedParents($aTables);
|
||||
foreach($this->m_aFields as $sFieldAlias => $oField)
|
||||
{
|
||||
$aTables = array();
|
||||
|
||||
$this->m_oConditionExpr->CollectUsedParents($aTables);
|
||||
foreach($this->m_aFields as $sFieldAlias => $oField)
|
||||
$oField->CollectUsedParents($aTables);
|
||||
}
|
||||
if ($this->m_aGroupBy)
|
||||
{
|
||||
foreach($this->m_aGroupBy as $sAlias => $oExpression)
|
||||
{
|
||||
$oField->CollectUsedParents($aTables);
|
||||
}
|
||||
if ($this->m_aGroupBy)
|
||||
{
|
||||
foreach($this->m_aGroupBy as $sAlias => $oExpression)
|
||||
{
|
||||
$oExpression->CollectUsedParents($aTables);
|
||||
}
|
||||
}
|
||||
if (!is_null($this->m_oSelectedIdField))
|
||||
{
|
||||
$this->m_oSelectedIdField->CollectUsedParents($aTables);
|
||||
$oExpression->CollectUsedParents($aTables);
|
||||
}
|
||||
}
|
||||
if (!is_null($this->m_oSelectedIdField))
|
||||
{
|
||||
$this->m_oSelectedIdField->CollectUsedParents($aTables);
|
||||
}
|
||||
|
||||
foreach ($this->m_aJoinSelects as $i => $aJoinInfo)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user