Passed
Pull Request — 2.11.x (#3971)
by Grégoire
03:18
created

SQLAzureShardManager::__construct()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 12
dl 0
loc 21
ccs 13
cts 13
cp 1
rs 9.8666
c 0
b 0
f 0
cc 4
nc 4
nop 1
crap 4
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