[2.0] Work on SchemaTool and DBAL.
This commit is contained in:
parent
0612e6b0a6
commit
b1d34fca1c
@ -8,15 +8,15 @@
|
||||
<xs:annotation>
|
||||
<xs:documentation><![CDATA[
|
||||
This is the XML Schema for the object/relational
|
||||
mapping file used by Doctrine.
|
||||
mapping file used by the Doctrine ORM.
|
||||
]]></xs:documentation>
|
||||
</xs:annotation>
|
||||
|
||||
<xs:element name="doctrine-mapping">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="mapped-superclass" type="orm:mapped-superclass" minOccurs="0" />
|
||||
<xs:element name="entity" type="orm:entity" minOccurs="0" />
|
||||
<xs:element name="mapped-superclass" type="orm:mapped-superclass" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="entity" type="orm:entity" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
@ -52,27 +52,28 @@
|
||||
|
||||
<xs:complexType name="lifecycle-callbacks">
|
||||
<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:complexType>
|
||||
|
||||
<xs:complexType name="entity">
|
||||
<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="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="id" type="orm:id" />
|
||||
<xs:element name="field" type="orm:field" minOccurs="0" />
|
||||
<xs:element name="one-to-one" type="orm:one-to-one" minOccurs="0"/>
|
||||
<xs:element name="one-to-many" type="orm:one-to-many" minOccurs="0" />
|
||||
<xs:element name="many-to-many" type="orm:many-to-many" 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" maxOccurs="unbounded"/>
|
||||
<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" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
<xs:attribute name="name" type="xs:string" use="required" />
|
||||
<xs:attribute name="table" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="schema" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="repository-class" type="xs:NMTOKEN"/>
|
||||
<xs:attribute name="inheritance-type" type="orm:inheritance-type"/>
|
||||
<xs:attribute name="discriminator-value" type="xs:NMTOKEN"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="mapped-superclass" >
|
||||
@ -122,6 +123,39 @@
|
||||
<xs:attribute name="field-name" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="length" type="xs:NMTOKEN" />
|
||||
</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:attribute name="strategy" type="orm:generator-strategy" use="required" />
|
||||
@ -138,13 +172,13 @@
|
||||
|
||||
<xs:complexType name="inverse-join-columns">
|
||||
<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:complexType>
|
||||
|
||||
<xs:complexType name="join-column">
|
||||
<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="nullable" type="xs:boolean" default="true" />
|
||||
<xs:attribute name="on-delete" type="orm:fk-action" />
|
||||
@ -153,7 +187,7 @@
|
||||
|
||||
<xs:complexType name="join-columns">
|
||||
<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:complexType>
|
||||
|
||||
@ -171,7 +205,7 @@
|
||||
<xs:element name="cascade" type="orm:cascade-type" minOccurs="0" />
|
||||
<xs:element name="join-table" type="orm:join-table" />
|
||||
</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:complexType>
|
||||
|
||||
@ -179,8 +213,8 @@
|
||||
<xs:sequence>
|
||||
<xs:element name="cascade" type="orm:cascade-type" minOccurs="0" />
|
||||
</xs:sequence>
|
||||
<xs:attribute name="targetEntity" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="mappedBy" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="target-entity" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="mapped-by" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="field" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="orphan-removal" type="xs:boolean" default="false" />
|
||||
</xs:complexType>
|
||||
@ -193,8 +227,8 @@
|
||||
<xs:element name="join-columns" type="orm:join-columns"/>
|
||||
</xs:choice>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="targetEntity" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="mappedBy" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="target-entity" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="mapped-by" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="field" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="orphan-removal" type="xs:boolean" default="false" />
|
||||
</xs:complexType>
|
||||
|
@ -362,14 +362,6 @@ abstract class AbstractPlatform
|
||||
* must contain a logical expression or an array with logical expressions.
|
||||
* 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|array(string) values that will be matched against $column
|
||||
* @return string logical expression
|
||||
@ -390,14 +382,6 @@ abstract class AbstractPlatform
|
||||
/**
|
||||
* 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
|
||||
* @return string logical expression
|
||||
*/
|
||||
@ -409,14 +393,6 @@ abstract class AbstractPlatform
|
||||
/**
|
||||
* 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
|
||||
* @return string logical expression
|
||||
*/
|
||||
@ -435,14 +411,6 @@ abstract class AbstractPlatform
|
||||
* http://www.w3schools.com/sql/sql_between.asp. If you want complete database
|
||||
* 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 $value1 the lower value to compare with
|
||||
* @param string $value2 the higher value to compare with
|
||||
@ -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.
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
* @param array $options
|
||||
* @return array
|
||||
* @param string $table The name of the table.
|
||||
* @param array $columns The column definitions for the table.
|
||||
* @param array $options The table constraints.
|
||||
* @return array The sequence of SQL statements.
|
||||
*/
|
||||
public function getCreateTableSql($table, array $columns, array $options = array())
|
||||
{
|
||||
$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'])) {
|
||||
$columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')';
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ class MySqlPlatform extends AbstractPlatform
|
||||
$fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
|
||||
|
||||
return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
|
||||
: ($length ? 'VARCHAR(' . $length . ')' : 'TEXT');
|
||||
: ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)');
|
||||
}
|
||||
|
||||
public function getClobDeclarationSql(array $field)
|
||||
@ -408,7 +408,7 @@ class MySqlPlatform extends AbstractPlatform
|
||||
$queryFields = $this->getColumnDeclarationListSql($fields);
|
||||
|
||||
// build indexes for all foreign key fields (needed in MySQL!!)
|
||||
if (isset($options['foreignKeys'])) {
|
||||
/*if (isset($options['foreignKeys'])) {
|
||||
foreach ($options['foreignKeys'] as $fk) {
|
||||
$local = $fk['local'];
|
||||
$found = false;
|
||||
@ -433,6 +433,12 @@ class MySqlPlatform extends AbstractPlatform
|
||||
$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
|
||||
@ -471,9 +477,7 @@ class MySqlPlatform extends AbstractPlatform
|
||||
// get the type of the table
|
||||
if (isset($options['type'])) {
|
||||
$type = $options['type'];
|
||||
}/* else {
|
||||
$type = $this->getAttribute(Doctrine::ATTR_DEFAULT_TABLE_TYPE);
|
||||
}*/
|
||||
}
|
||||
|
||||
if ($type) {
|
||||
$optionStrings[] = 'ENGINE = ' . $type;
|
||||
@ -589,6 +593,7 @@ class MySqlPlatform extends AbstractPlatform
|
||||
if ( ! $name) {
|
||||
throw DoctrineException::updateMe('no valid table name specified');
|
||||
}
|
||||
|
||||
foreach ($changes as $changeName => $change) {
|
||||
switch ($changeName) {
|
||||
case 'add':
|
||||
@ -670,61 +675,6 @@ class MySqlPlatform extends AbstractPlatform
|
||||
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
|
||||
* field to be used in statements like CREATE TABLE.
|
||||
@ -791,7 +741,7 @@ class MySqlPlatform extends AbstractPlatform
|
||||
*/
|
||||
public function getIndexDeclarationSql($name, array $definition)
|
||||
{
|
||||
$type = '';
|
||||
$type = '';
|
||||
if (isset($definition['type'])) {
|
||||
switch (strtolower($definition['type'])) {
|
||||
case 'fulltext':
|
||||
@ -818,7 +768,6 @@ class MySqlPlatform extends AbstractPlatform
|
||||
}
|
||||
|
||||
/**
|
||||
* getIndexFieldDeclarationList
|
||||
* Obtain DBMS specific SQL code portion needed to set an index
|
||||
* declaration to be used in statements like CREATE TABLE.
|
||||
*
|
||||
@ -908,7 +857,7 @@ class MySqlPlatform extends AbstractPlatform
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the platform name for this instance
|
||||
* Get the platform name for this instance.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -241,7 +241,7 @@ class OraclePlatform extends AbstractPlatform
|
||||
|
||||
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();
|
||||
$sql = parent::getCreateTableSql($table, $columns, $options);
|
||||
|
||||
@ -258,9 +258,9 @@ class OraclePlatform extends AbstractPlatform
|
||||
|
||||
if (isset($indexes) && ! empty($indexes)) {
|
||||
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']) ||
|
||||
(isset($definition['type']) && strtolower($definition['type']) != 'unique')) {
|
||||
(isset($definition['type']) && strtolower($definition['type']) != 'unique')) {
|
||||
$sql[] = $this->getCreateIndexSql($table, $indexName, $definition);
|
||||
}
|
||||
}
|
||||
|
@ -616,11 +616,8 @@ class PostgreSqlPlatform extends AbstractPlatform
|
||||
}
|
||||
|
||||
if (isset($options['foreignKeys'])) {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
* List the columns for a given table
|
||||
* List the columns for a given table.
|
||||
*
|
||||
* @param string $table The name of the table
|
||||
* @return array $tableColumns
|
||||
* @param string $table The name of the table.
|
||||
* @return array $tableColumns The column descriptions.
|
||||
*/
|
||||
public function listTableColumns($table)
|
||||
{
|
||||
|
@ -233,11 +233,6 @@ final class ClassMetadata
|
||||
* The value specifies the name of the index. To create a multi-column index,
|
||||
* 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>
|
||||
*
|
||||
* @var array
|
||||
@ -316,6 +311,8 @@ final class ClassMetadata
|
||||
*
|
||||
* name => <tableName>
|
||||
* schema => <schemaName>
|
||||
* indexes => array
|
||||
* uniqueConstraints => array
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
|
@ -73,10 +73,21 @@ class AnnotationDriver implements Driver
|
||||
// Evaluate DoctrineTable annotation
|
||||
if (isset($classAnnotations['Doctrine\ORM\Mapping\Table'])) {
|
||||
$tableAnnot = $classAnnotations['Doctrine\ORM\Mapping\Table'];
|
||||
$metadata->setPrimaryTable(array(
|
||||
$primaryTable = array(
|
||||
'name' => $tableAnnot->name,
|
||||
'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
|
||||
@ -135,7 +146,6 @@ class AnnotationDriver implements Driver
|
||||
);
|
||||
} else if ($joinColumnsAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumns')) {
|
||||
foreach ($joinColumnsAnnot->value as $joinColumn) {
|
||||
//$joinColumns = $joinColumnsAnnot->value;
|
||||
$joinColumns[] = array(
|
||||
'name' => $joinColumn->name,
|
||||
'referencedColumnName' => $joinColumn->referencedColumnName,
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use \Doctrine\Common\Annotations\Annotation;
|
||||
use Doctrine\Common\Annotations\Annotation;
|
||||
|
||||
/* Annotations */
|
||||
|
||||
@ -94,6 +94,16 @@ final class ElementCollection extends Annotation {
|
||||
final class Table extends Annotation {
|
||||
public $name;
|
||||
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 {
|
||||
public $name;
|
||||
|
@ -55,6 +55,21 @@ class XmlDriver extends AbstractFileDriver
|
||||
if (isset($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
|
||||
if (isset($xmlRoot->field)) {
|
||||
@ -69,6 +84,12 @@ class XmlDriver extends AbstractFileDriver
|
||||
if (isset($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);
|
||||
}
|
||||
}
|
||||
@ -96,10 +117,10 @@ class XmlDriver extends AbstractFileDriver
|
||||
foreach ($xmlRoot->{'one-to-one'} as $oneToOneElement) {
|
||||
$mapping = array(
|
||||
'fieldName' => (string)$oneToOneElement['field'],
|
||||
'targetEntity' => (string)$oneToOneElement['targetEntity']
|
||||
'targetEntity' => (string)$oneToOneElement['target-entity']
|
||||
);
|
||||
if (isset($oneToOneElement['mappedBy'])) {
|
||||
$mapping['mappedBy'] = (string)$oneToOneElement['mappedBy'];
|
||||
if (isset($oneToOneElement['mapped-by'])) {
|
||||
$mapping['mappedBy'] = (string)$oneToOneElement['mapped-by'];
|
||||
} else {
|
||||
$joinColumns = array();
|
||||
if (isset($oneToOneElement->{'join-column'})) {
|
||||
@ -127,8 +148,8 @@ class XmlDriver extends AbstractFileDriver
|
||||
foreach ($xmlRoot->{'one-to-many'} as $oneToManyElement) {
|
||||
$mapping = array(
|
||||
'fieldName' => (string)$oneToManyElement['field'],
|
||||
'targetEntity' => (string)$oneToManyElement['targetEntity'],
|
||||
'mappedBy' => (string)$oneToManyElement['mappedBy']
|
||||
'targetEntity' => (string)$oneToManyElement['target-entity'],
|
||||
'mappedBy' => (string)$oneToManyElement['mapped-by']
|
||||
);
|
||||
if (isset($oneToManyElement->cascade)) {
|
||||
$mapping['cascade'] = $this->_getCascadeMappings($oneToManyElement->cascade);
|
||||
@ -142,7 +163,7 @@ class XmlDriver extends AbstractFileDriver
|
||||
foreach ($xmlRoot->{'many-to-one'} as $manyToOneElement) {
|
||||
$mapping = array(
|
||||
'fieldName' => (string)$manyToOneElement['field'],
|
||||
'targetEntity' => (string)$manyToOneElement['targetEntity']
|
||||
'targetEntity' => (string)$manyToOneElement['target-entity']
|
||||
);
|
||||
$joinColumns = array();
|
||||
if (isset($manyToOneElement->{'join-column'})) {
|
||||
@ -167,11 +188,11 @@ class XmlDriver extends AbstractFileDriver
|
||||
foreach ($xmlRoot->{'many-to-many'} as $manyToManyElement) {
|
||||
$mapping = array(
|
||||
'fieldName' => (string)$manyToManyElement['field'],
|
||||
'targetEntity' => (string)$manyToManyElement['targetEntity']
|
||||
'targetEntity' => (string)$manyToManyElement['target-entity']
|
||||
);
|
||||
|
||||
if (isset($manyToManyElement['mappedBy'])) {
|
||||
$mapping['mappedBy'] = (string)$manyToManyElement['mappedBy'];
|
||||
$mapping['mappedBy'] = (string)$manyToManyElement['mapped-by'];
|
||||
} else if (isset($manyToManyElement->{'join-table'})) {
|
||||
$joinTableElement = $manyToManyElement->{'join-table'};
|
||||
$joinTable = array(
|
||||
@ -242,7 +263,7 @@ class XmlDriver extends AbstractFileDriver
|
||||
{
|
||||
$joinColumn = array(
|
||||
'name' => (string)$joinColumnElement['name'],
|
||||
'referencedColumnName' => (string)$joinColumnElement['referencedColumnName']
|
||||
'referencedColumnName' => (string)$joinColumnElement['referenced-column-name']
|
||||
);
|
||||
if (isset($joinColumnElement['unique'])) {
|
||||
$joinColumn['unique'] = (bool)$joinColumnElement['unique'];
|
||||
@ -251,10 +272,10 @@ class XmlDriver extends AbstractFileDriver
|
||||
$joinColumn['nullable'] = (bool)$joinColumnElement['nullable'];
|
||||
}
|
||||
if (isset($joinColumnElement['onDelete'])) {
|
||||
$joinColumn['onDelete'] = (string)$joinColumnElement['onDelete'];
|
||||
$joinColumn['onDelete'] = (string)$joinColumnElement['on-delete'];
|
||||
}
|
||||
if (isset($joinColumnElement['onUpdate'])) {
|
||||
$joinColumn['onUpdate'] = (string)$joinColumnElement['onUpdate'];
|
||||
$joinColumn['onUpdate'] = (string)$joinColumnElement['on-update'];
|
||||
}
|
||||
|
||||
return $joinColumn;
|
||||
|
@ -28,8 +28,6 @@ use Doctrine\DBAL\Types\Type,
|
||||
* The SchemaTool is a tool to create and/or drop database schemas based on
|
||||
* <tt>ClassMetadata</tt> class descriptors.
|
||||
*
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
@ -70,10 +68,11 @@ class SchemaTool
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of DDL statements for the specified array of ClassMetadata instances.
|
||||
* Gets the list of DDL statements that are required to create the database schema for
|
||||
* the given list of ClassMetadata instances.
|
||||
*
|
||||
* @param array $classes
|
||||
* @return array $sql
|
||||
* @return array $sql The SQL statements needed to create the schema for the classes.
|
||||
*/
|
||||
public function getCreateSchemaSql(array $classes)
|
||||
{
|
||||
@ -140,11 +139,18 @@ class SchemaTool
|
||||
$foreignKeyConstraints[] = $constraint;
|
||||
}
|
||||
} else if ($class->isInheritanceTypeTablePerClass()) {
|
||||
//TODO
|
||||
throw DoctrineException::notSupported();
|
||||
} else {
|
||||
$columns = $this->_gatherColumns($class, $options);
|
||||
$this->_gatherRelationsSql($class, $sql, $columns, $foreignKeyConstraints);
|
||||
}
|
||||
|
||||
if (isset($class->primaryTable['indexes'])) {
|
||||
$options['indexes'] = $class->primaryTable['indexes'];
|
||||
}
|
||||
if (isset($class->primaryTable['uniqueConstraints'])) {
|
||||
$options['uniqueConstraints'] = $class->primaryTable['uniqueConstraints'];
|
||||
}
|
||||
|
||||
$sql = array_merge($sql, $this->_platform->getCreateTableSql(
|
||||
$class->getQuotedTableName($this->_platform), $columns, $options));
|
||||
@ -175,6 +181,14 @@ class SchemaTool
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a portable column definition as required by the DBAL for the discriminator
|
||||
* column of a class.
|
||||
*
|
||||
* @param ClassMetadata $class
|
||||
* @return array The portable column definition of the discriminator column as required by
|
||||
* the DBAL.
|
||||
*/
|
||||
private function _getDiscriminatorColumnDefinition($class)
|
||||
{
|
||||
$discrColumn = $class->discriminatorColumn;
|
||||
@ -187,11 +201,13 @@ class SchemaTool
|
||||
}
|
||||
|
||||
/**
|
||||
* Gathers the column definitions of all field mappings found in the given class.
|
||||
* Gathers the column definitions as required by the DBAL of all field mappings
|
||||
* found in the given class.
|
||||
*
|
||||
* @param ClassMetadata $class
|
||||
* @param array $options
|
||||
* @return array
|
||||
* @param array $options The table options/constraints where any additional options/constraints
|
||||
* that are required by columns should be appended.
|
||||
* @return array The list of portable column definitions as required by the DBAL.
|
||||
*/
|
||||
private function _gatherColumns($class, array &$options)
|
||||
{
|
||||
@ -203,14 +219,23 @@ class SchemaTool
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a column definition as required by the DBAL from an ORM field mapping definition.
|
||||
*
|
||||
* @param ClassMetadata $class The class that owns the field mapping.
|
||||
* @param array $mapping The field mapping.
|
||||
* @param array $options The table options/constraints where any additional options/constraints
|
||||
* required by the column should be appended.
|
||||
* @return array The portable column definition as required by the DBAL.
|
||||
*/
|
||||
private function _gatherColumn($class, array $mapping, array &$options)
|
||||
{
|
||||
$column = array();
|
||||
$column['name'] = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform);
|
||||
$column['type'] = Type::getType($mapping['type']);
|
||||
$column['length'] = $mapping['length'];
|
||||
$column['notnull'] = ! $mapping['nullable'];
|
||||
$column['length'] = isset($mapping['length']) ? $mapping['length'] : null;
|
||||
$column['notnull'] = isset($mapping['nullable']) ? ! $mapping['nullable'] : false;
|
||||
if (isset($mapping['default'])) {
|
||||
$column['default'] = $mapping['default'];
|
||||
}
|
||||
@ -225,6 +250,18 @@ class SchemaTool
|
||||
return $column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gathers the SQL for properly setting up the relations of the given class.
|
||||
* This includes the SQL for foreign key constraints and join tables.
|
||||
*
|
||||
* @param ClassMetadata $class
|
||||
* @param array $sql The sequence of SQL statements where any new statements should be appended.
|
||||
* @param array $columns The list of columns in the class's primary table where any additional
|
||||
* columns required by relations should be appended.
|
||||
* @param array $constraints The constraints of the table where any additional constraints
|
||||
* required by relations should be appended.
|
||||
* @return void
|
||||
*/
|
||||
private function _gatherRelationsSql($class, array &$sql, array &$columns, array &$constraints)
|
||||
{
|
||||
foreach ($class->associationMappings as $fieldName => $mapping) {
|
||||
@ -246,16 +283,24 @@ class SchemaTool
|
||||
$columns[$column['name']] = $column;
|
||||
$constraint['local'][] = $column['name'];
|
||||
$constraint['foreign'][] = $joinColumn['referencedColumnName'];
|
||||
if (isset($joinColumn['onUpdate'])) {
|
||||
$constraint['onUpdate'] = $joinColumn['onUpdate'];
|
||||
}
|
||||
if (isset($joinColumn['onDelete'])) {
|
||||
$constraint['onDelete'] = $joinColumn['onDelete'];
|
||||
}
|
||||
}
|
||||
$constraints[] = $constraint;
|
||||
} else if ($mapping->isOneToMany() && $mapping->isOwningSide) {
|
||||
//... create join table, one-many through join table supported later
|
||||
throw DoctrineException::updateMe("Not yet implemented.");
|
||||
throw DoctrineException::notSupported();
|
||||
} else if ($mapping->isManyToMany() && $mapping->isOwningSide) {
|
||||
// create join table
|
||||
$joinTableColumns = array();
|
||||
$joinTableOptions = array();
|
||||
$joinTable = $mapping->getJoinTable();
|
||||
|
||||
// Build first FK constraint (relation table => source table)
|
||||
$constraint1 = array(
|
||||
'tableName' => $mapping->getQuotedJoinTableName($this->_platform),
|
||||
'foreignTable' => $class->getQuotedTableName($this->_platform),
|
||||
@ -271,9 +316,16 @@ class SchemaTool
|
||||
$joinTableColumns[$column['name']] = $column;
|
||||
$constraint1['local'][] = $column['name'];
|
||||
$constraint1['foreign'][] = $joinColumn['referencedColumnName'];
|
||||
if (isset($joinColumn['onUpdate'])) {
|
||||
$constraint1['onUpdate'] = $joinColumn['onUpdate'];
|
||||
}
|
||||
if (isset($joinColumn['onDelete'])) {
|
||||
$constraint1['onDelete'] = $joinColumn['onDelete'];
|
||||
}
|
||||
}
|
||||
$constraints[] = $constraint1;
|
||||
|
||||
|
||||
// Build second FK constraint (relation table => target table)
|
||||
$constraint2 = array();
|
||||
$constraint2['tableName'] = $mapping->getQuotedJoinTableName($this->_platform);
|
||||
$constraint2['foreignTable'] = $foreignClass->getQuotedTableName($this->_platform);
|
||||
@ -289,33 +341,192 @@ class SchemaTool
|
||||
$joinTableColumns[$inverseJoinColumn['name']] = $column;
|
||||
$constraint2['local'][] = $inverseJoinColumn['name'];
|
||||
$constraint2['foreign'][] = $inverseJoinColumn['referencedColumnName'];
|
||||
if (isset($inverseJoinColumn['onUpdate'])) {
|
||||
$constraint2['onUpdate'] = $inverseJoinColumn['onUpdate'];
|
||||
}
|
||||
if (isset($joinColumn['onDelete'])) {
|
||||
$constraint2['onDelete'] = $inverseJoinColumn['onDelete'];
|
||||
}
|
||||
}
|
||||
$constraints[] = $constraint2;
|
||||
|
||||
|
||||
// Get the SQL for creating the join table and merge it with the others
|
||||
$sql = array_merge($sql, $this->_platform->getCreateTableSql(
|
||||
$mapping->getQuotedJoinTableName($this->_platform), $joinTableColumns, $joinTableOptions)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Drops the database schema for the given classes.
|
||||
*
|
||||
* @param array $classes
|
||||
* @return void
|
||||
*/
|
||||
public function dropSchema(array $classes)
|
||||
{
|
||||
//TODO
|
||||
$dropSchemaSql = $this->getDropSchemaSql($classes);
|
||||
$conn = $this->_em->getConnection();
|
||||
foreach ($dropSchemaSql as $sql) {
|
||||
$conn->execute($sql);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the SQL needed to drop the database schema for the given classes.
|
||||
*
|
||||
* @param array $classes
|
||||
* @return array
|
||||
*/
|
||||
public function getDropSchemaSql(array $classes)
|
||||
{
|
||||
//TODO
|
||||
$sql = array();
|
||||
$commitOrder = $classes; //FIXME: get real commit order!!
|
||||
|
||||
// Drop tables in reverse commit order
|
||||
for ($i = count($commitOrder) - 1; $i >= 0; --$i) {
|
||||
$class = $commitOrder[$i];
|
||||
if ($class->isInheritanceTypeSingleTable() && $class->name != $class->rootEntityName) {
|
||||
continue;
|
||||
}
|
||||
$sql[] = $this->_platform->getDropTableSql($class->getTableName());
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the database schema of the given classes by comparing the ClassMetadata
|
||||
* instances to the current database schema that is inspected.
|
||||
*
|
||||
* @param array $classes
|
||||
* @return void
|
||||
*/
|
||||
public function updateSchema(array $classes)
|
||||
{
|
||||
//TODO
|
||||
$updateSchemaSql = $this->getUpdateSchemaSql($classes);
|
||||
$conn = $this->_em->getConnection();
|
||||
foreach ($updateSchemaSql as $sql) {
|
||||
$conn->execute($sql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sequence of SQL statements that need to be performed in order
|
||||
* to bring the given class mappings in-synch with the relational schema.
|
||||
*
|
||||
* @param array $classes The classes to consider.
|
||||
* @return array The sequence of SQL statements.
|
||||
*/
|
||||
public function getUpdateSchemaSql(array $classes)
|
||||
{
|
||||
//TODO
|
||||
$sql = array();
|
||||
$conn = $this->_em->getConnection();
|
||||
$sm = $conn->getSchemaManager();
|
||||
|
||||
$tables = $sm->listTables();
|
||||
$newClasses = array();
|
||||
|
||||
foreach ($classes as $class) {
|
||||
$tableName = $class->getTableName();
|
||||
$tableExists = false;
|
||||
foreach ($tables as $index => $table) {
|
||||
if ($tableName == $table) {
|
||||
$tableExists = true;
|
||||
unset($tables[$index]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( ! $tableExists) {
|
||||
$newClasses[] = $class;
|
||||
} else {
|
||||
$newFields = array();
|
||||
$newJoinColumns = array();
|
||||
$currentColumns = $sm->listTableColumns($tableName);
|
||||
|
||||
foreach ($class->fieldMappings as $fieldMapping) {
|
||||
$exists = false;
|
||||
foreach ($currentColumns as $index => $column) {
|
||||
if ($column['name'] == $fieldMapping['columnName']) {
|
||||
// Column exists, check for changes
|
||||
|
||||
// 1. check for nullability change
|
||||
// 2. check for uniqueness change
|
||||
// 3. check for length change if type string
|
||||
// 4. check for type change
|
||||
|
||||
unset($currentColumns[$index]);
|
||||
$exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( ! $exists) {
|
||||
$newFields[] = $fieldMapping;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($class->associationMappings as $assoc) {
|
||||
if ($assoc->isOwningSide && $assoc->isOneToOne()) {
|
||||
foreach ($assoc->targetToSourceKeyColumns as $targetColumn => $sourceColumn) {
|
||||
$exists = false;
|
||||
foreach ($currentColumns as $index => $column) {
|
||||
if ($column['name'] == $sourceColumn) {
|
||||
// Column exists, check for changes
|
||||
|
||||
// 1. check for nullability change
|
||||
|
||||
unset($currentColumns[$index]);
|
||||
$exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( ! $exists) {
|
||||
$newJoinColumns[$sourceColumn] = array(
|
||||
'name' => $sourceColumn,
|
||||
'type' => 'integer' //FIXME!!!
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($newFields || $newJoinColumns) {
|
||||
$changes = array();
|
||||
foreach ($newFields as $newField) {
|
||||
$options = array();
|
||||
$changes['add'][$newField['columnName']] = $this->_gatherColumn($class, $newField, $options);
|
||||
}
|
||||
foreach ($newJoinColumns as $name => $joinColumn) {
|
||||
$changes['add'][$name] = $joinColumn;
|
||||
}
|
||||
$sql[] = $this->_platform->getAlterTableSql($tableName, $changes);
|
||||
}
|
||||
|
||||
// Drop any remaining columns
|
||||
if ($currentColumns) {
|
||||
$changes = array();
|
||||
foreach ($currentColumns as $column) {
|
||||
$options = array();
|
||||
$changes['remove'][$column['name']] = $column;
|
||||
}
|
||||
$sql[] = $this->_platform->getAlterTableSql($tableName, $changes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($newClasses) {
|
||||
$sql = array_merge($this->getCreateSchemaSql($newClasses), $sql);
|
||||
}
|
||||
|
||||
// Drop any remaining tables (Probably not a good idea, because the given class list
|
||||
// may not be complete!)
|
||||
/*if ($tables) {
|
||||
foreach ($tables as $table) {
|
||||
$sql[] = $this->_platform->getDropTableSql($table);
|
||||
}
|
||||
}*/
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,7 @@ use Doctrine\Common\Collections\ArrayCollection,
|
||||
Doctrine\Common\Collections\Collection,
|
||||
Doctrine\Common\DoctrineException,
|
||||
Doctrine\Common\PropertyChangedListener,
|
||||
Doctrine\ORM\Event\LifecycleEventArgs,
|
||||
Doctrine\ORM\Internal\CommitOrderCalculator,
|
||||
Doctrine\ORM\Internal\CommitOrderNode;
|
||||
Doctrine\ORM\Event\LifecycleEventArgs;
|
||||
|
||||
/**
|
||||
* The UnitOfWork is responsible for tracking changes to objects during an
|
||||
@ -233,7 +231,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
{
|
||||
$this->_em = $em;
|
||||
$this->_evm = $em->getEventManager();
|
||||
$this->_commitOrderCalculator = new CommitOrderCalculator();
|
||||
$this->_commitOrderCalculator = new Internal\CommitOrderCalculator();
|
||||
$this->_useCExtension = $this->_em->getConfiguration()->getUseCExtension();
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ class MySqlPlatformTest extends \Doctrine\Tests\DbalTestCase
|
||||
'Variable string declaration is not correct'
|
||||
);
|
||||
$this->assertEquals(
|
||||
'TEXT',
|
||||
'VARCHAR(255)',
|
||||
$this->_platform->getVarcharTypeDeclarationSql(array()),
|
||||
'Long string declaration is not correct'
|
||||
);
|
||||
|
@ -26,7 +26,6 @@ class AllTests
|
||||
$suite->addTest(Query\AllTests::suite());
|
||||
$suite->addTest(Hydration\AllTests::suite());
|
||||
$suite->addTest(Entity\AllTests::suite());
|
||||
$suite->addTest(Tools\AllTests::suite());
|
||||
$suite->addTest(Associations\AllTests::suite());
|
||||
$suite->addTest(Mapping\AllTests::suite());
|
||||
$suite->addTest(Functional\AllTests::suite());
|
||||
|
@ -42,6 +42,7 @@ class AllTests
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\EntityRepositoryTest');
|
||||
|
||||
$suite->addTest(Locking\AllTests::suite());
|
||||
$suite->addTest(SchemaTool\AllTests::suite());
|
||||
|
||||
return $suite;
|
||||
}
|
||||
|
30
tests/Doctrine/Tests/ORM/Functional/SchemaTool/AllTests.php
Normal file
30
tests/Doctrine/Tests/ORM/Functional/SchemaTool/AllTests.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\SchemaTool;
|
||||
|
||||
if (!defined('PHPUnit_MAIN_METHOD')) {
|
||||
define('PHPUnit_MAIN_METHOD', 'Orm_Functional_Tools_AllTests::main');
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
class AllTests
|
||||
{
|
||||
public static function main()
|
||||
{
|
||||
\PHPUnit_TextUI_TestRunner::run(self::suite());
|
||||
}
|
||||
|
||||
public static function suite()
|
||||
{
|
||||
$suite = new \Doctrine\Tests\DoctrineTestSuite('Doctrine Orm Functional Tools');
|
||||
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\SchemaTool\MySqlSchemaToolTest');
|
||||
|
||||
return $suite;
|
||||
}
|
||||
}
|
||||
|
||||
if (PHPUnit_MAIN_METHOD == 'Orm_Functional_Tools_AllTests::main') {
|
||||
AllTests::main();
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
<?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;
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
<?php
|
@ -17,23 +17,23 @@
|
||||
|
||||
<field name="name" column="name" type="string" length="50"/>
|
||||
|
||||
<one-to-one field="address" targetEntity="Address">
|
||||
<join-column name="address_id" referencedColumnName="id"/>
|
||||
<one-to-one field="address" target-entity="Address">
|
||||
<join-column name="address_id" referenced-column-name="id"/>
|
||||
</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-persist/>
|
||||
</cascade>
|
||||
</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-columns>
|
||||
<join-column name="user_id" referencedColumnName="id"/>
|
||||
<join-column name="user_id" referenced-column-name="id"/>
|
||||
</join-columns>
|
||||
<inverse-join-columns>
|
||||
<join-column name="group_id" referencedColumnName="id"/>
|
||||
<join-column name="group_id" referenced-column-name="id"/>
|
||||
</inverse-join-columns>
|
||||
</join-table>
|
||||
</many-to-many>
|
||||
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Tools;
|
||||
|
||||
if (!defined('PHPUnit_MAIN_METHOD')) {
|
||||
define('PHPUnit_MAIN_METHOD', 'Orm_Tools_AllTests::main');
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
class AllTests
|
||||
{
|
||||
public static function main()
|
||||
{
|
||||
\PHPUnit_TextUI_TestRunner::run(self::suite());
|
||||
}
|
||||
|
||||
public static function suite()
|
||||
{
|
||||
$suite = new \Doctrine\Tests\DoctrineTestSuite('Doctrine Orm Tools');
|
||||
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Tools\SchemaToolTest');
|
||||
|
||||
return $suite;
|
||||
}
|
||||
}
|
||||
|
||||
if (PHPUnit_MAIN_METHOD == 'Orm_Tools_AllTests::main') {
|
||||
AllTests::main();
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user