Вход Регистрация
Файл: src/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php
Строк: 350
<?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 MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace DoctrineDBALShardingSQLAzure;

use 
DoctrineDBALSchemaSchema;
use 
DoctrineDBALConnection;
use 
DoctrineDBALTypesType;

use 
DoctrineDBALSchemaSynchronizerAbstractSchemaSynchronizer;
use 
DoctrineDBALSchemaSynchronizerSingleDatabaseSynchronizer;
use 
DoctrineDBALSchemaSynchronizerSchemaSynchronizer;

/**
 * SQL Azure Schema Synchronizer.
 *
 * Will iterate over all shards when performing schema operations. This is done
 * by partitioning the passed schema into subschemas for the federation and the
 * global database and then applying the operations step by step using the
 * {@see DoctrineDBALSchemaSynchronizerSingleDatabaseSynchronizer}.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class SQLAzureFederationsSynchronizer extends AbstractSchemaSynchronizer
{
    const 
FEDERATION_TABLE_FEDERATED   'azure.federated';
    const 
FEDERATION_DISTRIBUTION_NAME 'azure.federatedOnDistributionName';

    
/**
     * @var DoctrineDBALShardingSQLAzureSQLAzureShardManager
     */
    
private $shardManager;

    
/**
     * @var DoctrineDBALSchemaSynchronizerSchemaSynchronizer
     */
    
private $synchronizer;

    
/**
     * @param DoctrineDBALConnection                                  $conn
     * @param DoctrineDBALShardingSQLAzureSQLAzureShardManager      $shardManager
     * @param DoctrineDBALSchemaSynchronizerSchemaSynchronizer|null $sync
     */
    
public function __construct(Connection $connSQLAzureShardManager $shardManagerSchemaSynchronizer $sync null)
    {
        
parent::__construct($conn);
        
$this->shardManager $shardManager;
        
$this->synchronizer $sync ?: new SingleDatabaseSynchronizer($conn);
    }

    
/**
     * {@inheritdoc}
     */
    
public function getCreateSchema(Schema $createSchema)
    {
        
$sql = array();

        list(
$global$federation) = $this->partitionSchema($createSchema);

        
$globalSql $this->synchronizer->getCreateSchema($global);
        if (
$globalSql) {
            
$sql[] = "-- Create Root Federationn" .
                     
"USE FEDERATION ROOT WITH RESET;";
            
$sql array_merge($sql$globalSql);
        }

        
$federationSql $this->synchronizer->getCreateSchema($federation);

        if (
$federationSql) {
            
$defaultValue $this->getFederationTypeDefaultValue();

            
$sql[] = $this->getCreateFederationStatement();
            
$sql[] = "USE FEDERATION " $this->shardManager->getFederationName() . " (" $this->shardManager->getDistributionKey() . " = " $defaultValue ") WITH RESET, FILTERING = OFF;";
            
$sql array_merge($sql$federationSql);
        }

        return 
$sql;
    }

    
/**
     * {@inheritdoc}
     */
    
public function getUpdateSchema(Schema $toSchema$noDrops false)
    {
        return 
$this->work($toSchema, function ($synchronizer$schema) use ($noDrops) {
            return 
$synchronizer->getUpdateSchema($schema$noDrops);
        });
    }

    
/**
     * {@inheritdoc}
     */
    
public function getDropSchema(Schema $dropSchema)
    {
        return 
$this->work($dropSchema, function ($synchronizer$schema) {
            return 
$synchronizer->getDropSchema($schema);
        });
    }

    
/**
     * {@inheritdoc}
     */
    
public function createSchema(Schema $createSchema)
    {
        
$this->processSql($this->getCreateSchema($createSchema));
    }

    
/**
     * {@inheritdoc}
     */
    
public function updateSchema(Schema $toSchema$noDrops false)
    {
        
$this->processSql($this->getUpdateSchema($toSchema$noDrops));
    }

    
/**
     * {@inheritdoc}
     */
    
public function dropSchema(Schema $dropSchema)
    {
        
$this->processSqlSafely($this->getDropSchema($dropSchema));
    }

    
/**
     * {@inheritdoc}
     */
    
public function getDropAllSchema()
    {
        
$this->shardManager->selectGlobal();
        
$globalSql $this->synchronizer->getDropAllSchema();

        if (
$globalSql) {
            
$sql[] = "-- Work on Root FederationnUSE FEDERATION ROOT WITH RESET;";
            
$sql array_merge($sql$globalSql);
        }

        
$shards $this->shardManager->getShards();
        foreach (
$shards as $shard) {
            
$this->shardManager->selectShard($shard['rangeLow']);

            
$federationSql $this->synchronizer->getDropAllSchema();
            if (
$federationSql) {
                
$sql[] = "-- Work on Federation ID " $shard['id'] . "n" .
                         
"USE FEDERATION " $this->shardManager->getFederationName() . " (" $this->shardManager->getDistributionKey() . " = " $shard['rangeLow'].") WITH RESET, FILTERING = OFF;";
                
$sql array_merge($sql$federationSql);
            }
        }

        
$sql[] = "USE FEDERATION ROOT WITH RESET;";
        
$sql[] = "DROP FEDERATION " $this->shardManager->getFederationName();

        return 
$sql;
    }

    
/**
     * {@inheritdoc}
     */
    
public function dropAllSchema()
    {
        
$this->processSqlSafely($this->getDropAllSchema());
    }

    
/**
     * @param DoctrineDBALSchemaSchema $schema
     *
     * @return array
     */
    
private function partitionSchema(Schema $schema)
    {
        return array(
            
$this->extractSchemaFederation($schemafalse),
            
$this->extractSchemaFederation($schematrue),
        );
    }

    
/**
     * @param DoctrineDBALSchemaSchema $schema
     * @param boolean                      $isFederation
     *
     * @return DoctrineDBALSchemaSchema
     *
     * @throws RuntimeException
     */
    
private function extractSchemaFederation(Schema $schema$isFederation)
    {
        
$partitionedSchema = clone $schema;

        foreach (
$partitionedSchema->getTables() as $table) {
            if (
$isFederation) {
                
$table->addOption(self::FEDERATION_DISTRIBUTION_NAME$this->shardManager->getDistributionKey());
            }

            if (
$table->hasOption(self::FEDERATION_TABLE_FEDERATED) !== $isFederation) {
                
$partitionedSchema->dropTable($table->getName());
            } else {
                foreach (
$table->getForeignKeys() as $fk) {
                    
$foreignTable $schema->getTable($fk->getForeignTableName());
                    if (
$foreignTable->hasOption(self::FEDERATION_TABLE_FEDERATED) !== $isFederation) {
                        throw new 
RuntimeException("Cannot have foreign key between global/federation.");
                    }
                }
            }
        }

        return 
$partitionedSchema;
    }

    
/**
     * Work on the Global/Federation based on currently existing shards and
     * perform the given operation on the underlying schema synchronizer given
     * the different partitioned schema instances.
     *
     * @param DoctrineDBALSchemaSchema $schema
     * @param Closure                     $operation
     *
     * @return array
     */
    
private function work(Schema $schemaClosure $operation)
    {
        list(
$global$federation) = $this->partitionSchema($schema);
        
$sql = array();

        
$this->shardManager->selectGlobal();
        
$globalSql $operation($this->synchronizer$global);

        if (
$globalSql) {
            
$sql[] = "-- Work on Root FederationnUSE FEDERATION ROOT WITH RESET;";
            
$sql   array_merge($sql$globalSql);
        }

        
$shards $this->shardManager->getShards();

        foreach (
$shards as $shard) {
            
$this->shardManager->selectShard($shard['rangeLow']);

            
$federationSql $operation($this->synchronizer$federation);
            if (
$federationSql) {
                
$sql[] = "-- Work on Federation ID " $shard['id'] . "n" .
                         
"USE FEDERATION " $this->shardManager->getFederationName() . " (" $this->shardManager->getDistributionKey() . " = " $shard['rangeLow'].") WITH RESET, FILTERING = OFF;";
                
$sql   array_merge($sql$federationSql);
            }
        }

        return 
$sql;
    }

    
/**
     * @return string
     */
    
private function getFederationTypeDefaultValue()
    {
        
$federationType Type::getType($this->shardManager->getDistributionType());

        switch (
$federationType->getName()) {
            case 
Type::GUID:
                
$defaultValue '00000000-0000-0000-0000-000000000000';
                break;
            case 
Type::INTEGER:
            case 
Type::SMALLINT:
            case 
Type::BIGINT:
                
$defaultValue '0';
                break;
            default:
                
$defaultValue '';
                break;
        }

        return 
$defaultValue;
    }

    
/**
     * @return string
     */
    
private function getCreateFederationStatement()
    {
        
$federationType Type::getType($this->shardManager->getDistributionType());
        
$federationTypeSql $federationType->getSqlDeclaration(array(), $this->conn->getDatabasePlatform());

        return 
"--Create Federationn" .
               
"CREATE FEDERATION " $this->shardManager->getFederationName() . " (" $this->shardManager->getDistributionKey() . " " $federationTypeSql ."  RANGE)";
    }
}
Онлайн: 0
Реклама