Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions lib/Doctrine/DBAL/Schema/Comparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,24 @@ public function compare(Schema $fromSchema, Schema $toSchema)
$diff->removedSequences[] = $sequence;
}

foreach ($toSchema->getViews() as $view) {
$viewName = $view->getShortestName($toSchema->getName());
if (! $fromSchema->hasView($viewName)) {
$diff->newViews[$viewName] = $view;
} elseif (! $fromSchema->getView($viewName)->isSameAs($view)) {
$diff->changedViews[$viewName] = $view;
}
}

foreach ($fromSchema->getViews() as $view) {
$viewName = $view->getShortestName($fromSchema->getName());
if ($toSchema->hasView($viewName)) {
continue;
}

$diff->removedViews[$viewName] = $view;
}

return $diff;
}

Expand Down
90 changes: 86 additions & 4 deletions lib/Doctrine/DBAL/Schema/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,25 @@ class Schema extends AbstractAsset
/** @var Sequence[] */
protected $_sequences = [];

/** @var View[] */
protected $_views = [];

/** @var SchemaConfig */
protected $_schemaConfig = false;

/**
* @param Table[] $tables
* @param Sequence[] $sequences
* @param string[] $namespaces
* @param Table[] $tables
* @param Sequence[] $sequences
* @param SchemaConfig | null $schemaConfig
* @param string[] $namespaces
* @param View[] $views
*/
public function __construct(
array $tables = [],
array $sequences = [],
?SchemaConfig $schemaConfig = null,
array $namespaces = []
array $namespaces = [],
array $views = []
) {
if ($schemaConfig === null) {
$schemaConfig = new SchemaConfig();
Expand All @@ -81,6 +87,10 @@ public function __construct(
foreach ($sequences as $sequence) {
$this->_addSequence($sequence);
}

foreach ($views as $view) {
$this->_addView($view);
}
}

/**
Expand Down Expand Up @@ -134,6 +144,27 @@ protected function _addSequence(Sequence $sequence)
$this->_sequences[$seqName] = $sequence;
}

/**
* @return void
*
* @throws SchemaException
*/
protected function _addView(View $view)
{
$namespaceName = $view->getNamespaceName();
$viewName = $view->getFullQualifiedName($this->getName());

if (isset($this->_views[$viewName])) {
throw SchemaException::viewAlreadyExists($viewName);
}

if (! $view->isInDefaultNamespace($this->getName()) && ! $this->hasNamespace($namespaceName)) {
$this->createNamespace($namespaceName);
}

$this->_views[$viewName] = $view;
}

/**
* Returns the namespaces of this schema.
*
Expand Down Expand Up @@ -384,6 +415,50 @@ public function dropSequence($sequenceName)
return $this;
}

public function hasView(string $viewName): bool
{
$viewName = $this->getFullQualifiedAssetName($viewName);

return isset($this->_views[$viewName]);
}

/**
* @throws SchemaException
*/
public function getView(string $viewName) : View
{
$viewName = $this->getFullQualifiedAssetName($viewName);
if (! isset($this->_views[$viewName])) {
throw SchemaException::viewDoesNotExist($viewName);
}

return $this->_views[$viewName];
}

/**
* @return View[]
*/
public function getViews() : array
{
return $this->_views;
}

public function createView(string $viewName, string $sql) : View
{
$view = new View($viewName, $sql);
$this->_addView($view);

return $view;
}

public function dropView(string $viewName) : self
{
$viewName = $this->getFullQualifiedAssetName($viewName);
unset($this->_views[$viewName]);

return $this;
}

/**
* Returns an array of necessary SQL queries to create the schema on the given platform.
*
Expand Down Expand Up @@ -452,6 +527,10 @@ public function visit(Visitor $visitor)
foreach ($this->_sequences as $sequence) {
$sequence->visit($visitor);
}

foreach ($this->_views as $view) {
$view->visit($visitor);
}
}

/**
Expand All @@ -467,5 +546,8 @@ public function __clone()
foreach ($this->_sequences as $k => $sequence) {
$this->_sequences[$k] = clone $sequence;
}
foreach ($this->_views as $k => $view) {
$this->_views[$k] = clone $view;
}
}
}
25 changes: 25 additions & 0 deletions lib/Doctrine/DBAL/Schema/SchemaDiff.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ class SchemaDiff
/** @var ForeignKeyConstraint[] */
public $orphanedForeignKeys = [];

/** @var View[] */
public $newViews = [];

/** @var View[] */
public $changedViews = [];

/** @var View[] */
public $removedViews = [];

/**
* Constructs an SchemaDiff object.
*
Expand Down Expand Up @@ -136,6 +145,22 @@ protected function _toSql(AbstractPlatform $platform, $saveMode = false)
}
}

if ($platform->supportsViews() === true) {
if ($saveMode === false) {
foreach ($this->removedViews as $view) {
$sql[] = $platform->getDropViewSQL($view->getName());
}
}
foreach ($this->changedViews as $view) {
$sql[] = $platform->getDropViewSQL($view->getName());
$sql[] = $platform->getCreateViewSQL($view->getName(), $view->getSql());
}

foreach ($this->newViews as $view) {
$sql[] = $platform->getCreateViewSQL($view->getName(), $view->getSql());
}
}

$foreignKeySql = [];
foreach ($this->newTables as $table) {
$sql = array_merge(
Expand Down
12 changes: 12 additions & 0 deletions lib/Doctrine/DBAL/Schema/SchemaException.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class SchemaException extends DBALException
public const INDEX_INVALID_NAME = 90;
public const FOREIGNKEY_DOESNT_EXIST = 100;
public const NAMESPACE_ALREADY_EXISTS = 110;
public const VIEW_DOENST_EXIST = 120;
public const VIEW_ALREADY_EXISTS = 130;

/**
* @param string $tableName
Expand Down Expand Up @@ -180,4 +182,14 @@ public static function alterTableChangeNotSupported($changeName)
sprintf("Alter table change not supported, given '%s'", $changeName)
);
}

public static function viewAlreadyExists(string $viewName)
{
return new self("The view '" . $viewName . "' already exists.", self::VIEW_ALREADY_EXISTS);
}

public static function viewDoesNotExist(string $viewName)
{
return new self("There exists no view with the name '" . $viewName . "'.", self::VIEW_DOENST_EXIST);
}
}
28 changes: 19 additions & 9 deletions lib/Doctrine/DBAL/Schema/View.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace Doctrine\DBAL\Schema;

use Doctrine\DBAL\Schema\Visitor\ViewVisitor;
use Doctrine\DBAL\Schema\Visitor\Visitor;

/**
* Representation of a Database View.
*/
Expand All @@ -10,21 +13,28 @@ class View extends AbstractAsset
/** @var string */
private $sql;

/**
* @param string $name
* @param string $sql
*/
public function __construct($name, $sql)
public function __construct(string $name, string $sql)
{
$this->_setName($name);
$this->sql = $sql;
}

/**
* @return string
*/
public function getSql()
public function getSql(): string
{
return $this->sql;
}

public function visit(Visitor $visitor): void
{
if (! ($visitor instanceof ViewVisitor)) {
return;
}

$visitor->acceptView($this);
}

public function isSameAs(View $anotherView): bool
{
return $anotherView->getSql() === $this->getSql();
}
}
7 changes: 6 additions & 1 deletion lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Sequence;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\View;

/**
* Abstract Visitor with empty methods for easy extension.
*/
class AbstractVisitor implements Visitor, NamespaceVisitor
class AbstractVisitor implements Visitor, NamespaceVisitor, ViewVisitor
{
public function acceptSchema(Schema $schema)
{
Expand Down Expand Up @@ -44,4 +45,8 @@ public function acceptIndex(Table $table, Index $index)
public function acceptSequence(Sequence $sequence)
{
}

public function acceptView(View $view)
{
}
}
16 changes: 15 additions & 1 deletion lib/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
use Doctrine\DBAL\Schema\Sequence;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\View;
use function array_merge;

class CreateSchemaSqlCollector extends AbstractVisitor
Expand All @@ -22,6 +23,9 @@ class CreateSchemaSqlCollector extends AbstractVisitor
/** @var string[] */
private $createFkConstraintQueries = [];

/** @var string[] */
private $createViewQueries = [];

/** @var AbstractPlatform */
private $platform = null;

Expand Down Expand Up @@ -70,6 +74,14 @@ public function acceptSequence(Sequence $sequence)
$this->createSequenceQueries[] = $this->platform->getCreateSequenceSQL($sequence);
}

/**
* {@inheritdoc}
*/
public function acceptView(View $view)
{
$this->createViewQueries[] = $this->platform->getCreateViewSQL($view->getName(), $view->getSql());
}

/**
* @return void
*/
Expand All @@ -79,6 +91,7 @@ public function resetQueries()
$this->createTableQueries = [];
$this->createSequenceQueries = [];
$this->createFkConstraintQueries = [];
$this->createViewQueries = [];
}

/**
Expand All @@ -92,7 +105,8 @@ public function getQueries()
$this->createNamespaceQueries,
$this->createTableQueries,
$this->createSequenceQueries,
$this->createFkConstraintQueries
$this->createFkConstraintQueries,
$this->createViewQueries
);
}
}
Loading