249 if ($source instanceof $this)
251 $this->entity = Entity::getInstanceByQuery($source);
253 elseif ($source instanceof
Entity)
255 $this->entity = clone $source;
257 elseif (is_string($source))
264 'Unknown source type "%s" for new %s', gettype($source), __CLASS__
268 $this->filterHandler = static::filter();
269 $this->whereHandler = static::filter();
270 $this->havingHandler = static::filter();
280 public function __call($method, $arguments)
283 if (substr($method, 0, 6) ===
'having')
285 $method = str_replace(
'having',
'where', $method);
288 if (substr($method, 0, 5) ===
'where')
290 if (method_exists($this->filterHandler, $method))
292 call_user_func_array(
293 [$this->filterHandler, $method],
301 if (substr($method, 0, 4) ===
'with')
303 $dataClass = $this->entity->getDataClass();
305 if (method_exists($dataClass, $method))
308 array_unshift($arguments, $this);
310 call_user_func_array(
311 [$dataClass, $method],
329 return $this->select;
340 $this->select = $select;
355 $this->select[$alias] = $definition;
359 $this->select[] = $definition;
372 return $this->filter;
396 if (is_null($key) && is_array($value))
402 $this->
filter[$key] = $value;
413 return $this->filterHandler;
476 $this->order = array();
483 foreach (
$order as $k => $v)
508 public function addOrder($definition, $order =
'ASC')
512 if (!in_array(
$order, array(
'ASC',
'DESC'),
true))
517 $connection = $this->entity->getConnection();
518 $helper = $connection->getSqlHelper();
522 $order = $helper->getAscendingOrder();
526 $order = $helper->getDescendingOrder();
529 $this->order[$definition] =
$order;
563 return $this->offset;
582 return $this->countTotal;
599 public function union()
601 foreach (func_get_args() as $arg)
619 foreach (func_get_args() as $arg)
696 $this->data_doubling_off =
false;
709 if (count($this->entity->getPrimaryArray()) !== 1)
713 trigger_error(sprintf(
714 'Disabling data doubling available for Entities with 1 primary field only. Number of primaries of your entity `%s` is %d.',
715 $this->entity->getFullName(), count($this->entity->getPrimaryArray())
720 $this->data_doubling_off =
true;
733 $this->private_fields_on =
true;
745 $this->private_fields_on =
false;
755 return $this->private_fields_on;
761 foreach ($this->filter_chains as $chain)
763 if (static::isFieldPrivate($chain->getLastElement()->getValue()))
765 $columnField = $chain->getLastElement()->getValue();
768 'Private field %s.%s is restricted in filter',
769 $columnField->getEntity()->getDataClass(),
770 $columnField->getName()
776 if ($this->private_fields_on !==
true)
778 foreach ($this->global_chains as $chain)
780 if (static::isFieldPrivate($chain->getLastElement()->getValue()))
782 $columnField = $chain->getLastElement()->getValue();
785 'Private field %s.%s is restricted in query, use Query::enablePrivateFields() to allow it',
786 $columnField->getEntity()->getDataClass(),
787 $columnField->getName()
805 return $field->isPrivate();
809 foreach ($field->getBuildFromChains() as $chain)
811 if (static::isFieldPrivate($chain->getLastElement()->getValue()))
833 if ($name instanceof
Field && $fieldInfo ===
null)
837 $name = $fieldInfo->getName();
839 elseif ((empty($name) || is_numeric($name)) && $fieldInfo instanceof
Field)
841 $name = $fieldInfo->getName();
846 if ($fieldInfo instanceof
Field)
848 $fieldInfo = clone $fieldInfo;
852 $this->entity->addField($fieldInfo, $name);
860 $this->collectExprChains($chain, array(
'hidden'));
868 $this->table_alias_postfix = $postfix;
874 return $this->table_alias_postfix;
886 $this->custom_base_table_alias = $alias;
914 if (static::$expressionHelper ===
null)
919 return static::$expressionHelper;
931 $this->is_executing =
true;
939 if($this->cacheTtl > 0 && (empty($this->join_map) || $this->
cacheJoins ==
true))
941 $ttl = $this->entity->getCacheTtl($this->cacheTtl);
946 $cacheId = md5($query);
947 $result = $this->entity->readFromCache($ttl, $cacheId, $this->
countTotal);
952 $result = $this->query($query);
956 $result = $this->entity->writeToCache($result, $cacheId, $this->
countTotal);
960 $this->is_executing =
false;
962 $queryResult =
new Result($this, $result);
964 if (!empty($this->forcedObjectPrimaryFields))
966 $queryResult->setHiddenObjectFields($this->forcedObjectPrimaryFields);
983 return $this->
exec()->fetch($converter);
997 return $this->
exec()->fetchAll($converter);
1010 return $this->
exec()->fetchObject();
1022 return $this->
exec()->fetchCollection();
1025 protected function ensurePrimarySelect()
1029 if ($this->hasAggregation() || $this->hasDistinct())
1034 $entities = [[$this->entity,
'']];
1036 foreach ($this->join_map as $join)
1038 $entities[] = [$join[
'entity'], $join];
1042 foreach ($entities as list($entity, $join))
1045 foreach ($entity->getPrimaryArray() as $primary)
1047 if (!empty($entity->getField($primary)->hasParameter(
'auto_generated')))
1052 $needDefinition = !empty($join[
'definition']) ? $join[
'definition'].
'.'.$primary : $primary;
1054 $chain = $this->getRegisteredChain($needDefinition,
true);
1056 if (empty($this->select_chains[$chain->getAlias()]))
1059 $alias = $this->getUniqueAlias();
1060 $chain->setCustomAlias($alias);
1062 $this->registerChain(
'select', $chain);
1065 $this->forcedObjectPrimaryFields[] = $alias;
1069 ? $chain->getLastElement()->setParameter(
'talias', $join[
'alias'])
1070 : $chain->getLastElement()->setParameter(
'talias', $this->getInitAlias());
1084 protected function addToSelectChain($definition, $alias =
null)
1086 if ($definition instanceof ExpressionField)
1090 $alias = $definition->getName();
1100 if ($chain->getLastElement()->getValue() instanceof ExpressionField)
1102 $this->collectExprChains($chain, array(
'hidden',
'select_expr'));
1105 elseif (is_array($definition))
1109 throw new Main\ArgumentException(
1110 'Expression as an array in `select` section is no more supported due to security reason.'
1111 .
' Please use `runtime` parameter, or Query->registerRuntimeField method, or pass ExpressionField object instead of array.'
1117 $localDefinitionPos = strrpos($definition,
'.');
1119 if ($localDefinitionPos !==
false)
1121 $localDefinition = substr($definition, $localDefinitionPos + 1);
1122 $localEntityDef = substr($definition, 0, $localDefinitionPos);
1123 $localChain = Chain::getChainByDefinition($this->entity, $localEntityDef.
'.*');
1124 $lastElemValue = $localChain->getLastElement()->getValue();
1126 if ($lastElemValue instanceof Reference)
1128 $localEntity = $lastElemValue->getRefEntity();
1130 elseif (is_array($lastElemValue))
1132 list($localEntity, ) = $lastElemValue;
1136 $localEntity = $lastElemValue;
1141 $localDefinition = $definition;
1142 $localEntityDef =
"";
1143 $dataClass = $this->entity->getDataClass();
1144 $localEntity = $dataClass::getEntity();
1148 if ((strlen($localDefinition) > 1 && strpos($localDefinition,
'*') !==
false)
1149 || strpos($localDefinition,
'?') !==
false
1153 foreach ($localEntity->getFields() as $field)
1156 ($field instanceof ScalarField || $field instanceof ExpressionField)
1157 && fnmatch($localDefinition, $field->getName())
1161 if ($field instanceof ScalarField && $field->isPrivate())
1168 substr($field->getName(), 0, 3) ==
'UF_' && substr($field->getName(), -7) ==
'_SINGLE'
1169 && $localEntity->hasField(substr($field->getName(), 0, -7))
1177 $customAlias =
null;
1179 if ($alias !==
null)
1182 $customAlias = $alias.$field->getName();
1186 $fieldDefinition = $field->getName();
1188 if (!empty($localEntityDef))
1190 $fieldDefinition = $localEntityDef.
'.'.$fieldDefinition;
1193 $this->addToSelectChain($fieldDefinition, $customAlias);
1203 if ($alias !==
null)
1206 $chain = clone $chain;
1207 $chain->setCustomAlias($alias);
1210 $last_elem = $chain->getLastElement();
1214 $expand_entity =
null;
1216 if ($last_elem->getValue() instanceof Reference)
1218 $expand_entity = $last_elem->getValue()->getRefEntity();
1220 elseif (is_array($last_elem->getValue()))
1222 list($expand_entity, ) = $last_elem->getValue();
1224 elseif ($last_elem->getValue() instanceof Entity)
1226 $expand_entity = $last_elem->getValue();
1228 elseif ($last_elem->getValue() instanceof OneToMany)
1230 $expand_entity = $last_elem->getValue()->getRefEntity();
1232 elseif ($last_elem->getValue() instanceof ManyToMany)
1234 $expand_entity = $last_elem->getValue()->getRefEntity();
1237 if (!$expand_entity && $alias !==
null)
1241 $this->entity->hasField($alias)
1244 $this->entity->getFullName() !== $last_elem->getValue()->getEntity()->getFullName()
1246 $last_elem->getValue()->getName() !== $alias
1251 throw new Main\ArgumentException(sprintf(
1252 'Alias "%s" matches already existing field "%s" of initial entity "%s". '.
1253 'Please choose another name for alias.',
1254 $alias, $alias, $this->entity->getFullName()
1262 foreach ($expand_entity->getFields() as $exp_field)
1265 if ($exp_field instanceof ScalarField)
1268 if ($exp_field->isPrivate())
1273 $exp_chain = clone $chain;
1274 $exp_chain->addElement(
new ChainElement(
1279 if ($alias !==
null)
1281 $fieldAlias = $alias . $exp_field->getName();
1284 if ($this->entity->hasField($fieldAlias))
1286 throw new Main\ArgumentException(sprintf(
1287 'Alias "%s" + field "%s" match already existing field "%s" of initial entity "%s". '.
1288 'Please choose another name for alias.',
1289 $alias, $exp_field->getName(), $fieldAlias, $this->entity->getFullName()
1293 $exp_chain->setCustomAlias($fieldAlias);
1311 if ($chain->getLastElement()->getValue() instanceof ExpressionField)
1313 $this->collectExprChains($chain, array(
'hidden',
'select_expr'));
1328 public function setFilterChains(&$filter, $section =
'filter')
1330 foreach ($filter as $filter_def => &$filter_match)
1332 if ($filter_def ===
'LOGIC')
1337 if (!is_numeric($filter_def))
1339 $sqlWhere = new \CSQLWhere();
1340 $csw_result = $sqlWhere->makeOperation($filter_def);
1341 list($definition, ) = array_values($csw_result);
1351 $chain = $this->filter_chains[$definition] ?? Chain::getChainByDefinition($this->entity, $definition);
1355 $dstField = $chain->getLastElement()->getValue();
1356 $dstEntity = $dstField->getEntity();
1358 if ($dstField instanceof ExpressionField && count($dstField->getBuildFromChains()) == 1)
1361 $dstBuildFromChains = $dstField->getBuildFromChains();
1364 $firstChain = $dstBuildFromChains[0];
1365 $dstField = $firstChain->getLastElement()->getValue();
1369 if (($dstField instanceof TextField || $dstField instanceof ArrayField)
1370 && $dstEntity->hasField($dstField->getName().
'_SINGLE'))
1372 $utmLinkField = $dstEntity->getField($dstField->getName().
'_SINGLE');
1374 if ($utmLinkField instanceof ExpressionField)
1376 $buildFromChains = $utmLinkField->getBuildFromChains();
1379 if (count($buildFromChains) == 1 && $buildFromChains[0]->
hasBackReference())
1381 $endField = $buildFromChains[0]->getLastElement()->getValue();
1384 if(strpos($endField->getEntity()->getName(),
'Utm'))
1386 $expressionChain = clone $chain;
1387 $expressionChain->removeLastElement();
1388 $expressionChain->addElement(
new ChainElement(clone $utmLinkField));
1389 $expressionChain->forceDataDoublingOff();
1391 $chain = $expressionChain;
1394 unset($filter[$filter_def]);
1395 $filter[$filter_def.
'_SINGLE'] = $filter_match;
1396 $definition .=
'_SINGLE';
1403 $registerChain =
true;
1406 if ($chain->forcesDataDoublingOff() || ($this->data_doubling_off && $chain->hasBackReference()))
1408 $registerChain =
false;
1416 if ($chain->getLastElement()->getValue() instanceof ExpressionField)
1418 $this->collectExprChains($chain);
1425 $this->filter_chains[$chain->getAlias()] = $chain;
1426 $this->filter_chains[$definition] = $chain;
1432 elseif (is_array($filter_match))
1434 $this->setFilterChains($filter_match, $section);
1446 public function setFilterHandlerChains(Filter $where, $section =
'filter')
1448 foreach ($where->getConditions() as $condition)
1450 if ($condition instanceof Filter)
1453 $this->setFilterHandlerChains($condition, $section);
1457 $definition = $condition->getDefinition();
1460 if ($definition instanceof Field)
1466 $definition = $definition->getName();
1467 $condition->setDefinition($definition);
1471 if ($definition !==
null)
1480 $chain = $this->filter_chains[$definition] ?? Chain::getChainByDefinition($this->entity, $definition);
1484 $dstField = $chain->getLastElement()->getValue();
1485 $dstEntity = $dstField->getEntity();
1487 if ($dstField instanceof ExpressionField && count($dstField->getBuildFromChains()) == 1)
1490 $dstBuildFromChains = $dstField->getBuildFromChains();
1493 $firstChain = $dstBuildFromChains[0];
1494 $dstField = $firstChain->getLastElement()->getValue();
1498 if (($dstField instanceof TextField || $dstField instanceof ArrayField)
1499 && $dstEntity->hasField($dstField->getName().
'_SINGLE'))
1501 $utmLinkField = $dstEntity->getField($dstField->getName().
'_SINGLE');
1503 if ($utmLinkField instanceof ExpressionField)
1505 $buildFromChains = $utmLinkField->getBuildFromChains();
1508 if (count($buildFromChains) == 1 && $buildFromChains[0]->
hasBackReference())
1510 $endField = $buildFromChains[0]->getLastElement()->getValue();
1513 if(strpos($endField->getEntity()->getName(),
'Utm'))
1515 $expressionChain = clone $chain;
1516 $expressionChain->removeLastElement();
1517 $expressionChain->addElement(
new ChainElement(clone $utmLinkField));
1518 $expressionChain->forceDataDoublingOff();
1520 $chain = $expressionChain;
1523 $definition .=
'_SINGLE';
1524 $condition->setDefinition($definition);
1531 $registerChain =
true;
1534 if ($chain->forcesDataDoublingOff() || ($this->data_doubling_off && $chain->hasBackReference()))
1536 $registerChain =
false;
1544 if ($chain->getLastElement()->getValue() instanceof ExpressionField)
1546 $this->collectExprChains($chain);
1553 $this->filter_chains[$chain->getAlias()] = $chain;
1554 $this->filter_chains[$definition] = $chain;
1562 foreach ($condition->getAtomicValues() as $value)
1564 if ($value instanceof ColumnExpression)
1566 $valueDefinition = $value->getDefinition();
1568 $chain = $this->filter_chains[$valueDefinition] ?? Chain::getChainByDefinition($this->entity, $valueDefinition);
1574 if ($value instanceof Main\DB\SqlExpression)
1576 $value->setConnection($this->entity->getConnection());
1591 $logic = $this->
filter[
'LOGIC'] ??
'AND';
1598 $this->where = array();
1599 $this->where_chains = array();
1601 $this->having = $this->filter;
1602 $this->having_chains = $this->filter_chains;
1606 $this->where = $this->filter;
1607 $this->where_chains = $this->filter_chains;
1609 $this->having = array();
1610 $this->having_chains = array();
1613 elseif ($logic ==
'AND')
1616 foreach ($this->
filter as $k => $sub_filter)
1620 $this->where[$k] = $sub_filter;
1621 $this->having[$k] = $sub_filter;
1626 $tmp_filter = array($k => $sub_filter);
1630 $this->having[$k] = $sub_filter;
1631 $this->setFilterChains($tmp_filter,
'having');
1635 $this->where[$k] = $sub_filter;
1636 $this->setFilterChains($tmp_filter,
'where');
1642 foreach ($this->having_chains as $chain)
1646 $this->collectExprChains($chain, array(
'hidden',
'having_expr'));
1657 $logic = $this->filterHandler->logic();
1664 $this->havingHandler = $this->filterHandler;
1665 $this->having_chains = $this->filter_chains;
1669 $this->whereHandler = $this->filterHandler;
1670 $this->where_chains = $this->filter_chains;
1673 elseif ($logic ==
'and')
1676 foreach ($this->filterHandler->getConditions() as $condition)
1678 $tmpFilter = static::filter()->addCondition($condition);
1682 $this->havingHandler->addCondition($tmpFilter);
1683 $this->setFilterHandlerChains($tmpFilter,
'having');
1687 $this->whereHandler->addCondition($condition);
1688 $this->setFilterHandlerChains($tmpFilter,
'where');
1694 foreach ($this->having_chains as $chain)
1698 $this->collectExprChains($chain, array(
'hidden',
'having_expr'));
1711 foreach (
$filter as $filter_def => $filter_match)
1713 if ($filter_def ===
'LOGIC')
1719 if (!is_numeric($filter_def))
1721 $sqlWhere = new \CSQLWhere();
1722 $csw_result = $sqlWhere->makeOperation($filter_def);
1723 list($definition, ) = array_values($csw_result);
1725 $chain = $this->filter_chains[$definition];
1726 $last = $chain->getLastElement();
1730 elseif (is_array($filter_match))
1752 foreach ($filter->getConditions() as $condition)
1756 if ($condition instanceof Filter)
1764 if ($condition->getDefinition() !==
null)
1767 $chain = $this->filter_chains[$condition->getDefinition()];
1768 $last = $chain->getLastElement();
1775 $chain = $this->filter_chains[$condition->getValue()->getDefinition()];
1776 $last = $chain->getLastElement();
1803 foreach ($filter->getConditions() as $condition)
1805 if ($condition instanceof Filter)
1810 elseif ($condition->getDefinition() !==
null)
1813 $chain = $this->filter_chains[$condition->getDefinition()];
1815 if ($chain->forcesDataDoublingOff() || ($this->data_doubling_off && $chain->hasBackReference()))
1817 $primaryName = $this->entity->getPrimary();
1818 $uniquePostfix =
'_TMP'.rand();
1821 $dataClass = $this->entity->getDataClass();
1823 $subQuery = $dataClass::query()
1824 ->addSelect($primaryName)
1825 ->where(clone $condition)
1826 ->setTableAliasPostfix(strtolower($uniquePostfix));
1829 $condition->setColumn($primaryName);
1830 $condition->setOperator(
'in');
1831 $condition->setValue($subQuery);
1853 $this->collectExprChains($chain);
1869 $this->collectExprChains($chain);
1879 protected function buildJoinMap($chains =
null)
1881 $connection = $this->entity->getConnection();
1882 $helper = $connection->getSqlHelper();
1884 $aliasLength = $helper->getAliasLength();
1888 $chains = $this->global_chains;
1891 foreach ($chains as $chain)
1893 if ($chain->getLastElement()->getParameter(
'talias'))
1900 if ($chain->forcesDataDoublingOff() || ($this->data_doubling_off && $chain->hasBackReference()))
1902 $alias = $chain->getAlias();
1904 if (isset($this->filter_chains[$alias])
1905 && !isset($this->select_chains[$alias]) && !isset($this->select_expr_chains[$alias])
1906 && !isset($this->group_chains[$alias]) && !isset($this->order_chains[$alias])
1913 $prev_alias = $this->getInitAlias(
false);
1921 $elements = array_slice($chain->getAllElements(), 1);
1923 $currentDefinition = array();
1925 foreach ($elements as $element)
1927 $table_alias =
null;
1934 if ($element->getValue() instanceof Reference)
1937 $ref_field = $element->getValue();
1938 $dst_entity = $ref_field->getRefEntity();
1939 $joinType = $ref_field->getJoinType();
1941 elseif (is_array($element->getValue()))
1944 list($dst_entity, $ref_field) = $element->getValue();
1945 $joinType = $ref_field->getJoinType();
1947 elseif ($element->getValue() instanceof OneToMany)
1950 $dst_entity = $element->getValue()->getRefEntity();
1951 $ref_field = $element->getValue()->getRefField();
1952 $joinType = $element->getValue()->getJoinType() ?: $ref_field->getJoinType();
1954 elseif ($element->getValue() instanceof ManyToMany)
1956 $mtm = $element->getValue();
1960 $tmpChain = clone $chain;
1961 $mtmDefinition = join(
'.', $currentDefinition);
1963 while ($tmpChain->getDefinition() != $mtmDefinition)
1965 $tmpChain->removeLastElement();
1969 $tmpChain->addElement(
new ChainElement([
1970 $mtm->getMediatorEntity(), $mtm->getLocalReference()
1974 $tmpChain->addElement(
new ChainElement($mtm->getRemoteReference()));
1978 $this->buildJoinMap([$tmpChain]);
1981 $prev_alias = $tmpChain->getLastElement()->getParameter(
'talias');
1982 $element->setParameter(
'talias', $prev_alias);
1993 $element->setParameter(
'talias', $this->
getInitAlias());
1997 $element->setParameter(
'talias', $prev_alias.$this->table_alias_postfix);
2004 if (empty($map_key))
2006 $map_key = join(
'.', $currentDefinition);
2009 $map_key .=
'/' . $ref_field->getName() .
'/' . $dst_entity->getName();
2011 $currentDefinition[] = $element->getDefinitionFragment();
2013 if (isset($this->join_registry[$map_key]))
2016 $table_alias = $this->join_registry[$map_key];
2021 $reference = $ref_field->getReference();
2023 if ($element->getValue() instanceof Reference)
2026 if (is_null($table_alias))
2028 $table_alias = $prev_alias.
'_'.strtolower($ref_field->getName());
2030 if (strlen($table_alias.$this->table_alias_postfix) > $aliasLength)
2032 $old_table_alias = $table_alias;
2033 $table_alias =
'TALIAS_' . (count($this->replaced_taliases) + 1);
2034 $this->replaced_taliases[$table_alias] = $old_table_alias;
2038 $alias_this = $prev_alias;
2039 $alias_ref = $table_alias;
2041 $isBackReference =
false;
2043 $definition_this = join(
'.', array_slice($currentDefinition, 0, -1));
2044 $definition_ref = join(
'.', $currentDefinition);
2045 $definition_join = $definition_ref;
2047 elseif (is_array($element->getValue()) || $element->getValue() instanceof OneToMany)
2049 if (is_null($table_alias))
2051 $table_alias = StringHelper::camel2snake($dst_entity->getName()).
'_'.strtolower($ref_field->getName());
2052 $table_alias = $prev_alias.
'_'.$table_alias;
2054 if (strlen($table_alias.$this->table_alias_postfix) > $aliasLength)
2056 $old_table_alias = $table_alias;
2057 $table_alias =
'TALIAS_' . (count($this->replaced_taliases) + 1);
2058 $this->replaced_taliases[$table_alias] = $old_table_alias;
2062 $alias_this = $table_alias;
2063 $alias_ref = $prev_alias;
2065 $isBackReference =
true;
2067 $definition_this = join(
'.', $currentDefinition);
2068 $definition_ref = join(
'.', array_slice($currentDefinition, 0, -1));
2069 $definition_join = $definition_this;
2073 throw new Main\SystemException(sprintf(
'Unknown reference element `%s`', $element->getValue()));
2077 if ($reference instanceof Filter)
2081 $alias_this.$this->table_alias_postfix,
2082 $alias_ref.$this->table_alias_postfix,
2092 $alias_this.$this->table_alias_postfix,
2093 $alias_ref.$this->table_alias_postfix,
2101 if (!isset($this->join_registry[$map_key]))
2104 'type' => $joinType,
2105 'entity' => $dst_entity,
2106 'definition' => $definition_join,
2107 'table' => $dst_entity->getDBTableName(),
2108 'alias' => $table_alias.$this->table_alias_postfix,
2109 'reference' => $csw_reference,
2110 'map_key' => $map_key
2113 $this->join_map[] = $join;
2114 $this->join_registry[$map_key] = $table_alias;
2119 $element->setParameter(
'talias', $table_alias.$this->table_alias_postfix);
2121 $prev_alias = $table_alias;
2130 $helper = $this->entity->getConnection()->getSqlHelper();
2131 $aliasLength = (int) $helper->getAliasLength();
2133 foreach ($this->select_chains as $chain)
2135 $definition = $chain->getSqlDefinition();
2136 $alias = $chain->getAlias();
2138 if (strlen($alias) > $aliasLength)
2141 $newAlias =
'FALIAS_'.count($this->replaced_aliases);
2142 $this->replaced_aliases[$newAlias] = $alias;
2147 $sql[] = $definition .
' AS ' . $helper->quote($alias);
2152 (!empty($this->forcedObjectPrimaryFields) && count($sql) == count($this->forcedObjectPrimaryFields))
2158 $strSql = join(
",\n\t", $sql);
2163 $strSql =
'DISTINCT '.$strSql;
2166 return "\n\t".$strSql;
2176 $csw = new \CSQLWhere;
2178 $connection = $this->entity->getConnection();
2179 $helper = $connection->getSqlHelper();
2181 foreach ($this->join_map as $join)
2185 $csw->setFields($csw_fields);
2187 if ($join[
'reference'] instanceof Filter)
2189 $joinConditionSql = $join[
'reference']->getSql($this->global_chains);
2193 $joinConditionSql = trim($csw->getQuery($join[
'reference']));
2197 $sql[] = sprintf(
'%s JOIN %s %s ON %s',
2200 $helper->quote($join[
'alias']),
2205 return "\n".join(
"\n", $sql);
2218 if (!empty($this->where))
2220 $csw = new \CSQLWhere;
2222 $csw_fields = $this->getFilterCswFields($this->where);
2223 $csw->setFields($csw_fields);
2225 $sql[] = trim($csw->getQuery($this->where));
2229 if ($this->whereHandler && $this->whereHandler->hasConditions())
2234 $sql[] = $this->whereHandler->getSql($this->where_chains);
2237 return join(
' AND ', array_filter($sql));
2251 foreach ($this->global_chains as $chain)
2253 $alias = $chain->getAlias();
2256 if ($chain->isConstant())
2261 if (isset($this->select_chains[$alias]) || isset($this->order_chains[$alias]) || isset($this->having_chains[$alias]))
2263 if (isset($this->group_chains[$alias]))
2268 elseif (!$chain->hasAggregation() && !$chain->hasSubquery())
2273 elseif (!$chain->hasAggregation() && $chain->hasSubquery() && $chain->getLastElement()->getValue() instanceof
ExpressionField)
2276 $sub_chains = $chain->getLastElement()->getValue()->getBuildFromChains();
2278 foreach ($sub_chains as $sub_chain)
2281 $real_sub_chain = clone $chain;
2283 foreach (array_slice($sub_chain->getAllElements(), 1) as $sub_chain_elem)
2285 $real_sub_chain->addElement($sub_chain_elem);
2289 $this->
registerChain(
'group', $this->global_chains[$real_sub_chain->getAlias()]);
2293 elseif (isset($this->having_expr_chains[$alias]))
2295 if (!$chain->hasAggregation() && $chain->hasSubquery())
2303 foreach ($this->group_chains as $chain)
2305 $connection = $this->entity->getConnection();
2306 $sqlDefinition = $chain->getSqlDefinition();
2307 $valueField = $chain->getLastElement()->getValue();
2311 $valueField = $valueField->getValueField();
2314 if (($connection instanceof Main\DB\OracleConnection || $connection instanceof Main\DB\MssqlConnection)
2318 $sqlDefinition = $connection->getSqlHelper()->softCastTextToChar($sqlDefinition);
2321 $sql[] = $sqlDefinition;
2324 return join(
', ', $sql);
2337 if (!empty($this->having))
2339 $csw = new \CSQLWhere;
2341 $csw_fields = $this->getFilterCswFields($this->having);
2342 $csw->setFields($csw_fields);
2344 $sql[] = trim($csw->getQuery($this->having));
2348 if ($this->havingHandler && $this->havingHandler->hasConditions())
2353 $sql[] = $this->havingHandler->getSql($this->having_chains);
2356 return join(
' AND ', array_filter($sql));
2367 foreach ($this->order_chains as $chain)
2369 $sort = isset($this->order[$chain->getDefinition()])
2370 ? $this->order[$chain->getDefinition()]
2371 : ($this->order[$chain->getAlias()] ??
'');
2373 $connection = $this->entity->getConnection();
2376 $valueField = $chain->getLastElement()->getValue();
2379 $valueField = $valueField->getValueField();
2383 if (isset($this->select_chains[$chain->getAlias()]))
2386 $alias = $chain->getAlias();
2388 if ($key = array_search($alias, $this->replaced_aliases))
2394 $sqlDefinition = $connection->getSqlHelper()->quote($alias);
2398 $sqlDefinition = $chain->getSqlDefinition();
2401 if (($connection instanceof Main\DB\OracleConnection || $connection instanceof Main\DB\MssqlConnection)
2405 $sqlDefinition = $connection->getSqlHelper()->softCastTextToChar($sqlDefinition);
2408 $sql[] = $sqlDefinition.
' ' . $sort;
2411 return join(
', ', $sql);
2423 $connection = $this->entity->getConnection();
2424 $helper = $connection->getSqlHelper();
2426 if ($this->query_build_parts ===
null)
2429 foreach ($this->select as $key => $value)
2431 $this->addToSelectChain($value, is_numeric($key) ?
null : $key);
2434 $this->setFilterChains($this->
filter);
2438 $this->entity->setDefaultScope($this);
2440 $this->setFilterHandlerChains($this->filterHandler);
2443 foreach ($this->group as $value)
2448 foreach ($this->order as $key => $value)
2453 $this->buildJoinMap();
2455 if ($forceObjectPrimary && empty($this->unionHandler))
2457 $this->ensurePrimarySelect();
2471 $sqlFrom .=
' '.$sqlJoin;
2473 $this->query_build_parts = array_filter(array(
2474 'SELECT' => $sqlSelect,
2476 'WHERE' => $sqlWhere,
2477 'GROUP BY' => $sqlGroup,
2478 'HAVING' => $sqlHaving,
2479 'ORDER BY' => $sqlOrder
2486 $build_parts = $this->query_build_parts;
2488 foreach ($build_parts as $k => &$v)
2493 $query = join(
"\n", $build_parts);
2495 if ($this->limit > 0)
2497 $query = $helper->getTopSql($query, $this->limit, $this->offset);
2501 if (!empty($this->unionHandler))
2503 if ($this->order || $this->limit)
2505 $query =
"({$query})";
2508 foreach ($this->unionHandler->getQueries() as $union)
2510 $query .=
" ".$union->getSql();
2514 if ($this->unionHandler->getOrder())
2516 $sqlUnionOrder = array();
2517 foreach ($this->unionHandler->getOrder() as $definition => $sort)
2519 $sqlDefinition = $connection->getSqlHelper()->quote(
2520 $this->global_chains[$definition]->getAlias()
2523 $sqlUnionOrder[] = $sqlDefinition .
' ' . $sort;
2526 $query .=
' ORDER BY ' . join(
', ', $sqlUnionOrder);
2530 if ($this->unionHandler->getLimit())
2532 $query = $helper->getTopSql($query, $this->unionHandler->getLimit(), $this->unionHandler->getOffset());
2546 protected function getFilterCswFields(&$filter)
2550 foreach ($filter as $filter_def => &$filter_match)
2552 if ($filter_def ===
'LOGIC')
2557 if (!is_numeric($filter_def))
2559 $sqlWhere = new \CSQLWhere();
2560 $csw_result = $sqlWhere->makeOperation($filter_def);
2561 list($definition, $operation) = array_values($csw_result);
2563 $chain = $this->filter_chains[$definition];
2564 $last = $chain->getLastElement();
2567 $field_type = $last->getValue()->getDataType();
2571 if (in_array($operation, array(
'SE',
'SN'),
true)
2572 && in_array($filter_match, array(
null,
true,
false),
true)
2575 $field_type =
'callback';
2577 if ($filter_match ===
null)
2579 $callback = array($this,
'nullEqualityCallback');
2585 $callback = array($this,
'booleanStrongEqualityCallback');
2588 elseif ($field_type ==
'integer')
2590 $field_type =
'int';
2592 elseif ($field_type ==
'boolean')
2594 $field_type =
'string';
2597 $field = $last->getValue();
2598 $values = $field->getValues();
2600 if (is_numeric($values[0]) && is_numeric($values[1]))
2602 $field_type =
'int';
2605 if (is_scalar($filter_match))
2607 $filter_match = $field->normalizeValue($filter_match);
2610 elseif ($field_type ==
'float')
2612 $field_type =
'double';
2614 elseif ($field_type ==
'enum' || $field_type ==
'text')
2616 $field_type =
'string';
2619 $sqlDefinition = $chain->getSqlDefinition();
2623 if ($chain->forcesDataDoublingOff() || ($this->data_doubling_off && $chain->hasBackReference()))
2625 $primaryName = $this->entity->getPrimary();
2626 $uniquePostfix =
'_TMP'.rand();
2629 $subQuery =
new Query($this->entity);
2630 $subQuery->addSelect($primaryName);
2631 $subQuery->addFilter($filter_def, $filter_match);
2632 $subQuery->setTableAliasPostfix(strtolower($uniquePostfix));
2633 $subQuerySql = $subQuery->getQuery();
2636 $filter_match = $subQuerySql;
2637 $callback = array($this,
'dataDoublingCallback');
2639 $field_type =
'callback';
2643 $sqlDefinition = $idChain->getSqlDefinition();
2647 if ($filter_match instanceof Main\DB\SqlExpression)
2649 $filter_match->setConnection($this->entity->getConnection());
2689 $fields[$definition] = array(
2690 'TABLE_ALIAS' =>
'table',
2691 'FIELD_NAME' => $sqlDefinition,
2692 'FIELD_TYPE' => $field_type,
2695 'CALLBACK' => $callback
2698 elseif (is_array($filter_match))
2700 $fields = array_merge($fields, $this->getFilterCswFields($filter_match));
2719 protected function prepareJoinReference($reference, $alias_this, $alias_ref, $baseDefinition, $refDefinition, $isBackReference)
2723 foreach ($reference as $k => $v)
2734 $new[$k] = $this->
prepareJoinReference($v, $alias_this, $alias_ref, $baseDefinition, $refDefinition, $isBackReference);
2739 $sqlWhere = new \CSQLWhere();
2740 $csw_result = $sqlWhere->makeOperation($k);
2741 list($field, $operation) = array_values($csw_result);
2743 if (strpos($field,
'this.') === 0)
2746 $definition = str_replace(\CSQLWhere::getOperationByCode($operation).
'this.',
'', $k);
2747 $absDefinition = $baseDefinition <>
''? $baseDefinition.
'.'.$definition : $definition;
2751 if (!$isBackReference)
2754 $this->buildJoinMap(array($chain));
2758 $chain->getLastElement()->setParameter(
'talias', $alias_this);
2764 $this->collectExprChains($chain);
2765 $buildFrom = $chain->getLastElement()->getValue()->getBuildFromChains();
2767 foreach ($buildFrom as $bf)
2770 $baseChain = clone $chain;
2773 $baseChain->removeLastElement();
2776 $bf->removeFirstElement();
2779 $bf->prepend($baseChain);
2782 $this->buildJoinMap($buildFrom);
2785 $k = \CSQLWhere::getOperationByCode($operation).$chain->getSqlDefinition();
2787 elseif (strpos($field,
'ref.') === 0)
2789 $definition = str_replace(\CSQLWhere::getOperationByCode($operation).
'ref.',
'', $k);
2791 if (strpos($definition,
'.') !==
false)
2794 'Reference chain `%s` is not allowed here. First-level definitions only.', $field
2798 $absDefinition = $refDefinition <>
''? $refDefinition.
'.'.$definition : $definition;
2801 if ($isBackReference)
2804 $this->buildJoinMap(array($chain));
2808 $chain->getLastElement()->setParameter(
'talias', $alias_ref);
2814 $this->collectExprChains($chain);
2815 $this->buildJoinMap($chain->getLastElement()->getValue()->getBuildFromChains());
2818 $k = \CSQLWhere::getOperationByCode($operation).$chain->getSqlDefinition();
2822 throw new Main\SystemException(sprintf(
'Unknown reference key `%s`, it should start with "this." or "ref."', $k));
2829 $v = new \CSQLWhereExpression($v[0], array_slice($v, 1));
2834 $v->setConnection($this->entity->getConnection());
2836 elseif (!is_object($v))
2838 if (strpos($v,
'this.') === 0)
2840 $definition = str_replace(
'this.',
'', $v);
2841 $absDefinition = $baseDefinition <>
''? $baseDefinition.
'.'.$definition : $definition;
2845 if (!$isBackReference)
2848 $this->buildJoinMap(array($chain));
2852 $chain->getLastElement()->setParameter(
'talias', $alias_this);
2858 $this->collectExprChains($chain);
2859 $buildFrom = $chain->getLastElement()->getValue()->getBuildFromChains();
2861 foreach ($buildFrom as $bf)
2864 $baseChain = clone $chain;
2867 $baseChain->removeLastElement();
2870 $bf->removeFirstElement();
2873 $bf->prepend($baseChain);
2876 $this->buildJoinMap($buildFrom);
2879 $field_def = $chain->getSqlDefinition();
2881 elseif (strpos($v,
'ref.') === 0)
2883 $definition = str_replace(
'ref.',
'', $v);
2885 if (strpos($definition,
'.') !==
false)
2888 'Reference chain `%s` is not allowed here. First-level definitions only.', $v
2892 $absDefinition = $refDefinition <>
''? $refDefinition.
'.'.$definition : $definition;
2895 if ($isBackReference)
2898 $this->buildJoinMap(array($chain));
2902 $chain->getLastElement()->setParameter(
'talias', $alias_ref);
2905 $this->buildJoinMap(array($chain));
2911 $buildFromChains = $this->collectExprChains($chain);
2914 foreach ($buildFromChains as $buildFromChain)
2916 if (!$isBackReference && $buildFromChain->getSize() > $chain->getSize())
2919 'Reference chain `%s` is not allowed here. First-level definitions only.',
2920 $buildFromChain->getDefinition()
2924 if ($buildFromChain->getSize() === $chain->getSize())
2927 $buildFromChain->getLastElement()->setParameter(
'talias', $alias_ref);
2931 $this->buildJoinMap($buildFromChains);
2934 $field_def = $chain->getSqlDefinition();
2941 $v = new \CSQLWhereExpression($field_def);
2945 throw new Main\SystemException(sprintf(
'Unknown reference value `%s`, it should start with "this." or "ref."', $v));
2968 protected function prepareJoinFilterReference(Filter $reference, $alias_this, $alias_ref, $baseDefinition, $refDefinition, $isBackReference, $firstCall =
true)
2973 $reference = clone $reference;
2976 foreach ($reference->getConditions() as $condition)
2978 if ($condition instanceof Filter)
2994 $field = $condition->getDefinition();
2996 if (strpos($field,
'this.') === 0)
2999 $definition = str_replace(
'this.',
'', $field);
3000 $absDefinition = $baseDefinition <>
''? $baseDefinition.
'.'.$definition : $definition;
3004 if (!$isBackReference)
3007 $this->buildJoinMap(array($chain));
3011 $chain->getLastElement()->setParameter(
'talias', $alias_this);
3017 $this->collectExprChains($chain);
3018 $buildFrom = $chain->getLastElement()->getValue()->getBuildFromChains();
3020 foreach ($buildFrom as $bf)
3023 $baseChain = clone $chain;
3026 $baseChain->removeLastElement();
3029 $bf->removeFirstElement();
3032 $bf->prepend($baseChain);
3035 $this->buildJoinMap($buildFrom);
3038 $condition->setColumn($absDefinition);
3040 elseif (strpos($field,
'ref.') === 0)
3042 $definition = str_replace(
'ref.',
'', $field);
3044 if (strpos($definition,
'.') !==
false)
3047 'Reference chain `%s` is not allowed here. First-level definitions only.', $field
3051 $absDefinition = $refDefinition <>
''? $refDefinition.
'.'.$definition : $definition;
3054 if ($isBackReference)
3057 $this->buildJoinMap(array($chain));
3061 $chain->getLastElement()->setParameter(
'talias', $alias_ref);
3067 $this->collectExprChains($chain);
3068 $this->buildJoinMap($chain->getLastElement()->getValue()->getBuildFromChains());
3071 $condition->setColumn($absDefinition);
3075 throw new Main\SystemException(sprintf(
'Unknown reference key `%s`, it should start with "this." or "ref."', $field));
3079 $v = $condition->getValue();
3084 $v->setConnection($this->entity->getConnection());
3088 if (strpos($v->getDefinition(),
'this.') === 0)
3090 $definition = str_replace(
'this.',
'', $v->getDefinition());
3091 $absDefinition = $baseDefinition <>
''? $baseDefinition.
'.'.$definition : $definition;
3095 if (!$isBackReference)
3098 $this->buildJoinMap(array($chain));
3102 $chain->getLastElement()->setParameter(
'talias', $alias_this);
3108 $this->collectExprChains($chain);
3109 $buildFrom = $chain->getLastElement()->getValue()->getBuildFromChains();
3111 foreach ($buildFrom as $bf)
3114 $baseChain = clone $chain;
3117 $baseChain->removeLastElement();
3120 $bf->removeFirstElement();
3123 $bf->prepend($baseChain);
3126 $this->buildJoinMap($buildFrom);
3129 $v->setDefinition($absDefinition);
3131 elseif (strpos($v->getDefinition(),
'ref.') === 0)
3133 $definition = str_replace(
'ref.',
'', $v->getDefinition());
3135 if (strpos($definition,
'.') !==
false)
3138 'Reference chain `%s` is not allowed here. First-level definitions only.', $v->getDefinition()
3142 $absDefinition = $refDefinition <>
''? $refDefinition.
'.'.$definition : $definition;
3145 if ($isBackReference)
3148 $this->buildJoinMap(array($chain));
3152 $chain->getLastElement()->setParameter(
'talias', $alias_ref);
3155 $this->buildJoinMap(array($chain));
3161 $buildFromChains = $this->collectExprChains($chain);
3164 foreach ($buildFromChains as $buildFromChain)
3166 if (!$isBackReference && $buildFromChain->getSize() > $chain->getSize())
3169 'Reference chain `%s` is not allowed here. First-level definitions only.',
3170 $buildFromChain->getDefinition()
3174 if ($buildFromChain->getSize() === $chain->getSize())
3177 $buildFromChain->getLastElement()->setParameter(
'talias', $alias_ref);
3181 $this->buildJoinMap($buildFromChains);
3184 $v->setDefinition($absDefinition);
3197 foreach ($reference as $k => $v)
3211 $sqlWhere = new \CSQLWhere();
3212 $csw_result = $sqlWhere->makeOperation($k);
3213 list($field, ) = array_values($csw_result);
3215 $fields[$field] = array(
3216 'TABLE_ALIAS' =>
'alias',
3217 'FIELD_NAME' => $field,
3218 'FIELD_TYPE' =>
'string',
3236 protected function checkChainsAggregation($chain)
3239 $chains = is_array($chain) ? $chain : array($chain);
3241 foreach ($chains as $chain)
3243 $last = $chain->getLastElement();
3255 protected function checkChainsDistinct($chain)
3258 $chains = is_array($chain) ? $chain : array($chain);
3260 foreach ($chains as $chain)
3262 $field = $chain->getLastElement()->getValue();
3264 if ($field instanceof ExpressionField)
3266 $expression = $field->getFullExpression();
3267 $expression = ExpressionField::removeSubqueries($expression);
3269 preg_match_all(
'/(?:^|[^a-z0-9_])(DISTINCT)[\s\(]+/i', $expression, $matches);
3271 if (!empty($matches[1]))
3283 return !empty($this->group_chains) || !empty($this->having_chains)
3284 || $this->checkChainsAggregation($this->select_chains)
3285 || $this->checkChainsAggregation($this->order_chains);
3290 $this->is_distinct = (bool) $distinct;
3297 $distinctInSelect = $this->checkChainsDistinct($this->select_chains);
3299 if ($distinctInSelect && $this->is_distinct)
3302 $this->is_distinct =
false;
3305 return ($distinctInSelect || $this->is_distinct);
3317 protected function collectExprChains(
Chain $chain, $storages = array(
'hidden'))
3320 $bf_chains = $last_elem->getValue()->getBuildFromChains();
3322 $pre_chain = clone $chain;
3324 $scopedBuildFrom = [];
3326 foreach ($bf_chains as $bf_chain)
3329 $tmp_chain = clone $pre_chain;
3333 $bf_elements = array_slice($bf_chain->getAllElements(), 1);
3336 foreach ($bf_elements as $bf_element)
3338 $tmp_chain->addElement($bf_element);
3343 foreach ($storages as $storage)
3345 $reg_chain = $this->registerChain($storage, $tmp_chain);
3350 $bf_chain->removeLastElement();
3352 $bf_chain->addElement($reg_chain->getLastElement());
3355 $scoped_bf_chain = clone $pre_chain;
3356 $scoped_bf_chain->removeLastElement();
3359 $tail = array_slice($reg_chain->getAllElements(), $pre_chain->getSize());
3361 foreach ($tail as $tailElement)
3363 $scoped_bf_chain->addElement($tailElement);
3366 $scopedBuildFrom[] = $scoped_bf_chain;
3370 foreach ($bf_elements as $bf_element)
3372 if ($bf_element->getValue() instanceof ExpressionField)
3374 $this->collectExprChains($tmp_chain);
3379 return $scopedBuildFrom;
3388 if ($this->unionHandler ===
null)
3390 $this->unionHandler =
new Union($this->entity->getConnection());
3393 return $this->unionHandler;
3400 if (isset($this->global_chains[$alias]))
3402 if ($this->global_chains[$alias]->getDefinition() == $chain->
getDefinition())
3404 $reg_chain = $this->global_chains[$alias];
3412 $reg_chain = $chain;
3414 $this->global_chains[$reg_chain->getDefinition()] = $chain;
3419 $this->global_chains[$alias] = $chain;
3424 $reg_chain = $chain;
3427 $this->global_chains[$alias] = $chain;
3428 $this->global_chains[$def] = $chain;
3431 $storage_name = $section .
'_chains';
3434 if (!isset($this->{$storage_name}[$alias]))
3436 $this->{$storage_name}[$alias] = $reg_chain;
3440 if (!is_null($opt_key))
3442 $this->{$storage_name}[$opt_key] = $reg_chain;
3458 if (isset($this->global_chains[$key]))
3460 return $this->global_chains[$key];
3465 $chain = Chain::getChainByDefinition($this->entity, $key);
3476 return 'UALIAS_'.($this->uniqueAliasCounter++);
3481 $value = ($operation ==
'SE') ? $value : !$value;
3482 return ($value ?
'' :
'NOT ') . $field;
3487 return $field.
' IS '.($operation ==
'SE' ?
'' :
'NOT ') .
'NULL';
3492 return $field.
' IN ('.$value.
')';
3503 protected function query($query)
3506 $connection = $this->entity->getConnection();
3507 $configuration = $connection->getConfiguration();
3512 if (isset($configuration[
'handlersocket'][
'read']))
3515 $nosqlConnectionName = $configuration[
'handlersocket'][
'read'];
3517 $nosqlConnection = Main\Application::getInstance()->getConnectionPool()->getConnection($nosqlConnectionName);
3520 if ($isNosqlCapable)
3526 if (!empty($nosqlResult))
3531 foreach ($this->getSelectChains() as $selectChain)
3533 $field = $selectChain->getLastElement()->getValue();
3537 $converter = $connection->getSqlHelper()->getConverter($field);
3539 if (is_callable($converter))
3541 $converter[$selectChain->getAlias()] = $converter;
3546 if (!empty($converters))
3548 $result->setConverters($converters);
3554 if ($result ===
null)
3557 $result = $connection->query($query);
3558 $result->setReplacedAliases($this->replaced_aliases);
3560 if($this->countTotal)
3562 if ($this->limit && ($result->getSelectedRowsCount() < $this->limit))
3565 $result->setCount((
int) $this->offset + $result->getSelectedRowsCount());
3567 elseif (empty($this->limit))
3570 $result->setCount($result->getSelectedRowsCount());
3579 static::$last_query = $query;
3584 $result->addFetchDataModifier(array($this,
'fetchDataModificationCallback'));
3592 if ($this->query_build_parts ===
null)
3597 $buildParts = $this->query_build_parts;
3600 unset($buildParts[
'ORDER BY']);
3603 $buildParts[
'SELECT'] =
"1 cntholder";
3605 foreach ($buildParts as $k => &$v)
3610 $cntQuery = join(
"\n", $buildParts);
3614 "SELECT COUNT(cntholder) AS TMP_ROWS_CNT FROM ({$cntQuery}) xxx";
3616 return $this->entity->getConnection()->queryScalar($cntQuery);
3626 foreach ($this->selectFetchModifiers as $alias => $modifiers)
3628 foreach ($modifiers as $modifier)
3630 $data[$alias] = call_user_func_array($modifier, array($data[$alias], $this, $data, $alias));
3642 $this->selectFetchModifiers = array();
3644 foreach ($this->select_chains as $chain)
3646 if ($chain->getLastElement()->getValue()->getFetchDataModifiers())
3648 $this->selectFetchModifiers[$chain->getAlias()] = $chain->getLastElement()->getValue()->getFetchDataModifiers();
3652 return !empty($this->selectFetchModifiers) || !empty($this->files);
3664 $connection = $this->entity->getConnection();
3665 $helper = $connection->getSqlHelper();
3667 $length = (int) $helper->getAliasLength();
3668 $leftQuote = $helper->getLeftQuote();
3669 $rightQuote = $helper->getRightQuote();
3671 $replaced = array();
3674 '/ AS '.preg_quote($leftQuote).
'([a-z0-9_]{'.($length+1).
',})'.preg_quote($rightQuote).
'/i',
3678 if (!empty($matches[1]))
3680 foreach ($matches[1] as $alias)
3682 $newAlias =
'FALIAS_'.count($replaced);
3683 $replaced[$newAlias] = $alias;
3685 $query = str_replace(
3686 ' AS ' . $helper->quote($alias),
3687 ' AS ' . $helper->quote($newAlias) .
'/* '.$alias.
' */',
3693 return array($query, $replaced);
3705 if (!preg_match(
'/\s*\(\s*SELECT.*\)\s*/is', $source))
3707 $source = $this->entity->getConnection()->getSqlHelper()->quote($source);
3715 $this->entity = clone $this->entity;
3717 $this->filterHandler = clone $this->filterHandler;
3718 $this->whereHandler = clone $this->whereHandler;
3719 $this->havingHandler = clone $this->havingHandler;
3721 foreach ($this->select as $k => $v)
3725 $this->select[$k] = clone $v;
3736 if (empty($this->global_chains))
3741 foreach ($this->global_chains as $chain)
3743 if ($chain->hasBackReference())
3757 return $this->global_chains;
3765 return $this->group_chains;
3773 return $this->hidden_chains;
3781 return $this->having_chains;
3789 return $this->filter_chains;
3797 return $this->order_chains;
3805 return $this->select_chains;
3813 return $this->where_chains;
3821 return $this->runtime_chains;
3826 return $this->join_map;
3840 return $this->
buildQuery($forceObjectPrimary);
3850 return static::$last_query;
3855 return $this->entity;
3871 $query =
new static($entity);
3873 if (
$filter instanceof Filter)
3886 return $query->query_build_parts[
'WHERE'];
3897 if ($this->custom_base_table_alias !==
null)
3899 return $this->custom_base_table_alias;
3902 $init_alias = strtolower($this->entity->getCode());
3907 $init_alias .= $this->table_alias_postfix;
3911 $connection = $this->entity->getConnection();
3912 $aliasLength = $connection->getSqlHelper()->getAliasLength();
3914 if (strlen($init_alias) > $aliasLength)
3916 $init_alias =
'base';
3921 $init_alias .= $this->table_alias_postfix;
3930 return $this->replaced_aliases;
3940 $this->cacheTtl = (int)$ttl;
3959 echo
'last query: ';
3960 var_dump(static::$last_query);
3963 echo
'size of select_chains: '.count($this->select_chains);
3965 foreach ($this->select_chains as $num => $chain)
3967 echo
' chain ['.$num.
'] has '.$chain->getSize().
' elements: '.PHP_EOL;
3972 echo PHP_EOL.PHP_EOL;
3974 echo
'size of where_chains: '.count($this->where_chains);
3976 foreach ($this->where_chains as $num => $chain)
3978 echo
' chain ['.$num.
'] has '.$chain->getSize().
' elements: '.PHP_EOL;
3983 echo PHP_EOL.PHP_EOL;
3985 echo
'size of group_chains: '.count($this->group_chains);
3987 foreach ($this->group_chains as $num => $chain)
3989 echo
' chain ['.$num.
'] has '.$chain->getSize().
' elements: '.PHP_EOL;
3994 echo PHP_EOL.PHP_EOL;
3996 echo
'size of having_chains: '.count($this->having_chains);
3998 foreach ($this->having_chains as $num => $chain)
4000 echo
' chain ['.$num.
'] has '.$chain->getSize().
' elements: '.PHP_EOL;
4005 echo PHP_EOL.PHP_EOL;
4007 echo
'size of filter_chains: '.count($this->filter_chains);
4009 foreach ($this->filter_chains as $num => $chain)
4011 echo
' chain ['.$num.
'] has '.$chain->getSize().
' elements: '.PHP_EOL;
4016 echo PHP_EOL.PHP_EOL;
4018 echo
'size of select_expr_chains: '.count($this->select_expr_chains);
4020 foreach ($this->select_expr_chains as $num => $chain)
4022 echo
' chain ['.$num.
'] has '.$chain->getSize().
' elements: '.PHP_EOL;
4027 echo PHP_EOL.PHP_EOL;
4029 echo
'size of hidden_chains: '.count($this->hidden_chains);
4031 foreach ($this->hidden_chains as $num => $chain)
4033 echo
' chain ['.$num.
'] has '.$chain->getSize().
' elements: '.PHP_EOL;
4038 echo PHP_EOL.PHP_EOL;
4040 echo
'size of global_chains: '.count($this->global_chains);
4042 foreach ($this->global_chains as $num => $chain)
4044 echo
' chain ['.$num.
'] has '.$chain->getSize().
' elements: '.PHP_EOL;
4049 echo PHP_EOL.PHP_EOL;
4051 var_dump($this->join_map);