Rajout de doctrine/orm
[zf2.biz/application_blanche.git] / vendor / doctrine / dbal / docs / design / AZURE_FEDERATIONS.md
diff --git a/vendor/doctrine/dbal/docs/design/AZURE_FEDERATIONS.md b/vendor/doctrine/dbal/docs/design/AZURE_FEDERATIONS.md
new file mode 100644 (file)
index 0000000..99d7e3c
--- /dev/null
@@ -0,0 +1,94 @@
+# Azure Federations\r
+\r
+Implementing Federations inside a new Doctrine Sharding Extension. Some extensions to the DBAL and ORM core have to be done to get this working.\r
+\r
+1. DBAL (Database Abstraction Layer)\r
+\r
+* Add support for Database Schema Operations\r
+    * CREATE FEDERATION\r
+    * CREATE TABLE ... FEDERATED ON\r
+    * Add support to create a multi-tenent schema from any given schema\r
+* Add API to pick a shard based on distribution key and atomic value\r
+* Add API to ask about federations, federation members and so on.\r
+* Add Sharding Abstraction\r
+    * If a shard is picked via distribution key and atomic value fire queries against this only\r
+    * Or query the global database.\r
+\r
+2. ORM (Object-Relational Mapper)\r
+\r
+* Federation Key has to be part of the clustered index of the table\r
+    * Test with a pure Multi-Tenent App with Filtering = ON (TaskList)\r
+    * Test with sharded app (Weather)\r
+\r
+## Implementation Details\r
+\r
+SQL Azure requires one and exactly one clustered index. It makes no difference if the primary key\r
+or any other key is the clustered index. Sharding requires an external ID generation (no auto-increment)\r
+such as GUIDs. GUIDs have negative properties with regard to clustered index performance, so that\r
+typically you would add a "created" timestamp for example that holds the clustered index instead\r
+of making the GUID a clustered index.\r
+\r
+## Example API:\r
+\r
+    @@@ php\r
+    <?php\r
+    use Doctrine\DBAL\DriverManager;\r
+\r
+    $dbParams = array(\r
+        'dbname' => 'tcp:dbname.database.windows.net',\r
+        'sharding' => array(\r
+            'federationName'   => 'Orders_Federation',\r
+            'distributionKey'  => 'CustID',\r
+            'distributionType' => 'integer',\r
+            'filteringEnabled' => false,\r
+        ),\r
+        // ...\r
+    );\r
+\r
+    $conn = DriverManager::getConnection($dbParams);\r
+    $shardManager = $conn->getShardManager();\r
+\r
+    // Example 1: query against root database\r
+    $sql = "SELECT * FROM Products";\r
+    $rows = $conn->executeQuery($sql);\r
+\r
+    // Example 2:  query against the selected shard with CustomerId = 100\r
+    $aCustomerID = 100;\r
+    $shardManager->selectShard($aCustomerID); // Using Default federationName and distributionKey\r
+    // Query: "USE FEDERATION Orders_Federation (CustID = $aCustomerID) WITH RESET, FILTERING OFF;"\r
+\r
+    $sql = "SELECT * FROM Customers";\r
+    $rows = $conn->executeQuery($sql);\r
+\r
+    // Example 3: Reset API to root database again\r
+    $shardManager->selectGlobal();\r
+\r
+## ID Generation\r
+\r
+With sharding all the ids have to be generated for global uniqueness. There are three strategies for this.\r
+\r
+1. Use GUIDs as described here http://blogs.msdn.com/b/cbiyikoglu/archive/2011/06/20/id-generation-in-federations-identity-sequences-and-guids-uniqueidentifier.aspx\r
+2. Having a central table that is accessed with a second connection to generate sequential ids\r
+3. Using natural keys from the domain.\r
+\r
+The second approach has the benefit of having numerical primary keys, however also a central failure location. The third strategy can seldom be used, because the domains dont allow this. Identity columns cannot be used at all.\r
+\r
+    @@@ php\r
+    <?php\r
+    use Doctrine\DBAL\DriverManager;\r
+    use Doctrine\DBAL\Id\TableHiLoIdGenerator;\r
+\r
+    $dbParams = array(\r
+        'dbname' => 'dbname.database.windows.net',\r
+        // ...\r
+    );\r
+    $conn = DriverManager::getConnection($dbParams);\r
+\r
+    $idGenerator = new TableHiLoIdGenerator($conn, 'id_table_name', $multiplicator = 1);\r
+    // only once, create this table\r
+    $idGenerator->createTable();\r
+\r
+    $nextId = $idGenerator->generateId('for_table_name');\r
+    $nextOtherId = $idGenerator->generateId('for_other_table');\r
+\r
+The connection for the table generator has to be a different one than the one used for the main app to avoid transaction clashes.\r