Passed
Pull Request — master (#29)
by Sébastien
08:57
created

ShardingInsertQuery   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 251
Duplicated Lines 0 %

Test Coverage

Coverage 81.16%

Importance

Changes 0
Metric Value
wmc 28
eloc 62
dl 0
loc 251
ccs 56
cts 69
cp 0.8116
rs 10
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A connection() 0 3 1
A mode() 0 9 2
A columns() 0 9 2
A values() 0 8 1
A on() 0 7 1
A into() 0 9 2
A ignore() 0 3 2
A currentQuery() 0 23 3
A setCompiler() 0 3 1
A cacheNamespace() 0 3 1
A compiler() 0 3 1
A __construct() 0 5 2
A bulk() 0 3 1
A execute() 0 9 2
A replace() 0 3 2
A from() 0 3 1
A getShardId() 0 13 3
1
<?php
2
3
namespace Bdf\Prime\Sharding\Query;
4
5
use BadMethodCallException;
6
use Bdf\Prime\Connection\ConnectionInterface;
7
use Bdf\Prime\Query\CommandInterface;
8
use Bdf\Prime\Query\CompilableClause;
9
use Bdf\Prime\Query\Compiler\CompilerInterface;
10
use Bdf\Prime\Query\Compiler\Preprocessor\DefaultPreprocessor;
11
use Bdf\Prime\Query\Compiler\Preprocessor\PreprocessorInterface;
12
use Bdf\Prime\Query\Contract\Cachable;
13
use Bdf\Prime\Query\Contract\Query\InsertQueryInterface;
14
use Bdf\Prime\Query\Custom\BulkInsert\BulkInsertQuery;
15
use Bdf\Prime\Query\Extension\CachableTrait;
16
use Bdf\Prime\Sharding\Extension\ShardPicker;
17
use Bdf\Prime\Sharding\ShardingConnection;
18
19
/**
20
 * Handle INSERT operations on Sharding connection set
21
 * The shard will be choosed using inserted data value, and the operation will be delegated to the shard connection
22
 *
23
 * @implements CommandInterface<ShardingConnection>
24
 */
25
class ShardingInsertQuery extends CompilableClause implements InsertQueryInterface, CommandInterface, Cachable
26
{
27
    use CachableTrait;
28
    use ShardPicker;
29
30
    /**
31
     * The DBAL Connection.
32
     *
33
     * @var ShardingConnection
34
     */
35
    private $connection;
36
37
    /**
38
     * @var string
39
     */
40
    private $table;
41
42
    /**
43
     * @var string[]
44
     */
45
    private $columns = [];
46
47
    /**
48
     * @var string
49
     */
50
    private $mode = self::MODE_INSERT;
51
52
    /**
53
     * @var array
54
     */
55
    private $values = [];
56
57
    /**
58
     * Queries indexed by shard id
59
     *
60
     * @var BulkInsertQuery[]
61
     */
62
    private $queries = [];
63
64
    /**
65
     * @var BulkInsertQuery
66
     */
67
    private $currentQuery;
68
69
70
    /**
71
     * ShardingInsertQuery constructor.
72
     *
73
     * @param ShardingConnection $connection
74
     * @param PreprocessorInterface $preprocessor
75
     */
76 32
    public function __construct(ShardingConnection $connection, PreprocessorInterface $preprocessor = null)
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line before function; 2 found
Loading history...
77
    {
78 32
        parent::__construct($preprocessor ?: new DefaultPreprocessor());
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
79
80 32
        $this->connection = $connection;
81 32
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
86
    public function compiler(): CompilerInterface
87
    {
88
        throw new BadMethodCallException('Cannot directly compile a sharding query');
89
    }
90
91
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $compiler should have a doc-comment as per coding-style.
Loading history...
92
     * {@inheritdoc}
93
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
94
    public function setCompiler(CompilerInterface $compiler)
95
    {
96
        throw new BadMethodCallException('Cannot directly compile a sharding query');
97
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102
    public function connection(): ConnectionInterface
103
    {
104
        return $this->connection;
105
    }
106
107
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $connection should have a doc-comment as per coding-style.
Loading history...
108
     * {@inheritdoc}
109
     */
110
    public function on(ConnectionInterface $connection)
111
    {
112
        $this->connection = $connection;
0 ignored issues
show
Documentation Bug introduced by
$connection is of type Bdf\Prime\Connection\ConnectionInterface, but the property $connection was declared to be of type Bdf\Prime\Sharding\ShardingConnection. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
113
        $this->queries = [];
114
        $this->currentQuery = null;
115
116
        return $this;
117
    }
118
119
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $alias should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $from should have a doc-comment as per coding-style.
Loading history...
120
     * {@inheritdoc}
121
     */
122 20
    public function from($from, $alias = null)
0 ignored issues
show
Coding Style introduced by
The method parameter $alias is never used
Loading history...
123
    {
124 20
        return $this->into($from);
125
    }
126
127
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $flag should have a doc-comment as per coding-style.
Loading history...
128
     * {@inheritdoc}
129
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
130
    public function bulk(bool $flag = true)
131
    {
132
        throw new BadMethodCallException('Bulk insert is not (yet ?) supported by sharding connection');
133
    }
134
135
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $table should have a doc-comment as per coding-style.
Loading history...
136
     * {@inheritdoc}
137
     */
138 31
    public function into(string $table)
139
    {
140 31
        $this->table = $table;
141
142 31
        foreach ($this->queries as $query) {
143 1
            $query->into($table);
144
        }
145
146 31
        return $this;
147
    }
148
149
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $columns should have a doc-comment as per coding-style.
Loading history...
150
     * {@inheritdoc}
151
     */
152 21
    public function columns(array $columns)
153
    {
154 21
        $this->columns = $columns;
155
156 21
        foreach ($this->queries as $query) {
157 1
            $query->columns($columns);
158
        }
159
160 21
        return $this;
161
    }
162
163
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $replace should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $data should have a doc-comment as per coding-style.
Loading history...
164
     * {@inheritdoc}
165
     */
166 30
    public function values(array $data, bool $replace = false)
0 ignored issues
show
Coding Style introduced by
The method parameter $replace is never used
Loading history...
167
    {
168 30
        $this->values = $data;
169 30
        $this->currentQuery = null;
170
171 30
        $this->currentQuery()->values($data);
172
173 30
        return $this;
174
    }
175
176
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $mode should have a doc-comment as per coding-style.
Loading history...
177
     * {@inheritdoc}
178
     */
179 22
    public function mode(string $mode)
180
    {
181 22
        $this->mode = $mode;
182
183 22
        foreach ($this->queries as $query) {
184 11
            $query->mode($mode);
185
        }
186
187 22
        return $this;
188
    }
189
190
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $flag should have a doc-comment as per coding-style.
Loading history...
191
     * {@inheritdoc}
192
     */
193 21
    public function ignore(bool $flag = true)
194
    {
195 21
        return $this->mode($flag ? self::MODE_IGNORE : self::MODE_INSERT);
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
196
    }
197
198
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $flag should have a doc-comment as per coding-style.
Loading history...
199
     * {@inheritdoc}
200
     */
201 1
    public function replace(bool $flag = true)
202
    {
203 1
        return $this->mode($flag ? self::MODE_REPLACE : self::MODE_INSERT);
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
204
    }
205
206
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $columns should have a doc-comment as per coding-style.
Loading history...
207
     * {@inheritdoc}
208
     */
209 31
    public function execute($columns = null)
210
    {
211 31
        $count = $this->currentQuery()->execute($columns);
212
213 30
        if ($count > 0) {
214 30
            $this->clearCacheOnWrite();
215
        }
216
217 30
        return $count;
218
    }
219
220
    /**
221
     * Get the query associated to the matching sharding
222
     *
223
     * @return BulkInsertQuery
224
     */
225 31
    private function currentQuery()
0 ignored issues
show
Coding Style introduced by
Private method name "ShardingInsertQuery::currentQuery" must be prefixed with an underscore
Loading history...
226
    {
227 31
        if ($this->currentQuery !== null) {
228 30
            return $this->currentQuery;
229
        }
230
231 31
        $shardId = $this->getShardId();
232
233 30
        if (isset($this->queries[$shardId])) {
234 11
            return $this->queries[$shardId];
235
        }
236
237
        /** @var BulkInsertQuery $query */
0 ignored issues
show
Coding Style introduced by
Block comments must be started with /*
Loading history...
Coding Style introduced by
Inline doc block comments are not allowed; use "/* Comment */" or "// Comment" instead
Loading history...
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
238 30
        $query = $this->connection->getConnection($shardId)->make(BulkInsertQuery::class, $this->preprocessor());
239
240
        $query
241 30
            ->setCache($this->cache)
0 ignored issues
show
introduced by
Object operator not indented correctly; expected 10 spaces but found 12
Loading history...
Coding Style introduced by
Space found before object operator
Loading history...
242 30
            ->into($this->table)
0 ignored issues
show
Coding Style introduced by
Space found before object operator
Loading history...
243 30
            ->columns($this->columns)
0 ignored issues
show
Coding Style introduced by
Space found before object operator
Loading history...
244 30
            ->mode($this->mode)
0 ignored issues
show
Coding Style introduced by
Space found before object operator
Loading history...
Coding Style introduced by
Space after closing parenthesis of function call prohibited
Loading history...
245
        ;
0 ignored issues
show
Coding Style introduced by
Space found before semicolon; expected ");" but found ")
;"
Loading history...
246
247 30
        return $this->currentQuery = $this->queries[$shardId] = $query;
0 ignored issues
show
Coding Style introduced by
Assignments must be the first block of code on a line
Loading history...
248
    }
249
250
    /**
251
     * Get the targeted shard ID
252
     *
253
     * @return string|null
254
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
255 31
    private function getShardId()
0 ignored issues
show
Coding Style introduced by
Private method name "ShardingInsertQuery::getShardId" must be prefixed with an underscore
Loading history...
256
    {
257 31
        if ($this->shardId !== null) {
258 2
            return $this->shardId;
259
        }
260
261 29
        $distributionKey = $this->connection->getDistributionKey();
262
263 29
        if (!isset($this->values[$distributionKey])) {
264 1
            throw new \LogicException('The value "'.$distributionKey.'" must be provided for selecting the sharding');
265
        }
266
267 28
        return $this->connection->getShardChoser()->pick($this->values[$distributionKey], $this->connection);
268
    }
269
270
    /**
271
     * {@inheritdoc}
272
     */
273 1
    protected function cacheNamespace()
274
    {
275 1
        return $this->connection->getName().':'.$this->table;
276
    }
277
}
278