From a6d9236ef245b04c93b5beb8c068a8c371c91cf8 Mon Sep 17 00:00:00 2001 From: romanb Date: Tue, 5 May 2009 17:20:55 +0000 Subject: [PATCH] [2.0] Fixes and enhancements to sequence generators. Test suite now runs & passes against postgres. Other minor, unrelated cleanups. --- COPYRIGHT | 4 +- lib/Doctrine/DBAL/Connection.php | 42 ++++----- lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php | 22 ++++- .../DBAL/Platforms/AbstractPlatform.php | 76 ++++++---------- .../DBAL/Platforms/OraclePlatform.php | 72 +++++---------- .../DBAL/Platforms/PostgreSqlPlatform.php | 25 +----- lib/Doctrine/ORM/Cache/ArrayCache.php | 2 +- lib/Doctrine/ORM/Configuration.php | 1 + lib/Doctrine/ORM/Id/SequenceGenerator.php | 4 +- .../ORM/Import/Reader/AbstractReader.php | 40 --------- lib/Doctrine/ORM/Import/Reader/Db.php | 90 ------------------- lib/Doctrine/ORM/Import/Reader/Propel.php | 54 ----------- lib/Doctrine/ORM/Mapping/ClassMetadata.php | 7 +- .../ORM/Mapping/ClassMetadataFactory.php | 12 ++- .../ORM/Mapping/Driver/AnnotationDriver.php | 12 +-- .../Mapping/Driver/DoctrineAnnotations.php | 1 + .../ORM/Mapping/Driver/YamlDriver.php | 28 ++++-- lib/Doctrine/ORM/Tools/SchemaTool.php | 21 ++++- lib/Doctrine/ORM/UnitOfWork.php | 4 +- .../Functional/SingleTableInheritanceTest.php | 2 +- .../Tests/ORM/Id/SequenceGeneratorTest.php | 2 +- 21 files changed, 170 insertions(+), 351 deletions(-) delete mode 100644 lib/Doctrine/ORM/Import/Reader/AbstractReader.php delete mode 100644 lib/Doctrine/ORM/Import/Reader/Db.php delete mode 100644 lib/Doctrine/ORM/Import/Reader/Propel.php diff --git a/COPYRIGHT b/COPYRIGHT index b636ae96b..8c445d0db 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -6,8 +6,8 @@ Doctrine Doctrine is a Object Relational Mapper built from scratch with PHP5. It contains a few ports of other popular PHP classes/libraries. -Url: http://www.phpdoctrine.org -Copyright: 2005-2007 Konsta Vesterinen +Url: http://www.doctrine-project.org +Copyright: 2005-2009 Konsta Vesterinen License: LGPL - see LICENSE file symfony diff --git a/lib/Doctrine/DBAL/Connection.php b/lib/Doctrine/DBAL/Connection.php index 13b8383fe..d47c0c825 100644 --- a/lib/Doctrine/DBAL/Connection.php +++ b/lib/Doctrine/DBAL/Connection.php @@ -149,6 +149,13 @@ class Connection * @var Doctrine\DBAL\Driver */ protected $_driver; + + /** + * Whether to quote identifiers. Read from the configuration upon construction. + * + * @var boolean + */ + protected $_quoteIdentifiers = false; /** * Initializes a new instance of the Connection class. @@ -171,14 +178,18 @@ class Connection // Create default config and event manager if none given if ( ! $config) { - $this->_config = new Configuration(); + $config = new Configuration(); } if ( ! $eventManager) { - $this->_eventManager = new EventManager(); + $eventManager = new EventManager(); } + $this->_config = $config; + $this->_eventManager = $eventManager; $this->_platform = $driver->getDatabasePlatform(); $this->_transactionIsolationLevel = $this->_platform->getDefaultTransactionIsolationLevel(); + $this->_quoteIdentifiers = $config->getQuoteIdentifiers(); + $this->_platform->setQuoteIdentifiers($this->_quoteIdentifiers); } /** @@ -354,29 +365,15 @@ class Connection } /** - * Quote a string so it can be safely used as a table or column name. + * Quote a string so it can be safely used as a table or column name, even if + * it is a reserved name. * - * Delimiting style depends on which database driver is being used. + * Delimiting style depends on the underlying database platform that is being used. * - * NOTE: just because you CAN use delimited identifiers doesn't mean + * NOTE: Just because you CAN use delimited identifiers doesn't mean * you SHOULD use them. In general, they end up causing way more * problems than they solve. * - * Portability is broken by using the following characters inside - * delimited identifiers: - * + backtick (`) -- due to MySQL - * + double quote (") -- due to Oracle - * + brackets ([ or ]) -- due to Access - * - * Delimited identifiers are known to generally work correctly under - * the following drivers: - * + mssql - * + mysql - * + mysqli - * + oci8 - * + pgsql - * + sqlite - * * @param string $str identifier name to be quoted * @param bool $checkOption check the 'quote_identifier' option * @@ -384,7 +381,10 @@ class Connection */ public function quoteIdentifier($str) { - return $this->_platform->quoteIdentifier($str); + if ($this->_quoteIdentifiers) { + return $this->_platform->quoteIdentifier($str); + } + return $str; } /** diff --git a/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php b/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php index 119ac8049..f07407cdd 100644 --- a/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php +++ b/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php @@ -42,7 +42,27 @@ class Driver implements \Doctrine\DBAL\Driver */ private function _constructPdoDsn(array $params) { - //TODO + $dsn = 'oci:'; + if (isset($params['host'])) { + $dsn .= 'dbname=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)' . + '(HOST=' . $params['host'] . ')'; + + if (isset($params['port'])) { + $dsn .= '(PORT=' . $params['port'] . ')'; + } else { + $dsn .= '(PORT=1521)'; + } + + $dsn .= '))(CONNECT_DATA=(SID=' . $params['dbname'] . ')))'; + } else { + $dsn .= 'dbname=' . $params['dbname']; + } + + if (isset($params['charset'])) { + $dsn .= ';charset=' . $params['charset']; + } + + return $dsn; } public function getDatabasePlatform() diff --git a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php index 929e5c8d6..7b47f61be 100644 --- a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php @@ -35,21 +35,7 @@ use Doctrine\DBAL\Connection; */ abstract class AbstractPlatform { - protected $_quoteIdentifiers = false; - - protected $valid_default_values = array( - 'text' => '', - 'boolean' => true, - 'integer' => 0, - 'decimal' => 0.0, - 'float' => 0.0, - 'timestamp' => '1970-01-01 00:00:00', - 'time' => '00:00:00', - 'date' => '1970-01-01', - 'clob' => '', - 'blob' => '', - 'string' => '' - ); + private $_quoteIdentifiers = false; /** * Constructor. @@ -61,7 +47,7 @@ abstract class AbstractPlatform */ public function setQuoteIdentifiers($bool) { - $this->_quoteIdentifiers = (bool)$bool; + $this->_quoteIdentifiers = $bool; } /** @@ -986,39 +972,34 @@ abstract class AbstractPlatform } /** - * Enter description here... + * Gets the SQL statement(s) to create a table with the specified name, columns and options + * on this platform. * - * @todo Throw exception by default? + * @param string $table + * @param array $columns + * @param array $options + * @return array */ public function getCreateTableSql($table, array $columns, array $options = array()) { - if ( ! $table) { - throw DoctrineException::updateMe('no valid table name specified'); - } - if (empty($columns)) { - throw DoctrineException::updateMe('no fields specified for table ' . $name); - } - - $queryFields = $this->getColumnDeclarationListSql($columns); + $columnListSql = $this->getColumnDeclarationListSql($columns); if (isset($options['primary']) && ! empty($options['primary'])) { - $queryFields .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')'; + $columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')'; } if (isset($options['indexes']) && ! empty($options['indexes'])) { foreach($options['indexes'] as $index => $definition) { - $queryFields .= ', ' . $this->getIndexDeclaration($index, $definition); + $columnListSql .= ', ' . $this->getIndexDeclarationSql($index, $definition); } } - $query = 'CREATE TABLE ' . $this->quoteIdentifier($table, true) . ' (' . $queryFields; + $query = 'CREATE TABLE ' . $this->quoteIdentifier($table, true) . ' (' . $columnListSql; - /*$check = $this->getCheckDeclaration($columns); - + $check = $this->getCheckDeclarationSql($columns); if ( ! empty($check)) { $query .= ', ' . $check; - }*/ - + } $query .= ')'; $sql[] = $query; @@ -1030,13 +1011,18 @@ abstract class AbstractPlatform } } } + return $sql; } /** - * Enter description here... + * Gets the SQL to create a sequence on this platform. * - * @todo Throw exception by default? + * @param string $sequenceName + * @param integer $start + * @param integer $allocationSize + * @return string + * @throws DoctrineException */ public function getCreateSequenceSql($sequenceName, $start = 1, $allocationSize = 1) { @@ -1044,7 +1030,7 @@ abstract class AbstractPlatform } /** - * Creates a constraint on a table. + * Gets the SQL to create a constraint on a table on this platform. * * @param string $table name of the table on which the constraint is to be created * @param string $name name of the constraint to be created @@ -1062,6 +1048,7 @@ abstract class AbstractPlatform * 'last_login' => array() * ) * ) + * @return string */ public function getCreateConstraintSql($table, $name, $definition) { @@ -1083,12 +1070,11 @@ abstract class AbstractPlatform } /** - * Get the stucture of a field into an array + * Gets the SQL to create an index on a table on this platform. * * @param string $table name of the table on which the index is to be created * @param string $name name of the index to be created * @param array $definition associative array that defines properties of the index to be created. - * @see Doctrine_Export::createIndex() * @return string */ public function getCreateIndexSql($table, $name, array $definition) @@ -1116,22 +1102,14 @@ abstract class AbstractPlatform } /** - * Quote a string so it can be safely used as a table or column name. + * Quotes a string so that it can be safely used as a table or column name, + * even if it is a reserved word of the platform. * - * Delimiting style depends on which database driver is being used. - * - * NOTE: just because you CAN use delimited identifiers doesn't mean + * NOTE: Just because you CAN use quoted identifiers doesn't mean * you SHOULD use them. In general, they end up causing way more * problems than they solve. * - * Portability is broken by using the following characters inside - * delimited identifiers: - * + backtick (`) -- due to MySQL - * + double quote (") -- due to Oracle - * + brackets ([ or ]) -- due to Access - * * @param string $str identifier name to be quoted - * @param bool $checkOption check the 'quote_identifier' option * @return string quoted identifier string */ public function quoteIdentifier($str) diff --git a/lib/Doctrine/DBAL/Platforms/OraclePlatform.php b/lib/Doctrine/DBAL/Platforms/OraclePlatform.php index 483e36a6e..5b543df53 100644 --- a/lib/Doctrine/DBAL/Platforms/OraclePlatform.php +++ b/lib/Doctrine/DBAL/Platforms/OraclePlatform.php @@ -16,15 +16,13 @@ * * This software consists of voluntary contributions made by many individuals * and is licensed under the LGPL. For more information, see - * . + * . */ namespace Doctrine\DBAL\Platforms; /** - * Base class for all DatabasePlatforms. The DatabasePlatforms are the central - * point of abstraction of platform-specific behaviors, features and SQL dialects. - * They are a passive source of information. + * OraclePlatform. * * @since 2.0 * @author Roman Borschel @@ -40,24 +38,10 @@ class OraclePlatform extends AbstractPlatform parent::__construct(); } - /** - * Adds an driver-specific LIMIT clause to the query - * - * @param string $query query to modify - * @param integer $limit limit the number of rows - * @param integer $offset start reading from given offset - * @return string the modified query - * @override - */ - public function writeLimitClause($query, $limit = false, $offset = false) - { - return $this->_createLimitSubquery($query, $limit, $offset); - } - /** * @todo Doc */ - private function _createLimitSubquery($query, $limit, $offset, $column = null) + /*private function _createLimitSubquery($query, $limit, $offset, $column = null) { $limit = (int) $limit; $offset = (int) $offset; @@ -81,27 +65,7 @@ class OraclePlatform extends AbstractPlatform } } return $query; - } - - /** - * Creates the SQL for Oracle that can be used in the subquery for the limit-subquery - * algorithm. - * - * @override - */ - public function writeLimitClauseInSubquery(Doctrine_ClassMetadata $rootClass, - $query, $limit = false, $offset = false) - { - // NOTE: no composite key support - $columnNames = $rootClass->getIdentifierColumnNames(); - if (count($columnNames) > 1) { - throw \Doctrine\Common\DoctrineException::updateMe("Composite keys in LIMIT queries are " - . "currently not supported."); - } - $column = $columnNames[0]; - - return $this->_createLimitSubquery($query, $limit, $offset, $column); - } + }*/ /** * return string to call a function to get a substring inside an SQL statement @@ -188,7 +152,7 @@ class OraclePlatform extends AbstractPlatform * declare the specified field. * @override */ - public function getNativeDeclaration(array $field) + /*public function getNativeDeclaration(array $field) { if ( ! isset($field['type'])) { throw \Doctrine\Common\DoctrineException::updateMe('Missing column type.'); @@ -232,7 +196,7 @@ class OraclePlatform extends AbstractPlatform default: } throw \Doctrine\Common\DoctrineException::updateMe('Unknown field type \'' . $field['type'] . '\'.'); - } + }*/ /** * Maps a native array description of a field to a doctrine datatype and length @@ -242,7 +206,7 @@ class OraclePlatform extends AbstractPlatform * @throws Doctrine_DataDict_Oracle_Exception * @override */ - public function getPortableDeclaration(array $field) + /*public function getPortableDeclaration(array $field) { if ( ! isset($field['data_type'])) { throw \Doctrine\Common\DoctrineException::updateMe('Native oracle definition must have a data_type key specified'); @@ -332,12 +296,24 @@ class OraclePlatform extends AbstractPlatform 'length' => $length, 'unsigned' => $unsigned, 'fixed' => $fixed); + }*/ + + /** + * {@inheritdoc} + * + * @return string + * @override + */ + public function getCreateSequenceSql($sequenceName, $start = 1, $allocationSize = 1) + { + return 'CREATE SEQUENCE ' . $this->quoteIdentifier($sequenceName) + . ' START WITH ' . $start . ' INCREMENT BY ' . $allocationSize; } /** - * Enter description here... + * {@inheritdoc} * - * @param unknown_type $sequenceName + * @param string $sequenceName * @override */ public function getSequenceNextValSql($sequenceName) @@ -346,9 +322,9 @@ class OraclePlatform extends AbstractPlatform } /** - * Enter description here... + * {@inheritdoc} * - * @param unknown_type $level + * @param integer $level * @override */ public function getSetTransactionIsolationSql($level) @@ -359,7 +335,7 @@ class OraclePlatform extends AbstractPlatform /** * Enter description here... * - * @param unknown_type $level + * @param integer $level * @override */ protected function _getTransactionIsolationLevelSql($level) diff --git a/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php b/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php index d3f37d11c..7dc0d9c8a 100644 --- a/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php @@ -288,7 +288,6 @@ class PostgreSqlPlatform extends AbstractPlatform public function getMd5Expression($column) { $column = $this->quoteIdentifier($column); - if ($this->_version > 7) { return 'MD5(' . $column . ')'; } else { @@ -795,17 +794,8 @@ class PostgreSqlPlatform extends AbstractPlatform } /** - * return RDBMS specific create sequence statement - * - * @throws Doctrine\DBAL\ConnectionException if something fails at database level - * @param string $seqName name of the sequence to be created - * @param string $start start value of the sequence; default is 1 - * @param array $options An associative array of table options: - * array( - * 'comment' => 'Foo', - * 'charset' => 'utf8', - * 'collate' => 'utf8_unicode_ci', - * ); + * {@inheritdoc} + * * @return string * @override */ @@ -836,22 +826,15 @@ class PostgreSqlPlatform extends AbstractPlatform */ public function getCreateTableSql($name, array $fields, array $options = array()) { - if ( ! $name) { - throw DoctrineException::updateMe('no valid table name specified'); - } - if (empty($fields)) { - throw DoctrineException::updateMe('no fields specified for table ' . $name); - } - $queryFields = $this->getColumnDeclarationListSql($fields); if (isset($options['primary']) && ! empty($options['primary'])) { - $keyColumns = array_values($options['primary']); + $keyColumns = array_unique(array_values($options['primary'])); $keyColumns = array_map(array($this, 'quoteIdentifier'), $keyColumns); $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; } - $query = 'CREATE TABLE ' . $this->quoteIdentifier($name, true) . ' (' . $queryFields . ')'; + $query = 'CREATE TABLE ' . $this->quoteIdentifier($name) . ' (' . $queryFields . ')'; $sql[] = $query; diff --git a/lib/Doctrine/ORM/Cache/ArrayCache.php b/lib/Doctrine/ORM/Cache/ArrayCache.php index 58b90b9ad..6a6d2ff39 100644 --- a/lib/Doctrine/ORM/Cache/ArrayCache.php +++ b/lib/Doctrine/ORM/Cache/ArrayCache.php @@ -16,7 +16,7 @@ * * This software consists of voluntary contributions made by many individuals * and is licensed under the LGPL. For more information, see - * . + * . */ namespace Doctrine\ORM\Cache; diff --git a/lib/Doctrine/ORM/Configuration.php b/lib/Doctrine/ORM/Configuration.php index 4d13cebd7..f04c8b987 100644 --- a/lib/Doctrine/ORM/Configuration.php +++ b/lib/Doctrine/ORM/Configuration.php @@ -39,6 +39,7 @@ class Configuration extends \Doctrine\DBAL\Configuration */ public function __construct() { + parent::__construct(); $this->_attributes = array_merge($this->_attributes, array( 'resultCacheImpl' => null, 'queryCacheImpl' => null, diff --git a/lib/Doctrine/ORM/Id/SequenceGenerator.php b/lib/Doctrine/ORM/Id/SequenceGenerator.php index 4aaec13f4..45e932d52 100644 --- a/lib/Doctrine/ORM/Id/SequenceGenerator.php +++ b/lib/Doctrine/ORM/Id/SequenceGenerator.php @@ -62,8 +62,8 @@ class SequenceGenerator extends AbstractIdGenerator implements \Serializable // Allocate new values $conn = $em->getConnection(); $sql = $conn->getDatabasePlatform()->getSequenceNextValSql($this->_sequenceName); - $this->_maxValue = $conn->fetchOne($sql); - $this->_nextValue = $this->_maxValue - $this->_allocationSize; + $this->_nextValue = $conn->fetchOne($sql); + $this->_maxValue = $this->_nextValue + $this->_allocationSize; } return $this->_nextValue++; } diff --git a/lib/Doctrine/ORM/Import/Reader/AbstractReader.php b/lib/Doctrine/ORM/Import/Reader/AbstractReader.php deleted file mode 100644 index 6e1483d51..000000000 --- a/lib/Doctrine/ORM/Import/Reader/AbstractReader.php +++ /dev/null @@ -1,40 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Import\Reader; - -/** - * class Doctrine_Import_Reader - * Is responsible of reading a database definitions from a source and costructing a - * database schema - * - * @package Doctrine - * @subpackage Import - * @link www.phpdoctrine.org - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @since 1.0 - * @version $Revision: 3882 $ - * @author Konsta Vesterinen - */ -abstract class AbstractRader -{ - abstract public function read(); -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Import/Reader/Db.php b/lib/Doctrine/ORM/Import/Reader/Db.php deleted file mode 100644 index 3936e12fb..000000000 --- a/lib/Doctrine/ORM/Import/Reader/Db.php +++ /dev/null @@ -1,90 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Import\Reader; - -/** - * class Doctrine_Import_Reader_Db - * Reads a database using the given PDO connection and constructs a database - * schema - * - * @package Doctrine - * @subpackage Import - * @link www.phpdoctrine.org - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @since 1.0 - * @version $Revision: 3882 $ - * @author Konsta Vesterinen - */ -class Db extends AbstractReader -{ - /** - * @access private - */ - private $pdo; - - /** - * - * @param object pdo * @return - * @access public - */ - public function setPdo( $pdo ) - { - - } // end of member function setPdo - - /** - * - * @return Doctrine_Schema - * @access public - */ - public function read() - { - $dataDict = Doctrine_Manager::getInstance()->getCurrentConnection()->getDataDict(); - - $schema = new Doctrine_Schema(); /* @todo FIXME i am incomplete*/ - $db = new Doctrine_Schema_Database(); - $schema->addDatabase($db); - - $dbName = 'XXtest'; // @todo FIXME where should we get - - $this->conn->set("name",$dbName); - $tableNames = $dataDict->listTables(); - foreach ($tableNames as $tableName) { - $table = new Doctrine_Schema_Table(); - $table->set("name",$tableName); - $tableColumns = $dataDict->listTableColumns($tableName); - foreach ($tableColumns as $tableColumn) { - $table->addColumn($tableColumn); - } - $this->conn->addTable($table); - if ($fks = $dataDict->listTableConstraints($tableName)) { - foreach ($fks as $fk) { - $relation = new Doctrine_Schema_Relation(); - $relation->setRelationBetween($fk['referencingColumn'],$fk['referencedTable'],$fk['referencedColumn']); - $table->setRelation($relation); - } - } - } - - return $schema; - } -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Import/Reader/Propel.php b/lib/Doctrine/ORM/Import/Reader/Propel.php deleted file mode 100644 index 9ec8fd922..000000000 --- a/lib/Doctrine/ORM/Import/Reader/Propel.php +++ /dev/null @@ -1,54 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Import\Reader; - -/** - * class Doctrine_Import_Reader_Xml_Propel - * - * @package Doctrine - * @subpackage Import - * @link www.phpdoctrine.org - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @since 1.0 - * @version $Revision: 3882 $ - * @author Konsta Vesterinen - */ -class Propel extends AbstractReader -{ - /** - * @access private - */ - private $xml; - - /** - * - * @param string xml * @return - * @access public - */ - public function setXml( $xml ) - { - - } // end of member function setXml - - public function read() - { } -} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadata.php b/lib/Doctrine/ORM/Mapping/ClassMetadata.php index dd386a96e..066232b5b 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadata.php @@ -873,10 +873,11 @@ final class ClassMetadata } /** + * Sets the value of a field on an entity of the mapped class. * - * @param $entity - * @param $field - * @param $value + * @param object $entity + * @param string $field + * @param mixed $value */ public function setValue($entity, $field, $value) { diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php index 55de5d03c..4532de41f 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php @@ -141,7 +141,17 @@ class ClassMetadataFactory if ( ! $class->getIdentifier()) { throw MappingException::identifierRequired($className); } - $this->_completeIdGeneratorMapping($class); + if ($parent) { + if ($parent->isIdGeneratorSequence()) { + $class->setSequenceGeneratorDefinition($parent->getSequenceGeneratorDefinition()); + } else if ($parent->isIdGeneratorTable()) { + $class->getTableGeneratorDefinition($parent->getTableGeneratorDefinition()); + } + $class->setIdGeneratorType($parent->getIdGeneratorType()); + $class->setidGenerator($parent->getIdGenerator()); + } else { + $this->_completeIdGeneratorMapping($class); + } if ($parent && $parent->isInheritanceTypeSingleTable()) { $class->setTableName($parent->getTableName()); diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php index e2c46ddc6..0a5241abc 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php @@ -75,12 +75,7 @@ class AnnotationDriver 'length' => $discrColumnAnnot->length )); } -/* - // Evaluate DoctrineDiscriminatorMap annotation - if ($discrMapAnnot = $annotClass->getAnnotation('DoctrineDiscriminatorMap')) { - $metadata->setDiscriminatorMap((array)$discrMapAnnot->value); - } -*/ + // Evaluate DoctrineDiscriminatorMap annotation if ($discrValueAnnot = $annotClass->getAnnotation('DoctrineDiscriminatorValue')) { $metadata->setDiscriminatorValue($discrValueAnnot->value); @@ -91,6 +86,11 @@ class AnnotationDriver $metadata->setSubclasses($subClassesAnnot->value); } + // Evaluate DoctrineChangeTrackingPolicy annotation + if ($changeTrackingAnnot = $annotClass->getAnnotation('DoctrineChangeTrackingPolicy')) { + $metadata->setChangeTrackingPolicy($changeTrackingAnnot->value); + } + // Evaluate annotations on properties/fields foreach ($annotClass->getProperties() as $property) { if ($metadata->hasField($property->getName())) { diff --git a/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php b/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php index cbc88070a..087ade4d7 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php +++ b/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php @@ -96,3 +96,4 @@ final class DoctrineSequenceGenerator extends \Addendum\Annotation { /** The name of the class that defines the generator. */ //public $definingClass; } +final class DoctrineChangeTrackingPolicy {} diff --git a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php index bf6566585..3c7318782 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php @@ -1,4 +1,23 @@ . + */ namespace Doctrine\ORM\Mapping\Driver; @@ -12,7 +31,7 @@ if ( ! class_exists('sfYaml', false)) { } /** - * The YamlDriver reads the mapping metadata from yaml schema files + * The YamlDriver reads the mapping metadata from yaml schema files. * * @author Jonathan H. Wage * @since 2.0 @@ -54,8 +73,8 @@ class YamlDriver $metadata->setDiscriminatorColumn($entity['discriminatorColumn']); } - if (isset($entity['discriminatorMap']) && $entity['discriminatorMap']) { - $metadata->setDiscriminatorMap((array) $entity['discriminatorMap']); + if (isset($entity['discriminatorValue']) && $entity['discriminatorValue']) { + $metadata->setDiscriminatorValue($entity['discriminatorValue']); } if (isset($entity['subClasses']) && $entity['subClasses']) { @@ -82,8 +101,7 @@ class YamlDriver if (in_array($type, $relationTypes)) { unset($property['type']); - switch ($type) - { + switch ($type) { case 'ManyToOne': case 'OneToOne': $mapping['joinColumns'] = $joinColumns; diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php index 4f5547c3c..b726311fb 100644 --- a/lib/Doctrine/ORM/Tools/SchemaTool.php +++ b/lib/Doctrine/ORM/Tools/SchemaTool.php @@ -77,9 +77,10 @@ class SchemaTool */ public function getCreateSchemaSql(array $classes) { - $processedClasses = array(); - $sql = array(); - $foreignKeyConstraints = array(); + $sql = array(); // All SQL statements + $processedClasses = array(); // Reminder for processed classes, used for hierarchies + $foreignKeyConstraints = array(); // FK SQL statements. Appended to $sql at the end. + $sequences = array(); // Sequence SQL statements. Appended to $sql at the end. // First we create the tables foreach ($classes as $class) { @@ -116,15 +117,27 @@ class SchemaTool $sql = array_merge($sql, $this->_platform->getCreateTableSql($class->getTableName(), $columns, $options)); $processedClasses[$class->getClassName()] = true; + + if ($class->isIdGeneratorSequence()) { + $seqDef = $class->getSequenceGeneratorDefinition(); + $sequences[] = $this->_platform->getCreateSequenceSql( + $seqDef['sequenceName'], + $seqDef['initialValue'], + $seqDef['allocationSize'] + ); + } } - // Now create the foreign key constraints + // Append the foreign key constraints SQL if ($this->_platform->supportsForeignKeyConstraints()) { foreach ($foreignKeyConstraints as $fkConstraint) { $sql = array_merge($sql, (array)$this->_platform->getCreateForeignKeySql($fkConstraint['tableName'], $fkConstraint)); } } + // Append the sequence SQL + $sql = array_merge($sql, $sequences); + return $sql; } diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 1744dffc3..aa02c583e 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -313,6 +313,8 @@ class UnitOfWork implements PropertyChangedListener $entitySet = $this->_identityMap; } + //TODO: Compute changesets for NEW entities first here + foreach ($entitySet as $className => $entities) { $class = $this->_em->getClassMetadata($className); @@ -338,7 +340,7 @@ class UnitOfWork implements PropertyChangedListener if ($state == self::STATE_MANAGED || $state == self::STATE_NEW) { $actualData = array(); foreach ($class->getReflectionProperties() as $name => $refProp) { - if ( ! $class->isIdentifier($name) || $class->isIdentifierNatural()) { + if ( ! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity()) { $actualData[$name] = $refProp->getValue($entity); } diff --git a/tests/Doctrine/Tests/ORM/Functional/SingleTableInheritanceTest.php b/tests/Doctrine/Tests/ORM/Functional/SingleTableInheritanceTest.php index 7ab3aaa8e..017d1bd5c 100644 --- a/tests/Doctrine/Tests/ORM/Functional/SingleTableInheritanceTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/SingleTableInheritanceTest.php @@ -42,7 +42,7 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->_em->flush(); $this->_em->clear(); - $query = $this->_em->createQuery("select e from Doctrine\Tests\ORM\Functional\ParentEntity e"); + $query = $this->_em->createQuery("select e from Doctrine\Tests\ORM\Functional\ParentEntity e order by e.id asc"); $entities = $query->getResultList(); diff --git a/tests/Doctrine/Tests/ORM/Id/SequenceGeneratorTest.php b/tests/Doctrine/Tests/ORM/Id/SequenceGeneratorTest.php index 0f6307566..6e50d5ad0 100644 --- a/tests/Doctrine/Tests/ORM/Id/SequenceGeneratorTest.php +++ b/tests/Doctrine/Tests/ORM/Id/SequenceGeneratorTest.php @@ -26,7 +26,7 @@ class SequenceGeneratorTest extends \Doctrine\Tests\OrmTestCase { for ($i=0; $i < 42; ++$i) { if ($i % 10 == 0) { - $this->_em->getConnection()->setFetchOneResult((int)($i / 10) * 10 + 10); + $this->_em->getConnection()->setFetchOneResult((int)($i / 10) * 10); } $id = $this->_seqGen->generate($this->_em, null); $this->assertEquals($i, $id);