示例#1
0
 /**
  * Creates a column definition as required by the DBAL from an ORM field mapping definition.
  *
  * @param ClassMetadata $class The class that owns the field mapping.
  * @param array $mapping The field mapping.
  * @param Table $table
  * @return array The portable column definition as required by the DBAL.
  */
 private function _gatherColumn($class, array $mapping, $table)
 {
     $columnName = $this->quoteStrategy->getColumnName($mapping['fieldName'], $class, $this->platform);
     $columnType = $mapping['type'];
     $options = array();
     $options['length'] = isset($mapping['length']) ? $mapping['length'] : null;
     $options['notnull'] = isset($mapping['nullable']) ? !$mapping['nullable'] : true;
     if ($class->isInheritanceTypeSingleTable() && count($class->parentClasses) > 0) {
         $options['notnull'] = false;
     }
     $options['platformOptions'] = array();
     $options['platformOptions']['version'] = $class->isVersioned && $class->versionField == $mapping['fieldName'] ? true : false;
     if (strtolower($columnType) == 'string' && $options['length'] === null) {
         $options['length'] = 255;
     }
     if (isset($mapping['precision'])) {
         $options['precision'] = $mapping['precision'];
     }
     if (isset($mapping['scale'])) {
         $options['scale'] = $mapping['scale'];
     }
     if (isset($mapping['default'])) {
         $options['default'] = $mapping['default'];
     }
     if (isset($mapping['columnDefinition'])) {
         $options['columnDefinition'] = $mapping['columnDefinition'];
     }
     if (isset($mapping['options'])) {
         if (isset($mapping['options']['comment'])) {
             $options['comment'] = $mapping['options']['comment'];
             unset($mapping['options']['comment']);
         }
         if (isset($mapping['options']['unsigned'])) {
             $options['unsigned'] = $mapping['options']['unsigned'];
             unset($mapping['options']['unsigned']);
         }
         if (isset($mapping['options']['fixed'])) {
             $options['fixed'] = $mapping['options']['fixed'];
             unset($mapping['options']['fixed']);
         }
         $options['customSchemaOptions'] = $mapping['options'];
     }
     if ($class->isIdGeneratorIdentity() && $class->getIdentifierFieldNames() == array($mapping['fieldName'])) {
         $options['autoincrement'] = true;
     }
     if ($class->isInheritanceTypeJoined() && $class->name != $class->rootEntityName) {
         $options['autoincrement'] = false;
     }
     if ($table->hasColumn($columnName)) {
         // required in some inheritance scenarios
         $table->changeColumn($columnName, $options);
     } else {
         $table->addColumn($columnName, $columnType, $options);
     }
     $isUnique = isset($mapping['unique']) ? $mapping['unique'] : false;
     if ($isUnique) {
         $table->addUniqueIndex(array($columnName));
     }
 }
示例#2
0
 public function getEntityHistory($className, $id)
 {
     if (!$this->metadataFactory->isAudited($className)) {
         throw new NotAuditedException($className);
     }
     /** @var ClassMetadataInfo|ClassMetadata $class */
     $class = $this->em->getClassMetadata($className);
     $tableName = $this->config->getTableName($class);
     if (!is_array($id)) {
         $id = array($class->identifier[0] => $id);
     }
     $whereId = array();
     foreach ($class->identifier as $idField) {
         if (isset($class->fieldMappings[$idField])) {
             $columnName = $class->fieldMappings[$idField]['columnName'];
         } else {
             if (isset($class->associationMappings[$idField])) {
                 $columnName = $class->associationMappings[$idField]['joinColumns'][0];
             } else {
                 continue;
             }
         }
         $whereId[] = "{$columnName} = ?";
     }
     $whereSQL = implode(' AND ', $whereId);
     $columnList = array($this->config->getRevisionFieldName());
     $columnMap = array();
     foreach ($class->fieldNames as $columnName => $field) {
         $type = Type::getType($class->fieldMappings[$field]['type']);
         $columnList[] = $type->convertToPHPValueSQL($this->quoteStrategy->getColumnName($field, $class, $this->platform), $this->platform) . ' AS ' . $this->platform->quoteSingleIdentifier($field);
         $columnMap[$field] = $this->platform->getSQLResultCasing($columnName);
     }
     foreach ($class->associationMappings as $assoc) {
         if (($assoc['type'] & ClassMetadata::TO_ONE) == 0 || !$assoc['isOwningSide']) {
             continue;
         }
         foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) {
             $columnList[] = $sourceCol;
             $columnMap[$sourceCol] = $this->platform->getSQLResultCasing($sourceCol);
         }
     }
     $values = array_values($id);
     $query = "SELECT " . implode(', ', $columnList) . " FROM " . $tableName . " e WHERE " . $whereSQL . " ORDER BY e.rev DESC";
     $stmt = $this->em->getConnection()->executeQuery($query, $values);
     $result = array();
     while ($row = $stmt->fetch(Query::HYDRATE_ARRAY)) {
         $rev = $row[$this->config->getRevisionFieldName()];
         unset($row[$this->config->getRevisionFieldName()]);
         $result[] = $this->createEntity($class->name, $columnMap, $row, $rev);
     }
     return $result;
 }
 /**
  * Generates a new order by clause that works in the scope of a select query wrapping the original
  *
  * @param OrderByClause $orderByClause
  * @return array
  */
 private function rebuildOrderByClauseForOuterScope(OrderByClause $orderByClause)
 {
     $dqlAliasToSqlTableAliasMap = $searchPatterns = $replacements = $dqlAliasToClassMap = $selectListAdditions = $orderByItems = [];
     // Generate DQL alias -> SQL table alias mapping
     foreach (array_keys($this->rsm->aliasMap) as $dqlAlias) {
         $dqlAliasToClassMap[$dqlAlias] = $class = $this->queryComponents[$dqlAlias]['metadata'];
         $dqlAliasToSqlTableAliasMap[$dqlAlias] = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
     }
     // Pattern to find table path expressions in the order by clause
     $fieldSearchPattern = '/(?<![a-z0-9_])%s\\.%s(?![a-z0-9_])/i';
     // Generate search patterns for each field's path expression in the order by clause
     foreach ($this->rsm->fieldMappings as $fieldAlias => $fieldName) {
         $dqlAliasForFieldAlias = $this->rsm->columnOwnerMap[$fieldAlias];
         $class = $dqlAliasToClassMap[$dqlAliasForFieldAlias];
         // If the field is from a joined child table, we won't be ordering
         // on it.
         if (!isset($class->fieldMappings[$fieldName])) {
             continue;
         }
         $fieldMapping = $class->fieldMappings[$fieldName];
         // Get the proper column name as will appear in the select list
         $columnName = $this->quoteStrategy->getColumnName($fieldName, $dqlAliasToClassMap[$dqlAliasForFieldAlias], $this->em->getConnection()->getDatabasePlatform());
         // Get the SQL table alias for the entity and field
         $sqlTableAliasForFieldAlias = $dqlAliasToSqlTableAliasMap[$dqlAliasForFieldAlias];
         if (isset($fieldMapping['declared']) && $fieldMapping['declared'] !== $class->name) {
             // Field was declared in a parent class, so we need to get the proper SQL table alias
             // for the joined parent table.
             $otherClassMetadata = $this->em->getClassMetadata($fieldMapping['declared']);
             if (!$otherClassMetadata->isMappedSuperclass) {
                 $sqlTableAliasForFieldAlias = $this->getSQLTableAlias($otherClassMetadata->getTableName(), $dqlAliasForFieldAlias);
             }
         }
         // Compose search/replace patterns
         $searchPatterns[] = sprintf($fieldSearchPattern, $sqlTableAliasForFieldAlias, $columnName);
         $replacements[] = $fieldAlias;
     }
     foreach ($orderByClause->orderByItems as $orderByItem) {
         // Walk order by item to get string representation of it
         $orderByItemString = $this->walkOrderByItem($orderByItem);
         // Replace path expressions in the order by clause with their column alias
         $orderByItemString = preg_replace($searchPatterns, $replacements, $orderByItemString);
         $orderByItems[] = $orderByItemString;
     }
     return $orderByItems;
 }
 private function getUniqueAndRequiredFields(ClassMetadata $meta, $entity)
 {
     $fields = array();
     foreach ($meta->getFieldNames() as $fieldName) {
         $mapping = $meta->getFieldMapping($fieldName);
         if (!empty($mapping['id']) && $meta->usesIdGenerator()) {
             // autogenerated id
             continue;
         }
         if (!empty($mapping['nullable']) && empty($mapping['unique'])) {
             // is nullable and is not unique
             continue;
         }
         $fields[$fieldName]['value'] = $meta->getFieldValue($entity, $fieldName);
         $fields[$fieldName]['quotedColumn'] = $this->quotes->getColumnName($fieldName, $meta, $this->platform);
         $fields[$fieldName]['type'] = Type::getType($mapping['type']);
     }
     return $fields;
 }
 /**
  * Generates a new order by clause that works in the scope of a select query wrapping the original
  *
  * @param OrderByClause $orderByClause
  * @return array
  */
 private function rebuildOrderByClauseForOuterScope(OrderByClause $orderByClause)
 {
     $dqlAliasToSqlTableAliasMap = $searchPatterns = $replacements = $dqlAliasToClassMap = $selectListAdditions = $orderByItems = [];
     // Generate DQL alias -> SQL table alias mapping
     foreach (array_keys($this->rsm->aliasMap) as $dqlAlias) {
         $dqlAliasToClassMap[$dqlAlias] = $class = $this->queryComponents[$dqlAlias]['metadata'];
         $dqlAliasToSqlTableAliasMap[$dqlAlias] = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
     }
     // Pattern to find table path expressions in the order by clause
     $fieldSearchPattern = '/(?<![a-z0-9_])%s\\.%s(?![a-z0-9_])/i';
     // Generate search patterns for each field's path expression in the order by clause
     foreach ($this->rsm->fieldMappings as $fieldAlias => $columnName) {
         $dqlAliasForFieldAlias = $this->rsm->columnOwnerMap[$fieldAlias];
         $columnName = $this->quoteStrategy->getColumnName($columnName, $dqlAliasToClassMap[$dqlAliasForFieldAlias], $this->em->getConnection()->getDatabasePlatform());
         $sqlTableAliasForFieldAlias = $dqlAliasToSqlTableAliasMap[$dqlAliasForFieldAlias];
         $searchPatterns[] = sprintf($fieldSearchPattern, $sqlTableAliasForFieldAlias, $columnName);
         $replacements[] = $fieldAlias;
     }
     $complexAddedOrderByAliases = 0;
     foreach ($orderByClause->orderByItems as $orderByItem) {
         // Walk order by item to get string representation of it
         $orderByItemString = $this->walkOrderByItem($orderByItem);
         // Replace path expressions in the order by clause with their column alias
         $orderByItemString = preg_replace($searchPatterns, $replacements, $orderByItemString);
         // The order by items are not required to be in the select list on Oracle and PostgreSQL, but
         // for the sake of simplicity, order by items will be included in the select list on all platforms.
         // This doesn't impact functionality.
         $selectListAddition = trim(preg_replace('/([^ ]+) (?:asc|desc)/i', '$1', $orderByItemString));
         // If the expression is an arithmetic expression, we need to create an alias for it.
         if ($orderByItem->expression instanceof ArithmeticTerm) {
             $orderByAlias = "ordr_" . $complexAddedOrderByAliases++;
             $orderByItemString = $orderByAlias . " " . $orderByItem->type;
             $selectListAddition .= " AS {$orderByAlias}";
         }
         $selectListAdditions[] = $selectListAddition;
         $orderByItems[] = $orderByItemString;
     }
     return array($selectListAdditions, $orderByItems);
 }
 /**
  * @param ClassMetadata $class
  *
  * @return string
  * @throws \Doctrine\DBAL\DBALException
  */
 private function getInsertRevisionSQL($class)
 {
     if (!isset($this->insertRevisionSQL[$class->name])) {
         $placeholders = array('?', '?');
         $tableName = $this->config->getTableName($class);
         $sql = "INSERT INTO " . $tableName . " (" . $this->config->getRevisionFieldName() . ", " . $this->config->getRevisionTypeFieldName();
         $fields = array();
         foreach ($class->associationMappings as $field => $assoc) {
             if ($class->isInheritanceTypeJoined() && $class->isInheritedAssociation($field)) {
                 continue;
             }
             if (($assoc['type'] & ClassMetadata::TO_ONE) > 0 && $assoc['isOwningSide']) {
                 foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) {
                     $fields[$sourceCol] = true;
                     $sql .= ', ' . $sourceCol;
                     $placeholders[] = '?';
                 }
             }
         }
         foreach ($class->fieldNames as $field) {
             if (array_key_exists($field, $fields)) {
                 continue;
             }
             if ($class->isInheritanceTypeJoined() && $class->isInheritedField($field) && !$class->isIdentifier($field)) {
                 continue;
             }
             $type = Type::getType($class->fieldMappings[$field]['type']);
             $placeholders[] = !empty($class->fieldMappings[$field]['requireSQLConversion']) ? $type->convertToDatabaseValueSQL('?', $this->platform) : '?';
             $sql .= ', ' . $this->quoteStrategy->getColumnName($field, $class, $this->platform);
         }
         if ($class->isInheritanceTypeJoined() && $class->rootEntityName == $class->name || $class->isInheritanceTypeSingleTable()) {
             $sql .= ', ' . $class->discriminatorColumn['name'];
             $placeholders[] = '?';
         }
         $sql .= ") VALUES (" . implode(", ", $placeholders) . ")";
         $this->insertRevisionSQL[$class->name] = $sql;
     }
     return $this->insertRevisionSQL[$class->name];
 }
示例#7
0
 /**
  * {@inheritdoc}
  */
 public function walkCollectionMemberExpression($collMemberExpr)
 {
     $sql = $collMemberExpr->not ? 'NOT ' : '';
     $sql .= 'EXISTS (SELECT 1 FROM ';
     $entityExpr = $collMemberExpr->entityExpression;
     $collPathExpr = $collMemberExpr->collectionValuedPathExpression;
     $fieldName = $collPathExpr->field;
     $dqlAlias = $collPathExpr->identificationVariable;
     $class = $this->queryComponents[$dqlAlias]['metadata'];
     switch (true) {
         // InputParameter
         case $entityExpr instanceof AST\InputParameter:
             $dqlParamKey = $entityExpr->name;
             $entitySql = '?';
             break;
             // SingleValuedAssociationPathExpression | IdentificationVariable
         // SingleValuedAssociationPathExpression | IdentificationVariable
         case $entityExpr instanceof AST\PathExpression:
             $entitySql = $this->walkPathExpression($entityExpr);
             break;
         default:
             throw new \BadMethodCallException("Not implemented");
     }
     $assoc = $class->associationMappings[$fieldName];
     if ($assoc['type'] == ClassMetadata::ONE_TO_MANY) {
         $targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
         $targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName());
         $sourceTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
         $sql .= $this->quoteStrategy->getTableName($targetClass, $this->platform) . ' ' . $targetTableAlias . ' WHERE ';
         $owningAssoc = $targetClass->associationMappings[$assoc['mappedBy']];
         $sqlParts = array();
         foreach ($owningAssoc['targetToSourceKeyColumns'] as $targetColumn => $sourceColumn) {
             $targetColumn = $this->quoteStrategy->getColumnName($class->fieldNames[$targetColumn], $class, $this->platform);
             $sqlParts[] = $sourceTableAlias . '.' . $targetColumn . ' = ' . $targetTableAlias . '.' . $sourceColumn;
         }
         foreach ($this->quoteStrategy->getIdentifierColumnNames($targetClass, $this->platform) as $targetColumnName) {
             if (isset($dqlParamKey)) {
                 $this->parserResult->addParameterMapping($dqlParamKey, $this->sqlParamIndex++);
             }
             $sqlParts[] = $targetTableAlias . '.' . $targetColumnName . ' = ' . $entitySql;
         }
         $sql .= implode(' AND ', $sqlParts);
     } else {
         // many-to-many
         $targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
         $owningAssoc = $assoc['isOwningSide'] ? $assoc : $targetClass->associationMappings[$assoc['mappedBy']];
         $joinTable = $owningAssoc['joinTable'];
         // SQL table aliases
         $joinTableAlias = $this->getSQLTableAlias($joinTable['name']);
         $targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName());
         $sourceTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias);
         // join to target table
         $sql .= $this->quoteStrategy->getJoinTableName($owningAssoc, $targetClass, $this->platform) . ' ' . $joinTableAlias . ' INNER JOIN ' . $this->quoteStrategy->getTableName($targetClass, $this->platform) . ' ' . $targetTableAlias . ' ON ';
         // join conditions
         $joinColumns = $assoc['isOwningSide'] ? $joinTable['inverseJoinColumns'] : $joinTable['joinColumns'];
         $joinSqlParts = array();
         foreach ($joinColumns as $joinColumn) {
             $targetColumn = $this->quoteStrategy->getColumnName($targetClass->fieldNames[$joinColumn['referencedColumnName']], $targetClass, $this->platform);
             $joinSqlParts[] = $joinTableAlias . '.' . $joinColumn['name'] . ' = ' . $targetTableAlias . '.' . $targetColumn;
         }
         $sql .= implode(' AND ', $joinSqlParts);
         $sql .= ' WHERE ';
         $joinColumns = $assoc['isOwningSide'] ? $joinTable['joinColumns'] : $joinTable['inverseJoinColumns'];
         $sqlParts = array();
         foreach ($joinColumns as $joinColumn) {
             $targetColumn = $this->quoteStrategy->getColumnName($class->fieldNames[$joinColumn['referencedColumnName']], $class, $this->platform);
             $sqlParts[] = $joinTableAlias . '.' . $joinColumn['name'] . ' = ' . $sourceTableAlias . '.' . $targetColumn;
         }
         foreach ($this->quoteStrategy->getIdentifierColumnNames($targetClass, $this->platform) as $targetColumnName) {
             if (isset($dqlParamKey)) {
                 $this->parserResult->addParameterMapping($dqlParamKey, $this->sqlParamIndex++);
             }
             $sqlParts[] = $targetTableAlias . '.' . $targetColumnName . ' = ' . $entitySql;
         }
         $sql .= implode(' AND ', $sqlParts);
     }
     return $sql . ')';
 }
示例#8
0
    /**
     * Builds the left-hand-side of a where condition statement.
     *
     * @param string     $field
     * @param array|null $assoc
     *
     * @return string
     *
     * @throws \Doctrine\ORM\ORMException
     */
    protected function getSelectConditionStatementColumnSQL($field, $assoc = null)
    {
        if (isset($this->class->columnNames[$field])) {
            $className = (isset($this->class->fieldMappings[$field]['inherited']))
                ? $this->class->fieldMappings[$field]['inherited']
                : $this->class->name;

            return $this->getSQLTableAlias($className) . '.' . $this->quoteStrategy->getColumnName($field, $this->class, $this->platform);
        }

        if (isset($this->class->associationMappings[$field])) {

            if ( ! $this->class->associationMappings[$field]['isOwningSide']) {
                throw ORMException::invalidFindByInverseAssociation($this->class->name, $field);
            }

            $joinColumn = $this->class->associationMappings[$field]['joinColumns'][0];
            $className  = (isset($this->class->associationMappings[$field]['inherited']))
                ? $this->class->associationMappings[$field]['inherited']
                : $this->class->name;

            return $this->getSQLTableAlias($className) . '.' . $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform);
        }

        if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) {
            // very careless developers could potentially open up this normally hidden api for userland attacks,
            // therefore checking for spaces and function calls which are not allowed.

            // found a join column condition, not really a "field"
            return $field;
        }

        throw ORMException::unrecognizedField($field);
    }
 /**
  * Builds the left-hand-side of a where condition statement.
  *
  * @param string     $field
  * @param array|null $assoc
  *
  * @return string[]
  *
  * @throws \Doctrine\ORM\ORMException
  */
 private function getSelectConditionStatementColumnSQL($field, $assoc = null)
 {
     if (isset($this->class->columnNames[$field])) {
         $className = isset($this->class->fieldMappings[$field]['inherited']) ? $this->class->fieldMappings[$field]['inherited'] : $this->class->name;
         return array($this->getSQLTableAlias($className) . '.' . $this->quoteStrategy->getColumnName($field, $this->class, $this->platform));
     }
     if (isset($this->class->associationMappings[$field])) {
         $association = $this->class->associationMappings[$field];
         // Many-To-Many requires join table check for joinColumn
         $columns = array();
         $class = $this->class;
         if ($association['type'] === ClassMetadata::MANY_TO_MANY) {
             if (!$association['isOwningSide']) {
                 $association = $assoc;
             }
             $joinTableName = $this->quoteStrategy->getJoinTableName($association, $class, $this->platform);
             $joinColumns = $assoc['isOwningSide'] ? $association['joinTable']['joinColumns'] : $association['joinTable']['inverseJoinColumns'];
             foreach ($joinColumns as $joinColumn) {
                 $columns[] = $joinTableName . '.' . $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform);
             }
         } else {
             if (!$association['isOwningSide']) {
                 throw ORMException::invalidFindByInverseAssociation($this->class->name, $field);
             }
             $className = isset($association['inherited']) ? $association['inherited'] : $this->class->name;
             foreach ($association['joinColumns'] as $joinColumn) {
                 $columns[] = $this->getSQLTableAlias($className) . '.' . $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform);
             }
         }
         return $columns;
     }
     if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) {
         // very careless developers could potentially open up this normally hidden api for userland attacks,
         // therefore checking for spaces and function calls which are not allowed.
         // found a join column condition, not really a "field"
         return array($field);
     }
     throw ORMException::unrecognizedField($field);
 }
 /**
  * @param DoctrineSqlFilter $sqlFilter
  * @param QuoteStrategy $quoteStrategy
  * @param ClassMetadata $targetEntity
  * @param string $targetTableAlias
  * @param string $targetEntityPropertyName
  * @return string
  * @throws InvalidQueryRewritingConstraintException
  * @throws \Exception
  */
 protected function getSqlForSimpleProperty(DoctrineSqlFilter $sqlFilter, QuoteStrategy $quoteStrategy, ClassMetadata $targetEntity, $targetTableAlias, $targetEntityPropertyName)
 {
     $quotedColumnName = $quoteStrategy->getColumnName($targetEntityPropertyName, $targetEntity, $this->entityManager->getConnection()->getDatabasePlatform());
     $propertyPointer = $targetTableAlias . '.' . $quotedColumnName;
     if (is_array($this->operandDefinition)) {
         foreach ($this->operandDefinition as $operandIterator => $singleOperandValue) {
             $this->setParameter($sqlFilter, $operandIterator, $singleOperandValue);
         }
     } else {
         $this->setParameter($sqlFilter, $this->operandDefinition, $this->operand);
     }
     return $this->getConstraintStringForSimpleProperty($sqlFilter, $propertyPointer);
 }
 /**
  * Gets the SQL snippet of a qualified column name for the given field name.
  *
  * @param string        $field The field name.
  * @param ClassMetadata $class The class that declares this field. The table this class is
  *                             mapped to must own the column for the given field.
  * @param string        $alias
  *
  * @return string
  */
 protected function getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r')
 {
     $root = $alias == 'r' ? '' : $alias;
     $tableAlias = $this->getSQLTableAlias($class->name, $root);
     $columnName = $this->quoteStrategy->getColumnName($field, $class, $this->platform);
     $sql = $tableAlias . '.' . $columnName;
     $columnAlias = $this->getSQLColumnAlias($class->columnNames[$field]);
     $this->currentPersisterContext->rsm->addFieldResult($alias, $columnAlias, $field);
     if (isset($class->fieldMappings[$field]['requireSQLConversion'])) {
         $type = Type::getType($class->getTypeOfField($field));
         $sql = $type->convertToPHPValueSQL($sql, $this->platform);
     }
     return $sql . ' AS ' . $columnAlias;
 }