/** * Gets the SQL snippet for all join columns of the given class that are to be * placed in an SQL SELECT statement. * * @return string */ protected function _getSelectJoinColumnsSQL(ClassMetadata $class) { $sql = ''; foreach ($class->associationMappings as $assoc) { if ($assoc->isOwningSide && $assoc->isOneToOne()) { foreach ($assoc->targetToSourceKeyColumns as $srcColumn) { $columnAlias = $srcColumn . $this->_sqlAliasCounter++; $sql .= ', ' . $this->_getSQLTableAlias($this->_class) . ".{$srcColumn} AS {$columnAlias}"; $resultColumnName = $this->_platform->getSQLResultCasing($columnAlias); if (!isset($this->_resultColumnNames[$resultColumnName])) { $this->_resultColumnNames[$resultColumnName] = $srcColumn; } } } } return $sql; }
/** * Walks down a SelectExpression AST node and generates the corresponding SQL. * * @param SelectExpression $selectExpression * @return string The SQL. */ public function walkSelectExpression($selectExpression) { $sql = ''; $expr = $selectExpression->expression; if ($expr instanceof AST\PathExpression) { if ($expr->type == AST\PathExpression::TYPE_STATE_FIELD) { $parts = $expr->parts; $fieldName = array_pop($parts); $dqlAlias = $expr->identificationVariable . (!empty($parts) ? '.' . implode('.', $parts) : ''); $qComp = $this->_queryComponents[$dqlAlias]; $class = $qComp['metadata']; if (!$selectExpression->fieldIdentificationVariable) { $resultAlias = $fieldName; } else { $resultAlias = $selectExpression->fieldIdentificationVariable; } if ($class->isInheritanceTypeJoined()) { $tableName = $this->_em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName); } else { $tableName = $class->getTableName(); } $sqlTableAlias = $this->getSqlTableAlias($tableName, $dqlAlias); $columnName = $class->getQuotedColumnName($fieldName, $this->_platform); $columnAlias = $this->getSqlColumnAlias($columnName); $sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias); } else { throw QueryException::invalidPathExpression($expr->type); } } else { if ($expr instanceof AST\AggregateExpression) { if (!$selectExpression->fieldIdentificationVariable) { $resultAlias = $this->_scalarResultCounter++; } else { $resultAlias = $selectExpression->fieldIdentificationVariable; } $columnAlias = 'sclr' . $this->_aliasCounter++; $sql .= $this->walkAggregateExpression($expr) . ' AS ' . $columnAlias; $this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias); } else { if ($expr instanceof AST\Subselect) { if (!$selectExpression->fieldIdentificationVariable) { $resultAlias = $this->_scalarResultCounter++; } else { $resultAlias = $selectExpression->fieldIdentificationVariable; } $columnAlias = 'sclr' . $this->_aliasCounter++; $sql .= '(' . $this->walkSubselect($expr) . ') AS ' . $columnAlias; $this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias); } else { if ($expr instanceof AST\Functions\FunctionNode) { if (!$selectExpression->fieldIdentificationVariable) { $resultAlias = $this->_scalarResultCounter++; } else { $resultAlias = $selectExpression->fieldIdentificationVariable; } $columnAlias = 'sclr' . $this->_aliasCounter++; $sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias; $this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias); } else { if ($expr instanceof AST\SimpleArithmeticExpression) { if (!$selectExpression->fieldIdentificationVariable) { $resultAlias = $this->_scalarResultCounter++; } else { $resultAlias = $selectExpression->fieldIdentificationVariable; } $columnAlias = 'sclr' . $this->_aliasCounter++; $sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias; $this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias); } else { // IdentificationVariable or PartialObjectExpression if ($expr instanceof AST\PartialObjectExpression) { $dqlAlias = $expr->identificationVariable; $partialFieldSet = $expr->partialFieldSet; } else { $dqlAlias = $expr; $partialFieldSet = array(); } $queryComp = $this->_queryComponents[$dqlAlias]; $class = $queryComp['metadata']; if (!isset($this->_selectedClasses[$dqlAlias])) { $this->_selectedClasses[$dqlAlias] = $class; } $beginning = true; // Select all fields from the queried class foreach ($class->fieldMappings as $fieldName => $mapping) { if ($partialFieldSet && !in_array($fieldName, $partialFieldSet)) { continue; } if (isset($mapping['inherited'])) { $tableName = $this->_em->getClassMetadata($mapping['inherited'])->primaryTable['name']; } else { $tableName = $class->primaryTable['name']; } if ($beginning) { $beginning = false; } else { $sql .= ', '; } $sqlTableAlias = $this->getSqlTableAlias($tableName, $dqlAlias); $columnAlias = $this->getSqlColumnAlias($mapping['columnName']); $sql .= $sqlTableAlias . '.' . $class->getQuotedColumnName($fieldName, $this->_platform) . ' AS ' . $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name); } // Add any additional fields of subclasses (excluding inherited fields) // 1) on Single Table Inheritance: always, since its marginal overhead // 2) on Class Table Inheritance only if partial objects are disallowed, // since it requires outer joining subtables. if ($class->isInheritanceTypeSingleTable() || !$this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) { foreach ($class->subClasses as $subClassName) { $subClass = $this->_em->getClassMetadata($subClassName); $sqlTableAlias = $this->getSqlTableAlias($subClass->primaryTable['name'], $dqlAlias); foreach ($subClass->fieldMappings as $fieldName => $mapping) { if (isset($mapping['inherited']) || $partialFieldSet && !in_array($fieldName, $partialFieldSet)) { continue; } if ($beginning) { $beginning = false; } else { $sql .= ', '; } $columnAlias = $this->getSqlColumnAlias($mapping['columnName']); $sql .= $sqlTableAlias . '.' . $subClass->getQuotedColumnName($fieldName, $this->_platform) . ' AS ' . $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName); } // Add join columns (foreign keys) of the subclass //TODO: Probably better do this in walkSelectClause to honor the INCLUDE_META_COLUMNS hint foreach ($subClass->associationMappings as $fieldName => $assoc) { if ($assoc->isOwningSide && $assoc->isOneToOne() && !isset($subClass->inheritedAssociationFields[$fieldName])) { foreach ($assoc->targetToSourceKeyColumns as $srcColumn) { if ($beginning) { $beginning = false; } else { $sql .= ', '; } $columnAlias = $this->getSqlColumnAlias($srcColumn); $sql .= $sqlTableAlias . '.' . $srcColumn . ' AS ' . $columnAlias; $this->_rsm->addMetaResult($dqlAlias, $this->_platform->getSQLResultCasing($columnAlias), $srcColumn); } } } } } } } } } } return $sql; }
/** * Gets an SQL column alias for a column name. * * @param string $columnName * @return string */ public function getSQLColumnAlias($columnName) { // Trim the column alias to the maximum identifier length of the platform. // If the alias is to long, characters are cut off from the beginning. return $this->_platform->getSQLResultCasing(substr($columnName . $this->_aliasCounter++, -$this->_platform->getMaxIdentifierLength())); }