Passed
Pull Request — master (#140)
by Dmitriy
06:25
created

Client::prepareInsertAssocBulk()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 25
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 17
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 25
ccs 17
cts 17
cp 1
crap 5
rs 9.3888
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ClickHouseDB;
6
7
use ClickHouseDB\Exception\QueryException;
8
use ClickHouseDB\Query\Degeneration;
9
use ClickHouseDB\Query\Degeneration\Bindings;
10
use ClickHouseDB\Query\Degeneration\Conditions;
11
use ClickHouseDB\Query\WhereInFile;
12
use ClickHouseDB\Query\WriteToFile;
13
use ClickHouseDB\Quote\FormatLine;
14
use ClickHouseDB\Transport\Http;
15
use ClickHouseDB\Transport\Stream;
16
use function array_flip;
0 ignored issues
show
introduced by
Type array_flip is not used in this file.
Loading history...
17
use function array_keys;
18
use function array_rand;
0 ignored issues
show
introduced by
Type array_rand is not used in this file.
Loading history...
19
use function array_values;
20
use function count;
21
use function date;
0 ignored issues
show
introduced by
Type date is not used in this file.
Loading history...
22
use function implode;
23
use function in_array;
24
use function is_array;
25
use function is_callable;
26
use function is_file;
27
use function is_readable;
28
use function is_string;
29
use function sprintf;
30
use function stripos;
31
use function strtotime;
0 ignored issues
show
introduced by
Type strtotime is not used in this file.
Loading history...
32
use function trim;
33
34
/**
35
 * Class Client
36
 * @package ClickHouseDB
0 ignored issues
show
introduced by
Expected 1 lines between description and annotations, found 0.
Loading history...
introduced by
Use of annotation @package is forbidden.
Loading history...
37
 */
38
class Client
39
{
40
    const SUPPORTED_FORMATS = ['TabSeparated', 'TabSeparatedWithNames', 'CSV', 'CSVWithNames', 'JSONEachRow'];
0 ignored issues
show
introduced by
Constant \ClickHouseDB\Client::SUPPORTED_FORMATS visibility missing.
Loading history...
41
42
    /** @var Http */
43
    private $transport;
44
45
    /** @var string */
46
    private $connectUsername;
47
48
    /** @var string */
49
    private $connectPassword;
50
51
    /** @var string */
52
    private $connectHost;
53
54
    /** @var string */
55
    private $connectPort;
56
57
    /** @var bool */
58
    private $connectUserReadonly = false;
59
60
    /**
61
     * @param mixed[] $connectParams
62
     * @param mixed[] $settings
63
     */
64 66
    public function __construct(array $connectParams, array $settings = [])
65
    {
66 66
        if (!isset($connectParams['username'])) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
67
            throw  new \InvalidArgumentException('not set username');
0 ignored issues
show
introduced by
Class \InvalidArgumentException should not be referenced via a fully qualified name, but via a use statement.
Loading history...
68
        }
69
70 66
        if (!isset($connectParams['password'])) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
71
            throw  new \InvalidArgumentException('not set password');
0 ignored issues
show
introduced by
Class \InvalidArgumentException should not be referenced via a fully qualified name, but via a use statement.
Loading history...
72
        }
73
74 66
        if (!isset($connectParams['port'])) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
75
            throw  new \InvalidArgumentException('not set port');
0 ignored issues
show
introduced by
Class \InvalidArgumentException should not be referenced via a fully qualified name, but via a use statement.
Loading history...
76
        }
77
78 66
        if (!isset($connectParams['host'])) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
79
            throw  new \InvalidArgumentException('not set host');
0 ignored issues
show
introduced by
Class \InvalidArgumentException should not be referenced via a fully qualified name, but via a use statement.
Loading history...
80
        }
81
82 66
        $this->connectUsername = $connectParams['username'];
83 66
        $this->connectPassword = $connectParams['password'];
84 66
        $this->connectPort = $connectParams['port'];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
85 66
        $this->connectHost = $connectParams['host'];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
86
87
        // init transport class
88 66
        $this->transport = new Http(
89 66
            $this->connectHost,
90 66
            $this->connectPort,
91 66
            $this->connectUsername,
92 66
            $this->connectPassword
93
        );
94
95 66
        $this->transport->addQueryDegeneration(new Bindings());
96
97
        // apply settings to transport class
98 66
        $this->settings()->database('default');
99 66
        if (!empty($settings)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
100 1
            $this->settings()->apply($settings);
101
        }
102
103 66
        if (isset($connectParams['readonly'])) {
104
            $this->setReadOnlyUser($connectParams['readonly']);
105
        }
106
107 66
        if (isset($connectParams['https'])) {
108
            $this->https($connectParams['https']);
109
        }
110
111 66
        if (isset($connectParams['sslCA'])) {
112
            $this->transport->setSslCa($connectParams['sslCA']);
113
        }
114
115 66
        $this->enableHttpCompression();
116 66
    }
117
118
    /**
119
     * if the user has only read in the config file
120
     */
121
    public function setReadOnlyUser(bool $flag)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::setReadOnlyUser() does not have void return type hint.
Loading history...
122
    {
123
        $this->connectUserReadonly = $flag;
124
        $this->settings()->setReadOnlyUser($this->connectUserReadonly);
125
    }
126
127
    /**
128
     * Clear Degeneration processing request [template ]
129
     *
130
     * @return bool
131
     */
132 1
    public function cleanQueryDegeneration()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::cleanQueryDegeneration() does not have return type hint for its return value but it should be possible to add it based on @return annotation "bool".
Loading history...
133
    {
134 1
        return $this->transport->cleanQueryDegeneration();
135
    }
136
137
    /**
138
     * add Degeneration processing
139
     *
140
     * @return bool
141
     */
142
    public function addQueryDegeneration(Degeneration $degeneration)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::addQueryDegeneration() does not have return type hint for its return value but it should be possible to add it based on @return annotation "bool".
Loading history...
143
    {
144
        return $this->transport->addQueryDegeneration($degeneration);
145
    }
146
147
    /**
148
     * add Conditions in query
149
     *
150
     * @return bool
151
     */
152 3
    public function enableQueryConditions()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::enableQueryConditions() does not have return type hint for its return value but it should be possible to add it based on @return annotation "bool".
Loading history...
153
    {
154 3
        return $this->transport->addQueryDegeneration(new Conditions());
155
    }
156
157
    /**
158
     * Set connection host
159
     *
160
     * @param string $host
161
     */
162
    public function setHost($host)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::setHost() does not have parameter type hint for its parameter $host but it should be possible to add it based on @param annotation "string".
Loading history...
introduced by
Method \ClickHouseDB\Client::setHost() does not have void return type hint.
Loading history...
163
    {
164
        $this->connectHost = $host;
165
        $this->transport()->setHost($host);
166
    }
167
168
    /**
169
     * @return Settings
170
     */
171 2
    public function setTimeout(float $timeout)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::setTimeout() does not have return type hint for its return value but it should be possible to add it based on @return annotation "Settings".
Loading history...
172
    {
173 2
        return $this->settings()->max_execution_time($timeout);
174
    }
175
176
    /**
177
     * @return mixed
178
     */
179 1
    public function getTimeout()
180
    {
181 1
        return $this->settings()->getTimeOut();
182
    }
183
184
    /**
185
     * ConnectTimeOut in seconds ( support 1.5 = 1500ms )
186
     */
187 2
    public function setConnectTimeOut(int $connectTimeOut)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::setConnectTimeOut() does not have void return type hint.
Loading history...
188
    {
189 2
        $this->transport()->setConnectTimeOut($connectTimeOut);
190 2
    }
191
192
    /**
193
     * @return int
194
     */
195 1
    public function getConnectTimeOut()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::getConnectTimeOut() does not have return type hint for its return value but it should be possible to add it based on @return annotation "int".
Loading history...
196
    {
197 1
        return $this->transport()->getConnectTimeOut();
198
    }
199
200
    /**
201
     * @return Http
202
     */
203 66
    public function transport()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::transport() does not have return type hint for its return value but it should be possible to add it based on @return annotation "Http".
Loading history...
204
    {
205 66
        if (!$this->transport) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
206
            throw  new \InvalidArgumentException('Empty transport class');
0 ignored issues
show
introduced by
Class \InvalidArgumentException should not be referenced via a fully qualified name, but via a use statement.
Loading history...
207
        }
208
209 66
        return $this->transport;
210
    }
211
212
    /**
213
     * @return string
214
     */
215
    public function getConnectHost()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::getConnectHost() does not have return type hint for its return value but it should be possible to add it based on @return annotation "string".
Loading history...
216
    {
217
        return $this->connectHost;
218
    }
219
220
    /**
221
     * @return string
222
     */
223
    public function getConnectPassword()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::getConnectPassword() does not have return type hint for its return value but it should be possible to add it based on @return annotation "string".
Loading history...
224
    {
225
        return $this->connectPassword;
226
    }
227
228
    /**
229
     * @return string
230
     */
231
    public function getConnectPort()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::getConnectPort() does not have return type hint for its return value but it should be possible to add it based on @return annotation "string".
Loading history...
232
    {
233
        return $this->connectPort;
234
    }
235
236
    /**
237
     * @return string
238
     */
239
    public function getConnectUsername()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::getConnectUsername() does not have return type hint for its return value but it should be possible to add it based on @return annotation "string".
Loading history...
240
    {
241
        return $this->connectUsername;
242
    }
243
244
    /**
245
     * @return Http
246
     */
247
    public function getTransport()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::getTransport() does not have return type hint for its return value but it should be possible to add it based on @return annotation "Http".
Loading history...
248
    {
249
        return $this->transport;
250
    }
251
252
    /**
253
     * @return mixed
254
     */
255
    public function verbose()
256
    {
257
        return $this->transport()->verbose(true);
258
    }
259
260
    /**
261
     * @return Settings
262
     */
263 66
    public function settings()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::settings() does not have return type hint for its return value but it should be possible to add it based on @return annotation "Settings".
Loading history...
264
    {
265 66
        return $this->transport()->settings();
266
    }
267
268
    /**
269
     * @param string|null $useSessionId
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
introduced by
Method \ClickHouseDB\Client::useSession() has useless @param annotation for parameter $useSessionId.
Loading history...
270
     * @return $this
271
     */
272 2
    public function useSession(string $useSessionId = null)
0 ignored issues
show
introduced by
Parameter $useSessionId has null default value, but is not marked as nullable.
Loading history...
273
    {
274 2
        if (!$this->settings()->getSessionId()) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
275 2
            if (!$useSessionId) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
276 2
                $this->settings()->makeSessionId();
277
            } else {
278
                $this->settings()->session_id($useSessionId);
279
            }
280
        }
281 2
        return $this;
282
    }
283
284
    /**
285
     * @return mixed
286
     */
287 2
    public function getSession()
288
    {
289 2
        return $this->settings()->getSessionId();
290
    }
291
292
    /**
293
     * Query CREATE/DROP
294
     *
295
     * @param mixed[] $bindings
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
296
     * @return Statement
297
     */
298 26
    public function write(string $sql, array $bindings = [], bool $exception = true)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::write() does not have return type hint for its return value but it should be possible to add it based on @return annotation "Statement".
Loading history...
299
    {
300 26
        return $this->transport()->write($sql, $bindings, $exception);
301
    }
302
303
    /**
304
     * set db name
305
     * @return static
0 ignored issues
show
introduced by
Expected 1 lines between description and annotations, found 0.
Loading history...
306
     */
307 66
    public function database(string $db)
308
    {
309 66
        $this->settings()->database($db);
310
311 66
        return $this;
312
    }
313
314
    /**
315
     * Write to system.query_log
316
     *
317
     * @return static
318
     */
319
    public function enableLogQueries(bool $flag = true)
320
    {
321
        $this->settings()->set('log_queries', (int)$flag);
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after cast statement; 0 found
Loading history...
322
323
        return $this;
324
    }
325
326
    /**
327
     * Compress the result if the HTTP client said that it understands data compressed with gzip or deflate
328
     *
329
     * @return static
330
     */
331 66
    public function enableHttpCompression(bool $flag = true)
332
    {
333 66
        $this->settings()->enableHttpCompression($flag);
334
335 66
        return $this;
336
    }
337
338
    /**
339
     * Enable / Disable HTTPS
340
     *
341
     * @return static
342
     */
343 1
    public function https(bool $flag = true)
344
    {
345 1
        $this->settings()->https($flag);
346
347 1
        return $this;
348
    }
349
350
    /**
351
     * Read extremes of the result columns. They can be output in JSON-formats.
352
     *
353
     * @return static
354
     */
355 2
    public function enableExtremes(bool $flag = true)
356
    {
357 2
        $this->settings()->set('extremes', (int)$flag);
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after cast statement; 0 found
Loading history...
358
359 2
        return $this;
360
    }
361
362
    /**
363
     * @param mixed[] $bindings
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
364
     * @return Statement
365
     */
366 30
    public function select(
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::select() does not have return type hint for its return value but it should be possible to add it based on @return annotation "Statement".
Loading history...
367
        string $sql,
368
        array $bindings = [],
369
        WhereInFile $whereInFile = null,
0 ignored issues
show
introduced by
Parameter $whereInFile has null default value, but is not marked as nullable.
Loading history...
370
        WriteToFile $writeToFile = null
0 ignored issues
show
introduced by
Parameter $writeToFile has null default value, but is not marked as nullable.
Loading history...
371
    )
372
    {
0 ignored issues
show
Coding Style introduced by
The closing parenthesis and the opening brace of a multi-line function declaration must be on the same line
Loading history...
373 30
        return $this->transport()->select($sql, $bindings, $whereInFile, $writeToFile);
374
    }
375
376
    /**
377
     * @return bool
378
     */
379 10
    public function executeAsync()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::executeAsync() does not have return type hint for its return value but it should be possible to add it based on @return annotation "bool".
Loading history...
380
    {
381 10
        return $this->transport()->executeAsync();
382
    }
383
384
    public function maxTimeExecutionAllAsync()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::maxTimeExecutionAllAsync() does not have void return type hint.
Loading history...
385
    {
386
387
    }
0 ignored issues
show
Coding Style introduced by
Function closing brace must go on the next line following the body; found 1 blank lines before brace
Loading history...
388
389
    /**
390
     * set progressFunction
391
     */
392
    public function progressFunction(callable $callback)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::progressFunction() does not have void return type hint.
Loading history...
393
    {
394
        if (!is_callable($callback)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
395
            throw new \InvalidArgumentException('Not is_callable progressFunction');
0 ignored issues
show
introduced by
Class \InvalidArgumentException should not be referenced via a fully qualified name, but via a use statement.
Loading history...
396
        }
397
398
        if (!$this->settings()->is('send_progress_in_http_headers')) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
399
            $this->settings()->set('send_progress_in_http_headers', 1);
400
        }
401
        if (!$this->settings()->is('http_headers_progress_interval_ms')) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
402
            $this->settings()->set('http_headers_progress_interval_ms', 100);
403
        }
404
405
        $this->transport()->setProgressFunction($callback);
406
    }
407
408
    /**
409
     * prepare select
410
     *
411
     * @param mixed[] $bindings
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
412
     * @return Statement
413
     */
414 7
    public function selectAsync(
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::selectAsync() does not have return type hint for its return value but it should be possible to add it based on @return annotation "Statement".
Loading history...
415
        string $sql,
416
        array $bindings = [],
417
        WhereInFile $whereInFile = null,
0 ignored issues
show
introduced by
Parameter $whereInFile has null default value, but is not marked as nullable.
Loading history...
418
        WriteToFile $writeToFile = null
0 ignored issues
show
introduced by
Parameter $writeToFile has null default value, but is not marked as nullable.
Loading history...
419
    )
420
    {
0 ignored issues
show
Coding Style introduced by
The closing parenthesis and the opening brace of a multi-line function declaration must be on the same line
Loading history...
421 7
        return $this->transport()->selectAsync($sql, $bindings, $whereInFile, $writeToFile);
422
    }
423
424
    /**
425
     * SHOW PROCESSLIST
426
     *
427
     * @return array
0 ignored issues
show
introduced by
@return annotation of method \ClickHouseDB\Client::showProcesslist() does not specify type hint for items of its traversable return value.
Loading history...
428
     */
429
    public function showProcesslist()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::showProcesslist() does not have return type hint for its return value but it should be possible to add it based on @return annotation "array".
Loading history...
430
    {
431
        return $this->select('SHOW PROCESSLIST')->rows();
432
    }
433
434
    /**
435
     * show databases
436
     *
437
     * @return array
0 ignored issues
show
introduced by
@return annotation of method \ClickHouseDB\Client::showDatabases() does not specify type hint for items of its traversable return value.
Loading history...
438
     */
439
    public function showDatabases()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::showDatabases() does not have return type hint for its return value but it should be possible to add it based on @return annotation "array".
Loading history...
440
    {
441
        return $this->select('show databases')->rows();
442
    }
443
444
    /**
445
     * statement = SHOW CREATE TABLE
446
     *
447
     * @return mixed
448
     */
449
    public function showCreateTable(string $table)
450
    {
451
        return $this->select('SHOW CREATE TABLE ' . $table)->fetchOne('statement');
452
    }
453
454
    /**
455
     * SHOW TABLES
456
     *
457
     * @return mixed[]
458
     */
459 1
    public function showTables()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::showTables() does not have return type hint for its return value but it should be possible to add it based on @return annotation "mixed[]".
Loading history...
460
    {
461 1
        return $this->select('SHOW TABLES')->rowsAsTree('name');
462
    }
463
464
    /**
465
     * Get the number of simultaneous/Pending requests
466
     *
467
     * @return int
468
     */
469 12
    public function getCountPendingQueue()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::getCountPendingQueue() does not have return type hint for its return value but it should be possible to add it based on @return annotation "int".
Loading history...
470
    {
471 12
        return $this->transport()->getCountPendingQueue();
472
    }
473
474
    /**
475
     * @param mixed[][] $values
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
476
     * @param string[] $columns
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
477
     * @return Statement
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::insert() has useless @return annotation.
Loading history...
478
     * @throws Exception\TransportException
479
     */
480 10
    public function insert(string $table, array $values, array $columns = []): Statement
0 ignored issues
show
introduced by
There must be exactly 1 whitespace between closing parenthesis and return type colon.
Loading history...
481
    {
482 10
        if (empty($values)) {
483 1
            throw QueryException::cannotInsertEmptyValues();
484
        }
485
486 9
        if (stripos($table, '`') === false && stripos($table, '.') === false) {
487 6
            $table = '`' . $table . '`'; //quote table name for dot names
488
        }
489 9
        $sql = 'INSERT INTO ' . $table;
490
491 9
        if (count($columns) !== 0) {
492 8
            $sql .= ' (`' . implode('`,`', $columns) . '`) ';
493
        }
494
495 9
        $sql .= ' VALUES ';
496
497 9
        foreach ($values as $row) {
498 9
            $sql .= ' (' . FormatLine::Insert($row) . '), ';
499
        }
500 9
        $sql = trim($sql, ', ');
501
502 9
        return $this->transport()->write($sql);
503
    }
504
505
    /**
506
     *       * Prepares the values to insert from the associative array.
507
     *       * There may be one or more lines inserted, but then the keys inside the array list must match (including in the sequence)
508
     *       *
509
     *       * @param mixed[] $values - array column_name => value (if we insert one row) or array list column_name => value if we insert many lines
510
     *       * @return mixed[][] - list of arrays - 0 => fields, 1 => list of value arrays for insertion
511
     *       */
512 3
    public function prepareInsertAssocBulk(array $values)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::prepareInsertAssocBulk() does not have @param annotation for its traversable parameter $values.
Loading history...
introduced by
Method \ClickHouseDB\Client::prepareInsertAssocBulk() does not have return type hint nor @return annotation for its return value.
Loading history...
513
    {
514 3
        if (isset($values[0]) && is_array($values[0])) { //случай, когда много строк вставляется
515 2
            $preparedFields = array_keys($values[0]);
516 2
            $preparedValues = [];
517 2
            foreach ($values as $idx => $row) {
518 2
                $_fields = array_keys($row);
519 2
                if ($_fields !== $preparedFields) {
520 1
                    throw new QueryException(
521 1
                        sprintf(
522 1
                            'Fields not match: %s and %s on element %s',
523 1
                            implode(',', $_fields),
524 1
                            implode(',', $preparedFields),
525 1
                            $idx
526
                        )
527
                    );
528
                }
529 2
                $preparedValues[] = array_values($row);
530
            }
531
        } else {
532 1
            $preparedFields = array_keys($values);
533 1
            $preparedValues = [array_values($values)];
534
        }
535
536 2
        return [$preparedFields, $preparedValues];
537
    }
538
539
    /**
540
     * Inserts one or more rows from an associative array.
541
     * If there is a discrepancy between the keys of the value arrays (or their order) - throws an exception.
542
     *
543
     * @param mixed[] $values - array column_name => value (if we insert one row) or array list column_name => value if we insert many lines
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
544
     * @return Statement
545
     */
546
    public function insertAssocBulk(string $tableName, array $values)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::insertAssocBulk() does not have return type hint for its return value but it should be possible to add it based on @return annotation "Statement".
Loading history...
547
    {
548
        list($columns, $vals) = $this->prepareInsertAssocBulk($values);
0 ignored issues
show
introduced by
list(...) is forbidden, use [...] instead.
Loading history...
549
550
        return $this->insert($tableName, $vals, $columns);
551
    }
552
553
    /**
554
     * insert TabSeparated files
555
     *
556
     * @param string|string[] $fileNames
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
557
     * @param string[] $columns
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
558
     * @return mixed
559
     */
560 1
    public function insertBatchTSVFiles(string $tableName, $fileNames, array $columns = [])
561
    {
562 1
        return $this->insertBatchFiles($tableName, $fileNames, $columns, 'TabSeparated');
563
    }
564
565
    /**
566
     * insert Batch Files
567
     *
568
     * @param string|string[] $fileNames
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
569
     * @param string[] $columns
0 ignored issues
show
Coding Style introduced by
Expected 8 spaces after parameter type; 1 found
Loading history...
570
     * @param string $format ['TabSeparated','TabSeparatedWithNames','CSV','CSVWithNames']
0 ignored issues
show
Coding Style introduced by
Expected 10 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
571
     * @return Statement[]
572
     * @throws Exception\TransportException
573
     */
574 8
    public function insertBatchFiles(string $tableName, $fileNames, array $columns = [], string $format = 'CSV')
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::insertBatchFiles() does not have return type hint for its return value but it should be possible to add it based on @return annotation "Statement[]".
Loading history...
575
    {
576 8
        if (is_string($fileNames)) {
577
            $fileNames = [$fileNames];
578
        }
579 8
        if ($this->getCountPendingQueue() > 0) {
580
            throw new QueryException('Queue must be empty, before insertBatch, need executeAsync');
581
        }
582
583 8
        if (!in_array($format, self::SUPPORTED_FORMATS, true)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
584
            throw new QueryException('Format not support in insertBatchFiles');
585
        }
586
587 8
        $result = [];
588
589 8
        foreach ($fileNames as $fileName) {
590 8
            if (!is_file($fileName) || !is_readable($fileName)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
591
                throw  new QueryException('Cant read file: ' . $fileName . ' ' . (is_file($fileName) ? '' : ' is not file'));
592
            }
593
594 8
            if (empty($columns)) {
595
                $sql = 'INSERT INTO ' . $tableName . ' FORMAT ' . $format;
596
            } else {
597 8
                $sql = 'INSERT INTO ' . $tableName . ' ( ' . implode(',', $columns) . ' ) FORMAT ' . $format;
598
            }
599 8
            $result[$fileName] = $this->transport()->writeAsyncCSV($sql, $fileName);
600
        }
601
602
        // exec
603 8
        $this->executeAsync();
604
605
        // fetch resutl
606 8
        foreach ($fileNames as $fileName) {
607 8
            if (!$result[$fileName]->isError()) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
608 6
                continue;
609
            }
610
611 2
            $result[$fileName]->error();
612
        }
613
614 6
        return $result;
615
    }
616
617
    /**
618
     * insert Batch Stream
619
     *
620
     * @param string[] $columns
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
621
     * @param string $format ['TabSeparated','TabSeparatedWithNames','CSV','CSVWithNames']
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
622
     * @return Transport\CurlerRequest
623
     */
624 2
    public function insertBatchStream(string $tableName, array $columns = [], string $format = 'CSV')
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::insertBatchStream() does not have return type hint for its return value but it should be possible to add it based on @return annotation "Transport\CurlerRequest".
Loading history...
625
    {
626 2
        if ($this->getCountPendingQueue() > 0) {
627
            throw new QueryException('Queue must be empty, before insertBatch, need executeAsync');
628
        }
629
630 2
        if (!in_array($format, self::SUPPORTED_FORMATS, true)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after NOT operator; 0 found
Loading history...
631
            throw new QueryException('Format not support in insertBatchFiles');
632
        }
633
634 2
        if (empty($columns)) {
635
            $sql = 'INSERT INTO ' . $tableName . ' FORMAT ' . $format;
636
        } else {
637 2
            $sql = 'INSERT INTO ' . $tableName . ' ( ' . implode(',', $columns) . ' ) FORMAT ' . $format;
638
        }
639
640 2
        return $this->transport()->writeStreamData($sql);
641
    }
642
643
    /**
644
     * stream Write
645
     *
646
     * @param string[] $bind
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
647
     * @return Statement
648
     * @throws Exception\TransportException
649
     */
650 1
    public function streamWrite(Stream $stream, string $sql, array $bind = [])
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::streamWrite() does not have return type hint for its return value but it should be possible to add it based on @return annotation "Statement".
Loading history...
651
    {
652 1
        if ($this->getCountPendingQueue() > 0) {
653
            throw new QueryException('Queue must be empty, before streamWrite');
654
        }
655
656 1
        return $this->transport()->streamWrite($stream, $sql, $bind);
657
    }
658
659
    /**
660
     * stream Read
661
     *
662
     * @param string[] $bind
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
663
     * @return Statement
664
     */
665 1
    public function streamRead(Stream $streamRead, string $sql, array $bind = [])
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::streamRead() does not have return type hint for its return value but it should be possible to add it based on @return annotation "Statement".
Loading history...
666
    {
667 1
        if ($this->getCountPendingQueue() > 0) {
668
            throw new QueryException('Queue must be empty, before streamRead');
669
        }
670
671 1
        return $this->transport()->streamRead($streamRead, $sql, $bind);
672
    }
673
674
    /**
675
     * Size of database
676
     *
677
     * @return mixed|null
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
678
     * @throws \Exception
0 ignored issues
show
introduced by
Class \Exception should not be referenced via a fully qualified name, but via a use statement.
Loading history...
679
     */
680
    public function databaseSize()
681
    {
682
        $b = $this->settings()->getDatabase();
683
684
        return $this->select(
685
            '
686
            SELECT database,formatReadableSize(sum(bytes)) as size
687
            FROM system.parts
688
            WHERE active AND database=:database
689
            GROUP BY database
690
            ',
691
            ['database' => $b]
692
        )->fetchOne();
693
    }
694
695
    /**
696
     * Size of tables
697
     *
698
     * @return mixed
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
699
     * @throws \Exception
0 ignored issues
show
introduced by
Class \Exception should not be referenced via a fully qualified name, but via a use statement.
Loading history...
700
     */
701
    public function tableSize(string $tableName)
702
    {
703
        $tables = $this->tablesSize();
704
705
        if (isset($tables[$tableName])) {
706
            return $tables[$tableName];
707
        }
708
709
        return null;
710
    }
711
712
    /**
713
     * Ping server
714
     *
715
     * @return bool
716
     */
717 37
    public function ping()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::ping() does not have return type hint for its return value but it should be possible to add it based on @return annotation "bool".
Loading history...
718
    {
719 37
        return $this->transport()->ping();
720
    }
721
722
    /**
723
     * Tables sizes
724
     *
725
     * @param bool $flatList
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
726
     * @return mixed[][]
727
     * @throws \Exception
0 ignored issues
show
introduced by
Class \Exception should not be referenced via a fully qualified name, but via a use statement.
Loading history...
728
     */
729
    public function tablesSize($flatList = false)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::tablesSize() does not have parameter type hint for its parameter $flatList but it should be possible to add it based on @param annotation "bool".
Loading history...
introduced by
Method \ClickHouseDB\Client::tablesSize() does not have return type hint for its return value but it should be possible to add it based on @return annotation "mixed[][]".
Loading history...
730
    {
731
        $result = $this->select('
732
        SELECT name as table,database,
733
            max(sizebytes) as sizebytes,
734
            max(size) as size,
735
            min(min_date) as min_date,
736
            max(max_date) as max_date
737
            FROM system.tables
738
            ANY LEFT JOIN 
739
            (
740
            SELECT table,database,
741
                        formatReadableSize(sum(bytes)) as size,
742
                        sum(bytes) as sizebytes,
743
                        min(min_date) as min_date,
744
                        max(max_date) as max_date
745
                        FROM system.parts 
746
                        WHERE active AND database=:database
747
                        GROUP BY table,database
748
            ) USING ( table,database )
749
            WHERE database=:database
750
            GROUP BY table,database
751
        ',
752
            ['database' => $this->settings()->getDatabase()]);
753
754
        if ($flatList) {
755
            return $result->rows();
756
        }
757
758
        return $result->rowsAsTree('table');
759
    }
760
761
    /**
762
     * isExists
763
     *
764
     * @return array
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
introduced by
@return annotation of method \ClickHouseDB\Client::isExists() does not specify type hint for items of its traversable return value.
Loading history...
765
     * @throws \Exception
0 ignored issues
show
introduced by
Class \Exception should not be referenced via a fully qualified name, but via a use statement.
Loading history...
766
     */
767
    public function isExists(string $database, string $table)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::isExists() does not have return type hint for its return value but it should be possible to add it based on @return annotation "array".
Loading history...
768
    {
769
        return $this->select(
770
            '
771
            SELECT *
772
            FROM system.tables 
773
            WHERE name=\'' . $table . '\' AND database=\'' . $database . '\''
774
        )->rowsAsTree('name');
775
    }
776
777
    /**
778
     * List of partitions
779
     *
780
     * @return mixed[][]
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
781
     * @throws \Exception
0 ignored issues
show
introduced by
Class \Exception should not be referenced via a fully qualified name, but via a use statement.
Loading history...
782
     */
783
    public function partitions(string $table, int $limit = null, bool $active = null)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::partitions() does not have return type hint for its return value but it should be possible to add it based on @return annotation "mixed[][]".
Loading history...
introduced by
Parameter $limit has null default value, but is not marked as nullable.
Loading history...
introduced by
Parameter $active has null default value, but is not marked as nullable.
Loading history...
784
    {
785
        $database = $this->settings()->getDatabase();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 10 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
786
        $whereActiveClause = $active === null ? '' : sprintf(' AND active = %s', (int)$active);
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after cast statement; 0 found
Loading history...
787
        $limitClause = $limit !== null ? ' LIMIT ' . $limit : '';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 7 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
788
789
        return $this->select(<<<CLICKHOUSE
790
SELECT *
791
FROM system.parts 
792
WHERE like(table,'%$table%') AND database='$database'$whereActiveClause
793
ORDER BY max_date $limitClause
794
CLICKHOUSE
795
        )->rowsAsTree('name');
796
    }
797
798
    /**
799
     * dropPartition
800
     * @return Statement
0 ignored issues
show
introduced by
Expected 1 lines between description and annotations, found 0.
Loading history...
introduced by
Incorrect annotations group.
Loading history...
801
     * @deprecated
802
     */
803
    public function dropPartition(string $dataBaseTableName, string $partition_id)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::dropPartition() does not have return type hint for its return value but it should be possible to add it based on @return annotation "Statement".
Loading history...
804
    {
0 ignored issues
show
Coding Style introduced by
Expected 0 blank lines after opening function brace; 1 found
Loading history...
805
806
        $partition_id = trim($partition_id, '\'');
807
        $this->settings()->set('replication_alter_partitions_sync', 2);
808
        $state = $this->write('ALTER TABLE {dataBaseTableName} DROP PARTITION :partion_id',
0 ignored issues
show
introduced by
Useless variable $state.
Loading history...
809
            [
810
                'dataBaseTableName' => $dataBaseTableName,
811
                'partion_id' => $partition_id,
812
            ]);
813
814
        return $state;
815
    }
816
817
    /**
818
     * Truncate ( drop all partitions )
819
     * @return array
0 ignored issues
show
introduced by
Expected 1 lines between description and annotations, found 0.
Loading history...
introduced by
Incorrect annotations group.
Loading history...
introduced by
@return annotation of method \ClickHouseDB\Client::truncateTable() does not specify type hint for items of its traversable return value.
Loading history...
820
     * @throws \Exception
0 ignored issues
show
introduced by
Class \Exception should not be referenced via a fully qualified name, but via a use statement.
Loading history...
821
     * @deprecated
822
     */
823
    public function truncateTable(string $tableName)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::truncateTable() does not have return type hint for its return value but it should be possible to add it based on @return annotation "array".
Loading history...
824
    {
825
        $partions = $this->partitions($tableName);
826
        $out = [];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 6 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
827
        foreach ($partions as $part_key => $part) {
828
            $part_id = $part['partition'];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 7 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
829
            $out[$part_id] = $this->dropPartition($tableName, $part_id);
0 ignored issues
show
Deprecated Code introduced by
The function ClickHouseDB\Client::dropPartition() 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

829
            $out[$part_id] = /** @scrutinizer ignore-deprecated */ $this->dropPartition($tableName, $part_id);
Loading history...
830
        }
831
832
        return $out;
833
    }
834
835
    /**
836
     * Returns the server's uptime in seconds.
837
     *
838
     * @return int
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
839
     * @throws Exception\TransportException
840
     * @throws \Exception
0 ignored issues
show
introduced by
Class \Exception should not be referenced via a fully qualified name, but via a use statement.
Loading history...
841
     */
842 1
    public function getServerUptime()
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::getServerUptime() does not have return type hint for its return value but it should be possible to add it based on @return annotation "int".
Loading history...
843
    {
844 1
        return $this->select('SELECT uptime() as uptime')->fetchOne('uptime');
845
    }
846
847
    /**
848
     * Returns string with the server version.
849
     */
850 1
    public function getServerVersion(): string
0 ignored issues
show
introduced by
There must be exactly 1 whitespace between closing parenthesis and return type colon.
Loading history...
851
    {
852 1
        return (string)$this->select('SELECT version() as version')->fetchOne('version');
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after cast statement; 0 found
Loading history...
853
    }
854
855
    /**
856
     * Read system.settings table
857
     *
858
     * @return mixed[][]
0 ignored issues
show
introduced by
Incorrect annotations group.
Loading history...
859
     * @throws \Exception
0 ignored issues
show
introduced by
Class \Exception should not be referenced via a fully qualified name, but via a use statement.
Loading history...
860
     */
861 1
    public function getServerSystemSettings(string $like = '')
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::getServerSystemSettings() does not have return type hint for its return value but it should be possible to add it based on @return annotation "mixed[][]".
Loading history...
862
    {
863 1
        $l = [];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
864 1
        $list = $this->select('SELECT * FROM system.settings' . ($like ? ' WHERE name LIKE :like' : ''),
865 1
            ['like' => '%' . $like . '%'])->rows();
866 1
        foreach ($list as $row) {
867 1
            if (isset($row['name'])) {
0 ignored issues
show
introduced by
Use early exit to reduce code nesting.
Loading history...
868 1
                $n = $row['name'];
869 1
                unset($row['name']);
870 1
                $l[$n] = $row;
871
            }
872
        }
873
874 1
        return $l;
875
    }
876
877
}
0 ignored issues
show
introduced by
There must be exactly 0 empty lines before class closing brace.
Loading history...
878