/** * @param $elem * @param $select * @param $is_init_entity_aggregated * @param $fList * @param Entity\QueryChain[] $fChainList * @param $helper_class * @param Entity\Base $entity * * @return array */ public static function prepareSelectViewElement($elem, $select, $is_init_entity_aggregated, $fList, $fChainList, $helper_class, Entity\Base $entity) { $result = null; $alias = null; if (empty($elem['aggr']) && !strlen($elem['prcnt'])) { $result = $elem['name']; } else { $expression = ''; /** @var Entity\Field $field */ $field = $fList[$elem['name']]; $chain = $fChainList[$elem['name']]; $alias = $chain->getAlias(); $dataType = call_user_func(array($helper_class, 'getFieldDataType'), $field); if (!empty($elem['aggr'])) { $alias = $elem['aggr'] . '_' . $alias; if ($dataType == 'boolean') { // sum int for boolean global $DB; /** @var Entity\BooleanField $field */ $trueValue = $field->normalizeValue(true); $localDef = 'CASE WHEN %s = \'' . $DB->ForSql($trueValue) . '\' THEN 1 ELSE 0 END'; } else { $localDef = '%s'; } if ($elem['aggr'] == 'COUNT_DISTINCT') { $dataType = 'integer'; $expression = array('COUNT(DISTINCT ' . $localDef . ')', $elem['name']); } else { if ($dataType == 'boolean') { $dataType = 'integer'; } if ($elem['aggr'] == 'GROUP_CONCAT') { $expression = array($localDef, $elem['name']); } else { $expression = array($elem['aggr'] . '(' . $localDef . ')', $elem['name']); } } // pack 1:N aggregations into subquery if ($chain->hasBackReference() && $elem['aggr'] != 'GROUP_CONCAT') { $confirm = call_user_func_array(array($helper_class, 'confirmSelectBackReferenceRewrite'), array(&$elem, $chain)); if ($confirm) { $filter = array(); foreach ($entity->GetPrimaryArray() as $primary) { $filter['=' . $primary] = new CSQLWhereExpression('?#', ToLower($entity->getCode()) . '.' . $primary); } $query = new Entity\Query($entity); $query->addSelect(new Entity\ExpressionField('X', $expression[0], $elem['name'])); $query->setFilter($filter); $query->setTableAliasPostfix('_sub'); $expression = array('(' . $query->getQuery() . ')'); // double aggregation if init entity aggregated if ($is_init_entity_aggregated) { if ($elem['aggr'] == 'COUNT_DISTINCT') { $expression[0] = 'SUM(' . $expression[0] . ')'; } else { $expression[0] = $elem['aggr'] . '(' . $expression[0] . ')'; } } } // confirmed } } if (strlen($elem['prcnt'])) { $alias = $alias . '_PRCNT'; $dataType = 'integer'; if ($elem['prcnt'] == 'self_column') { if (empty($expression)) { $expression = array('%s', $elem['name']); } } else { if (empty($expression)) { $localDef = '%s'; $localMembers = array($elem['name']); } else { $localDef = $expression[0]; $localMembers = array_slice($expression, 1); } list($remoteAlias, $remoteSelect) = self::prepareSelectViewElement($select[$elem['prcnt']], $select, $is_init_entity_aggregated, $fList, $fChainList, $helper_class, $entity); if (is_array($remoteSelect) && !empty($remoteSelect['expression'])) { // remote field is expression $remoteDef = $remoteSelect['expression'][0]; $remoteMembers = array_slice($remoteSelect['expression'], 1); $alias = $alias . '_FROM_' . $remoteAlias; } else { // remote field is usual field $remoteDef = '%s'; $remoteMembers = array($remoteSelect); $remoteAlias = Entity\QueryChain::getAliasByDefinition($entity, $remoteSelect); $alias = $alias . '_FROM_' . $remoteAlias; } $exprDef = '(' . $localDef . ') / (' . $remoteDef . ') * 100'; $expression = array_merge(array($exprDef), $localMembers, $remoteMembers); // 'ROUND(STATUS / ID * 100)' // 'ROUND( (EX1(F1, F2)) / (EX2(F3, F1)) * 100)', // F1, F2, F3, F1 } } $result = array('data_type' => $dataType, 'expression' => $expression); } return array($alias, $result); }