mirror of
https://github.com/doctrine/shards.git
synced 2026-03-24 00:22:10 +01:00
Alternative Federation Schema Visitor that creates a federation ready database-schema. It has to be used manually in code at the moment as there is no way to switch the visitor in DBAL/ORM.
This commit is contained in:
4
composer.lock
generated
4
composer.lock
generated
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"hash": "e21f09d98eab36f406f41df55b7e18dd",
|
||||
"hash": "f1bf274cd5347d7e1223a2212281f907",
|
||||
"packages": [
|
||||
{
|
||||
"package": "doctrine/common",
|
||||
@@ -8,7 +8,7 @@
|
||||
{
|
||||
"package": "doctrine/dbal",
|
||||
"version": "dev-master",
|
||||
"source-reference": "636286f1a573b3fa4f6020b08bb4102745d64fc0"
|
||||
"source-reference": "c64dd83702f5f51814444540554a2ee906cd9416"
|
||||
}
|
||||
],
|
||||
"aliases": []
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
/*
|
||||
* 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\Shards\DBAL\SQLAzure\Schema;
|
||||
|
||||
use Doctrine\DBAL\Schema\Visitor\Visitor,
|
||||
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,
|
||||
Doctrine\DBAL\Types\Type,
|
||||
Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
|
||||
/**
|
||||
* SQL Azure specific schema creator that will add the CREATE Federations
|
||||
* statements.
|
||||
*
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class CreateFederationSchemaVisitor implements Visitor
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $createTableQueries;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $createSequenceQueries;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $createFkConstraintQueries;
|
||||
|
||||
/**
|
||||
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
|
||||
*/
|
||||
private $platform;
|
||||
|
||||
/**
|
||||
* Details about all federations that need to be created.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $federations = array();
|
||||
|
||||
/**
|
||||
* @param AbstractPlatform $platform
|
||||
*/
|
||||
public function __construct(AbstractPlatform $platform)
|
||||
{
|
||||
$this->platform = $platform;
|
||||
$this->resetQueries();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Table $table
|
||||
*/
|
||||
public function acceptTable(Table $table)
|
||||
{
|
||||
$federationName = $this->getFederationName($table);
|
||||
|
||||
$this->createTableQueries[$federationName] = array_merge(
|
||||
$this->createTableQueries[$federationName],
|
||||
$this->platform->getCreateTableSQL($table)
|
||||
);
|
||||
}
|
||||
|
||||
private function getFederationName(Table $table)
|
||||
{
|
||||
$federationName = $table->getOption('azure.federationName');
|
||||
if ( !$federationName) {
|
||||
return '_root';
|
||||
}
|
||||
|
||||
if ( ! $table->getOption('azure.federatedOnDistributionName')) {
|
||||
throw new \RuntimeException("Missing 'azure.federatedOnDistributionName' option on table that is part of a federation.");
|
||||
}
|
||||
|
||||
if ( ! $table->getOption('azure.federatedOnColumnName')) {
|
||||
throw new \RuntimeException("Missing 'azure.federatedOnColumnName' option on table that is part of a federation.");
|
||||
}
|
||||
|
||||
if ( ! isset($this->createTableQueries[$federationName])) {
|
||||
$this->createTableQueries[$federationName] = array();
|
||||
$this->createFkConstraintQueries[$federationName] = array();
|
||||
|
||||
$this->federations[$federationName] = array(
|
||||
'name' => $federationName,
|
||||
'type' => $table->getColumn($table->getOption('azure.federatedOnColumnName'))->getType(),
|
||||
'distributionName' => $table->getOption('azure.federatedOnDistributionName'),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
return $federationName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Table $localTable
|
||||
* @param ForeignKeyConstraint $fkConstraint
|
||||
*/
|
||||
public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint)
|
||||
{
|
||||
$federationName = $this->getFederationName($localTable);
|
||||
|
||||
$this->createFkConstraintQueries[$federationName] = array_merge(
|
||||
$this->createFkConstraintQueries[$federationName],
|
||||
(array) $this->platform->getCreateForeignKeySQL(
|
||||
$fkConstraint, $localTable
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function acceptSchema(Schema $schema)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Column $column
|
||||
*/
|
||||
public function acceptColumn(Table $table, Column $column)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Table $table
|
||||
* @param Index $index
|
||||
*/
|
||||
public function acceptIndex(Table $table, Index $index)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Sequence $sequence
|
||||
*/
|
||||
public function acceptSequence(Sequence $sequence)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function resetQueries()
|
||||
{
|
||||
$this->createTableQueries = array('_root' => array());
|
||||
$this->createSequenceQueries = array('_root' => array());
|
||||
$this->createFkConstraintQueries = array('_root' => array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all queries collected so far.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getQueries()
|
||||
{
|
||||
$sql = array();
|
||||
foreach ($this->federations as $federation) {
|
||||
$sql[] = "CREATE FEDERATION " . $federation['name'] . " (" .
|
||||
$federation['distributionName'] . " " .
|
||||
$federation['type']->getSQLDeclaration(array(), $this->platform) .
|
||||
")";
|
||||
}
|
||||
|
||||
$sqls = array($this->createTableQueries, $this->createFkConstraintQueries);
|
||||
foreach ($sqls as $allSql) {
|
||||
foreach ($allSql as $name => $federationSql) {
|
||||
if ($federationSql) {
|
||||
$sql = array_merge($sql, $this->getSwitchFederationSQL($name));
|
||||
$sql = array_merge($sql, $federationSql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch Federation SQL
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
private function getSwitchFederationSQL($name)
|
||||
{
|
||||
if ($name === '_root') {
|
||||
return array("GO", "USE FEDERATION ROOT WITH RESET", "GO");
|
||||
}
|
||||
|
||||
switch ($this->federations[$name]['type']->getName()) {
|
||||
case Type::GUID:
|
||||
$value = '00000000-0000-0000-0000-000000000000';
|
||||
break;
|
||||
case Type::INTEGER:
|
||||
case Type::SMALLINT:
|
||||
case Type::BIGINT:
|
||||
$value = '0';
|
||||
break;
|
||||
default:
|
||||
$value = '';
|
||||
}
|
||||
|
||||
return array(
|
||||
"GO",
|
||||
"USE FEDERATION " . $name . " (" . $this->federations[$name]['distributionName'] . " = '" . $value . "') WITH RESET, FILTERING=OFF",
|
||||
"GO"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
namespace Doctrine\Tests\Shards\DBAL\SQLAzure;
|
||||
|
||||
use Doctrine\DBAL\Platforms\SQLAzurePlatform;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Shards\DBAL\SQLAzure\Schema\CreateFederationSchemaVisitor;
|
||||
|
||||
class CreateFederationSchemaVisitorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCreateFederations()
|
||||
{
|
||||
$platform = new SQLAzurePlatform();
|
||||
$visitor = new CreateFederationSchemaVisitor($platform);
|
||||
|
||||
$schema = new Schema();
|
||||
$tasks = $schema->createTable('tasks');
|
||||
$tasks->addOption('azure.federationName', 'UserFed');
|
||||
$tasks->addOption('azure.federatedOnDistributionName', 'user_id');
|
||||
$tasks->addOption('azure.federatedOnColumnName', 'user_id');
|
||||
$tasks->addColumn('id', 'guid');
|
||||
$tasks->addColumn('user_id', 'guid');
|
||||
$tasks->setPrimaryKey(array('id'));
|
||||
$schema->visit($visitor);
|
||||
|
||||
$sql = $visitor->getQueries();
|
||||
$this->assertEquals(array(
|
||||
'CREATE FEDERATION UserFed (user_id UNIQUEIDENTIFIER)',
|
||||
'GO',
|
||||
"USE FEDERATION UserFed (user_id = '') WITH RESET, FILTERING=OFF",
|
||||
'GO',
|
||||
'CREATE TABLE tasks (id UNIQUEIDENTIFIER NOT NULL, user_id UNIQUEIDENTIFIER NOT NULL, PRIMARY KEY (id)) FEDERATED ON (user_id = user_id)',
|
||||
), $sql);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user