Completed
Push — master ( 8c2434...6692d3 )
by Sébastien
14:40
created

ShardingInsertQuery::getShardId()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 6
c 0
b 0
f 0
dl 0
loc 13
ccs 7
cts 7
cp 1
rs 10
cc 3
nc 3
nop 0
crap 3
1
<?php
2
3
namespace Bdf\Prime\Sharding\Query;
4
5
use Bdf\Prime\Connection\ConnectionInterface;
6
use Bdf\Prime\Query\CommandInterface;
7
use Bdf\Prime\Query\CompilableClause;
8
use Bdf\Prime\Query\Compiler\CompilerInterface;
9
use Bdf\Prime\Query\Compiler\Preprocessor\DefaultPreprocessor;
10
use Bdf\Prime\Query\Compiler\Preprocessor\PreprocessorInterface;
11
use Bdf\Prime\Query\Contract\Cachable;
12
use Bdf\Prime\Query\Contract\Query\InsertQueryInterface;
13
use Bdf\Prime\Query\Custom\BulkInsert\BulkInsertQuery;
14
use Bdf\Prime\Query\Extension\CachableTrait;
15
use Bdf\Prime\Sharding\Extension\ShardPicker;
16
use Bdf\Prime\Sharding\ShardingConnection;
17
18
/**
19
 * Handle INSERT operations on Sharding connection set
20
 * The shard will be choosed using inserted data value, and the operation will be delegated to the shard connection
0 ignored issues
show
introduced by
Doc comment short description must be on a single line, further text should be a separate paragraph
Loading history...
21
 */
22
class ShardingInsertQuery extends CompilableClause implements InsertQueryInterface, CommandInterface, Cachable
23
{
24
    use CachableTrait;
25
    use ShardPicker;
26
27
    /**
28
     * The DBAL Connection.
29
     *
30
     * @var ShardingConnection
31
     */
32
    private $connection;
33
34
    /**
35
     * @var string
36
     */
37
    private $table;
38
39
    /**
40
     * @var string[]
41
     */
42
    private $columns = [];
43
44
    /**
45
     * @var string
46
     */
47
    private $mode = self::MODE_INSERT;
48
49
    /**
50
     * @var array
51
     */
52
    private $values = [];
53
54
    /**
55
     * Queries indexed by shard id
56
     *
57
     * @var BulkInsertQuery[]
58
     */
59
    private $queries = [];
60
61
    /**
62
     * @var BulkInsertQuery
63
     */
64
    private $currentQuery;
65
66
67
    /**
68
     * ShardingInsertQuery constructor.
69
     *
70
     * @param ShardingConnection $connection
71
     * @param PreprocessorInterface $preprocessor
72
     */
73 31
    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...
74
    {
75 31
        parent::__construct($preprocessor ?: new DefaultPreprocessor());
0 ignored issues
show
Coding Style introduced by
Inline IF statements are not allowed
Loading history...
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
76
77 31
        $this->connection = $connection;
78 31
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83
    public function compiler() { }
0 ignored issues
show
Coding Style introduced by
Opening brace should be on a new line
Loading history...
introduced by
There should be no white space after an opening "{"
Loading history...
introduced by
There should be no white space before a closing "}"
Loading history...
84
85
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $compiler should have a doc-comment as per coding-style.
Loading history...
86
     * {@inheritdoc}
87
     */
88
    public function setCompiler(CompilerInterface $compiler) { }
0 ignored issues
show
Coding Style introduced by
Opening brace should be on a new line
Loading history...
introduced by
There should be no white space after an opening "{"
Loading history...
introduced by
There should be no white space before a closing "}"
Loading history...
89
90
    /**
91
     * {@inheritdoc}
92
     */
93
    public function connection()
94
    {
95
        return $this->connection;
96
    }
97
98
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $connection should have a doc-comment as per coding-style.
Loading history...
99
     * {@inheritdoc}
100
     */
101
    public function on(ConnectionInterface $connection)
102
    {
103
        $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...
104
        $this->queries = [];
105
        $this->currentQuery = null;
106
    }
107
108
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $from should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $alias should have a doc-comment as per coding-style.
Loading history...
109
     * {@inheritdoc}
110
     */
111 19
    public function from($from, $alias = null)
0 ignored issues
show
Coding Style introduced by
The method parameter $alias is never used
Loading history...
112
    {
113 19
        return $this->into($from);
114
    }
115
116
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $flag should have a doc-comment as per coding-style.
Loading history...
117
     * {@inheritdoc}
118
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
119
    public function bulk($flag = true)
120
    {
121
        throw new \BadMethodCallException('Bulk insert is not (yet ?) supported by sharding connection');
122
    }
123
124
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $table should have a doc-comment as per coding-style.
Loading history...
125
     * {@inheritdoc}
126
     */
127 30
    public function into($table)
128
    {
129 30
        $this->table = $table;
130
131 30
        foreach ($this->queries as $query) {
132 1
            $query->into($table);
133
        }
134
135 30
        return $this;
136
    }
137
138
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $columns should have a doc-comment as per coding-style.
Loading history...
139
     * {@inheritdoc}
140
     */
141 20
    public function columns(array $columns)
142
    {
143 20
        $this->columns = $columns;
144
145 20
        foreach ($this->queries as $query) {
146 1
            $query->columns($columns);
147
        }
148
149 20
        return $this;
150
    }
151
152
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $data should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $replace should have a doc-comment as per coding-style.
Loading history...
153
     * {@inheritdoc}
154
     */
155 29
    public function values(array $data, $replace = false)
0 ignored issues
show
Coding Style introduced by
The method parameter $replace is never used
Loading history...
156
    {
157 29
        $this->values = $data;
158 29
        $this->currentQuery = null;
159
160 29
        $this->currentQuery()->values($data);
161
162 29
        return $this;
163
    }
164
165
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $mode should have a doc-comment as per coding-style.
Loading history...
166
     * {@inheritdoc}
167
     */
168 21
    public function mode($mode)
169
    {
170 21
        $this->mode = $mode;
171
172 21
        foreach ($this->queries as $query) {
173 11
            $query->mode($mode);
174
        }
175
176 21
        return $this;
177
    }
178
179
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $flag should have a doc-comment as per coding-style.
Loading history...
180
     * {@inheritdoc}
181
     */
182 20
    public function ignore($flag = true)
183
    {
184 20
        return $this->mode($flag ? self::MODE_IGNORE : self::MODE_INSERT);
0 ignored issues
show
Coding Style introduced by
Inline IF statements are not allowed
Loading history...
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
185
    }
186
187
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $flag should have a doc-comment as per coding-style.
Loading history...
188
     * {@inheritdoc}
189
     */
190 1
    public function replace($flag = true)
191
    {
192 1
        return $this->mode($flag ? self::MODE_REPLACE : self::MODE_INSERT);
0 ignored issues
show
Coding Style introduced by
Inline IF statements are not allowed
Loading history...
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
193
    }
194
195
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $columns should have a doc-comment as per coding-style.
Loading history...
196
     * {@inheritdoc}
197
     */
198 30
    public function execute($columns = null)
199
    {
200 30
        $count = $this->currentQuery()->execute($columns);
201
202 29
        if ($count > 0) {
203 29
            $this->clearCacheOnWrite();
204
        }
205
206 29
        return $count;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $count returns the type array which is incompatible with the return type mandated by Bdf\Prime\Query\Contract...eryInterface::execute() of integer.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
207
    }
208
209
    /**
210
     * Get the query associated to the matching sharding
211
     *
212
     * @return BulkInsertQuery
213
     */
214 30
    private function currentQuery()
0 ignored issues
show
Coding Style introduced by
Private method name "ShardingInsertQuery::currentQuery" must be prefixed with an underscore
Loading history...
215
    {
216 30
        if ($this->currentQuery !== null) {
217 29
            return $this->currentQuery;
218
        }
219
220 30
        $shardId = $this->getShardId();
221
222 29
        if (isset($this->queries[$shardId])) {
223 11
            return $this->queries[$shardId];
224
        }
225
226
        /** @var BulkInsertQuery $query */
0 ignored issues
show
Coding Style introduced by
Inline doc block comments are not allowed; use "/* Comment */" or "// Comment" instead
Loading history...
Coding Style introduced by
Block comments must be started with /*
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...
227 29
        $query = $this->connection->getConnection($shardId)->make(BulkInsertQuery::class, $this->preprocessor());
228
229
        $query
230 29
            ->setCache($this->cache)
0 ignored issues
show
Coding Style introduced by
Space found before object operator
Loading history...
introduced by
Object operator not indented correctly; expected 10 spaces but found 12
Loading history...
231 29
            ->into($this->table)
0 ignored issues
show
Coding Style introduced by
Space found before object operator
Loading history...
232 29
            ->columns($this->columns)
0 ignored issues
show
Coding Style introduced by
Space found before object operator
Loading history...
233 29
            ->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...
234
        ;
0 ignored issues
show
Coding Style introduced by
Space found before semicolon; expected ");" but found ")
;"
Loading history...
235
236 29
        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...
237
    }
238
239
    /**
240
     * Get the targeted shard ID
241
     *
242
     * @return string|null
243
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
244 30
    private function getShardId()
0 ignored issues
show
Coding Style introduced by
Private method name "ShardingInsertQuery::getShardId" must be prefixed with an underscore
Loading history...
245
    {
246 30
        if ($this->shardId !== null) {
247 2
            return $this->shardId;
248
        }
249
250 28
        $distributionKey = $this->connection->getDistributionKey();
251
252 28
        if (!isset($this->values[$distributionKey])) {
253 1
            throw new \LogicException('The value "'.$distributionKey.'" must be provided for selecting the sharding');
254
        }
255
256 27
        return $this->connection->getShardChoser()->pick($this->values[$distributionKey], $this->connection);
257
    }
258
259
    /**
260
     * {@inheritdoc}
261
     */
262 1
    protected function cacheNamespace()
263
    {
264 1
        return $this->connection->getName().':'.$this->table;
265
    }
266
}
267