diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php index b086c1785..8434e49b2 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php @@ -2643,6 +2643,42 @@ class ClassMetadataInfo implements ClassMetadata return $this->name; } + /** + * Gets the (possibly quoted) identifier column names for safe use in an SQL statement. + * + * @param AbstractPlatform $platform + * @return array + */ + public function getQuotedIdentifierColumnNames($platform) + { + $quotedColumnNames = array(); + + foreach ($this->identifier as $idProperty) { + if (isset($this->fieldMappings[$idProperty])) { + $quotedColumnNames[] = isset($this->fieldMappings[$idProperty]['quoted']) + ? $platform->quoteIdentifier($this->fieldMappings[$idProperty]['columnName']) + : $this->fieldMappings[$idProperty]['columnName']; + + continue; + } + + // Association defined as Id field + $joinColumns = $this->associationMappings[$idProperty]['joinColumns']; + $assocQuotedColumnNames = array_map( + function ($joinColumn) { + return isset($joinColumn['quoted']) + ? $platform->quoteIdentifier($joinColumn['name']) + : $joinColumn['name']; + }, + $joinColumns + ); + + $quotedColumnNames = array_merge($quotedColumnNames, $assocQuotedColumnNames); + } + + return $quotedColumnNames; + } + /** * Gets the (possibly quoted) column name of a mapped field for safe use * in an SQL statement. diff --git a/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php b/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php index e2ed4f95d..b8f83bed0 100644 --- a/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php +++ b/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php @@ -42,21 +42,21 @@ class SizeFunction extends FunctionNode */ public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) { - $platform = $sqlWalker->getConnection()->getDatabasePlatform(); - $dqlAlias = $this->collectionPathExpression->identificationVariable; - $assocField = $this->collectionPathExpression->field; + $quoteStrategy = $sqlWalker->getEntityManager()->getQuoteStrategy(); + $dqlAlias = $this->collectionPathExpression->identificationVariable; + $assocField = $this->collectionPathExpression->field; - $qComp = $sqlWalker->getQueryComponent($dqlAlias); - $class = $qComp['metadata']; - $assoc = $class->associationMappings[$assocField]; - $sql = 'SELECT COUNT(*) FROM '; + $qComp = $sqlWalker->getQueryComponent($dqlAlias); + $class = $qComp['metadata']; + $assoc = $class->associationMappings[$assocField]; + $sql = 'SELECT COUNT(*) FROM '; if ($assoc['type'] == \Doctrine\ORM\Mapping\ClassMetadata::ONE_TO_MANY) { - $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']); - $targetTableAlias = $sqlWalker->getSQLTableAlias($targetClass->getTableName()); - $sourceTableAlias = $sqlWalker->getSQLTableAlias($class->getTableName(), $dqlAlias); + $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']); + $targetTableAlias = $sqlWalker->getSQLTableAlias($targetClass->getTableName()); + $sourceTableAlias = $sqlWalker->getSQLTableAlias($class->getTableName(), $dqlAlias); - $sql .= $targetClass->getQuotedTableName($platform) . ' ' . $targetTableAlias . ' WHERE '; + $sql .= $quoteStrategy->getTableName($targetClass) . ' ' . $targetTableAlias . ' WHERE '; $owningAssoc = $targetClass->associationMappings[$assoc['mappedBy']]; @@ -67,7 +67,7 @@ class SizeFunction extends FunctionNode $sql .= $targetTableAlias . '.' . $sourceColumn . ' = ' - . $sourceTableAlias . '.' . $class->getQuotedColumnName($class->fieldNames[$targetColumn], $platform); + . $sourceTableAlias . '.' . $quoteStrategy->getColumnName($class->fieldNames[$targetColumn], $class); } } else { // many-to-many $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']); @@ -80,7 +80,7 @@ class SizeFunction extends FunctionNode $sourceTableAlias = $sqlWalker->getSQLTableAlias($class->getTableName(), $dqlAlias); // join to target table - $sql .= $targetClass->getQuotedJoinTableName($owningAssoc, $platform) . ' ' . $joinTableAlias . ' WHERE '; + $sql .= $quoteStrategy->getJoinTableName($owningAssoc, $targetClass) . ' ' . $joinTableAlias . ' WHERE '; $joinColumns = $assoc['isOwningSide'] ? $joinTable['joinColumns'] @@ -91,8 +91,8 @@ class SizeFunction extends FunctionNode foreach ($joinColumns as $joinColumn) { if ($first) $first = false; else $sql .= ' AND '; - $sourceColumnName = $class->getQuotedColumnName( - $class->fieldNames[$joinColumn['referencedColumnName']], $platform + $sourceColumnName = $quoteStrategy->getColumnName( + $class->fieldNames[$joinColumn['referencedColumnName']], $class ); $sql .= $joinTableAlias . '.' . $joinColumn['name'] diff --git a/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php b/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php index 02cc8a54b..5bb37834b 100644 --- a/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php +++ b/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php @@ -47,17 +47,18 @@ class MultiTableDeleteExecutor extends AbstractSqlExecutor */ public function __construct(AST\Node $AST, $sqlWalker) { - $em = $sqlWalker->getEntityManager(); - $conn = $em->getConnection(); - $platform = $conn->getDatabasePlatform(); + $em = $sqlWalker->getEntityManager(); + $conn = $em->getConnection(); + $platform = $conn->getDatabasePlatform(); + $quoteStrategy = $em->getQuoteStrategy(); - $primaryClass = $em->getClassMetadata($AST->deleteClause->abstractSchemaName); - $primaryDqlAlias = $AST->deleteClause->aliasIdentificationVariable; - $rootClass = $em->getClassMetadata($primaryClass->rootEntityName); + $primaryClass = $em->getClassMetadata($AST->deleteClause->abstractSchemaName); + $primaryDqlAlias = $AST->deleteClause->aliasIdentificationVariable; + $rootClass = $em->getClassMetadata($primaryClass->rootEntityName); - $tempTable = $platform->getTemporaryTableName($rootClass->getTemporaryIdTableName()); - $idColumnNames = $rootClass->getIdentifierColumnNames(); - $idColumnList = implode(', ', $idColumnNames); + $tempTable = $platform->getTemporaryTableName($rootClass->getTemporaryIdTableName()); + $idColumnNames = $rootClass->getIdentifierColumnNames(); + $idColumnList = implode(', ', $idColumnNames); // 1. Create an INSERT INTO temptable ... SELECT identifiers WHERE $AST->getWhereClause() $sqlWalker->setSQLTableAlias($primaryClass->getTableName(), 't0', $primaryDqlAlias); @@ -80,7 +81,7 @@ class MultiTableDeleteExecutor extends AbstractSqlExecutor // 3. Create and store DELETE statements $classNames = array_merge($primaryClass->parentClasses, array($primaryClass->name), $primaryClass->subClasses); foreach (array_reverse($classNames) as $className) { - $tableName = $em->getClassMetadata($className)->getQuotedTableName($platform); + $tableName = $quoteStrategy->getTableName($em->getClassMetadata($className)); $this->_sqlStatements[] = 'DELETE FROM ' . $tableName . ' WHERE (' . $idColumnList . ') IN (' . $idSubselect . ')'; } diff --git a/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php b/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php index 575e6dfb8..9f18ff8e8 100644 --- a/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php +++ b/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php @@ -50,20 +50,20 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor */ public function __construct(AST\Node $AST, $sqlWalker) { - $em = $sqlWalker->getEntityManager(); - $conn = $em->getConnection(); - $platform = $conn->getDatabasePlatform(); + $em = $sqlWalker->getEntityManager(); + $conn = $em->getConnection(); + $platform = $conn->getDatabasePlatform(); + $quoteStrategy = $em->getQuoteStrategy(); - $updateClause = $AST->updateClause; + $updateClause = $AST->updateClause; + $primaryClass = $sqlWalker->getEntityManager()->getClassMetadata($updateClause->abstractSchemaName); + $rootClass = $em->getClassMetadata($primaryClass->rootEntityName); - $primaryClass = $sqlWalker->getEntityManager()->getClassMetadata($updateClause->abstractSchemaName); - $rootClass = $em->getClassMetadata($primaryClass->rootEntityName); + $updateItems = $updateClause->updateItems; - $updateItems = $updateClause->updateItems; - - $tempTable = $platform->getTemporaryTableName($rootClass->getTemporaryIdTableName()); - $idColumnNames = $rootClass->getIdentifierColumnNames(); - $idColumnList = implode(', ', $idColumnNames); + $tempTable = $platform->getTemporaryTableName($rootClass->getTemporaryIdTableName()); + $idColumnNames = $rootClass->getIdentifierColumnNames(); + $idColumnList = implode(', ', $idColumnNames); // 1. Create an INSERT INTO temptable ... SELECT identifiers WHERE $AST->getWhereClause() $sqlWalker->setSQLTableAlias($primaryClass->getTableName(), 't0', $updateClause->aliasIdentificationVariable); @@ -86,7 +86,7 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor foreach (array_reverse($classNames) as $className) { $affected = false; $class = $em->getClassMetadata($className); - $updateSql = 'UPDATE ' . $class->getQuotedTableName($platform) . ' SET '; + $updateSql = 'UPDATE ' . $quoteStrategy->getTableName($class) . ' SET '; foreach ($updateItems as $updateItem) { $field = $updateItem->pathExpression->field; diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php index 3955b8c3d..d3cc44407 100644 --- a/lib/Doctrine/ORM/Tools/SchemaTool.php +++ b/lib/Doctrine/ORM/Tools/SchemaTool.php @@ -47,12 +47,19 @@ class SchemaTool /** * @var \Doctrine\ORM\EntityManager */ - private $_em; + private $em; /** * @var \Doctrine\DBAL\Platforms\AbstractPlatform */ - private $_platform; + private $platform; + + /** + * The quote strategy. + * + * @var \Doctrine\ORM\Mapping\QuoteStrategy + */ + protected $quoteStrategy; /** * Initializes a new SchemaTool instance that uses the connection of the @@ -62,8 +69,9 @@ class SchemaTool */ public function __construct(EntityManager $em) { - $this->_em = $em; - $this->_platform = $em->getConnection()->getDatabasePlatform(); + $this->em = $em; + $this->quoteStrategy = $em->getQuoteStrategy(); + $this->platform = $em->getConnection()->getDatabasePlatform(); } /** @@ -76,7 +84,7 @@ class SchemaTool public function createSchema(array $classes) { $createSchemaSql = $this->getCreateSchemaSql($classes); - $conn = $this->_em->getConnection(); + $conn = $this->em->getConnection(); foreach ($createSchemaSql as $sql) { try { @@ -97,7 +105,7 @@ class SchemaTool public function getCreateSchemaSql(array $classes) { $schema = $this->getSchemaFromMetadata($classes); - return $schema->toSql($this->_platform); + return $schema->toSql($this->platform); } /** @@ -124,23 +132,22 @@ class SchemaTool */ public function getSchemaFromMetadata(array $classes) { - $processedClasses = array(); // Reminder for processed classes, used for hierarchies + // Reminder for processed classes, used for hierarchies + $processedClasses = array(); + $eventManager = $this->em->getEventManager(); + $schemaManager = $this->em->getConnection()->getSchemaManager(); + $metadataSchemaConfig = $schemaManager->createSchemaConfig(); - $sm = $this->_em->getConnection()->getSchemaManager(); - $metadataSchemaConfig = $sm->createSchemaConfig(); $metadataSchemaConfig->setExplicitForeignKeyIndexes(false); $schema = new Schema(array(), array(), $metadataSchemaConfig); - $evm = $this->_em->getEventManager(); - foreach ($classes as $class) { if ($this->processingNotRequired($class, $processedClasses)) { continue; } - $table = $schema->createTable($class->getQuotedTableName($this->_platform)); - - $columns = array(); // table columns + $table = $schema->createTable($this->quoteStrategy->getTableName($class)); + $columns = array(); // table columns if ($class->isInheritanceTypeSingleTable()) { $columns = $this->_gatherColumns($class, $table); @@ -156,7 +163,7 @@ class SchemaTool } foreach ($class->subClasses as $subClassName) { - $subClass = $this->_em->getClassMetadata($subClassName); + $subClass = $this->em->getClassMetadata($subClassName); $this->_gatherColumns($subClass, $table); $this->_gatherRelationsSql($subClass, $table, $schema); $processedClasses[$subClassName] = true; @@ -166,7 +173,7 @@ class SchemaTool $pkColumns = array(); foreach ($class->fieldMappings as $fieldName => $mapping) { if ( ! isset($mapping['inherited'])) { - $columnName = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform); + $columnName = $this->quoteStrategy->getColumnName($mapping['fieldName'], $class); $this->_gatherColumn($class, $mapping, $table); if ($class->isIdentifier($fieldName)) { @@ -185,7 +192,7 @@ class SchemaTool /* @var \Doctrine\ORM\Mapping\ClassMetadata $class */ $idMapping = $class->fieldMappings[$class->identifier[0]]; $this->_gatherColumn($class, $idMapping, $table); - $columnName = $class->getQuotedColumnName($class->identifier[0], $this->_platform); + $columnName = $this->quoteStrategy->getColumnName($class->identifier[0], $class); // TODO: This seems rather hackish, can we optimize it? $table->getColumn($columnName)->setAutoincrement(false); @@ -193,7 +200,7 @@ class SchemaTool // Add a FK constraint on the ID column $table->addUnnamedForeignKeyConstraint( - $this->_em->getClassMetadata($class->rootEntityName)->getQuotedTableName($this->_platform), + $this->quoteStrategy->getTableName($this->em->getClassMetadata($class->rootEntityName)), array($columnName), array($columnName), array('onDelete' => 'CASCADE') ); } @@ -210,7 +217,7 @@ class SchemaTool $pkColumns = array(); foreach ($class->identifier as $identifierField) { if (isset($class->fieldMappings[$identifierField])) { - $pkColumns[] = $class->getQuotedColumnName($identifierField, $this->_platform); + $pkColumns[] = $this->quoteStrategy->getColumnName($identifierField, $class); } else if (isset($class->associationMappings[$identifierField])) { /* @var $assoc \Doctrine\ORM\Mapping\OneToOne */ $assoc = $class->associationMappings[$identifierField]; @@ -255,17 +262,17 @@ class SchemaTool } } - if ($evm->hasListeners(ToolEvents::postGenerateSchemaTable)) { - $evm->dispatchEvent(ToolEvents::postGenerateSchemaTable, new GenerateSchemaTableEventArgs($class, $schema, $table)); + if ($eventManager->hasListeners(ToolEvents::postGenerateSchemaTable)) { + $eventManager->dispatchEvent(ToolEvents::postGenerateSchemaTable, new GenerateSchemaTableEventArgs($class, $schema, $table)); } } - if ( ! $this->_platform->supportsSchemas() && ! $this->_platform->canEmulateSchemas() ) { + if ( ! $this->platform->supportsSchemas() && ! $this->platform->canEmulateSchemas() ) { $schema->visit(new RemoveNamespacedAssets()); } - if ($evm->hasListeners(ToolEvents::postGenerateSchema)) { - $evm->dispatchEvent(ToolEvents::postGenerateSchema, new GenerateSchemaEventArgs($this->_em, $schema)); + if ($eventManager->hasListeners(ToolEvents::postGenerateSchema)) { + $eventManager->dispatchEvent(ToolEvents::postGenerateSchema, new GenerateSchemaEventArgs($this->em, $schema)); } return $schema; @@ -321,7 +328,7 @@ class SchemaTool $column = $this->_gatherColumn($class, $mapping, $table); if ($class->isIdentifier($mapping['fieldName'])) { - $pkColumns[] = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform); + $pkColumns[] = $this->quoteStrategy->getColumnName($mapping['fieldName'], $class); } } @@ -344,7 +351,7 @@ class SchemaTool */ private function _gatherColumn($class, array $mapping, $table) { - $columnName = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform); + $columnName = $this->quoteStrategy->getColumnName($mapping['fieldName'], $class); $columnType = $mapping['type']; $options = array(); @@ -417,7 +424,7 @@ class SchemaTool continue; } - $foreignClass = $this->_em->getClassMetadata($mapping['targetEntity']); + $foreignClass = $this->em->getClassMetadata($mapping['targetEntity']); if ($mapping['type'] & ClassMetadata::TO_ONE && $mapping['isOwningSide']) { $primaryKeyColumns = $uniqueConstraints = array(); // PK is unnecessary for this relation-type @@ -434,7 +441,7 @@ class SchemaTool // create join table $joinTable = $mapping['joinTable']; - $theJoinTable = $schema->createTable($foreignClass->getQuotedJoinTableName($mapping, $this->_platform)); + $theJoinTable = $schema->createTable($this->quoteStrategy->getJoinTableName($mapping, $foreignClass)); $primaryKeyColumns = $uniqueConstraints = array(); @@ -477,7 +484,7 @@ class SchemaTool foreach ($class->getIdentifierFieldNames() as $fieldName) { if ($class->hasAssociation($fieldName) && $class->getSingleAssociationJoinColumnName($fieldName) == $referencedColumnName) { return $this->getDefiningClass( - $this->_em->getClassMetadata($class->associationMappings[$fieldName]['targetEntity']), + $this->em->getClassMetadata($class->associationMappings[$fieldName]['targetEntity']), $class->getSingleAssociationReferencedJoinColumnName($fieldName) ); } @@ -499,10 +506,10 @@ class SchemaTool */ private function _gatherRelationJoinColumns($joinColumns, $theJoinTable, $class, $mapping, &$primaryKeyColumns, &$uniqueConstraints) { - $localColumns = array(); - $foreignColumns = array(); - $fkOptions = array(); - $foreignTableName = $class->getQuotedTableName($this->_platform); + $localColumns = array(); + $foreignColumns = array(); + $fkOptions = array(); + $foreignTableName = $this->quoteStrategy->getTableName($class); foreach ($joinColumns as $joinColumn) { $columnName = $joinColumn['name']; @@ -572,7 +579,7 @@ class SchemaTool public function dropSchema(array $classes) { $dropSchemaSql = $this->getDropSchemaSQL($classes); - $conn = $this->_em->getConnection(); + $conn = $this->em->getConnection(); foreach ($dropSchemaSql as $sql) { try { @@ -591,7 +598,7 @@ class SchemaTool public function dropDatabase() { $dropSchemaSql = $this->getDropDatabaseSQL(); - $conn = $this->_em->getConnection(); + $conn = $this->em->getConnection(); foreach ($dropSchemaSql as $sql) { $conn->executeQuery($sql); @@ -605,10 +612,10 @@ class SchemaTool */ public function getDropDatabaseSQL() { - $sm = $this->_em->getConnection()->getSchemaManager(); + $sm = $this->em->getConnection()->getSchemaManager(); $schema = $sm->createSchema(); - $visitor = new \Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector($this->_platform); + $visitor = new \Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector($this->platform); /* @var $schema \Doctrine\DBAL\Schema\Schema */ $schema->visit($visitor); return $visitor->getQueries(); @@ -622,10 +629,10 @@ class SchemaTool */ public function getDropSchemaSQL(array $classes) { - $visitor = new \Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector($this->_platform); + $visitor = new \Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector($this->platform); $schema = $this->getSchemaFromMetadata($classes); - $sm = $this->_em->getConnection()->getSchemaManager(); + $sm = $this->em->getConnection()->getSchemaManager(); $fullSchema = $sm->createSchema(); foreach ($fullSchema->getTables() as $table) { if (!$schema->hasTable($table->getName())) { @@ -643,7 +650,7 @@ class SchemaTool } } - if ($this->_platform->supportsSequences()) { + if ($this->platform->supportsSequences()) { foreach ($schema->getSequences() as $sequence) { $visitor->acceptSequence($sequence); } @@ -676,7 +683,7 @@ class SchemaTool public function updateSchema(array $classes, $saveMode=false) { $updateSchemaSql = $this->getUpdateSchemaSql($classes, $saveMode); - $conn = $this->_em->getConnection(); + $conn = $this->em->getConnection(); foreach ($updateSchemaSql as $sql) { $conn->executeQuery($sql); @@ -695,7 +702,7 @@ class SchemaTool */ public function getUpdateSchemaSql(array $classes, $saveMode=false) { - $sm = $this->_em->getConnection()->getSchemaManager(); + $sm = $this->em->getConnection()->getSchemaManager(); $fromSchema = $sm->createSchema(); $toSchema = $this->getSchemaFromMetadata($classes); @@ -704,9 +711,9 @@ class SchemaTool $schemaDiff = $comparator->compare($fromSchema, $toSchema); if ($saveMode) { - return $schemaDiff->toSaveSql($this->_platform); + return $schemaDiff->toSaveSql($this->platform); } else { - return $schemaDiff->toSql($this->_platform); + return $schemaDiff->toSql($this->platform); } } }