Rajout de doctrine/orm
[zf2.biz/galerie.git] / vendor / doctrine / dbal / lib / Doctrine / DBAL / Sharding / SQLAzure / SQLAzureShardManager.php
1 <?php
2 /*
3  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14  *
15  * This software consists of voluntary contributions made by many individuals
16  * and is licensed under the MIT license. For more information, see
17  * <http://www.doctrine-project.org>.
18  */
19
20 namespace Doctrine\DBAL\Sharding\SQLAzure;
21
22 use Doctrine\DBAL\Sharding\ShardManager;
23 use Doctrine\DBAL\Sharding\ShardingException;
24 use Doctrine\DBAL\Connection;
25 use Doctrine\DBAL\Types\Type;
26
27 /**
28  * Sharding using the SQL Azure Federations support.
29  *
30  * @author Benjamin Eberlei <kontakt@beberlei.de>
31  */
32 class SQLAzureShardManager implements ShardManager
33 {
34     /**
35      * @var string
36      */
37     private $federationName;
38
39     /**
40      * @var bool
41      */
42     private $filteringEnabled;
43
44     /**
45      * @var string
46      */
47     private $distributionKey;
48
49     /**
50      * @var string
51      */
52     private $distributionType;
53
54     /**
55      * @var Connection
56      */
57     private $conn;
58
59     /**
60      * @var string
61      */
62     private $currentDistributionValue;
63
64     /**
65      * @param Connection $conn
66      */
67     public function __construct(Connection $conn)
68     {
69         $this->conn = $conn;
70         $params = $conn->getParams();
71
72         if ( ! isset($params['sharding']['federationName'])) {
73             throw ShardingException::missingDefaultFederationName();
74         }
75
76         if ( ! isset($params['sharding']['distributionKey'])) {
77             throw ShardingException::missingDefaultDistributionKey();
78         }
79
80         if ( ! isset($params['sharding']['distributionType'])) {
81             throw ShardingException::missingDistributionType();
82         }
83
84         $this->federationName = $params['sharding']['federationName'];
85         $this->distributionKey = $params['sharding']['distributionKey'];
86         $this->distributionType = $params['sharding']['distributionType'];
87         $this->filteringEnabled = (isset($params['sharding']['filteringEnabled'])) ? (bool)$params['sharding']['filteringEnabled'] : false;
88     }
89
90     /**
91      * Get name of the federation
92      *
93      * @return string
94      */
95     public function getFederationName()
96     {
97         return $this->federationName;
98     }
99
100     /**
101      * Get the distribution key
102      *
103      * @return string
104      */
105     public function getDistributionKey()
106     {
107         return $this->distributionKey;
108     }
109
110     /**
111      * Get the Doctrine Type name used for the distribution
112      *
113      * @return string
114      */
115     public function getDistributionType()
116     {
117         return $this->distributionType;
118     }
119
120     /**
121      * Enabled/Disable filtering on the fly.
122      *
123      * @param bool $flag
124      * @return void
125      */
126     public function setFilteringEnabled($flag)
127     {
128         $this->filteringEnabled = (bool)$flag;
129     }
130
131     /**
132      * {@inheritDoc}
133      */
134     public function selectGlobal()
135     {
136         if ($this->conn->isTransactionActive()) {
137             throw ShardingException::activeTransaction();
138         }
139
140         $sql = "USE FEDERATION ROOT WITH RESET";
141         $this->conn->exec($sql);
142         $this->currentDistributionValue = null;
143     }
144
145     /**
146      * {@inheritDoc}
147      */
148     public function selectShard($distributionValue)
149     {
150         if ($this->conn->isTransactionActive()) {
151             throw ShardingException::activeTransaction();
152         }
153
154         if ($distributionValue === null || is_bool($distributionValue) || !is_scalar($distributionValue)) {
155             throw ShardingException::noShardDistributionValue();
156         }
157
158         $platform = $this->conn->getDatabasePlatform();
159         $sql = sprintf(
160             "USE FEDERATION %s (%s = %s) WITH RESET, FILTERING = %s;",
161             $platform->quoteIdentifier($this->federationName),
162             $platform->quoteIdentifier($this->distributionKey),
163             $this->conn->quote($distributionValue),
164             ($this->filteringEnabled ? 'ON' : 'OFF')
165         );
166
167         $this->conn->exec($sql);
168         $this->currentDistributionValue = $distributionValue;
169     }
170
171     /**
172      * {@inheritDoc}
173      */
174     public function getCurrentDistributionValue()
175     {
176         return $this->currentDistributionValue;
177     }
178
179     /**
180      * {@inheritDoc}
181      */
182     public function getShards()
183     {
184         $sql = "SELECT member_id as id,
185                       distribution_name as distribution_key,
186                       CAST(range_low AS CHAR) AS rangeLow,
187                       CAST(range_high AS CHAR) AS rangeHigh
188                       FROM sys.federation_member_distributions d
189                       INNER JOIN sys.federations f ON f.federation_id = d.federation_id
190                       WHERE f.name = " . $this->conn->quote($this->federationName);
191         return $this->conn->fetchAll($sql);
192     }
193
194      /**
195       * {@inheritDoc}
196       */
197     public function queryAll($sql, array $params = array(), array $types = array())
198     {
199         $shards = $this->getShards();
200         if (!$shards) {
201             throw new \RuntimeException("No shards found for " . $this->federationName);
202         }
203
204         $result = array();
205         $oldDistribution = $this->getCurrentDistributionValue();
206
207         foreach ($shards as $shard) {
208             $this->selectShard($shard['rangeLow']);
209             foreach ($this->conn->fetchAll($sql, $params, $types) as $row) {
210                 $result[] = $row;
211             }
212         }
213
214         if ($oldDistribution === null) {
215             $this->selectGlobal();
216         } else {
217             $this->selectShard($oldDistribution);
218         }
219
220         return $result;
221     }
222
223     /**
224      * Split Federation at a given distribution value.
225      *
226      * @param mixed $splitDistributionValue
227      */
228     public function splitFederation($splitDistributionValue)
229     {
230         $type = Type::getType($this->distributionType);
231
232         $sql = "ALTER FEDERATION " . $this->getFederationName() . " " .
233                "SPLIT AT (" . $this->getDistributionKey() . " = " .
234                $this->conn->quote($splitDistributionValue, $type->getBindingType()) . ")";
235         $this->conn->exec($sql);
236     }
237 }
238