1 | <?php |
||||
2 | |||||
3 | namespace Bdf\Prime\Sharding\Query; |
||||
4 | |||||
5 | use BadMethodCallException; |
||||
6 | use Bdf\Prime\Connection\ConnectionInterface; |
||||
7 | use Bdf\Prime\Connection\Result\ResultSetInterface; |
||||
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\Contract\WriteOperation; |
||||
15 | use Bdf\Prime\Query\Custom\BulkInsert\BulkInsertQuery; |
||||
16 | use Bdf\Prime\Query\Extension\CachableTrait; |
||||
17 | use Bdf\Prime\Sharding\Extension\ShardPicker; |
||||
18 | use Bdf\Prime\Sharding\ShardingConnection; |
||||
19 | |||||
20 | /** |
||||
21 | * Handle INSERT operations on Sharding connection set |
||||
22 | * The shard will be choosed using inserted data value, and the operation will be delegated to the shard connection |
||||
23 | * |
||||
24 | * @implements InsertQueryInterface<ShardingConnection> |
||||
25 | */ |
||||
26 | class ShardingInsertQuery extends CompilableClause implements InsertQueryInterface, Cachable |
||||
27 | { |
||||
28 | use CachableTrait; |
||||
29 | use ShardPicker; |
||||
30 | |||||
31 | /** |
||||
32 | * The DBAL Connection. |
||||
33 | * |
||||
34 | * @var ShardingConnection |
||||
35 | */ |
||||
36 | private $connection; |
||||
37 | |||||
38 | /** |
||||
39 | * @var string |
||||
40 | */ |
||||
41 | private $table; |
||||
42 | |||||
43 | /** |
||||
44 | * @var string[] |
||||
45 | */ |
||||
46 | private $columns = []; |
||||
47 | |||||
48 | /** |
||||
49 | * @var InsertQueryInterface::MODE_* |
||||
50 | */ |
||||
51 | private $mode = self::MODE_INSERT; |
||||
52 | |||||
53 | /** |
||||
54 | * @var array |
||||
55 | */ |
||||
56 | private $values = []; |
||||
57 | |||||
58 | /** |
||||
59 | * Queries indexed by shard id |
||||
60 | * |
||||
61 | * @var BulkInsertQuery[] |
||||
62 | */ |
||||
63 | private $queries = []; |
||||
64 | |||||
65 | /** |
||||
66 | * @var BulkInsertQuery|null |
||||
67 | */ |
||||
68 | private $currentQuery; |
||||
69 | |||||
70 | |||||
71 | /** |
||||
72 | * ShardingInsertQuery constructor. |
||||
73 | * |
||||
74 | * @param ShardingConnection $connection |
||||
75 | * @param PreprocessorInterface $preprocessor |
||||
76 | */ |
||||
77 | 32 | public function __construct(ShardingConnection $connection, PreprocessorInterface $preprocessor = null) |
|||
78 | { |
||||
79 | 32 | parent::__construct($preprocessor ?: new DefaultPreprocessor()); |
|||
80 | |||||
81 | 32 | $this->connection = $connection; |
|||
82 | } |
||||
83 | |||||
84 | /** |
||||
85 | * {@inheritdoc} |
||||
86 | */ |
||||
87 | public function compiler(): CompilerInterface |
||||
88 | { |
||||
89 | throw new BadMethodCallException('Cannot directly compile a sharding query'); |
||||
90 | } |
||||
91 | |||||
92 | /** |
||||
93 | * {@inheritdoc} |
||||
94 | */ |
||||
95 | public function setCompiler(CompilerInterface $compiler) |
||||
0 ignored issues
–
show
|
|||||
96 | { |
||||
97 | throw new BadMethodCallException('Cannot directly compile a sharding query'); |
||||
98 | } |
||||
99 | |||||
100 | /** |
||||
101 | * {@inheritdoc} |
||||
102 | */ |
||||
103 | public function connection(): ConnectionInterface |
||||
104 | { |
||||
105 | return $this->connection; |
||||
106 | } |
||||
107 | |||||
108 | /** |
||||
109 | * {@inheritdoc} |
||||
110 | */ |
||||
111 | public function on(ConnectionInterface $connection) |
||||
112 | { |
||||
113 | $this->connection = $connection; |
||||
0 ignored issues
–
show
$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;
}
![]() |
|||||
114 | $this->queries = []; |
||||
115 | $this->currentQuery = null; |
||||
116 | |||||
117 | return $this; |
||||
118 | } |
||||
119 | |||||
120 | /** |
||||
121 | * {@inheritdoc} |
||||
122 | */ |
||||
123 | 20 | public function from(string $from, ?string $alias = null) |
|||
124 | { |
||||
125 | 20 | return $this->into($from); |
|||
126 | } |
||||
127 | |||||
128 | /** |
||||
129 | * {@inheritdoc} |
||||
130 | */ |
||||
131 | public function bulk(bool $flag = true) |
||||
132 | { |
||||
133 | throw new BadMethodCallException('Bulk insert is not (yet ?) supported by sharding connection'); |
||||
134 | } |
||||
135 | |||||
136 | /** |
||||
137 | * {@inheritdoc} |
||||
138 | */ |
||||
139 | 31 | public function into(string $table) |
|||
140 | { |
||||
141 | 31 | $this->table = $table; |
|||
142 | |||||
143 | 31 | foreach ($this->queries as $query) { |
|||
144 | 1 | $query->into($table); |
|||
145 | } |
||||
146 | |||||
147 | 31 | return $this; |
|||
148 | } |
||||
149 | |||||
150 | /** |
||||
151 | * {@inheritdoc} |
||||
152 | */ |
||||
153 | 21 | public function columns(array $columns) |
|||
154 | { |
||||
155 | 21 | $this->columns = $columns; |
|||
156 | |||||
157 | 21 | foreach ($this->queries as $query) { |
|||
158 | 1 | $query->columns($columns); |
|||
159 | } |
||||
160 | |||||
161 | 21 | return $this; |
|||
162 | } |
||||
163 | |||||
164 | /** |
||||
165 | * {@inheritdoc} |
||||
166 | */ |
||||
167 | 30 | public function values(array $data, bool $replace = false) |
|||
168 | { |
||||
169 | 30 | $this->values = $data; |
|||
170 | 30 | $this->currentQuery = null; |
|||
171 | |||||
172 | 30 | $this->currentQuery()->values($data); |
|||
173 | |||||
174 | 30 | return $this; |
|||
175 | } |
||||
176 | |||||
177 | /** |
||||
178 | * {@inheritdoc} |
||||
179 | */ |
||||
180 | 22 | public function mode(string $mode) |
|||
181 | { |
||||
182 | 22 | $this->mode = $mode; |
|||
0 ignored issues
–
show
It seems like
$mode of type string is incompatible with the declared type Bdf\Prime\Query\Contract...ry\InsertQueryInterface of property $mode .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||||
183 | |||||
184 | 22 | foreach ($this->queries as $query) { |
|||
185 | 11 | $query->mode($mode); |
|||
186 | } |
||||
187 | |||||
188 | 22 | return $this; |
|||
189 | } |
||||
190 | |||||
191 | /** |
||||
192 | * {@inheritdoc} |
||||
193 | */ |
||||
194 | 21 | public function ignore(bool $flag = true) |
|||
195 | { |
||||
196 | 21 | return $this->mode($flag ? self::MODE_IGNORE : self::MODE_INSERT); |
|||
197 | } |
||||
198 | |||||
199 | /** |
||||
200 | * {@inheritdoc} |
||||
201 | */ |
||||
202 | 1 | public function replace(bool $flag = true) |
|||
203 | { |
||||
204 | 1 | return $this->mode($flag ? self::MODE_REPLACE : self::MODE_INSERT); |
|||
205 | } |
||||
206 | |||||
207 | /** |
||||
208 | * {@inheritdoc} |
||||
209 | * |
||||
210 | * @return ResultSetInterface<array<string, mixed>> |
||||
211 | */ |
||||
212 | #[WriteOperation] |
||||
213 | 31 | public function execute($columns = null): ResultSetInterface |
|||
214 | { |
||||
215 | 31 | $result = $this->currentQuery()->execute($columns); |
|||
216 | |||||
217 | 30 | if ($result->hasWrite()) { |
|||
218 | 30 | $this->clearCacheOnWrite(); |
|||
219 | } |
||||
220 | |||||
221 | 30 | return $result; |
|||
222 | } |
||||
223 | |||||
224 | /** |
||||
225 | * Get the query associated to the matching sharding |
||||
226 | * |
||||
227 | * @return BulkInsertQuery |
||||
228 | */ |
||||
229 | 31 | private function currentQuery() |
|||
230 | { |
||||
231 | 31 | if ($this->currentQuery !== null) { |
|||
232 | 30 | return $this->currentQuery; |
|||
233 | } |
||||
234 | |||||
235 | 31 | $shardId = $this->getShardId(); |
|||
236 | |||||
237 | 30 | if (isset($this->queries[$shardId])) { |
|||
238 | 11 | return $this->queries[$shardId]; |
|||
239 | } |
||||
240 | |||||
241 | /** @var BulkInsertQuery $query */ |
||||
242 | 30 | $query = $this->connection->getConnection($shardId)->make(BulkInsertQuery::class, $this->preprocessor()); |
|||
243 | |||||
244 | 30 | $query |
|||
245 | 30 | ->setCache($this->cache) |
|||
246 | 30 | ->into($this->table) |
|||
247 | 30 | ->columns($this->columns) |
|||
248 | 30 | ->mode($this->mode) |
|||
0 ignored issues
–
show
$this->mode of type Bdf\Prime\Query\Contract...ry\InsertQueryInterface is incompatible with the type string expected by parameter $mode of Bdf\Prime\Query\Custom\B...BulkInsertQuery::mode() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
249 | 30 | ; |
|||
250 | |||||
251 | 30 | return $this->currentQuery = $this->queries[$shardId] = $query; |
|||
252 | } |
||||
253 | |||||
254 | /** |
||||
255 | * Get the targeted shard ID |
||||
256 | * |
||||
257 | * @return string |
||||
258 | */ |
||||
259 | 31 | private function getShardId() |
|||
260 | { |
||||
261 | 31 | if ($this->shardId !== null) { |
|||
262 | 2 | return $this->shardId; |
|||
263 | } |
||||
264 | |||||
265 | 29 | $distributionKey = $this->connection->getDistributionKey(); |
|||
266 | |||||
267 | 29 | if (!isset($this->values[$distributionKey])) { |
|||
268 | 1 | throw new \LogicException('The value "'.$distributionKey.'" must be provided for selecting the sharding'); |
|||
269 | } |
||||
270 | |||||
271 | 28 | return $this->connection->getShardChoser()->pick($this->values[$distributionKey], $this->connection); |
|||
272 | } |
||||
273 | |||||
274 | /** |
||||
275 | * {@inheritdoc} |
||||
276 | */ |
||||
277 | 1 | protected function cacheNamespace(): string |
|||
278 | { |
||||
279 | 1 | return $this->connection->getName().':'.$this->table; |
|||
280 | } |
||||
281 | } |
||||
282 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.