Skip to content
This repository has been archived by the owner on Dec 11, 2018. It is now read-only.

Commit

Permalink
Add tests for multi tenant visitor
Browse files Browse the repository at this point in the history
  • Loading branch information
beberlei committed Mar 12, 2012
1 parent ea37c27 commit c506290
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 14 deletions.
8 changes: 8 additions & 0 deletions AZURE_FEDERATIONS.md
Expand Up @@ -22,6 +22,14 @@ Implementing Federations inside a new Doctrine Sharding Extension. Some extensio
* Extend ID Generation layer
* Implement API that allow users to choose the shard target for any given query

## Implementation Details

SQL Azure requires one and exactly one clustered index. It makes no difference if the primary key
or any other key is the clustered index. Sharding requires an external ID generation (no auto-increment)
such as GUIDs. GUIDs have negative properties with regard to clustered index performance, so that
typically you would add a "created" timestamp for example that holds the clustered index instead
of making the GUID a clustered index.

## Example API:

@@@ php
Expand Down
14 changes: 8 additions & 6 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 17 additions & 6 deletions lib/Doctrine/Shards/DBAL/SQLAzure/Schema/MultiTenantVisitor.php
Expand Up @@ -33,7 +33,9 @@
* Federations under the following assumptions:
*
* - Every table is part of the multi-tenant application, only explicitly
* excluded tables are non-federated.
* 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')`.
Expand All @@ -42,7 +44,7 @@
* - Primary keys are either using globally unique ids (GUID, Table Generator)
* or you explicitly add the tenent_id in every UPDATE or DELETE statement
* (otherwise they will affect the same-id rows from other tenents as well).
* SQLAzure throws exception when IDENTIY columns are used on federated
* SQLAzure throws errors when you try to create IDENTIY columns on federated
* tables.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
Expand All @@ -64,10 +66,19 @@ class MultiTenantVisitor implements Visitor
*/
private $tenantColumnType = 'integer';

public function __construct(array $excludedTables = array(), $tenantColumnName = 'tenant_id')
/**
* Name of the federation distribution, defaulting to the tenantColumnName
* if not specified.
*
* @var string
*/
private $distributionName;

public function __construct(array $excludedTables = array(), $tenantColumnName = 'tenant_id', $distributionName = null)
{
$this->excludedTables = $excludedTables;
$this->tenantColumnName = $tenantColumnName;
$this->distributionName = $distributionName ?: $tenantColumnName;
}

/**
Expand All @@ -79,9 +90,8 @@ public function acceptTable(Table $table)
return;
}

// TODO: will only work with integer columns as of now.
$table->addColumn($this->tenantColumnName, $this->tenantColumnType, array(
'default' => "federation_filtering_value('". $this->tenantColumnName ."')",
'default' => "federation_filtering_value('". $this->distributionName ."')",
));

$clusteredIndex = $this->getClusteredIndex($table);
Expand All @@ -94,7 +104,8 @@ public function acceptTable(Table $table)
$table->setPrimaryKey($indexColumns);
} else {
$table->dropIndex($clusteredIndex->getName());
$table->addIndex($indexColumns);
$table->addIndex($indexColumns, $clusteredIndex->getName());
$table->getIndex($clusteredIndex->getName())->addFlag('clustered');
}
}

Expand Down
Expand Up @@ -25,7 +25,7 @@

class MultiTenantVisitorTest extends \PHPUnit_Framework_TestCase
{
public function testMultiTenant()
public function testMultiTenantPrimaryKey()
{
$platform = new SQLAzurePlatform();
$visitor = new MultiTenantVisitor();
Expand All @@ -36,7 +36,30 @@ public function testMultiTenant()
$foo->setPrimaryKey(array('id'));
$schema->visit($visitor);

var_dump($schema);
$this->assertEquals(array('id', 'tenant_id'), $foo->getPrimaryKey()->getColumns());
$this->assertTrue($foo->hasColumn('tenant_id'));
}

public function testMultiTenantNonPrimaryKey()
{
$platform = new SQLAzurePlatform();
$visitor = new MultiTenantVisitor();

$schema = new Schema();
$foo = $schema->createTable('foo');
$foo->addColumn('id', 'string');
$foo->addColumn('created', 'datetime');
$foo->setPrimaryKey(array('id'));
$foo->addIndex(array('created'), 'idx');

$foo->getPrimaryKey()->addFlag('nonclustered');
$foo->getIndex('idx')->addFlag('clustered');

$schema->visit($visitor);

$this->assertEquals(array('id'), $foo->getPrimaryKey()->getColumns());
$this->assertTrue($foo->hasColumn('tenant_id'));
$this->assertEquals(array('created', 'tenant_id'), $foo->getIndex('idx')->getColumns());
}
}

0 comments on commit c506290

Please sign in to comment.