Commit 22cfa37f authored by beberlei's avatar beberlei

[2.0] - DDC-169 - Began refactoring of DBAL code, introduced object notation...

[2.0] - DDC-169 - Began refactoring of DBAL code, introduced object notation for a database schema, including Tables, Indexes, Constraints, Sequences and Columns. Added a CreateSql Visitor which transforms a schema object graph into the required SQL statements to create it. Next: Replacing SchemaTool::getCreateSql() with new syntax...
parent fdd9b051
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* The abstract asset allows to reset the name of all assets without publishing this to the public userland.
*
* This encapsulation hack is necessary to keep a consistent state of the database schema. Say we have a list of tables
* array($tableName => Table($tableName)); if you want to rename the table, you have to make sure
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
abstract class AbstractAsset
{
/**
* @var string
*/
protected $_name;
/**
* Set name of this asset
*
* @param string $name
*/
protected function _setName($name)
{
$this->_name = $name;
}
/**
* Return name of this schema asset.
*
* @return string
*/
public function getName()
{
return $this->_name;
}
}
\ No newline at end of file
...@@ -942,14 +942,14 @@ abstract class AbstractSchemaManager ...@@ -942,14 +942,14 @@ abstract class AbstractSchemaManager
/** /**
* Aggregate and group the index results according to the required data result. * Aggregate and group the index results according to the required data result.
* *
* @param array $tableIndexes * @param array $tableIndexRows
* @param string $tableName * @param string $tableName
* @return array * @return array
*/ */
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null)
{ {
$result = array(); $result = array();
foreach($tableIndexes AS $tableIndex) { foreach($tableIndexRows AS $tableIndex) {
$indexName = $keyName = $tableIndex['key_name']; $indexName = $keyName = $tableIndex['key_name'];
if($tableIndex['primary']) { if($tableIndex['primary']) {
$keyName = 'primary'; $keyName = 'primary';
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use \Doctrine\DBAL\Types\Type;
/**
* Object representation of a database column
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Column extends AbstractAsset
{
/**
* @var \Doctrine\DBAL\Types\Type
*/
protected $_type;
/**
* @var int
*/
protected $_length = 255;
/**
* @var int
*/
protected $_precision = 0;
/**
* @var int
*/
protected $_scale = 0;
/**
* @var bool
*/
protected $_unsigned = false;
/**
* @var bool
*/
protected $_fixed = false;
/**
* @var bool
*/
protected $_notnull = true;
/**
* @var string
*/
protected $_default;
/**
* @var array
*/
protected $_platformOptions = array();
/**
* Create a new Column
*
* @param string $columnName
* @param Doctrine\DBAL\Types\Type $type
* @param int $length
* @param bool $notNull
* @param mixed $default
* @param bool $unsigned
* @param bool $fixed
* @param int $precision
* @param int $scale
* @param array $platformOptions
*/
public function __construct($columnName, Type $type, array $options=array())
{
$this->_setName($columnName);
$this->setType($type);
$this->setOptions($options);
}
/**
* @param array $options
* @return Column
*/
public function setOptions(array $options)
{
foreach ($options AS $name => $value) {
$method = "set".$name;
if (method_exists($this, $method)) {
$this->$method($value);
}
}
return $this;
}
/**
* @param Type $type
* @return Column
*/
public function setType(Type $type)
{
$this->_type = $type;
return $this;
}
/**
* @param int $length
* @return Column
*/
public function setLength($length)
{
$this->_length = (int)$length;
return $this;
}
/**
* @param int $precision
* @return Column
*/
public function setPrecision($precision)
{
$this->_precision = (int)$precision;
return $this;
}
/**
* @param int $scale
* @return Column
*/
public function setScale($scale)
{
$this->_scale = $scale;
return $this;
}
/**
*
* @param bool $unsigned
* @return Column
*/
public function setUnsigned($unsigned)
{
$this->_unsigned = (bool)$unsigned;
return $this;
}
/**
*
* @param bool $fixed
* @return Column
*/
public function setFixed($fixed)
{
$this->_fixed = (bool)$fixed;
return $this;
}
/**
* @param bool $notnull
* @return Column
*/
public function setNotnull($notnull)
{
$this->_notnull = (bool)$notnull;
return $this;
}
/**
*
* @param mixed $default
* @return Column
*/
public function setDefault($default)
{
$this->_default = $default;
return $this;
}
/**
*
* @param array $platformOptions
* @return Column
*/
public function setPlatformOptions(array $platformOptions)
{
$this->_platformOptions = $platformOptions;
return $this;
}
/**
*
* @param string $name
* @param mixed $value
* @return Column
*/
public function setPlatformOption($name, $value)
{
$this->_platformOptions[$name] = $value;
return $this;
}
public function getType()
{
return $this->_type;
}
public function getLength()
{
return $this->_length;
}
public function getPrecision()
{
return $this->_precision;
}
public function getScale()
{
return $this->_scale;
}
public function getUnsigned()
{
return $this->_unsigned;
}
public function getFixed()
{
return $this->_fixed;
}
public function getNotnull()
{
return $this->_notnull;
}
public function getDefault()
{
return $this->_default;
}
public function getPlatformOptions()
{
return $this->_platformOptions;
}
public function hasPlatformOption($name)
{
return isset($this->_platformOptions[$name]);
}
public function getPlatformOption($name)
{
return $this->_platformOptions[$name];
}
/**
* @param Visitor $visitor
*/
public function visit(\Doctrine\DBAL\Schema\Visitor $visitor)
{
$visitor->accept($this);
}
}
\ No newline at end of file
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Marker interface for contraints
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
interface Constraint
{
}
\ No newline at end of file
<?php
namespace Doctrine\DBAL\Schema;
class ForeignKeyConstraint extends AbstractAsset implements Constraint
{
/**
* @var array
*/
protected $_localColumnNames;
/**
* @var string
*/
protected $_foreignTableName;
/**
* @var array
*/
protected $_foreignColumnNames;
/**
* @var string
*/
protected $_cascade = '';
/**
* @var array
*/
protected $_options;
/**
*
* @param array $localColumnNames
* @param string $foreignTableName
* @param array $foreignColumnNames
* @param string $cascade
* @param string|null $name
*/
public function __construct(array $localColumnNames, $foreignTableName, array $foreignColumnNames, $name=null, array $options=array())
{
$this->_setName($name);
$this->_localColumnNames = $localColumnNames;
$this->_foreignTableName = $foreignTableName;
$this->_foreignColumnNames = $foreignColumnNames;
$this->_options = $options;
}
/**
* @return array
*/
public function getLocalColumnNames()
{
return $this->_localColumnNames;
}
/**
* @return string
*/
public function getForeignTableName()
{
return $this->_foreignTableName;
}
/**
* @return array
*/
public function getForeignColumnNames()
{
return $this->_foreignColumnNames;
}
public function hasOption($name)
{
return isset($this->_options[$name]);
}
public function getOption($name)
{
return $this->_options[$name];
}
}
\ No newline at end of file
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
class Index extends AbstractAsset
{
/**
* @var string
*/
protected $_indexName;
/**
* @var array
*/
protected $_columns;
/**
* @var bool
*/
protected $_isUnique = false;
/**
* @var bool
*/
protected $_isPrimary = false;
/**
* @param string $indexName
* @param array $column
* @param bool $isUnique
* @param bool $isPrimary
*/
public function __construct($indexName, array $columns, $isUnique=false, $isPrimary=false)
{
$this->_setName($indexName);
$this->_isUnique = $isUnique;
$this->_isPrimary = $isPrimary;
foreach($columns AS $column) {
$this->_addColumn($column);
}
}
/**
* @param string $column
*/
protected function _addColumn($column)
{
if(is_string($column)) {
$this->_columns[] = $column;
} else {
throw new \InvalidArgumentException("Expecting a string as Index Column");
}
}
/**
* @return array
*/
public function getColumns()
{
return $this->_columns;
}
/**
* @return bool
*/
public function isUnique()
{
return $this->_isUnique;
}
/**
* @return bool
*/
public function isPrimary()
{
return $this->_isPrimary;
}
}
\ No newline at end of file
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Schema\Visitor\CreateSchemaSqlCollector;
/**
* Object representation of a database schema
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Schema extends AbstractAsset
{
/**
* @var array
*/
protected $_tables = array();
/**
* @var array
*/
protected $_sequences = array();
/**
* @param array $tables
* @param array $sequences
*/
public function __construct(array $tables=array(), array $sequences=array())
{
foreach ($tables AS $table) {
$this->_addTable($table);
}
foreach ($sequences AS $sequence) {
$this->_addSequence($sequence);
}
}
/**
* @param Table $table
*/
protected function _addTable(Table $table)
{
$tableName = $table->getName();
if(isset($this->_tables[$tableName])) {
throw SchemaException::tableAlreadyExists($tableName);
}
$this->_tables[$tableName] = $table;
}
/**
* @param Sequence $sequence
*/
protected function _addSequence(Sequence $sequence)
{
$seqName = $sequence->getName();
if (isset($this->_sequences[$seqName])) {
throw SchemaException::sequenceAlreadyExists($seqName);
}
$this->_sequences[$seqName] = $sequence;
}
/**
* Get all tables of this schema.
*
* @return array
*/
public function getTables()
{
return $this->_tables;
}
/**
* @param string $tableName
* @return Table
*/
public function getTable($tableName)
{
if (!isset($this->_tables[$tableName])) {
throw SchemaException::tableDoesNotExist($tableName);
}
return $this->_tables[$tableName];
}
/**
* Does this schema have a table with the given name?
*
* @param string $tableName
* @return Schema
*/
public function hasTable($tableName)
{
return isset($this->_tables[$tableName]);
}
/**
* @param string $sequenceName
* @return bool
*/
public function hasSequence($sequenceName)
{
return isset($this->_sequences[$sequenceName]);
}
/**
* @throws SchemaException
* @param string $sequenceName
* @return Doctrine\DBAL\Schema\Sequence
*/
public function getSequence($sequenceName)
{
if(!$this->hasSequence($sequenceName)) {
throw SchemaException::sequenceDoesNotExist($sequenceName);
}
return $this->_sequences[$sequenceName];
}
/**
* @return Doctrine\DBAL\Schema\Sequence[]
*/
public function getSequences()
{
return $this->_sequences;
}
/**
* Create a new table
*
* @param string $tableName
* @return Table
*/
public function createTable($tableName)
{
$table = new Table($tableName);
$this->_addTable($table);
return $table;
}
/**
* Rename a table
*
* @param string $oldTableName
* @param string $newTableName
* @return Schema
*/
public function renameTable($oldTableName, $newTableName)
{
$table = $this->getTable($oldTableName);
$table->_setName($newTableName);
$this->dropTable($oldTableName);
$this->_addTable($table);
return $this;
}
/**
* Drop a table from the schema.
*
* @param string $tableName
* @return Schema
*/
public function dropTable($tableName)
{
$table = $this->getTable($tableName);
unset($this->_tables[$tableName]);
return $this;
}
/**
* Create a new sequence
*
* @param string $sequenceName
* @param int $allocationSize
* @param int $initialValue
* @return Schema
*/
public function createSequence($sequenceName, $allocationSize=1, $initialValue=1)
{
$seq = new Sequence($sequenceName, $allocationSize, $initialValue);
$this->_addSequence($seq);
return $this;
}
/**
* @param string $sequenceName
* @return Schema
*/
public function dropSequence($sequenceName)
{
unset($this->_sequences[$sequenceName]);
return $this;
}
/**
* @param AbstractPlatform $platform
*/
public function toSql(\Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
$sqlCollector = new CreateSchemaSqlCollector($platform);
$this->visit($sqlCollector);
return $sqlCollector->getQueries();
}
/**
* @param Visitor $visitor
*/
public function visit(Visitor $visitor)
{
$visitor->acceptSchema($this);
foreach ($this->_tables AS $table) {
$table->visit($visitor);
}
foreach ($this->_sequences AS $sequence) {
$sequence->visit($visitor);
}
}
}
<?php
namespace Doctrine\DBAL\Schema;
class SchemaException extends \Doctrine\DBAL\DBALException
{
const TABLE_DOESNT_EXIST = 10;
const TABLE_ALREADY_EXISTS = 20;
const COLUMN_DOESNT_EXIST = 30;
const COLUMN_ALREADY_EXISTS = 40;
const INDEX_DOESNT_EXIST = 50;
const INDEX_ALREADY_EXISTS = 60;
const SEQUENCE_DOENST_EXIST = 70;
const SEQUENCE_ALREADY_EXISTS = 80;
const INDEX_INVALID_NAME = 90;
/**
* @param string $tableName
* @return SchemaException
*/
static public function tableDoesNotExist($tableName)
{
return new self("There is no table with name '".$tableName."' in the schema.", self::TABLE_DOESNT_EXIST);
}
/**
* @param string $indexName
* @return SchemaException
*/
static public function indexNameInvalid($indexName)
{
return new self("Invalid index-name $indexName given, has to be [a-zA-Z0-9_]", self::INDEX_INVALID_NAME);
}
/**
* @param string $indexName
* @return SchemaException
*/
static public function indexDoesNotExist($indexName)
{
return new self("Index '".$indexName."' does not exist.", self::INDEX_DOESNT_EXIST);
}
/**
* @param string $indexName
* @return SchemaException
*/
static public function indexAlreadyExists($indexName)
{
return new self("An index with name $indexName was already defined.", self::INDEX_ALREADY_EXISTS);
}
/**
* @param string $columnName
* @return SchemaException
*/
static public function columnDoesNotExist($columnName)
{
return new self("An unknown column-name $columnName was given.", self::COLUMN_DOESNT_EXIST);
}
/**
*
* @param string $tableName
* @return SchemaException
*/
static public function tableAlreadyExists($tableName)
{
return new self("The table with name '".$tableName."' already exists.", self::TABLE_ALREADY_EXISTS);
}
/**
*
* @param string $tableName
* @param string $columnName
* @return SchemaException
*/
static public function columnAlreadyExists($tableName, $columnName)
{
return new self(
"The column '".$columnName."' on table '".$tableName."' already exists.", self::COLUMN_ALREADY_EXISTS
);
}
/**
* @param string $sequenceName
* @return SchemaException
*/
static public function sequenceAlreadyExists($sequenceName)
{
return new self("The sequence '".$sequenceName."' already exists.", self::SEQUENCE_ALREADY_EXISTS);
}
/**
* @param string $sequenceName
* @return SchemaException
*/
static public function sequenceDoesNotExist($sequenceName)
{
return new self("There exists no sequence with the name '".$sequenceName."'.", self::SEQUENCE_DOENST_EXIST);
}
}
\ No newline at end of file
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Sequence Structure
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Sequence extends AbstractAsset
{
/**
* @var int
*/
protected $_allocationSize = 1;
/**
* @var int
*/
protected $_initialValue = 1;
/**
*
* @param string $name
* @param int $allocationSize
* @param int $initialValue
*/
public function __construct($name, $allocationSize=1, $initialValue=1)
{
$this->_setName($name);
$this->_allocationSize = (is_int($allocationSize))?:1;
$this->_initialValue = (is_int($initialValue))?:1;
}
public function getAllocationSize()
{
return $this->_allocationSize;
}
public function getInitialValue()
{
return $this->_initialValue;
}
/**
* @param Visitor $visitor
*/
public function visit(Visitor $visitor)
{
$visitor->acceptSequence($this);
}
}
This diff is collapsed.
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
/**
* Schema Visitor used for Validation or Generation purposes.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
interface Visitor
{
/**
* @param Schema $schema
*/
public function acceptSchema(Schema $schema);
/**
* @param Table $table
*/
public function acceptTable(Table $table);
/**
* @param Column $column
*/
public function acceptColunn(Table $table, Column $column);
/**
* @param Table $localTable
* @param ForeignKeyConstraint $fkConstraint
*/
public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint);
/**
* @param Table $table
* @param Constraint $constraint
*/
public function acceptCheckConstraint(Table $table, Constraint $constraint);
/**
* @param Table $table
* @param Index $index
*/
public function acceptIndex(Table $table, Index $index);
/**
* @param Sequence $sequence
*/
public function acceptSequence(Sequence $sequence);
}
\ No newline at end of file
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema\Visitor;
use Doctrine\DBAL\Schema\Visitor,
Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\DBAL\Schema\Table,
Doctrine\DBAL\Schema\Schema,
Doctrine\DBAL\Schema\Column,
Doctrine\DBAL\Schema\ForeignKeyConstraint,
Doctrine\DBAL\Schema\Constraint,
Doctrine\DBAL\Schema\Sequence,
Doctrine\DBAL\Schema\Index;
class CreateSchemaSqlCollector implements Visitor
{
/**
* @var array
*/
private $_createTableQueries = array();
/**
* @var array
*/
private $_createSequenceQueries = array();
/**
* @var array
*/
private $_createFkConstraintQueries = array();
/**
*
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
*/
private $_platform = null;
/**
* @param AbstractPlatform $platform
*/
public function __construct(AbstractPlatform $platform)
{
$this->_platform = $platform;
}
/**
* @param Schema $schema
*/
public function acceptSchema(Schema $schema)
{
}
/**
* Generate DDL Statements to create the accepted table with all its dependencies.
*
* @param Table $table
*/
public function acceptTable(Table $table)
{
$options = $table->getOptions();
$options['uniqueConstraints'] = array();
$options['indexes'] = array();
$options['primary'] = array();
foreach($table->getIndexes() AS $index) {
/* @var $index Index */
if(!$index->isPrimary() && !$index->isUnique()) {
$options['indexes'][$index->getName()] = $index->getColumns();
} else {
if($index->isPrimary()) {
$options['primary'] = $index->getColumns();
} else {
$options['uniqueConstraints'][$index->getName()] = $index->getColumns();
}
}
}
/**
$column = array();
$column['name'] = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform);
$column['type'] = Type::getType($mapping['type']);
$column['length'] = isset($mapping['length']) ? $mapping['length'] : null;
$column['notnull'] = isset($mapping['nullable']) ? ! $mapping['nullable'] : true;
$column['unique'] = isset($mapping['unique']) ? $mapping['unique'] : false;
$column['version'] = $class->isVersioned && $class->versionField == $mapping['fieldName'] ? true : false;
if(strtolower($column['type']) == 'string' && $column['length'] === null) {
$column['length'] = 255;
}
if (isset($mapping['precision'])) {
$column['precision'] = $mapping['precision'];
}
if (isset($mapping['scale'])) {
$column['scale'] = $mapping['scale'];
*/
$columns = array();
foreach($columns AS $column) {
/* @var \Doctrine\DBAL\Schema\Column $column */
$columnData = array();
$columnData['name'] = $column->getName();
$columnData['type'] = $column->getType();
$columnData['length'] = $column->getLength();
$columnData['notnull'] = $column->notNull();
$columnData['unique'] = false;
$columnData['version'] = ($column->hasPlatformOption("version"))?$column->getPlatformOptions('version'):false;
if(strtolower($columnData['type']) == "string" && $columnData['length'] === null) {
$columnData['length'] = 255;
}
$columnData['precision'] = $column->getPrecision();
$columnData['scale'] = $column->getScale();
$columnData['default'] = $column->getDefault();
// TODO: Fixed? Unsigned?
if(in_array($column->getName(), $options['primary'])) {
$columnData['primary'] = true;
if($table->isIdGeneratorIdentity()) {
$columnData['autoincrement'] = true;
}
}
$columns[] = $columnData;
}
$this->_createTableQueries = array_merge($this->_createTableQueries,
$this->_platform->getCreateTableSql($table->getName(), $columns, $options)
);
}
public function acceptColunn(Table $table, Column $column)
{
}
/**
* @param Table $localTable
* @param ForeignKeyConstraint $fkConstraint
*/
public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint)
{
$fkConstraintArray = array(
'tableName' => $fkConstraint->getName(),
'foreignTable' => $fkConstraint->getForeignTableName(),
'local' => $fkConstraint->getLocalColumnNames(),
'foreign' => $fkConstraint->getForeignColumnNames(),
'onUpdate' => ($fkConstraint->hasOption('onUpdate')?$fkConstraint->getOption('onUpdate'):null),
'onDelete' => ($fkConstraint->hasOption('onDelete')?$fkConstraint->getOption('onDelete'):null),
);
// Append the foreign key constraints SQL
if ($this->_platform->supportsForeignKeyConstraints()) {
$this->_createFkConstraintQueries = array_merge($this->_createFkConstraintQueries,
(array) $this->_platform->getCreateForeignKeySql($localTable->getName(), $fkConstraintArray)
);
}
}
/**
* @param Table $table
* @param Index $index
*/
public function acceptIndex(Table $table, Index $index)
{
}
/**
* @param Table $table
* @param Constraint $constraint
*/
public function acceptCheckConstraint(Table $table, Constraint $constraint)
{
}
/**
* @param Sequence $sequence
*/
public function acceptSequence(Sequence $sequence)
{
$this->_createSequenceQueries = array_merge($this->_createSequenceQueries,
(array)$this->_platform->getCreateSequenceSql(
$sequence->getName(),
$sequence->getInitialValue(),
$sequence->getAllocationSize()
)
);
}
/**
* @return array
*/
public function resetQueries()
{
$this->_createTableQueries = array();
$this->_createSequenceQueries = array();
$this->_createFkConstraintQueries = array();
}
/**
* Get all queries collected so far.
*
* @return array
*/
public function getQueries()
{
return array_merge(
$this->_createTableQueries,
$this->_createSequenceQueries,
$this->_createFkConstraintQueries
);
}
}
\ No newline at end of file
<?php
namespace Doctrine\Tests\DBAL\Schema;
require_once __DIR__ . '/../../TestInit.php';
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Types\Type;
class ColumnTest extends \PHPUnit_Framework_TestCase
{
public function testGet()
{
$options = array(
'length' => 200,
'precision' => 5,
'scale' => 2,
'unsigned' => true,
'notnull' => false,
'fixed' => true,
'default' => 'baz',
'platformOptions' => array('foo' => 'bar'),
);
$string = Type::getType('string');
$column = new Column("foo", $string, $options);
$this->assertEquals("foo", $column->getName());
$this->assertSame($string, $column->getType());
$this->assertEquals(200, $column->getLength());
$this->assertEquals(5, $column->getPrecision());
$this->assertEquals(2, $column->getScale());
$this->assertTrue($column->getUnsigned());
$this->assertFalse($column->getNotNull());
$this->assertTrue($column->getFixed());
$this->assertEquals("baz", $column->getDefault());
$this->assertEquals(array('foo' => 'bar'), $column->getPlatformOptions());
}
}
\ No newline at end of file
<?php
namespace Doctrine\Tests\DBAL\Schema;
require_once __DIR__ . '/../../TestInit.php';
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\Index;
class IndexTest extends \PHPUnit_Framework_TestCase
{
public function createIndex($unique=false, $primary=false)
{
return new Index("foo", array("bar", "baz"), $unique, $primary);
}
public function testCreateIndex()
{
$idx = $this->createIndex();
$this->assertEquals("foo", $idx->getName());
$columns = $idx->getColumns();
$this->assertEquals(2, count($columns));
$this->assertEquals(array("bar", "baz"), $columns);
$this->assertFalse($idx->isUnique());
$this->assertFalse($idx->isPrimary());
}
public function testCreatePrimary()
{
$idx = $this->createIndex(false, true);
$this->assertFalse($idx->isUnique());
$this->assertTrue($idx->isPrimary());
}
public function testCreateUnique()
{
$idx = $this->createIndex(true, false);
$this->assertTrue($idx->isUnique());
$this->assertFalse($idx->isPrimary());
}
}
\ No newline at end of file
<?php
namespace Doctrine\Tests\DBAL\Schema;
require_once __DIR__ . '/../../TestInit.php';
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\Sequence;
class SchemaTest extends \PHPUnit_Framework_TestCase
{
public function testAddTable()
{
$tableName = "foo";
$table = new Table($tableName);
$schema = new Schema(array($table));
$this->assertTrue($schema->hasTable($tableName));
$tables = $schema->getTables();
$this->assertTrue( isset($tables[$tableName]) );
$this->assertSame($table, $tables[$tableName]);
$this->assertSame($table, $schema->getTable($tableName));
$this->assertTrue($schema->hasTable($tableName));
}
public function testGetUnknownTableThrowsException()
{
$this->setExpectedException("Doctrine\DBAL\Schema\SchemaException");
$schema = new Schema();
$schema->getTable("unknown");
}
public function testCreateTableTwiceThrowsException()
{
$this->setExpectedException("Doctrine\DBAL\Schema\SchemaException");
$tableName = "foo";
$table = new Table($tableName);
$tables = array($table, $table);
$schema = new Schema($tables);
}
public function testRenameTable()
{
$tableName = "foo";
$table = new Table($tableName);
$schema = new Schema(array($table));
$this->assertTrue($schema->hasTable("foo"));
$schema->renameTable("foo", "bar");
$this->assertFalse($schema->hasTable("foo"));
$this->assertTrue($schema->hasTable("bar"));
$this->assertSame($table, $schema->getTable("bar"));
}
public function testDropTable()
{
$tableName = "foo";
$table = new Table($tableName);
$schema = new Schema(array($table));
$this->assertTrue($schema->hasTable("foo"));
$schema->dropTable("foo");
$this->assertFalse($schema->hasTable("foo"));
}
public function testCreateTable()
{
$schema = new Schema();
$this->assertFalse($schema->hasTable("foo"));
$table = $schema->createTable("foo");
$this->assertType('Doctrine\DBAL\Schema\Table', $table);
$this->assertEquals("foo", $table->getName());
$this->assertTrue($schema->hasTable("foo"));
}
public function testAddSequences()
{
$sequence = new Sequence("a_seq", 1, 1);
$schema = new Schema(array(), array($sequence));
$this->assertTrue($schema->hasSequence("a_seq"));
$this->assertType('Doctrine\DBAL\Schema\Sequence', $schema->getSequence("a_seq"));
$sequences = $schema->getSequences();
$this->assertArrayHasKey('a_seq', $sequences);
}
public function testGetUnknownSequenceThrowsException()
{
$this->setExpectedException("Doctrine\DBAL\Schema\SchemaException");
$schema = new Schema();
$schema->getSequence("unknown");
}
public function testCreateSequence()
{
$schema = new Schema();
$schema->createSequence('a_seq');
$this->assertTrue($schema->hasSequence("a_seq"));
$this->assertType('Doctrine\DBAL\Schema\Sequence', $schema->getSequence("a_seq"));
$sequences = $schema->getSequences();
$this->assertArrayHasKey('a_seq', $sequences);
}
public function testDropSequence()
{
$sequence = new Sequence("a_seq", 1, 1);
$schema = new Schema(array(), array($sequence));
$schema->dropSequence("a_seq");
$this->assertFalse($schema->hasSequence("a_seq"));
}
public function testAddSequenceTwiceThrowsException()
{
$this->setExpectedException("Doctrine\DBAL\Schema\SchemaException");
$sequence = new Sequence("a_seq", 1, 1);
$schema = new Schema(array(), array($sequence, $sequence));
}
}
\ No newline at end of file
This diff is collapsed.
<?php
namespace Doctrine\Tests\DBAL\Schema\Visitor;
require_once __DIR__ . '/../../../TestInit.php';
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Types\Type;
class CreateSchemaSqlCollectorTest extends \PHPUnit_Framework_TestCase
{
public function testCreateSchema()
{
$platformMock = $this->getMock(
'Doctrine\DBAL\Platforms\MySqlPlatform',
array('getCreateTableSql', 'getCreateSequenceSql', 'getCreateForeignKeySql')
);
$platformMock->expects($this->exactly(2))
->method('getCreateTableSql')
->will($this->returnValue(array("foo" => "bar")));
$platformMock->expects($this->exactly(1))
->method('getCreateSequenceSql')
->will($this->returnValue(array("bar" => "baz")));
$platformMock->expects($this->exactly(1))
->method('getCreateForeignKeySql')
->will($this->returnValue(array("baz" => "foo")));
$schema = new Schema();
$tableA = $schema->createTable("foo");
$tableA->createColumn("id", 'integer');
$tableA->createColumn("bar", 'string', array('length' => 255));
$tableA->setPrimaryKey(array("id"));
$tableA->setIdGeneratorType(Table::ID_SEQUENCE);
$schema->createSequence("foo_seq");
$tableB = $schema->createTable("bar");
$tableB->createColumn("id", 'integer');
$tableB->setPrimaryKey(array("id"));
$tableA->addForeignKeyConstraint($tableB, array("bar"), array("id"));
$sql = $schema->toSql($platformMock);
$this->assertEquals(array("foo" => "bar", "bar" => "baz", "baz" => "foo"), $sql);
}
}
\ 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