Completed
Push — 2.11.x ( eeed37...b3131f )
by Grégoire
13:08 queued 11s
created

SQLAzureShardManager   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 192
Duplicated Lines 0 %

Test Coverage

Coverage 38.24%

Importance

Changes 0
Metric Value
wmc 21
eloc 61
dl 0
loc 192
ccs 26
cts 68
cp 0.3824
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A getDistributionType() 0 3 1
A getFederationName() 0 3 1
A getDistributionKey() 0 3 1
A setFilteringEnabled() 0 3 1
A selectGlobal() 0 9 2
A __construct() 0 21 4
A splitFederation() 0 8 1
A getShards() 0 11 1
A selectShard() 0 17 3
A queryAll() 0 24 5
A getCurrentDistributionValue() 0 3 1
1
<?php
2
3
namespace Doctrine\DBAL\Sharding\SQLAzure;
4
5
use Doctrine\DBAL\Connection;
6
use Doctrine\DBAL\Sharding\ShardingException;
7
use Doctrine\DBAL\Sharding\ShardManager;
8
use Doctrine\DBAL\Types\Type;
9
use RuntimeException;
10
use function sprintf;
11
12
/**
13
 * Sharding using the SQL Azure Federations support.
14
 *
15
 * @deprecated
16
 */
17
class SQLAzureShardManager implements ShardManager
0 ignored issues
show
Deprecated Code introduced by
The interface Doctrine\DBAL\Sharding\ShardManager has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

17
class SQLAzureShardManager implements /** @scrutinizer ignore-deprecated */ ShardManager

This interface has been deprecated. The supplier of the interface has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the interface will be removed and what other interface to use instead.

Loading history...
18
{
19
    /** @var string */
20
    private $federationName;
21
22
    /** @var bool */
23
    private $filteringEnabled;
24
25
    /** @var string */
26
    private $distributionKey;
27
28
    /** @var string */
29
    private $distributionType;
30
31
    /** @var Connection */
32
    private $conn;
33
34
    /** @var string|null */
35
    private $currentDistributionValue;
36
37
    /**
38
     * @throws ShardingException
39
     */
40 145
    public function __construct(Connection $conn)
41
    {
42 145
        $this->conn = $conn;
43 145
        $params     = $conn->getParams();
44
45 145
        if (! isset($params['sharding']['federationName'])) {
46 139
            throw ShardingException::missingDefaultFederationName();
47
        }
48
49 121
        if (! isset($params['sharding']['distributionKey'])) {
50 1
            throw ShardingException::missingDefaultDistributionKey();
51
        }
52
53 120
        if (! isset($params['sharding']['distributionType'])) {
54 116
            throw ShardingException::missingDistributionType();
55
        }
56
57 96
        $this->federationName   = $params['sharding']['federationName'];
58 96
        $this->distributionKey  = $params['sharding']['distributionKey'];
59 96
        $this->distributionType = $params['sharding']['distributionType'];
60 96
        $this->filteringEnabled = (bool) ($params['sharding']['filteringEnabled'] ?? false);
61 96
    }
62
63
    /**
64
     * Gets the name of the federation.
65
     *
66
     * @return string
67
     */
68
    public function getFederationName()
69
    {
70
        return $this->federationName;
71
    }
72
73
    /**
74
     * Gets the distribution key.
75
     *
76
     * @return string
77
     */
78
    public function getDistributionKey()
79
    {
80
        return $this->distributionKey;
81
    }
82
83
    /**
84
     * Gets the Doctrine Type name used for the distribution.
85
     *
86
     * @return string
87
     */
88
    public function getDistributionType()
89
    {
90
        return $this->distributionType;
91
    }
92
93
    /**
94
     * Sets Enabled/Disable filtering on the fly.
95
     *
96
     * @param bool $flag
97
     *
98
     * @return void
99
     */
100
    public function setFilteringEnabled($flag)
101
    {
102
        $this->filteringEnabled = (bool) $flag;
103
    }
104
105
    /**
106
     * {@inheritDoc}
107
     */
108 71
    public function selectGlobal()
109
    {
110 71
        if ($this->conn->isTransactionActive()) {
111 70
            throw ShardingException::activeTransaction();
112
        }
113
114 47
        $sql = 'USE FEDERATION ROOT WITH RESET';
115 47
        $this->conn->exec($sql);
116 47
        $this->currentDistributionValue = null;
117 47
    }
118
119
    /**
120
     * {@inheritDoc}
121
     */
122 24
    public function selectShard($distributionValue)
123
    {
124 24
        if ($this->conn->isTransactionActive()) {
125 24
            throw ShardingException::activeTransaction();
126
        }
127
128
        $platform = $this->conn->getDatabasePlatform();
129
        $sql      = sprintf(
130
            'USE FEDERATION %s (%s = %s) WITH RESET, FILTERING = %s;',
131
            $platform->quoteIdentifier($this->federationName),
132
            $platform->quoteIdentifier($this->distributionKey),
133
            $this->conn->quote($distributionValue),
134
            ($this->filteringEnabled ? 'ON' : 'OFF')
135
        );
136
137
        $this->conn->exec($sql);
138
        $this->currentDistributionValue = $distributionValue;
139
    }
140
141
    /**
142
     * {@inheritDoc}
143
     */
144 93
    public function getCurrentDistributionValue()
145
    {
146 93
        return $this->currentDistributionValue;
147
    }
148
149
    /**
150
     * {@inheritDoc}
151
     */
152
    public function getShards()
153
    {
154
        $sql = 'SELECT member_id as id,
155
                      distribution_name as distribution_key,
156
                      CAST(range_low AS CHAR) AS rangeLow,
157
                      CAST(range_high AS CHAR) AS rangeHigh
158
                      FROM sys.federation_member_distributions d
159
                      INNER JOIN sys.federations f ON f.federation_id = d.federation_id
160
                      WHERE f.name = ' . $this->conn->quote($this->federationName);
161
162
        return $this->conn->fetchAll($sql);
163
    }
164
165
     /**
166
      * {@inheritDoc}
167
      */
168
    public function queryAll($sql, array $params = [], array $types = [])
169
    {
170
        $shards = $this->getShards();
171
        if (! $shards) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $shards of type array<mixed,mixed> is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
172
            throw new RuntimeException('No shards found for ' . $this->federationName);
173
        }
174
175
        $result          = [];
176
        $oldDistribution = $this->getCurrentDistributionValue();
177
178
        foreach ($shards as $shard) {
179
            $this->selectShard($shard['rangeLow']);
180
            foreach ($this->conn->fetchAll($sql, $params, $types) as $row) {
181
                $result[] = $row;
182
            }
183
        }
184
185
        if ($oldDistribution === null) {
186
            $this->selectGlobal();
187
        } else {
188
            $this->selectShard($oldDistribution);
189
        }
190
191
        return $result;
192
    }
193
194
    /**
195
     * Splits Federation at a given distribution value.
196
     *
197
     * @param mixed $splitDistributionValue
198
     *
199
     * @return void
200
     */
201
    public function splitFederation($splitDistributionValue)
202
    {
203
        $type = Type::getType($this->distributionType);
204
205
        $sql = 'ALTER FEDERATION ' . $this->getFederationName() . ' ' .
206
               'SPLIT AT (' . $this->getDistributionKey() . ' = ' .
207
               $this->conn->quote($splitDistributionValue, $type->getBindingType()) . ')';
208
        $this->conn->exec($sql);
209
    }
210
}
211