Commit b1d34fca authored by romanb's avatar romanb

[2.0] Work on SchemaTool and DBAL.

parent 0612e6b0
...@@ -8,15 +8,15 @@ ...@@ -8,15 +8,15 @@
<xs:annotation> <xs:annotation>
<xs:documentation><![CDATA[ <xs:documentation><![CDATA[
This is the XML Schema for the object/relational This is the XML Schema for the object/relational
mapping file used by Doctrine. mapping file used by the Doctrine ORM.
]]></xs:documentation> ]]></xs:documentation>
</xs:annotation> </xs:annotation>
<xs:element name="doctrine-mapping"> <xs:element name="doctrine-mapping">
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:sequence>
<xs:element name="mapped-superclass" type="orm:mapped-superclass" minOccurs="0" /> <xs:element name="mapped-superclass" type="orm:mapped-superclass" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="entity" type="orm:entity" minOccurs="0" /> <xs:element name="entity" type="orm:entity" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
...@@ -52,27 +52,28 @@ ...@@ -52,27 +52,28 @@
<xs:complexType name="lifecycle-callbacks"> <xs:complexType name="lifecycle-callbacks">
<xs:sequence> <xs:sequence>
<xs:element name="lifecycle-callback" type="orm:lifecycle-callback" minOccurs="1" /> <xs:element name="lifecycle-callback" type="orm:lifecycle-callback" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
<xs:complexType name="entity"> <xs:complexType name="entity">
<xs:sequence> <xs:sequence>
<xs:element name="indexes" type="orm:indexes" minOccurs="0"/>
<xs:element name="unique-constraints" type="orm:unique-constraints" minOccurs="0"/>
<xs:element name="discriminator-column" type="orm:discriminator-column" minOccurs="0"/> <xs:element name="discriminator-column" type="orm:discriminator-column" minOccurs="0"/>
<xs:element name="subclasses" type="xs:NMTOKENS" minOccurs="0"/> <xs:element name="discriminator-map" type="orm:discriminator-map" minOccurs="0"/>
<xs:element name="lifecycle-callbacks" type="orm:lifecycle-callbacks" minOccurs="0" maxOccurs="1" /> <xs:element name="lifecycle-callbacks" type="orm:lifecycle-callbacks" minOccurs="0" maxOccurs="1" />
<xs:element name="id" type="orm:id" /> <xs:element name="id" type="orm:id" />
<xs:element name="field" type="orm:field" minOccurs="0" /> <xs:element name="field" type="orm:field" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="one-to-one" type="orm:one-to-one" minOccurs="0"/> <xs:element name="one-to-one" type="orm:one-to-one" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="one-to-many" type="orm:one-to-many" minOccurs="0" /> <xs:element name="one-to-many" type="orm:one-to-many" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="many-to-many" type="orm:many-to-many" minOccurs="0" /> <xs:element name="many-to-many" type="orm:many-to-many" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence> </xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" /> <xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="table" type="xs:NMTOKEN" /> <xs:attribute name="table" type="xs:NMTOKEN" />
<xs:attribute name="schema" type="xs:NMTOKEN" /> <xs:attribute name="schema" type="xs:NMTOKEN" />
<xs:attribute name="repository-class" type="xs:NMTOKEN"/> <xs:attribute name="repository-class" type="xs:NMTOKEN"/>
<xs:attribute name="inheritance-type" type="orm:inheritance-type"/> <xs:attribute name="inheritance-type" type="orm:inheritance-type"/>
<xs:attribute name="discriminator-value" type="xs:NMTOKEN"/>
</xs:complexType> </xs:complexType>
<xs:complexType name="mapped-superclass" > <xs:complexType name="mapped-superclass" >
...@@ -122,6 +123,39 @@ ...@@ -122,6 +123,39 @@
<xs:attribute name="field-name" type="xs:NMTOKEN" /> <xs:attribute name="field-name" type="xs:NMTOKEN" />
<xs:attribute name="length" type="xs:NMTOKEN" /> <xs:attribute name="length" type="xs:NMTOKEN" />
</xs:complexType> </xs:complexType>
<xs:complexType name="unique-constraint">
<xs:attribute name="name" type="xs:NMTOKEN" use="optional"/>
<xs:attribute name="columns" type="xs:NMTOKENS" use="required"/>
</xs:complexType>
<xs:complexType name="unique-constraints">
<xs:sequence>
<xs:element name="unique-constraint" type="orm:unique-constraint" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="index">
<xs:attribute name="name" type="xs:NMTOKEN" use="optional"/>
<xs:attribute name="columns" type="xs:NMTOKENS" use="required"/>
</xs:complexType>
<xs:complexType name="indexes">
<xs:sequence>
<xs:element name="index" type="orm:index" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="discriminator-mapping">
<xs:attribute name="value" type="xs:NMTOKEN" use="required"/>
<xs:attribute name="class" type="xs:NMTOKEN" use="required"/>
</xs:complexType>
<xs:complexType name="discriminator-map">
<xs:sequence>
<xs:element name="discriminator-mapping" type="orm:discriminator-mapping" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="generator"> <xs:complexType name="generator">
<xs:attribute name="strategy" type="orm:generator-strategy" use="required" /> <xs:attribute name="strategy" type="orm:generator-strategy" use="required" />
...@@ -138,13 +172,13 @@ ...@@ -138,13 +172,13 @@
<xs:complexType name="inverse-join-columns"> <xs:complexType name="inverse-join-columns">
<xs:sequence> <xs:sequence>
<xs:element name="join-column" type="orm:join-column" /> <xs:element name="join-column" type="orm:join-column" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
<xs:complexType name="join-column"> <xs:complexType name="join-column">
<xs:attribute name="name" type="xs:NMTOKEN" use="required" /> <xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="referencedColumnName" type="xs:NMTOKEN" use="required" /> <xs:attribute name="referenced-column-name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="unique" type="xs:boolean" default="false" /> <xs:attribute name="unique" type="xs:boolean" default="false" />
<xs:attribute name="nullable" type="xs:boolean" default="true" /> <xs:attribute name="nullable" type="xs:boolean" default="true" />
<xs:attribute name="on-delete" type="orm:fk-action" /> <xs:attribute name="on-delete" type="orm:fk-action" />
...@@ -153,7 +187,7 @@ ...@@ -153,7 +187,7 @@
<xs:complexType name="join-columns"> <xs:complexType name="join-columns">
<xs:sequence> <xs:sequence>
<xs:element name="join-column" type="orm:join-column" /> <xs:element name="join-column" type="orm:join-column" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
...@@ -171,7 +205,7 @@ ...@@ -171,7 +205,7 @@
<xs:element name="cascade" type="orm:cascade-type" minOccurs="0" /> <xs:element name="cascade" type="orm:cascade-type" minOccurs="0" />
<xs:element name="join-table" type="orm:join-table" /> <xs:element name="join-table" type="orm:join-table" />
</xs:sequence> </xs:sequence>
<xs:attribute name="targetEntity" type="xs:NMTOKEN" use="required" /> <xs:attribute name="target-entity" type="xs:NMTOKEN" use="required" />
<xs:attribute name="field" type="xs:NMTOKEN" use="required" /> <xs:attribute name="field" type="xs:NMTOKEN" use="required" />
</xs:complexType> </xs:complexType>
...@@ -179,8 +213,8 @@ ...@@ -179,8 +213,8 @@
<xs:sequence> <xs:sequence>
<xs:element name="cascade" type="orm:cascade-type" minOccurs="0" /> <xs:element name="cascade" type="orm:cascade-type" minOccurs="0" />
</xs:sequence> </xs:sequence>
<xs:attribute name="targetEntity" type="xs:NMTOKEN" use="required" /> <xs:attribute name="target-entity" type="xs:NMTOKEN" use="required" />
<xs:attribute name="mappedBy" type="xs:NMTOKEN" /> <xs:attribute name="mapped-by" type="xs:NMTOKEN" />
<xs:attribute name="field" type="xs:NMTOKEN" use="required" /> <xs:attribute name="field" type="xs:NMTOKEN" use="required" />
<xs:attribute name="orphan-removal" type="xs:boolean" default="false" /> <xs:attribute name="orphan-removal" type="xs:boolean" default="false" />
</xs:complexType> </xs:complexType>
...@@ -193,8 +227,8 @@ ...@@ -193,8 +227,8 @@
<xs:element name="join-columns" type="orm:join-columns"/> <xs:element name="join-columns" type="orm:join-columns"/>
</xs:choice> </xs:choice>
</xs:sequence> </xs:sequence>
<xs:attribute name="targetEntity" type="xs:NMTOKEN" use="required" /> <xs:attribute name="target-entity" type="xs:NMTOKEN" use="required" />
<xs:attribute name="mappedBy" type="xs:NMTOKEN" /> <xs:attribute name="mapped-by" type="xs:NMTOKEN" />
<xs:attribute name="field" type="xs:NMTOKEN" use="required" /> <xs:attribute name="field" type="xs:NMTOKEN" use="required" />
<xs:attribute name="orphan-removal" type="xs:boolean" default="false" /> <xs:attribute name="orphan-removal" type="xs:boolean" default="false" />
</xs:complexType> </xs:complexType>
......
...@@ -362,14 +362,6 @@ abstract class AbstractPlatform ...@@ -362,14 +362,6 @@ abstract class AbstractPlatform
* must contain a logical expression or an array with logical expressions. * must contain a logical expression or an array with logical expressions.
* These expressions will be matched against the first parameter. * These expressions will be matched against the first parameter.
* *
* Example:
* <code>
* $q = new Doctrine_Query();
* $q->select('u.*')
* ->from('User u')
* ->where($q->expr->in( 'id', array(1,2,3)));
* </code>
*
* @param string $column the value that should be matched against * @param string $column the value that should be matched against
* @param string|array(string) values that will be matched against $column * @param string|array(string) values that will be matched against $column
* @return string logical expression * @return string logical expression
...@@ -390,14 +382,6 @@ abstract class AbstractPlatform ...@@ -390,14 +382,6 @@ abstract class AbstractPlatform
/** /**
* Returns SQL that checks if a expression is null. * Returns SQL that checks if a expression is null.
* *
* Example:
* <code>
* $q = new Doctrine_Query();
* $q->select('u.*')
* ->from('User u')
* ->where($q->expr->isNull('id'));
* </code>
*
* @param string $expression the expression that should be compared to null * @param string $expression the expression that should be compared to null
* @return string logical expression * @return string logical expression
*/ */
...@@ -409,14 +393,6 @@ abstract class AbstractPlatform ...@@ -409,14 +393,6 @@ abstract class AbstractPlatform
/** /**
* Returns SQL that checks if a expression is not null. * Returns SQL that checks if a expression is not null.
* *
* Example:
* <code>
* $q = new Doctrine_Query();
* $q->select('u.*')
* ->from('User u')
* ->where($q->expr->isNotNull('id'));
* </code>
*
* @param string $expression the expression that should be compared to null * @param string $expression the expression that should be compared to null
* @return string logical expression * @return string logical expression
*/ */
...@@ -435,14 +411,6 @@ abstract class AbstractPlatform ...@@ -435,14 +411,6 @@ abstract class AbstractPlatform
* http://www.w3schools.com/sql/sql_between.asp. If you want complete database * http://www.w3schools.com/sql/sql_between.asp. If you want complete database
* independence you should avoid using between(). * independence you should avoid using between().
* *
* Example:
* <code>
* $q = new Doctrine_Query();
* $q->select('u.*')
* ->from('User u')
* ->where($q->expr->between('id', 1, 5));
* </code>
*
* @param string $expression the value to compare to * @param string $expression the value to compare to
* @param string $value1 the lower value to compare with * @param string $value1 the lower value to compare with
* @param string $value2 the higher value to compare with * @param string $value2 the higher value to compare with
...@@ -504,18 +472,24 @@ abstract class AbstractPlatform ...@@ -504,18 +472,24 @@ abstract class AbstractPlatform
} }
/** /**
* Gets the SQL statement(s) to create a table with the specified name, columns and options * Gets the SQL statement(s) to create a table with the specified name, columns and constraints
* on this platform. * on this platform.
* *
* @param string $table * @param string $table The name of the table.
* @param array $columns * @param array $columns The column definitions for the table.
* @param array $options * @param array $options The table constraints.
* @return array * @return array The sequence of SQL statements.
*/ */
public function getCreateTableSql($table, array $columns, array $options = array()) public function getCreateTableSql($table, array $columns, array $options = array())
{ {
$columnListSql = $this->getColumnDeclarationListSql($columns); $columnListSql = $this->getColumnDeclarationListSql($columns);
if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) {
foreach ($options['uniqueConstraints'] as $uniqueConstraint) {
$columnListSql .= ', UNIQUE(' . implode(', ', array_values($uniqueConstraint)) . ')';
}
}
if (isset($options['primary']) && ! empty($options['primary'])) { if (isset($options['primary']) && ! empty($options['primary'])) {
$columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')'; $columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')';
} }
......
...@@ -227,7 +227,7 @@ class MySqlPlatform extends AbstractPlatform ...@@ -227,7 +227,7 @@ class MySqlPlatform extends AbstractPlatform
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false; $fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
: ($length ? 'VARCHAR(' . $length . ')' : 'TEXT'); : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)');
} }
public function getClobDeclarationSql(array $field) public function getClobDeclarationSql(array $field)
...@@ -408,7 +408,7 @@ class MySqlPlatform extends AbstractPlatform ...@@ -408,7 +408,7 @@ class MySqlPlatform extends AbstractPlatform
$queryFields = $this->getColumnDeclarationListSql($fields); $queryFields = $this->getColumnDeclarationListSql($fields);
// build indexes for all foreign key fields (needed in MySQL!!) // build indexes for all foreign key fields (needed in MySQL!!)
if (isset($options['foreignKeys'])) { /*if (isset($options['foreignKeys'])) {
foreach ($options['foreignKeys'] as $fk) { foreach ($options['foreignKeys'] as $fk) {
$local = $fk['local']; $local = $fk['local'];
$found = false; $found = false;
...@@ -433,6 +433,12 @@ class MySqlPlatform extends AbstractPlatform ...@@ -433,6 +433,12 @@ class MySqlPlatform extends AbstractPlatform
$options['indexes'][$local] = array('fields' => array($local => array())); $options['indexes'][$local] = array('fields' => array($local => array()));
} }
} }
}*/
if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) {
foreach ($options['uniqueConstraints'] as $uniqueConstraint) {
$queryFields .= ', UNIQUE(' . implode(', ', array_values($uniqueConstraint)) . ')';
}
} }
// add all indexes // add all indexes
...@@ -471,9 +477,7 @@ class MySqlPlatform extends AbstractPlatform ...@@ -471,9 +477,7 @@ class MySqlPlatform extends AbstractPlatform
// get the type of the table // get the type of the table
if (isset($options['type'])) { if (isset($options['type'])) {
$type = $options['type']; $type = $options['type'];
}/* else { }
$type = $this->getAttribute(Doctrine::ATTR_DEFAULT_TABLE_TYPE);
}*/
if ($type) { if ($type) {
$optionStrings[] = 'ENGINE = ' . $type; $optionStrings[] = 'ENGINE = ' . $type;
...@@ -589,6 +593,7 @@ class MySqlPlatform extends AbstractPlatform ...@@ -589,6 +593,7 @@ class MySqlPlatform extends AbstractPlatform
if ( ! $name) { if ( ! $name) {
throw DoctrineException::updateMe('no valid table name specified'); throw DoctrineException::updateMe('no valid table name specified');
} }
foreach ($changes as $changeName => $change) { foreach ($changes as $changeName => $change) {
switch ($changeName) { switch ($changeName) {
case 'add': case 'add':
...@@ -670,61 +675,6 @@ class MySqlPlatform extends AbstractPlatform ...@@ -670,61 +675,6 @@ class MySqlPlatform extends AbstractPlatform
return 'ALTER TABLE ' . $name . ' ' . $query; return 'ALTER TABLE ' . $name . ' ' . $query;
} }
/**
* Get the stucture of a field into an array
*
* @author Leoncx
* @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.
* Currently, only one property named FIELDS is supported. This property
* is also an associative with the names of the index fields as array
* indexes. Each entry of this array is set to another type of associative
* array that specifies properties of the index that are specific to
* each field.
*
* Currently, only the sorting property is supported. It should be used
* to define the sorting direction of the index. It may be set to either
* ascending or descending.
*
* Not all DBMS support index sorting direction configuration. The DBMS
* drivers of those that do not support it ignore this property. Use the
* function supports() to determine whether the DBMS driver can manage indexes.
*
* Example
* array(
* 'fields' => array(
* 'user_name' => array(
* 'sorting' => 'ASC'
* 'length' => 10
* ),
* 'last_login' => array()
* )
* )
* @throws PDOException
* @return void
* @override
*/
public function getCreateIndexSql($table, $name, array $definition)
{
$table = $table;
$type = '';
if (isset($definition['type'])) {
switch (strtolower($definition['type'])) {
case 'fulltext':
case 'unique':
$type = strtoupper($definition['type']) . ' ';
break;
default:
throw DoctrineException::updateMe('Unknown index type ' . $definition['type']);
}
}
$query = 'CREATE ' . $type . 'INDEX ' . $name . ' ON ' . $table;
$query .= ' (' . $this->getIndexFieldDeclarationListSql($definition['fields']) . ')';
return $query;
}
/** /**
* Obtain DBMS specific SQL code portion needed to declare an integer type * Obtain DBMS specific SQL code portion needed to declare an integer type
* field to be used in statements like CREATE TABLE. * field to be used in statements like CREATE TABLE.
...@@ -791,7 +741,7 @@ class MySqlPlatform extends AbstractPlatform ...@@ -791,7 +741,7 @@ class MySqlPlatform extends AbstractPlatform
*/ */
public function getIndexDeclarationSql($name, array $definition) public function getIndexDeclarationSql($name, array $definition)
{ {
$type = ''; $type = '';
if (isset($definition['type'])) { if (isset($definition['type'])) {
switch (strtolower($definition['type'])) { switch (strtolower($definition['type'])) {
case 'fulltext': case 'fulltext':
...@@ -818,7 +768,6 @@ class MySqlPlatform extends AbstractPlatform ...@@ -818,7 +768,6 @@ class MySqlPlatform extends AbstractPlatform
} }
/** /**
* getIndexFieldDeclarationList
* Obtain DBMS specific SQL code portion needed to set an index * Obtain DBMS specific SQL code portion needed to set an index
* declaration to be used in statements like CREATE TABLE. * declaration to be used in statements like CREATE TABLE.
* *
...@@ -908,7 +857,7 @@ class MySqlPlatform extends AbstractPlatform ...@@ -908,7 +857,7 @@ class MySqlPlatform extends AbstractPlatform
} }
/** /**
* Get the platform name for this instance * Get the platform name for this instance.
* *
* @return string * @return string
*/ */
......
...@@ -241,7 +241,7 @@ class OraclePlatform extends AbstractPlatform ...@@ -241,7 +241,7 @@ class OraclePlatform extends AbstractPlatform
public function getCreateTableSql($table, array $columns, array $options = array()) public function getCreateTableSql($table, array $columns, array $options = array())
{ {
$indexes = isset($options['indexes']) ? $options['indexes']:array(); $indexes = isset($options['indexes']) ? $options['indexes'] : array();
$options['indexes'] = array(); $options['indexes'] = array();
$sql = parent::getCreateTableSql($table, $columns, $options); $sql = parent::getCreateTableSql($table, $columns, $options);
...@@ -258,9 +258,9 @@ class OraclePlatform extends AbstractPlatform ...@@ -258,9 +258,9 @@ class OraclePlatform extends AbstractPlatform
if (isset($indexes) && ! empty($indexes)) { if (isset($indexes) && ! empty($indexes)) {
foreach ($indexes as $indexName => $definition) { foreach ($indexes as $indexName => $definition) {
// create nonunique indexes, as they are a part od CREATE TABLE DDL // create nonunique indexes, as they are a part of CREATE TABLE DDL
if ( ! isset($definition['type']) || if ( ! isset($definition['type']) ||
(isset($definition['type']) && strtolower($definition['type']) != 'unique')) { (isset($definition['type']) && strtolower($definition['type']) != 'unique')) {
$sql[] = $this->getCreateIndexSql($table, $indexName, $definition); $sql[] = $this->getCreateIndexSql($table, $indexName, $definition);
} }
} }
......
...@@ -616,11 +616,8 @@ class PostgreSqlPlatform extends AbstractPlatform ...@@ -616,11 +616,8 @@ class PostgreSqlPlatform extends AbstractPlatform
} }
if (isset($options['foreignKeys'])) { if (isset($options['foreignKeys'])) {
foreach ((array) $options['foreignKeys'] as $k => $definition) { foreach ((array) $options['foreignKeys'] as $k => $definition) {
if (is_array($definition)) { $sql[] = $this->getCreateForeignKeySql($name, $definition);
$sql[] = $this->getCreateForeignKeySql($name, $definition);
}
} }
} }
......
...@@ -166,10 +166,10 @@ abstract class AbstractSchemaManager ...@@ -166,10 +166,10 @@ abstract class AbstractSchemaManager
} }
/** /**
* List the columns for a given table * List the columns for a given table.
* *
* @param string $table The name of the table * @param string $table The name of the table.
* @return array $tableColumns * @return array $tableColumns The column descriptions.
*/ */
public function listTableColumns($table) public function listTableColumns($table)
{ {
......
...@@ -233,11 +233,6 @@ final class ClassMetadata ...@@ -233,11 +233,6 @@ final class ClassMetadata
* The value specifies the name of the index. To create a multi-column index, * The value specifies the name of the index. To create a multi-column index,
* just use the same name for several mappings. * just use the same name for several mappings.
* *
* - <b>unique (string, optional, schema-only)</b>
* Whether a unique constraint should be generated for the column.
* The value specifies the name of the unique constraint. To create a multi-column
* unique constraint, just use the same name for several mappings.
*
* - <b>foreignKey (string, optional, schema-only)</b> * - <b>foreignKey (string, optional, schema-only)</b>
* *
* @var array * @var array
...@@ -316,6 +311,8 @@ final class ClassMetadata ...@@ -316,6 +311,8 @@ final class ClassMetadata
* *
* name => <tableName> * name => <tableName>
* schema => <schemaName> * schema => <schemaName>
* indexes => array
* uniqueConstraints => array
* *
* @var array * @var array
*/ */
......
...@@ -73,10 +73,21 @@ class AnnotationDriver implements Driver ...@@ -73,10 +73,21 @@ class AnnotationDriver implements Driver
// Evaluate DoctrineTable annotation // Evaluate DoctrineTable annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\Table'])) { if (isset($classAnnotations['Doctrine\ORM\Mapping\Table'])) {
$tableAnnot = $classAnnotations['Doctrine\ORM\Mapping\Table']; $tableAnnot = $classAnnotations['Doctrine\ORM\Mapping\Table'];
$metadata->setPrimaryTable(array( $primaryTable = array(
'name' => $tableAnnot->name, 'name' => $tableAnnot->name,
'schema' => $tableAnnot->schema 'schema' => $tableAnnot->schema
)); );
if ($tableAnnot->indexes !== null) {
foreach ($tableAnnot->indexes as $indexAnnot) {
$primaryTable['indexes'][$indexAnnot->name] = array('fields' => $indexAnnot->columns);
}
}
if ($tableAnnot->uniqueConstraints !== null) {
foreach ($tableAnnot->uniqueConstraints as $uniqueConstraint) {
$primaryTable['uniqueConstraints'][] = $uniqueConstraint->columns;
}
}
$metadata->setPrimaryTable($primaryTable);
} }
// Evaluate InheritanceType annotation // Evaluate InheritanceType annotation
...@@ -135,7 +146,6 @@ class AnnotationDriver implements Driver ...@@ -135,7 +146,6 @@ class AnnotationDriver implements Driver
); );
} else if ($joinColumnsAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumns')) { } else if ($joinColumnsAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumns')) {
foreach ($joinColumnsAnnot->value as $joinColumn) { foreach ($joinColumnsAnnot->value as $joinColumn) {
//$joinColumns = $joinColumnsAnnot->value;
$joinColumns[] = array( $joinColumns[] = array(
'name' => $joinColumn->name, 'name' => $joinColumn->name,
'referencedColumnName' => $joinColumn->referencedColumnName, 'referencedColumnName' => $joinColumn->referencedColumnName,
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
namespace Doctrine\ORM\Mapping; namespace Doctrine\ORM\Mapping;
use \Doctrine\Common\Annotations\Annotation; use Doctrine\Common\Annotations\Annotation;
/* Annotations */ /* Annotations */
...@@ -94,6 +94,16 @@ final class ElementCollection extends Annotation { ...@@ -94,6 +94,16 @@ final class ElementCollection extends Annotation {
final class Table extends Annotation { final class Table extends Annotation {
public $name; public $name;
public $schema; public $schema;
public $indexes;
public $uniqueConstraints;
}
final class UniqueConstraint extends Annotation {
public $name;
public $columns;
}
final class Index extends Annotation {
public $name;
public $columns;
} }
final class JoinTable extends Annotation { final class JoinTable extends Annotation {
public $name; public $name;
......
...@@ -55,6 +55,21 @@ class XmlDriver extends AbstractFileDriver ...@@ -55,6 +55,21 @@ class XmlDriver extends AbstractFileDriver
if (isset($xmlRoot['inheritance-type'])) { if (isset($xmlRoot['inheritance-type'])) {
$metadata->setInheritanceType((string)$xmlRoot['inheritance-type']); $metadata->setInheritanceType((string)$xmlRoot['inheritance-type']);
} }
// Evaluate <indexes...>
if (isset($xmlRoot->indexes)) {
foreach ($xmlRoot->indexes->index as $index) {
$metadata->primaryTable['indexes'][$index['name']] = array('fields' =>
explode(',', $index['columns']));
}
}
// Evaluate <unique-constraints..>
if (isset($xmlRoot->{'unique-constraints'})) {
foreach ($xmlRoot->{'unique-constraints'}->{'unique-constraint'} as $unique) {
$metadata->primaryTable['uniqueConstraints'][] = explode(',', $index['columns']);
}
}
// Evaluate <field ...> mappings // Evaluate <field ...> mappings
if (isset($xmlRoot->field)) { if (isset($xmlRoot->field)) {
...@@ -69,6 +84,12 @@ class XmlDriver extends AbstractFileDriver ...@@ -69,6 +84,12 @@ class XmlDriver extends AbstractFileDriver
if (isset($fieldMapping['length'])) { if (isset($fieldMapping['length'])) {
$mapping['length'] = (int)$fieldMapping['length']; $mapping['length'] = (int)$fieldMapping['length'];
} }
if (isset($fieldMapping['precision'])) {
$mapping['precision'] = (int)$fieldMapping['precision'];
}
if (isset($fieldMapping['scale'])) {
$mapping['scale'] = (int)$fieldMapping['scale'];
}
$metadata->mapField($mapping); $metadata->mapField($mapping);
} }
} }
...@@ -96,10 +117,10 @@ class XmlDriver extends AbstractFileDriver ...@@ -96,10 +117,10 @@ class XmlDriver extends AbstractFileDriver
foreach ($xmlRoot->{'one-to-one'} as $oneToOneElement) { foreach ($xmlRoot->{'one-to-one'} as $oneToOneElement) {
$mapping = array( $mapping = array(
'fieldName' => (string)$oneToOneElement['field'], 'fieldName' => (string)$oneToOneElement['field'],
'targetEntity' => (string)$oneToOneElement['targetEntity'] 'targetEntity' => (string)$oneToOneElement['target-entity']
); );
if (isset($oneToOneElement['mappedBy'])) { if (isset($oneToOneElement['mapped-by'])) {
$mapping['mappedBy'] = (string)$oneToOneElement['mappedBy']; $mapping['mappedBy'] = (string)$oneToOneElement['mapped-by'];
} else { } else {
$joinColumns = array(); $joinColumns = array();
if (isset($oneToOneElement->{'join-column'})) { if (isset($oneToOneElement->{'join-column'})) {
...@@ -127,8 +148,8 @@ class XmlDriver extends AbstractFileDriver ...@@ -127,8 +148,8 @@ class XmlDriver extends AbstractFileDriver
foreach ($xmlRoot->{'one-to-many'} as $oneToManyElement) { foreach ($xmlRoot->{'one-to-many'} as $oneToManyElement) {
$mapping = array( $mapping = array(
'fieldName' => (string)$oneToManyElement['field'], 'fieldName' => (string)$oneToManyElement['field'],
'targetEntity' => (string)$oneToManyElement['targetEntity'], 'targetEntity' => (string)$oneToManyElement['target-entity'],
'mappedBy' => (string)$oneToManyElement['mappedBy'] 'mappedBy' => (string)$oneToManyElement['mapped-by']
); );
if (isset($oneToManyElement->cascade)) { if (isset($oneToManyElement->cascade)) {
$mapping['cascade'] = $this->_getCascadeMappings($oneToManyElement->cascade); $mapping['cascade'] = $this->_getCascadeMappings($oneToManyElement->cascade);
...@@ -142,7 +163,7 @@ class XmlDriver extends AbstractFileDriver ...@@ -142,7 +163,7 @@ class XmlDriver extends AbstractFileDriver
foreach ($xmlRoot->{'many-to-one'} as $manyToOneElement) { foreach ($xmlRoot->{'many-to-one'} as $manyToOneElement) {
$mapping = array( $mapping = array(
'fieldName' => (string)$manyToOneElement['field'], 'fieldName' => (string)$manyToOneElement['field'],
'targetEntity' => (string)$manyToOneElement['targetEntity'] 'targetEntity' => (string)$manyToOneElement['target-entity']
); );
$joinColumns = array(); $joinColumns = array();
if (isset($manyToOneElement->{'join-column'})) { if (isset($manyToOneElement->{'join-column'})) {
...@@ -167,11 +188,11 @@ class XmlDriver extends AbstractFileDriver ...@@ -167,11 +188,11 @@ class XmlDriver extends AbstractFileDriver
foreach ($xmlRoot->{'many-to-many'} as $manyToManyElement) { foreach ($xmlRoot->{'many-to-many'} as $manyToManyElement) {
$mapping = array( $mapping = array(
'fieldName' => (string)$manyToManyElement['field'], 'fieldName' => (string)$manyToManyElement['field'],
'targetEntity' => (string)$manyToManyElement['targetEntity'] 'targetEntity' => (string)$manyToManyElement['target-entity']
); );
if (isset($manyToManyElement['mappedBy'])) { if (isset($manyToManyElement['mappedBy'])) {
$mapping['mappedBy'] = (string)$manyToManyElement['mappedBy']; $mapping['mappedBy'] = (string)$manyToManyElement['mapped-by'];
} else if (isset($manyToManyElement->{'join-table'})) { } else if (isset($manyToManyElement->{'join-table'})) {
$joinTableElement = $manyToManyElement->{'join-table'}; $joinTableElement = $manyToManyElement->{'join-table'};
$joinTable = array( $joinTable = array(
...@@ -242,7 +263,7 @@ class XmlDriver extends AbstractFileDriver ...@@ -242,7 +263,7 @@ class XmlDriver extends AbstractFileDriver
{ {
$joinColumn = array( $joinColumn = array(
'name' => (string)$joinColumnElement['name'], 'name' => (string)$joinColumnElement['name'],
'referencedColumnName' => (string)$joinColumnElement['referencedColumnName'] 'referencedColumnName' => (string)$joinColumnElement['referenced-column-name']
); );
if (isset($joinColumnElement['unique'])) { if (isset($joinColumnElement['unique'])) {
$joinColumn['unique'] = (bool)$joinColumnElement['unique']; $joinColumn['unique'] = (bool)$joinColumnElement['unique'];
...@@ -251,10 +272,10 @@ class XmlDriver extends AbstractFileDriver ...@@ -251,10 +272,10 @@ class XmlDriver extends AbstractFileDriver
$joinColumn['nullable'] = (bool)$joinColumnElement['nullable']; $joinColumn['nullable'] = (bool)$joinColumnElement['nullable'];
} }
if (isset($joinColumnElement['onDelete'])) { if (isset($joinColumnElement['onDelete'])) {
$joinColumn['onDelete'] = (string)$joinColumnElement['onDelete']; $joinColumn['onDelete'] = (string)$joinColumnElement['on-delete'];
} }
if (isset($joinColumnElement['onUpdate'])) { if (isset($joinColumnElement['onUpdate'])) {
$joinColumn['onUpdate'] = (string)$joinColumnElement['onUpdate']; $joinColumn['onUpdate'] = (string)$joinColumnElement['on-update'];
} }
return $joinColumn; return $joinColumn;
......
This diff is collapsed.
...@@ -25,9 +25,7 @@ use Doctrine\Common\Collections\ArrayCollection, ...@@ -25,9 +25,7 @@ use Doctrine\Common\Collections\ArrayCollection,
Doctrine\Common\Collections\Collection, Doctrine\Common\Collections\Collection,
Doctrine\Common\DoctrineException, Doctrine\Common\DoctrineException,
Doctrine\Common\PropertyChangedListener, Doctrine\Common\PropertyChangedListener,
Doctrine\ORM\Event\LifecycleEventArgs, Doctrine\ORM\Event\LifecycleEventArgs;
Doctrine\ORM\Internal\CommitOrderCalculator,
Doctrine\ORM\Internal\CommitOrderNode;
/** /**
* The UnitOfWork is responsible for tracking changes to objects during an * The UnitOfWork is responsible for tracking changes to objects during an
...@@ -233,7 +231,7 @@ class UnitOfWork implements PropertyChangedListener ...@@ -233,7 +231,7 @@ class UnitOfWork implements PropertyChangedListener
{ {
$this->_em = $em; $this->_em = $em;
$this->_evm = $em->getEventManager(); $this->_evm = $em->getEventManager();
$this->_commitOrderCalculator = new CommitOrderCalculator(); $this->_commitOrderCalculator = new Internal\CommitOrderCalculator();
$this->_useCExtension = $this->_em->getConfiguration()->getUseCExtension(); $this->_useCExtension = $this->_em->getConfiguration()->getUseCExtension();
} }
......
...@@ -126,7 +126,7 @@ class MySqlPlatformTest extends \Doctrine\Tests\DbalTestCase ...@@ -126,7 +126,7 @@ class MySqlPlatformTest extends \Doctrine\Tests\DbalTestCase
'Variable string declaration is not correct' 'Variable string declaration is not correct'
); );
$this->assertEquals( $this->assertEquals(
'TEXT', 'VARCHAR(255)',
$this->_platform->getVarcharTypeDeclarationSql(array()), $this->_platform->getVarcharTypeDeclarationSql(array()),
'Long string declaration is not correct' 'Long string declaration is not correct'
); );
......
...@@ -26,7 +26,6 @@ class AllTests ...@@ -26,7 +26,6 @@ class AllTests
$suite->addTest(Query\AllTests::suite()); $suite->addTest(Query\AllTests::suite());
$suite->addTest(Hydration\AllTests::suite()); $suite->addTest(Hydration\AllTests::suite());
$suite->addTest(Entity\AllTests::suite()); $suite->addTest(Entity\AllTests::suite());
$suite->addTest(Tools\AllTests::suite());
$suite->addTest(Associations\AllTests::suite()); $suite->addTest(Associations\AllTests::suite());
$suite->addTest(Mapping\AllTests::suite()); $suite->addTest(Mapping\AllTests::suite());
$suite->addTest(Functional\AllTests::suite()); $suite->addTest(Functional\AllTests::suite());
......
...@@ -42,6 +42,7 @@ class AllTests ...@@ -42,6 +42,7 @@ class AllTests
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\EntityRepositoryTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\EntityRepositoryTest');
$suite->addTest(Locking\AllTests::suite()); $suite->addTest(Locking\AllTests::suite());
$suite->addTest(SchemaTool\AllTests::suite());
return $suite; return $suite;
} }
......
<?php <?php
namespace Doctrine\Tests\ORM\Tools; namespace Doctrine\Tests\ORM\Functional\SchemaTool;
if (!defined('PHPUnit_MAIN_METHOD')) { if (!defined('PHPUnit_MAIN_METHOD')) {
define('PHPUnit_MAIN_METHOD', 'Orm_Tools_AllTests::main'); define('PHPUnit_MAIN_METHOD', 'Orm_Functional_Tools_AllTests::main');
} }
require_once __DIR__ . '/../../TestInit.php'; require_once __DIR__ . '/../../../TestInit.php';
class AllTests class AllTests
{ {
...@@ -17,14 +17,14 @@ class AllTests ...@@ -17,14 +17,14 @@ class AllTests
public static function suite() public static function suite()
{ {
$suite = new \Doctrine\Tests\DoctrineTestSuite('Doctrine Orm Tools'); $suite = new \Doctrine\Tests\DoctrineTestSuite('Doctrine Orm Functional Tools');
$suite->addTestSuite('Doctrine\Tests\ORM\Tools\SchemaToolTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\SchemaTool\MySqlSchemaToolTest');
return $suite; return $suite;
} }
} }
if (PHPUnit_MAIN_METHOD == 'Orm_Tools_AllTests::main') { if (PHPUnit_MAIN_METHOD == 'Orm_Functional_Tools_AllTests::main') {
AllTests::main(); AllTests::main();
} }
\ No newline at end of file
<?php
namespace Doctrine\Tests\ORM\Functional\SchemaTool;
use Doctrine\ORM\Tools\SchemaTool,
Doctrine\ORM\Mapping\ClassMetadata;
require_once __DIR__ . '/../../../TestInit.php';
class MySqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp() {
parent::setUp();
if ($this->_em->getConnection()->getDatabasePlatform()->getName() !== 'mysql') {
$this->markTestSkipped('The ' . __CLASS__ .' requires the use of mysql.');
}
}
public function testGetCreateSchemaSql()
{
$classes = array(
$this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress'),
$this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'),
$this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsPhonenumber'),
);
$tool = new SchemaTool($this->_em);
$sql = $tool->getCreateSchemaSql($classes);
$this->assertEquals(count($sql), 8);
$this->assertEquals("CREATE TABLE cms_addresses (id INT AUTO_INCREMENT NOT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(id))", $sql[0]);
$this->assertEquals("CREATE TABLE cms_users_groups (user_id INT DEFAULT NULL, group_id INT DEFAULT NULL, PRIMARY KEY(user_id, group_id))", $sql[1]);
$this->assertEquals("CREATE TABLE cms_users (id INT AUTO_INCREMENT NOT NULL, status VARCHAR(50) NOT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))", $sql[2]);
$this->assertEquals("CREATE TABLE cms_phonenumbers (phonenumber VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(phonenumber))", $sql[3]);
$this->assertEquals("ALTER TABLE cms_addresses ADD FOREIGN KEY (user_id) REFERENCES cms_users(id)", $sql[4]);
$this->assertEquals("ALTER TABLE cms_users_groups ADD FOREIGN KEY (user_id) REFERENCES cms_users(id)", $sql[5]);
$this->assertEquals("ALTER TABLE cms_users_groups ADD FOREIGN KEY (group_id) REFERENCES cms_groups(id)", $sql[6]);
$this->assertEquals("ALTER TABLE cms_phonenumbers ADD FOREIGN KEY (user_id) REFERENCES cms_users(id)", $sql[7]);
}
public function testGetUpdateSchemaSql()
{
$classes = array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\SchemaToolEntityA')
);
$tool = new SchemaTool($this->_em);
$tool->createSchema($classes);
// Add field to SchemaToolEntityA
$classA = $classes[0];
$classA->mapField(array(
'fieldName' => 'newField',
'columnName' => 'new_field',
'type' => 'string',
'length' => 50,
'nullable' => false
));
// Introduce SchemaToolEntityB
$classB = new ClassMetadata(__NAMESPACE__ . '\SchemaToolEntityB');
$classB->setTableName('schematool_entity_b');
$classB->mapField(array(
'fieldName' => 'id',
'columnName' => 'id',
'type' => 'integer',
'nullable' => false,
'id' => true
));
$classB->mapField(array(
'fieldName' => 'field',
'columnName' => 'field',
'type' => 'string',
'nullable' => false
));
$classes[] = $classB;
$sql = $tool->getUpdateSchemaSql($classes);
$this->assertEquals(2, count($sql));
$this->assertEquals("CREATE TABLE schematool_entity_b (id INT NOT NULL, field VARCHAR(255) NOT NULL, PRIMARY KEY(id))", $sql[0]);
$this->assertEquals("ALTER TABLE schematool_entity_a ADD new_field VARCHAR(50) NOT NULL", $sql[1]);
}
}
/** @Entity @Table(name="schematool_entity_a") */
class SchemaToolEntityA {
/** @Id @Column(type="integer") */
private $id;
private $newField;
}
class SchemaToolEntityB {
private $id;
private $field;
}
...@@ -17,23 +17,23 @@ ...@@ -17,23 +17,23 @@
<field name="name" column="name" type="string" length="50"/> <field name="name" column="name" type="string" length="50"/>
<one-to-one field="address" targetEntity="Address"> <one-to-one field="address" target-entity="Address">
<join-column name="address_id" referencedColumnName="id"/> <join-column name="address_id" referenced-column-name="id"/>
</one-to-one> </one-to-one>
<one-to-many field="phonenumbers" targetEntity="Phonenumber" mappedBy="user"> <one-to-many field="phonenumbers" target-entity="Phonenumber" mapped-by="user">
<cascade> <cascade>
<cascade-persist/> <cascade-persist/>
</cascade> </cascade>
</one-to-many> </one-to-many>
<many-to-many field="groups" targetEntity="Group"> <many-to-many field="groups" target-entity="Group">
<join-table name="cms_users_groups"> <join-table name="cms_users_groups">
<join-columns> <join-columns>
<join-column name="user_id" referencedColumnName="id"/> <join-column name="user_id" referenced-column-name="id"/>
</join-columns> </join-columns>
<inverse-join-columns> <inverse-join-columns>
<join-column name="group_id" referencedColumnName="id"/> <join-column name="group_id" referenced-column-name="id"/>
</inverse-join-columns> </inverse-join-columns>
</join-table> </join-table>
</many-to-many> </many-to-many>
......
<?php
namespace Doctrine\Tests\ORM\Tools;
use Doctrine\ORM\Tools\SchemaTool;
require_once __DIR__ . '/../../TestInit.php';
class SchemaToolTest extends \Doctrine\Tests\OrmTestCase
{
public function testGetCreateSchemaSql()
{
$driver = new \Doctrine\Tests\Mocks\DriverMock;
$conn = new \Doctrine\Tests\Mocks\ConnectionMock(array(), $driver);
$conn->setDatabasePlatform(new \Doctrine\DBAL\Platforms\MySqlPlatform());
$em = $this->_getTestEntityManager($conn);
$classes = array(
$em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress'),
$em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'),
$em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsPhonenumber'),
);
$exporter = new SchemaTool($em);
$sql = $exporter->getCreateSchemaSql($classes);
$this->assertEquals(count($sql), 8);
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment