Skip to content
Browse files

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.
  • Loading branch information...
1 parent 256bad5 commit 1443881e5400aad65c5185d7119d5fabe75583ae @beberlei beberlei committed
View
4 composer.lock
@@ -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": []
View
235 lib/Doctrine/Shards/DBAL/SQLAzure/Schema/CreateFederationSchemaVisitor.php
@@ -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"
+ );
+ }
+}
+
View
35 tests/Doctrine/Tests/Shards/DBAL/SQLAzure/CreateFederationSchemaVisitorTest.php
@@ -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);
+ }
+}
+

0 comments on commit 1443881

Please sign in to comment.
Something went wrong with that request. Please try again.