Файл: vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php
Строк: 221
<?php
namespace DoctrineDBALShardingSQLAzureSchema;
use DoctrineDBALSchemaColumn;
use DoctrineDBALSchemaForeignKeyConstraint;
use DoctrineDBALSchemaIndex;
use DoctrineDBALSchemaSchema;
use DoctrineDBALSchemaSequence;
use DoctrineDBALSchemaTable;
use DoctrineDBALSchemaVisitorVisitor;
use RuntimeException;
use function in_array;
/**
* Converts a single tenant schema into a multi-tenant schema for SQL Azure
* Federations under the following assumptions:
*
* - Every table is part of the multi-tenant application, only explicitly
* excluded tables are non-federated. The behavior of the tables being in
* global or federated database is undefined. It depends on you selecting a
* federation before DDL statements or not.
* - Every Primary key of a federated table is extended by another column
* 'tenant_id' with a default value of the SQLAzure function
* `federation_filtering_value('tenant_id')`.
* - You always have to work with `filtering=On` when using federations with this
* multi-tenant approach.
* - Primary keys are either using globally unique ids (GUID, Table Generator)
* or you explicitly add the tenant_id in every UPDATE or DELETE statement
* (otherwise they will affect the same-id rows from other tenants as well).
* SQLAzure throws errors when you try to create IDENTIY columns on federated
* tables.
*
* @deprecated
*/
class MultiTenantVisitor implements Visitor
{
/** @var string[] */
private $excludedTables = [];
/** @var string */
private $tenantColumnName;
/** @var string */
private $tenantColumnType = 'integer';
/**
* Name of the federation distribution, defaulting to the tenantColumnName
* if not specified.
*
* @var string
*/
private $distributionName;
/**
* @param string[] $excludedTables
* @param string $tenantColumnName
* @param string|null $distributionName
*/
public function __construct(array $excludedTables = [], $tenantColumnName = 'tenant_id', $distributionName = null)
{
$this->excludedTables = $excludedTables;
$this->tenantColumnName = $tenantColumnName;
$this->distributionName = $distributionName ?: $tenantColumnName;
}
/**
* {@inheritdoc}
*/
public function acceptTable(Table $table)
{
if (in_array($table->getName(), $this->excludedTables)) {
return;
}
$table->addColumn($this->tenantColumnName, $this->tenantColumnType, [
'default' => "federation_filtering_value('" . $this->distributionName . "')",
]);
$clusteredIndex = $this->getClusteredIndex($table);
$indexColumns = $clusteredIndex->getColumns();
$indexColumns[] = $this->tenantColumnName;
if ($clusteredIndex->isPrimary()) {
$table->dropPrimaryKey();
$table->setPrimaryKey($indexColumns);
} else {
$table->dropIndex($clusteredIndex->getName());
$table->addIndex($indexColumns, $clusteredIndex->getName());
$table->getIndex($clusteredIndex->getName())->addFlag('clustered');
}
}
/**
* @param Table $table
*
* @return Index
*
* @throws RuntimeException
*/
private function getClusteredIndex($table)
{
foreach ($table->getIndexes() as $index) {
if ($index->isPrimary() && ! $index->hasFlag('nonclustered')) {
return $index;
}
if ($index->hasFlag('clustered')) {
return $index;
}
}
throw new RuntimeException('No clustered index found on table ' . $table->getName());
}
/**
* {@inheritdoc}
*/
public function acceptSchema(Schema $schema)
{
}
/**
* {@inheritdoc}
*/
public function acceptColumn(Table $table, Column $column)
{
}
/**
* {@inheritdoc}
*/
public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint)
{
}
/**
* {@inheritdoc}
*/
public function acceptIndex(Table $table, Index $index)
{
}
/**
* {@inheritdoc}
*/
public function acceptSequence(Sequence $sequence)
{
}
}