public function __construct(DBObjectSearch $oFilter, $sStyle = 'list', $bAsynchronous = false, $aParams = array(), $oSet = null) { $this->m_oFilter = $oFilter->DeepClone(); $this->m_aConditions = array(); $this->m_sStyle = $sStyle; $this->m_bAsynchronous = $bAsynchronous; $this->m_aParams = $aParams; $this->m_oSet = $oSet; }
/** * Create a new set based on a Search definition. * * @param DBObjectSearch $oFilter The search filter defining the objects which are part of the set (multiple columns/objects per row are supported) * @param hash $aOrderBy * @param hash $aArgs Values to substitute for the search/query parameters (if any). Format: param_name => value * @param hash $aExtendedDataSpec * @param int $iLimitCount Maximum number of rows to load (i.e. equivalent to MySQL's LIMIT start, count) * @param int $iLimitStart Index of the first row to load (i.e. equivalent to MySQL's LIMIT start, count) */ public function __construct(DBObjectSearch $oFilter, $aOrderBy = array(), $aArgs = array(), $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0) { $this->m_oFilter = $oFilter->DeepClone(); $this->m_aAddedIds = array(); $this->m_aOrderBy = $aOrderBy; $this->m_aArgs = $aArgs; $this->m_aAttToLoad = null; $this->m_aExtendedDataSpec = $aExtendedDataSpec; $this->m_iLimitCount = $iLimitCount; $this->m_iLimitStart = $iLimitStart; $this->m_iNumTotalDBRows = null; // Total number of rows for the query without LIMIT. null if unknown yet $this->m_iNumLoadedDBRows = 0; // Total number of rows LOADED in $this->m_oSQLResult via a SQL query. 0 by default $this->m_bLoaded = false; // true when the filter has been used OR the set is built step by step (AddObject...) $this->m_aAddedObjects = array(); // array of (row => array of (classalias) => object/null) storing the objects added "in memory" $this->m_iCurrRow = 0; $this->m_oSQLResult = null; }
public static function FromOQL($sQuery, $aParams = null) { if (empty($sQuery)) { return null; } // Query caching $bOQLCacheEnabled = true; if ($bOQLCacheEnabled && array_key_exists($sQuery, self::$m_aOQLQueries)) { // hit! $oClone = self::$m_aOQLQueries[$sQuery]->DeepClone(); if (!is_null($aParams)) { $oClone->m_aParams = $aParams; } return $oClone; } $oOql = new OqlInterpreter($sQuery); $oOqlQuery = $oOql->ParseObjectQuery(); $oMetaModel = new ModelReflectionRuntime(); $oOqlQuery->Check($oMetaModel, $sQuery); // Exceptions thrown in case of issue $sClass = $oOqlQuery->GetClass(); $sClassAlias = $oOqlQuery->GetClassAlias(); $oResultFilter = new DBObjectSearch($sClass, $sClassAlias); $aAliases = array($sClassAlias => $sClass); // Maintain an array of filters, because the flat list is in fact referring to a tree // And this will be an easy way to dispatch the conditions // $oResultFilter will be referenced by the other filters, or the other way around... $aJoinItems = array($sClassAlias => $oResultFilter); $aJoinSpecs = $oOqlQuery->GetJoins(); if (is_array($aJoinSpecs)) { foreach ($aJoinSpecs as $oJoinSpec) { $sJoinClass = $oJoinSpec->GetClass(); $sJoinClassAlias = $oJoinSpec->GetClassAlias(); // Assumption: ext key on the left only !!! // normalization should take care of this $oLeftField = $oJoinSpec->GetLeftField(); $sFromClass = $oLeftField->GetParent(); $sExtKeyAttCode = $oLeftField->GetName(); $oRightField = $oJoinSpec->GetRightField(); $sToClass = $oRightField->GetParent(); $aAliases[$sJoinClassAlias] = $sJoinClass; $aJoinItems[$sJoinClassAlias] = new DBObjectSearch($sJoinClass, $sJoinClassAlias); if ($sFromClass == $sJoinClassAlias) { $oReceiver = $aJoinItems[$sToClass]; $oNewComer = $aJoinItems[$sFromClass]; $aAliasTranslation = array(); $oReceiver->AddCondition_ReferencedBy_InNameSpace($oNewComer, $sExtKeyAttCode, $oReceiver->m_aClasses, $aAliasTranslation); } else { $sOperator = $oJoinSpec->GetOperator(); switch ($sOperator) { case '=': $iOperatorCode = TREE_OPERATOR_EQUALS; break; case 'BELOW': $iOperatorCode = TREE_OPERATOR_BELOW; break; case 'BELOW_STRICT': $iOperatorCode = TREE_OPERATOR_BELOW_STRICT; break; case 'NOT_BELOW': $iOperatorCode = TREE_OPERATOR_NOT_BELOW; break; case 'NOT_BELOW_STRICT': $iOperatorCode = TREE_OPERATOR_NOT_BELOW_STRICT; break; case 'ABOVE': $iOperatorCode = TREE_OPERATOR_ABOVE; break; case 'ABOVE_STRICT': $iOperatorCode = TREE_OPERATOR_ABOVE_STRICT; break; case 'NOT_ABOVE': $iOperatorCode = TREE_OPERATOR_NOT_ABOVE; break; case 'NOT_ABOVE_STRICT': $iOperatorCode = TREE_OPERATOR_NOT_ABOVE_STRICT; break; } $oReceiver = $aJoinItems[$sFromClass]; $oNewComer = $aJoinItems[$sToClass]; $aAliasTranslation = array(); $oReceiver->AddCondition_PointingTo_InNameSpace($oNewComer, $sExtKeyAttCode, $oReceiver->m_aClasses, $aAliasTranslation, $iOperatorCode); } } } // Check and prepare the select information $aSelected = array(); foreach ($oOqlQuery->GetSelectedClasses() as $oClassDetails) { $sClassToSelect = $oClassDetails->GetValue(); $aSelected[$sClassToSelect] = $aAliases[$sClassToSelect]; } $oResultFilter->m_aClasses = $aAliases; $oResultFilter->SetSelectedClasses($aSelected); $oConditionTree = $oOqlQuery->GetCondition(); if ($oConditionTree instanceof Expression) { $oResultFilter->m_oSearchCondition = $oResultFilter->OQLExpressionToCondition($sQuery, $oConditionTree, $aAliases); } if (!is_null($aParams)) { $oResultFilter->m_aParams = $aParams; } if ($bOQLCacheEnabled) { self::$m_aOQLQueries[$sQuery] = $oResultFilter->DeepClone(); } return $oResultFilter; }
public static function MakeGroupByQuery(DBObjectSearch $oFilter, $aArgs, $aGroupByExpr, $bExcludeNullValues = false) { $aAttToLoad = array(); if ($bExcludeNullValues) { // Null values are not handled (though external keys set to 0 are allowed) $oQueryFilter = $oFilter->DeepClone(); foreach ($aGroupByExpr as $oGroupByExp) { $oNull = new FunctionExpression('ISNULL', array($oGroupByExp)); $oNotNull = new BinaryExpression($oNull, '!=', new TrueExpression()); $oQueryFilter->AddConditionExpression($oNotNull); } } else { $oQueryFilter = $oFilter; } $oSelect = self::MakeSelectStructure($oQueryFilter, array(), $aArgs, $aAttToLoad, null, 0, 0, false, $aGroupByExpr); $aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams()); try { $bBeautifulSQL = self::$m_bTraceQueries || self::$m_bDebugQuery || self::$m_bIndentQueries; $sRes = $oSelect->RenderGroupBy($aScalarArgs, $bBeautifulSQL); } catch (MissingQueryArgument $e) { // Add some information... $e->addInfo('OQL', $oFilter->ToOQL()); throw $e; } self::AddQueryTraceGroupBy($oFilter, $aArgs, $aGroupByExpr, $sRes); return $sRes; }