mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-24 11:08:45 +02:00
Dashboard: optimized group by (done by MySQL) + proto of a group by on 2 dimensions
SVN:trunk[2041]
This commit is contained in:
@@ -951,12 +951,14 @@ class QueryBuilderExpressions
|
||||
{
|
||||
protected $m_oConditionExpr;
|
||||
protected $m_aSelectExpr;
|
||||
protected $m_aGroupByExpr;
|
||||
protected $m_aJoinFields;
|
||||
|
||||
public function __construct($oCondition)
|
||||
public function __construct($oCondition, $aGroupByExpr = null)
|
||||
{
|
||||
$this->m_oConditionExpr = $oCondition;
|
||||
$this->m_aSelectExpr = array();
|
||||
$this->m_aGroupByExpr = $aGroupByExpr;
|
||||
$this->m_aJoinFields = array();
|
||||
}
|
||||
|
||||
@@ -965,6 +967,11 @@ class QueryBuilderExpressions
|
||||
return $this->m_aSelectExpr;
|
||||
}
|
||||
|
||||
public function GetGroupBy()
|
||||
{
|
||||
return $this->m_aGroupByExpr;
|
||||
}
|
||||
|
||||
public function GetCondition()
|
||||
{
|
||||
return $this->m_oConditionExpr;
|
||||
@@ -998,6 +1005,13 @@ class QueryBuilderExpressions
|
||||
{
|
||||
$oExpr->GetUnresolvedFields($sAlias, $aUnresolved);
|
||||
}
|
||||
if ($this->m_aGroupByExpr)
|
||||
{
|
||||
foreach($this->m_aGroupByExpr as $sColAlias => $oExpr)
|
||||
{
|
||||
$oExpr->GetUnresolvedFields($sAlias, $aUnresolved);
|
||||
}
|
||||
}
|
||||
foreach($this->m_aJoinFields as $oExpression)
|
||||
{
|
||||
$oExpression->GetUnresolvedFields($sAlias, $aUnresolved);
|
||||
@@ -1011,6 +1025,13 @@ class QueryBuilderExpressions
|
||||
{
|
||||
$this->m_aSelectExpr[$sColAlias] = $oExpr->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
|
||||
}
|
||||
if ($this->m_aGroupByExpr)
|
||||
{
|
||||
foreach($this->m_aGroupByExpr as $sColAlias => $oExpr)
|
||||
{
|
||||
$this->m_aGroupByExpr[$sColAlias] = $oExpr->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
|
||||
}
|
||||
}
|
||||
foreach($this->m_aJoinFields as $index => $oExpression)
|
||||
{
|
||||
$this->m_aJoinFields[$index] = $oExpression->Translate($aTranslationData, $bMatchAll, $bMarkFieldsAsResolved);
|
||||
@@ -1024,6 +1045,13 @@ class QueryBuilderExpressions
|
||||
{
|
||||
$this->m_aSelectExpr[$sColAlias] = $oExpr->RenameParam($sOldName, $sNewName);
|
||||
}
|
||||
if ($this->m_aGroupByExpr)
|
||||
{
|
||||
foreach($this->m_aGroupByExpr as $sColAlias => $oExpr)
|
||||
{
|
||||
$this->m_aGroupByExpr[$sColAlias] = $oExpr->RenameParam($sOldName, $sNewName);
|
||||
}
|
||||
}
|
||||
foreach($this->m_aJoinFields as $index => $oExpression)
|
||||
{
|
||||
$this->m_aJoinFields[$index] = $oExpression->RenameParam($sOldName, $sNewName);
|
||||
|
||||
@@ -1933,7 +1933,81 @@ abstract class MetaModel
|
||||
return $aScalarArgs;
|
||||
}
|
||||
|
||||
public static function MakeGroupByQuery(DBObjectSearch $oFilter, $aArgs, $aGroupByExpr)
|
||||
{
|
||||
$aAttToLoad = array();
|
||||
$oSelect = self::MakeSelectStructure($oFilter, array(), $aArgs, $aAttToLoad, null, 0, 0, false, $aGroupByExpr);
|
||||
|
||||
$aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams());
|
||||
try
|
||||
{
|
||||
$sRes = $oSelect->RenderGroupBy($aScalarArgs);
|
||||
}
|
||||
catch (MissingQueryArgument $e)
|
||||
{
|
||||
// Add some information...
|
||||
$e->addInfo('OQL', $sOqlQuery);
|
||||
throw $e;
|
||||
}
|
||||
return $sRes;
|
||||
}
|
||||
|
||||
|
||||
public static function MakeSelectQuery(DBObjectSearch $oFilter, $aOrderBy = array(), $aArgs = array(), $aAttToLoad = null, $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0, $bGetCount = false)
|
||||
{
|
||||
// Check the order by specification, and prefix with the class alias
|
||||
// and make sure that the ordering columns are going to be selected
|
||||
//
|
||||
$aOrderSpec = array();
|
||||
foreach ($aOrderBy as $sFieldAlias => $bAscending)
|
||||
{
|
||||
if ($sFieldAlias != 'id')
|
||||
{
|
||||
MyHelpers::CheckValueInArray('field name in ORDER BY spec', $sFieldAlias, self::GetAttributesList($oFilter->GetFirstJoinedClass()));
|
||||
}
|
||||
if (!is_bool($bAscending))
|
||||
{
|
||||
throw new CoreException("Wrong direction in ORDER BY spec, found '$bAscending' and expecting a boolean value");
|
||||
}
|
||||
$sFirstClassAlias = $oFilter->GetFirstJoinedClassAlias();
|
||||
if (self::IsValidAttCode($oFilter->GetClass(), $sFieldAlias))
|
||||
{
|
||||
$oAttDef = self::GetAttributeDef($oFilter->GetClass(), $sFieldAlias);
|
||||
foreach($oAttDef->GetOrderBySQLExpressions($sFirstClassAlias) as $sSQLExpression)
|
||||
{
|
||||
$aOrderSpec[$sSQLExpression] = $bAscending;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aOrderSpec['`'.$sFirstClassAlias.$sFieldAlias.'`'] = $bAscending;
|
||||
}
|
||||
|
||||
// Make sure that the columns used for sorting are present in the loaded columns
|
||||
if (!is_null($aAttToLoad) && !isset($aAttToLoad[$sFirstClassAlias][$sFieldAlias]))
|
||||
{
|
||||
$aAttToLoad[$sFirstClassAlias][$sFieldAlias] = MetaModel::GetAttributeDef($oFilter->GetFirstJoinedClass(), $sFieldAlias);
|
||||
}
|
||||
}
|
||||
|
||||
$oSelect = self::MakeSelectStructure($oFilter, $aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount);
|
||||
|
||||
$aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams());
|
||||
try
|
||||
{
|
||||
$sRes = $oSelect->RenderSelect($aOrderSpec, $aScalarArgs, $iLimitCount, $iLimitStart, $bGetCount);
|
||||
}
|
||||
catch (MissingQueryArgument $e)
|
||||
{
|
||||
// Add some information...
|
||||
$e->addInfo('OQL', $sOqlQuery);
|
||||
throw $e;
|
||||
}
|
||||
return $sRes;
|
||||
}
|
||||
|
||||
|
||||
protected static function MakeSelectStructure(DBObjectSearch $oFilter, $aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr = null)
|
||||
{
|
||||
// Hide objects that are not visible to the current user
|
||||
//
|
||||
@@ -1984,6 +2058,13 @@ abstract class MetaModel
|
||||
$sRawId = $sOqlQuery.'|'.implode(',', array_keys($aAttributes));
|
||||
}
|
||||
}
|
||||
if (!is_null($aGroupByExpr))
|
||||
{
|
||||
foreach($aGroupByExpr as $sAlias => $oExpr)
|
||||
{
|
||||
$sRawId = 'g:'.$sAlias.'!'.$oExpr->Render();
|
||||
}
|
||||
}
|
||||
$sOqlId = md5($sRawId);
|
||||
}
|
||||
else
|
||||
@@ -2029,48 +2110,25 @@ abstract class MetaModel
|
||||
}
|
||||
}
|
||||
|
||||
// Check the order by specification, and prefix with the class alias
|
||||
// and make sure that the ordering columns are going to be selected
|
||||
//
|
||||
$aOrderSpec = array();
|
||||
foreach ($aOrderBy as $sFieldAlias => $bAscending)
|
||||
{
|
||||
if ($sFieldAlias != 'id')
|
||||
{
|
||||
MyHelpers::CheckValueInArray('field name in ORDER BY spec', $sFieldAlias, self::GetAttributesList($oFilter->GetFirstJoinedClass()));
|
||||
}
|
||||
if (!is_bool($bAscending))
|
||||
{
|
||||
throw new CoreException("Wrong direction in ORDER BY spec, found '$bAscending' and expecting a boolean value");
|
||||
}
|
||||
$sFirstClassAlias = $oFilter->GetFirstJoinedClassAlias();
|
||||
if (self::IsValidAttCode($oFilter->GetClass(), $sFieldAlias))
|
||||
{
|
||||
$oAttDef = self::GetAttributeDef($oFilter->GetClass(), $sFieldAlias);
|
||||
foreach($oAttDef->GetOrderBySQLExpressions($sFirstClassAlias) as $sSQLExpression)
|
||||
{
|
||||
$aOrderSpec[$sSQLExpression] = $bAscending;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aOrderSpec['`'.$sFirstClassAlias.$sFieldAlias.'`'] = $bAscending;
|
||||
}
|
||||
|
||||
// Make sure that the columns used for sorting are present in the loaded columns
|
||||
if (!is_null($aAttToLoad) && !isset($aAttToLoad[$sFirstClassAlias][$sFieldAlias]))
|
||||
{
|
||||
$aAttToLoad[$sFirstClassAlias][$sFieldAlias] = MetaModel::GetAttributeDef($oFilter->GetFirstJoinedClass(), $sFieldAlias);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($oSelect))
|
||||
{
|
||||
$oBuild = new QueryBuilderContext($oFilter, $aModifierProperties);
|
||||
$oBuild = new QueryBuilderContext($oFilter, $aModifierProperties, $aGroupByExpr);
|
||||
|
||||
$oKPI = new ExecutionKPI();
|
||||
$oSelect = self::MakeQuery($oBuild, $oFilter, $aAttToLoad, array(), true /* main query */);
|
||||
$oSelect->SetCondition($oBuild->m_oQBExpressions->GetCondition());
|
||||
$oSelect->SetSourceOQL($sOqlQuery);
|
||||
if ($aGroupByExpr)
|
||||
{
|
||||
$aCols = $oBuild->m_oQBExpressions->GetGroupBy();
|
||||
$oSelect->SetGroupBy($aCols);
|
||||
$oSelect->SetSelect($aCols);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oSelect->SetSelect($oBuild->m_oQBExpressions->GetSelect());
|
||||
}
|
||||
|
||||
$oKPI->ComputeStats('MakeQuery (select)', $sOqlQuery);
|
||||
|
||||
if (self::$m_bQueryCacheEnabled)
|
||||
@@ -2101,22 +2159,6 @@ abstract class MetaModel
|
||||
$oSelect->AddInnerJoin($oSelectExt, 'id', $aExtendedDataSpec['join_key'] /*, $sTableAlias*/);
|
||||
}
|
||||
|
||||
// Go
|
||||
//
|
||||
$aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams());
|
||||
|
||||
try
|
||||
{
|
||||
$sRes = $oSelect->RenderSelect($aOrderSpec, $aScalarArgs, $iLimitCount, $iLimitStart, $bGetCount);
|
||||
//echo "<p>MakeQuery: $sRes</p>";
|
||||
}
|
||||
catch (MissingQueryArgument $e)
|
||||
{
|
||||
// Add some information...
|
||||
$e->addInfo('OQL', $sOqlQuery);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if (self::$m_bTraceQueries)
|
||||
{
|
||||
$sQueryId = md5($sRes);
|
||||
@@ -2140,7 +2182,7 @@ abstract class MetaModel
|
||||
}
|
||||
}
|
||||
|
||||
return $sRes;
|
||||
return $oSelect;
|
||||
}
|
||||
|
||||
public static function ShowQueryTrace()
|
||||
@@ -2205,6 +2247,8 @@ abstract class MetaModel
|
||||
$aModifierProperties = self::MakeModifierProperties($oFilter);
|
||||
$oBuild = new QueryBuilderContext($oFilter, $aModifierProperties);
|
||||
$oSelect = self::MakeQuery($oBuild, $oFilter, null, array(), true /* main query */);
|
||||
$oSelect->SetCondition($oBuild->m_oQBExpressions->GetCondition());
|
||||
$oSelect->SetSelect($oBuild->m_oQBExpressions->GetSelect());
|
||||
$aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams());
|
||||
return $oSelect->RenderDelete($aScalarArgs);
|
||||
}
|
||||
@@ -2215,11 +2259,13 @@ abstract class MetaModel
|
||||
$aModifierProperties = self::MakeModifierProperties($oFilter);
|
||||
$oBuild = new QueryBuilderContext($oFilter, $aModifierProperties);
|
||||
$oSelect = self::MakeQuery($oBuild, $oFilter, null, $aValues, true /* main query */);
|
||||
$oSelect->SetCondition($oBuild->m_oQBExpressions->GetCondition());
|
||||
$oSelect->SetSelect($oBuild->m_oQBExpressions->GetSelect());
|
||||
$aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams());
|
||||
return $oSelect->RenderUpdate($aScalarArgs);
|
||||
}
|
||||
|
||||
private static function MakeQuery(&$oBuild, DBObjectSearch $oFilter, $aAttToLoad = null, $aValues = array(), $bIsMainQuery = false)
|
||||
private static function MakeQuery(&$oBuild, DBObjectSearch $oFilter, $aAttToLoad = null, $aValues = array(), $bIsMainQueryUNUSED = false)
|
||||
{
|
||||
// Note: query class might be different than the class of the filter
|
||||
// -> this occurs when we are linking our class to an external class (referenced by, or pointing to)
|
||||
@@ -2442,14 +2488,6 @@ abstract class MetaModel
|
||||
}
|
||||
}
|
||||
|
||||
// Translate the conditions... and go
|
||||
//
|
||||
if ($bIsMainQuery)
|
||||
{
|
||||
$oSelectBase->SetCondition($oBuild->m_oQBExpressions->GetCondition());
|
||||
$oSelectBase->SetSelect($oBuild->m_oQBExpressions->GetSelect());
|
||||
}
|
||||
|
||||
// That's all... cross fingers and we'll get some working query
|
||||
|
||||
//MyHelpers::var_dump_html($oSelectBase, true);
|
||||
|
||||
@@ -32,10 +32,10 @@ class QueryBuilderContext
|
||||
|
||||
public $m_oQBExpressions;
|
||||
|
||||
public function __construct($oFilter, $aModifierProperties)
|
||||
public function __construct($oFilter, $aModifierProperties, $aGroupByExpr = null)
|
||||
{
|
||||
$this->m_oRootFilter = $oFilter;
|
||||
$this->m_oQBExpressions = new QueryBuilderExpressions($oFilter->GetCriteria());
|
||||
$this->m_oQBExpressions = new QueryBuilderExpressions($oFilter->GetCriteria(), $aGroupByExpr);
|
||||
|
||||
$this->m_aClassAliases = $oFilter->GetJoinedClasses();
|
||||
$this->m_aTableAliases = array();
|
||||
|
||||
@@ -41,6 +41,7 @@ class SQLQuery
|
||||
private $m_sTable = '';
|
||||
private $m_sTableAlias = '';
|
||||
private $m_aFields = array();
|
||||
private $m_aGroupBy = array();
|
||||
private $m_oConditionExpr = null;
|
||||
private $m_bToDelete = true; // The current table must be listed for deletion ?
|
||||
private $m_aValues = array(); // Values to set in case of an update query
|
||||
@@ -62,6 +63,7 @@ class SQLQuery
|
||||
$this->m_sTable = $sTable;
|
||||
$this->m_sTableAlias = $sTableAlias;
|
||||
$this->m_aFields = $aFields;
|
||||
$this->m_aGroupBy = null;
|
||||
$this->m_oConditionExpr = null;
|
||||
$this->m_bToDelete = $bToDelete;
|
||||
$this->m_aValues = $aValues;
|
||||
@@ -125,11 +127,12 @@ class SQLQuery
|
||||
}
|
||||
$aFrom = array();
|
||||
$aFields = array();
|
||||
$aGroupBy = array();
|
||||
$oCondition = null;
|
||||
$aDelTables = array();
|
||||
$aSetValues = array();
|
||||
$aSelectedIdFields = array();
|
||||
$this->privRender($aFrom, $aFields, $oCondition, $aDelTables, $aSetValues, $aSelectedIdFields);
|
||||
$this->privRender($aFrom, $aFields, $aGroupBy, $oCondition, $aDelTables, $aSetValues, $aSelectedIdFields);
|
||||
echo "From ...<br/>\n";
|
||||
echo "<pre style=\"font-size: smaller;\">\n";
|
||||
print_r($aFrom);
|
||||
@@ -141,6 +144,11 @@ class SQLQuery
|
||||
$this->m_aFields = $aExpressions;
|
||||
}
|
||||
|
||||
public function SetGroupBy($aExpressions)
|
||||
{
|
||||
$this->m_aGroupBy = $aExpressions;
|
||||
}
|
||||
|
||||
public function SetCondition($oConditionExpr)
|
||||
{
|
||||
$this->m_oConditionExpr = $oConditionExpr;
|
||||
@@ -235,11 +243,12 @@ class SQLQuery
|
||||
// The goal will be to complete the list as we build the Joins
|
||||
$aFrom = array();
|
||||
$aFields = array();
|
||||
$aGroupBy = arry();
|
||||
$oCondition = null;
|
||||
$aDelTables = array();
|
||||
$aSetValues = array();
|
||||
$aSelectedIdFields = array();
|
||||
$this->privRender($aFrom, $aFields, $oCondition, $aDelTables, $aSetValues, $aSelectedIdFields);
|
||||
$this->privRender($aFrom, $aFields, $aGroupBy, $oCondition, $aDelTables, $aSetValues, $aSelectedIdFields);
|
||||
|
||||
// Target: DELETE myAlias1, myAlias2 FROM t1 as myAlias1, t2 as myAlias2, t3 as topreserve WHERE ...
|
||||
|
||||
@@ -270,11 +279,12 @@ class SQLQuery
|
||||
// The goal will be to complete the list as we build the Joins
|
||||
$aFrom = array();
|
||||
$aFields = array();
|
||||
$aGroupBy = array();
|
||||
$oCondition = null;
|
||||
$aDelTables = array();
|
||||
$aSetValues = array();
|
||||
$aSelectedIdFields = array();
|
||||
$this->privRender($aFrom, $aFields, $oCondition, $aDelTables, $aSetValues, $aSelectedIdFields);
|
||||
$this->privRender($aFrom, $aFields, $aGroupBy, $oCondition, $aDelTables, $aSetValues, $aSelectedIdFields);
|
||||
$sFrom = self::ClauseFrom($aFrom);
|
||||
$sValues = self::ClauseValues($aSetValues);
|
||||
$sWhere = self::ClauseWhere($oCondition, $aArgs);
|
||||
@@ -287,11 +297,12 @@ class SQLQuery
|
||||
// The goal will be to complete the lists as we build the Joins
|
||||
$aFrom = array();
|
||||
$aFields = array();
|
||||
$aGroupBy = array();
|
||||
$oCondition = null;
|
||||
$aDelTables = array();
|
||||
$aSetValues = array();
|
||||
$aSelectedIdFields = array();
|
||||
$this->privRender($aFrom, $aFields, $oCondition, $aDelTables, $aSetValues, $aSelectedIdFields);
|
||||
$this->privRender($aFrom, $aFields, $aGroupBy, $oCondition, $aDelTables, $aSetValues, $aSelectedIdFields);
|
||||
|
||||
$sFrom = self::ClauseFrom($aFrom);
|
||||
$sWhere = self::ClauseWhere($oCondition, $aArgs);
|
||||
@@ -328,6 +339,27 @@ class SQLQuery
|
||||
return $sSQL;
|
||||
}
|
||||
|
||||
// Interface, build the SQL query
|
||||
public function RenderGroupBy($aArgs = array())
|
||||
{
|
||||
// The goal will be to complete the lists as we build the Joins
|
||||
$aFrom = array();
|
||||
$aFields = array();
|
||||
$aGroupBy = array();
|
||||
$oCondition = null;
|
||||
$aDelTables = array();
|
||||
$aSetValues = array();
|
||||
$aSelectedIdFields = array();
|
||||
$this->privRender($aFrom, $aFields, $aGroupBy, $oCondition, $aDelTables, $aSetValues, $aSelectedIdFields);
|
||||
|
||||
$sSelect = self::ClauseSelect($aFields);
|
||||
$sFrom = self::ClauseFrom($aFrom);
|
||||
$sWhere = self::ClauseWhere($oCondition, $aArgs);
|
||||
$sGroupBy = self::ClauseGroupBy($aGroupBy);
|
||||
$sSQL = "SELECT $sSelect, COUNT(*) AS _itop_count_ FROM $sFrom WHERE $sWhere GROUP BY $sGroupBy";
|
||||
return $sSQL;
|
||||
}
|
||||
|
||||
private static function ClauseSelect($aFields)
|
||||
{
|
||||
$aSelect = array();
|
||||
@@ -339,6 +371,12 @@ class SQLQuery
|
||||
return $sSelect;
|
||||
}
|
||||
|
||||
private static function ClauseGroupBy($aGroupBy)
|
||||
{
|
||||
$sRes = implode(', ', $aGroupBy);
|
||||
return $sRes;
|
||||
}
|
||||
|
||||
private static function ClauseDelete($aDelTableAliases)
|
||||
{
|
||||
$aDelTables = array();
|
||||
@@ -415,14 +453,14 @@ class SQLQuery
|
||||
}
|
||||
|
||||
// Purpose: prepare the query data, once for all
|
||||
private function privRender(&$aFrom, &$aFields, &$oCondition, &$aDelTables, &$aSetValues, &$aSelectedIdFields)
|
||||
private function privRender(&$aFrom, &$aFields, &$aGroupBy, &$oCondition, &$aDelTables, &$aSetValues, &$aSelectedIdFields)
|
||||
{
|
||||
$sTableAlias = $this->privRenderSingleTable($aFrom, $aFields, $aDelTables, $aSetValues, $aSelectedIdFields, '', array('jointype' => 'first'));
|
||||
$sTableAlias = $this->privRenderSingleTable($aFrom, $aFields, $aGroupBy, $aDelTables, $aSetValues, $aSelectedIdFields, '', array('jointype' => 'first'));
|
||||
$oCondition = $this->m_oConditionExpr;
|
||||
return $sTableAlias;
|
||||
}
|
||||
|
||||
private function privRenderSingleTable(&$aFrom, &$aFields, &$aDelTables, &$aSetValues, &$aSelectedIdFields, $sCallerAlias = '', $aJoinData)
|
||||
private function privRenderSingleTable(&$aFrom, &$aFields, &$aGroupBy, &$aDelTables, &$aSetValues, &$aSelectedIdFields, $sCallerAlias = '', $aJoinData)
|
||||
{
|
||||
$aActualTableFields = CMDBSource::GetTableFieldsList($this->m_sTable);
|
||||
|
||||
@@ -506,6 +544,13 @@ class SQLQuery
|
||||
{
|
||||
$aFields["`$sAlias`"] = $oExpression->Render();
|
||||
}
|
||||
if ($this->m_aGroupBy)
|
||||
{
|
||||
foreach($this->m_aGroupBy as $sAlias => $oExpression)
|
||||
{
|
||||
$aGroupBy["`$sAlias`"] = $oExpression->Render();
|
||||
}
|
||||
}
|
||||
if ($this->m_bToDelete)
|
||||
{
|
||||
$aDelTables[] = "`{$this->m_sTableAlias}`";
|
||||
@@ -528,7 +573,7 @@ class SQLQuery
|
||||
{
|
||||
$oRightSelect = $aJoinData["select"];
|
||||
|
||||
$sJoinTableAlias = $oRightSelect->privRenderSingleTable($aTempFrom, $aFields, $aDelTables, $aSetValues, $aSelectedIdFields, $this->m_sTableAlias, $aJoinData);
|
||||
$sJoinTableAlias = $oRightSelect->privRenderSingleTable($aTempFrom, $aFields, $aGroupBy, $aDelTables, $aSetValues, $aSelectedIdFields, $this->m_sTableAlias, $aJoinData);
|
||||
}
|
||||
$aFrom[$this->m_sTableAlias]['subfrom'] = $aTempFrom;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user