Passed
Pull Request — master (#92)
by Šimon
02:21
created

Client::databaseSize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 13
ccs 0
cts 6
cp 0
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
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;
17
use function array_keys;
18
use function array_rand;
19
use function array_values;
20
use function count;
21
use function date;
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;
32
use function trim;
33
34
class Client
35
{
36
    const SUPPORTED_FORMATS = ['TabSeparated', 'TabSeparatedWithNames', 'CSV', 'CSVWithNames', 'JSONEachRow'];
0 ignored issues
show
introduced by
Constant \ClickHouseDB\Client::SUPPORTED_FORMATS visibility missing.
Loading history...
37
38
    /** @var Http */
39
    private $transport;
40
41
    /** @var string */
42
    private $connectUsername;
43
44
    /** @var string */
45
    private $connectPassword;
46
47
    /** @var string */
48
    private $connectHost;
49
50
    /** @var string */
51
    private $connectPort;
52
53
    /** @var bool */
54
    private $connectUserReadonly = false;
55
56
    /**
57
     * @param mixed[] $connectParams
58
     * @param mixed[] $settings
59
     */
60 59
    public function __construct(array $connectParams, array $settings = [])
61
    {
62 59
        if (! isset($connectParams['username'])) {
63
            throw  new \InvalidArgumentException('not set username');
64
        }
65
66 59
        if (! isset($connectParams['password'])) {
67
            throw  new \InvalidArgumentException('not set password');
68
        }
69
70 59
        if (! isset($connectParams['port'])) {
71
            throw  new \InvalidArgumentException('not set port');
72
        }
73
74 59
        if (! isset($connectParams['host'])) {
75
            throw  new \InvalidArgumentException('not set host');
76
        }
77
78 59
        $this->connectUsername = $connectParams['username'];
79 59
        $this->connectPassword = $connectParams['password'];
80 59
        $this->connectPort     = $connectParams['port'];
81 59
        $this->connectHost     = $connectParams['host'];
82
83
        // init transport class
84 59
        $this->transport = new Http(
85 59
            $this->connectHost,
86 59
            $this->connectPort,
87 59
            $this->connectUsername,
88 59
            $this->connectPassword
89
        );
90
91 59
        $this->transport->addQueryDegeneration(new Bindings());
92
93
        // apply settings to transport class
94 59
        $this->settings()->database('default');
95 59
        if (! empty($settings)) {
96 1
            $this->settings()->apply($settings);
97
        }
98
99 59
        if (isset($connectParams['readonly'])) {
100
            $this->setReadOnlyUser($connectParams['readonly']);
101
        }
102
103 59
        if (isset($connectParams['https'])) {
104
            $this->https($connectParams['https']);
105
        }
106
107 59
        $this->enableHttpCompression();
108 59
    }
109
110
    /**
111
     * if the user has only read in the config file
112
     */
113
    public function setReadOnlyUser(bool $flag)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::setReadOnlyUser() does not have void return type hint.
Loading history...
114
    {
115
        $this->connectUserReadonly = $flag;
116
        $this->settings()->setReadOnlyUser($this->connectUserReadonly);
117
    }
118
119
    /**
120
     * Clear Degeneration processing request [template ]
121
     *
122
     * @return bool
123
     */
124 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...
125
    {
126 1
        return $this->transport->cleanQueryDegeneration();
127
    }
128
129
    /**
130
     * add Degeneration processing
131
     *
132
     * @return bool
133
     */
134
    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...
135
    {
136
        return $this->transport->addQueryDegeneration($degeneration);
137
    }
138
139
    /**
140
     * add Conditions in query
141
     *
142
     * @return bool
143
     */
144 1
    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...
145
    {
146 1
        return $this->transport->addQueryDegeneration(new Conditions());
147
    }
148
149
    /**
150
     * Set connection host
151
     *
152
     * @param string|string[] $host
153
     */
154
    public function setHost($host)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::setHost() does not have void return type hint.
Loading history...
155
    {
156
        if (is_array($host)) {
157
            $host = array_rand(array_flip($host));
158
        }
159
160
        $this->connectHost = $host;
161
        $this->transport()->setHost($host);
162
    }
163
164
    /**
165
     * @return Settings
166
     */
167 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...
168
    {
169 2
        return $this->settings()->max_execution_time($timeout);
0 ignored issues
show
Bug introduced by
$timeout of type double is incompatible with the type integer expected by parameter $time of ClickHouseDB\Settings::max_execution_time(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

169
        return $this->settings()->max_execution_time(/** @scrutinizer ignore-type */ $timeout);
Loading history...
170
    }
171
172
    /**
173
     * @return mixed
174
     */
175 1
    public function getTimeout()
176
    {
177 1
        return $this->settings()->getTimeOut();
178
    }
179
180
    /**
181
     * ConnectTimeOut in seconds ( support 1.5 = 1500ms )
182
     */
183 2
    public function setConnectTimeOut(float $connectTimeOut)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::setConnectTimeOut() does not have void return type hint.
Loading history...
184
    {
185 2
        $this->transport()->setConnectTimeOut($connectTimeOut);
0 ignored issues
show
Bug introduced by
$connectTimeOut of type double is incompatible with the type integer expected by parameter $connectTimeOut of ClickHouseDB\Transport\Http::setConnectTimeOut(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

185
        $this->transport()->setConnectTimeOut(/** @scrutinizer ignore-type */ $connectTimeOut);
Loading history...
186 2
    }
187
188
    /**
189
     * @return int
190
     */
191 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...
192
    {
193 1
        return $this->transport()->getConnectTimeOut();
194
    }
195
196
    /**
197
     * @return Http
198
     */
199 59
    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...
200
    {
201 59
        if (! $this->transport) {
202
            throw  new \InvalidArgumentException('Empty transport class');
203
        }
204
205 59
        return $this->transport;
206
    }
207
208
    /**
209
     * @return string
210
     */
211
    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...
212
    {
213
        return $this->connectHost;
214
    }
215
216
    /**
217
     * @return string
218
     */
219
    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...
220
    {
221
        return $this->connectPassword;
222
    }
223
224
    /**
225
     * @return string
226
     */
227
    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...
228
    {
229
        return $this->connectPort;
230
    }
231
232
    /**
233
     * @return string
234
     */
235
    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...
236
    {
237
        return $this->connectUsername;
238
    }
239
240
    /**
241
     * @return Http
242
     */
243
    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...
244
    {
245
        return $this->transport;
246
    }
247
248
    /**
249
     * @return mixed
250
     */
251
    public function verbose()
252
    {
253
        return $this->transport()->verbose(true);
254
    }
255
256
    /**
257
     * @return Settings
258
     */
259 59
    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...
260
    {
261 59
        return $this->transport()->settings();
262
    }
263
264
    /**
265
     * @return static
266
     */
267 2
    public function useSession(bool $useSessionId = false)
268
    {
269 2
        if (! $this->settings()->getSessionId()) {
270 2
            if (! $useSessionId) {
271 2
                $this->settings()->makeSessionId();
272
            } else {
273
                $this->settings()->session_id($useSessionId);
0 ignored issues
show
Bug introduced by
$useSessionId of type true is incompatible with the type string expected by parameter $session_id of ClickHouseDB\Settings::session_id(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

273
                $this->settings()->session_id(/** @scrutinizer ignore-type */ $useSessionId);
Loading history...
274
            }
275
        }
276
277 2
        return $this;
278
    }
279
280
    /**
281
     * @return mixed
282
     */
283 2
    public function getSession()
284
    {
285 2
        return $this->settings()->getSessionId();
286
    }
287
288
    /**
289
     * Query CREATE/DROP
290
     *
291
     * @param string[] $bindings
292
     * @return Statement
293
     */
294 23
    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...
295
    {
296 23
        return $this->transport()->write($sql, $bindings, $exception);
297
    }
298
299
    /**
300
     * set db name
301
     * @return static
302
     */
303 59
    public function database(string $db)
304
    {
305 59
        $this->settings()->database($db);
306
307 59
        return $this;
308
    }
309
310
    /**
311
     * Write to system.query_log
312
     *
313
     * @return static
314
     */
315
    public function enableLogQueries(bool $flag = true)
316
    {
317
        $this->settings()->set('log_queries', (int) $flag);
318
319
        return $this;
320
    }
321
322
    /**
323
     * Compress the result if the HTTP client said that it understands data compressed with gzip or deflate
324
     *
325
     * @return static
326
     */
327 59
    public function enableHttpCompression(bool $flag = true)
328
    {
329 59
        $this->settings()->enableHttpCompression($flag);
330
331 59
        return $this;
332
    }
333
334
    /**
335
     * Enable / Disable HTTPS
336
     *
337
     * @return static
338
     */
339 1
    public function https(bool $flag = true)
340
    {
341 1
        $this->settings()->https($flag);
342
343 1
        return $this;
344
    }
345
346
    /**
347
     * Read extremes of the result columns. They can be output in JSON-formats.
348
     *
349
     * @return static
350
     */
351 2
    public function enableExtremes(bool $flag = true)
352
    {
353 2
        $this->settings()->set('extremes', (int) $flag);
354
355 2
        return $this;
356
    }
357
358
    /**
359
     * @param string[] $bindings
360
     * @return Statement
361
     */
362 26
    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...
363
        string $sql,
364
        array $bindings = [],
365
        WhereInFile $whereInFile = null,
0 ignored issues
show
introduced by
Parameter $whereInFile has null default value, but is not marked as nullable.
Loading history...
366
        WriteToFile $writeToFile = null
0 ignored issues
show
introduced by
Parameter $writeToFile has null default value, but is not marked as nullable.
Loading history...
367
    ) {
368 26
        return $this->transport()->select($sql, $bindings, $whereInFile, $writeToFile);
369
    }
370
371
    /**
372
     * @return bool
373
     */
374 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...
375
    {
376 10
        return $this->transport()->executeAsync();
377
    }
378
379
    /**
380
     * set progressFunction
381
     */
382 1
    public function progressFunction(callable $callback)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::progressFunction() does not have void return type hint.
Loading history...
383
    {
384 1
        if (! is_callable($callback)) {
385
            throw new \InvalidArgumentException('Not is_callable progressFunction');
386
        }
387
388 1
        if (! $this->settings()->is('send_progress_in_http_headers')) {
389 1
            $this->settings()->set('send_progress_in_http_headers', 1);
390
        }
391 1
        if (! $this->settings()->is('http_headers_progress_interval_ms')) {
392 1
            $this->settings()->set('http_headers_progress_interval_ms', 100);
393
        }
394
395 1
        $this->transport()->setProgressFunction($callback);
396 1
    }
397
398
    /**
399
     * prepare select
400
     *
401
     * @param string[] $bindings
402
     * @return Statement
403
     */
404 5
    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...
405
        string $sql,
406
        array $bindings = [],
407
        WhereInFile $whereInFile = null,
0 ignored issues
show
introduced by
Parameter $whereInFile has null default value, but is not marked as nullable.
Loading history...
408
        WriteToFile $writeToFile = null
0 ignored issues
show
introduced by
Parameter $writeToFile has null default value, but is not marked as nullable.
Loading history...
409
    ) {
410 5
        return $this->transport()->selectAsync($sql, $bindings, $whereInFile, $writeToFile);
411
    }
412
413
    /**
414
     * SHOW PROCESSLIST
415
     *
416
     * @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...
417
     */
418
    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...
419
    {
420
        return $this->select('SHOW PROCESSLIST')->rows();
421
    }
422
423
    /**
424
     * show databases
425
     *
426
     * @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...
427
     */
428
    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...
429
    {
430
        return $this->select('show databases')->rows();
431
    }
432
433
    /**
434
     * statement = SHOW CREATE TABLE
435
     *
436
     * @return mixed
437
     */
438
    public function showCreateTable(string $table)
439
    {
440
        return $this->select('SHOW CREATE TABLE ' . $table)->fetchOne('statement');
441
    }
442
443
    /**
444
     * SHOW TABLES
445
     *
446
     * @return mixed[]
447
     */
448 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...
449
    {
450 1
        return $this->select('SHOW TABLES')->rowsAsTree('name');
451
    }
452
453
    /**
454
     * Get the number of simultaneous/Pending requests
455
     *
456
     * @return int
457
     */
458 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...
459
    {
460 12
        return $this->transport()->getCountPendingQueue();
461
    }
462
463
    /**
464
     * Insert Array
465
     *
466
     * @param mixed[][] $values
467
     * @param string[]  $columns
468
     * @return Statement
469
     * @throws Exception\TransportException
470
     */
471 6
    public function insert(string $table, $values, $columns = [])
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::insert() does not have parameter type hint for its parameter $values but it should be possible to add it based on @param annotation "mixed[][]".
Loading history...
introduced by
Method \ClickHouseDB\Client::insert() 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...
472
    {
473 6
        if (stripos($table, '`') === false && stripos($table, '.') === false) {
474 3
            $table = '`' . $table . '`'; //quote table name for dot names
475
        }
476 6
        $sql = 'INSERT INTO ' . $table;
477
478 6
        if (count($columns) !== 0) {
479 6
            $sql .= ' (`' . implode('`,`', $columns) . '`) ';
480
        }
481
482 6
        $sql .= ' VALUES ';
483
484 6
        foreach ($values as $row) {
485 6
            $sql .= ' (' . FormatLine::Insert($row) . '), ';
486
        }
487 6
        $sql = trim($sql, ', ');
488
489 6
        return $this->transport()->write($sql);
490
    }
491
492
    /**
493
     *       * Prepares the values to insert from the associative array.
494
     *       * There may be one or more lines inserted, but then the keys inside the array list must match (including in the sequence)
495
     *       *
496
     *       * @param mixed[] $values - array column_name => value (if we insert one row) or array list column_name => value if we insert many lines
497
     *       * @return mixed[][] - list of arrays - 0 => fields, 1 => list of value arrays for insertion
498
     *       */
499 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...
500
    {
501 3
        if (isset($values[0]) && is_array($values[0])) { //случай, когда много строк вставляется
502 2
            $preparedFields = array_keys($values[0]);
503 2
            $preparedValues = [];
504 2
            foreach ($values as $idx => $row) {
505 2
                $_fields = array_keys($row);
506 2
                if ($_fields !== $preparedFields) {
507 1
                    throw new QueryException(
508 1
                        sprintf(
509 1
                            'Fields not match: %s and %s on element %s',
510 1
                            implode(',', $_fields),
511 1
                            implode(',', $preparedFields),
512 1
                            $idx
513
                        )
514
                    );
515
                }
516 2
                $preparedValues[] = array_values($row);
517
            }
518
        } else {
519 1
            $preparedFields = array_keys($values);
520 1
            $preparedValues = [array_values($values)];
521
        }
522
523 2
        return [$preparedFields, $preparedValues];
524
    }
525
526
    /**
527
     * Inserts one or more rows from an associative array.
528
     * If there is a discrepancy between the keys of the value arrays (or their order) - throws an exception.
529
     *
530
     * @param mixed[] $values - array column_name => value (if we insert one row) or array list column_name => value if we insert many lines
531
     * @return Statement
532
     */
533
    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...
534
    {
535
        list($columns, $vals) = $this->prepareInsertAssocBulk($values);
536
537
        return $this->insert($tableName, $vals, $columns);
538
    }
539
540
    /**
541
     * insert TabSeparated files
542
     *
543
     * @param string|string[] $fileNames
544
     * @param string[]        $columns
545
     * @return mixed
546
     */
547 1
    public function insertBatchTSVFiles(string $tableName, $fileNames, array $columns = [])
548
    {
549 1
        return $this->insertBatchFiles($tableName, $fileNames, $columns, 'TabSeparated');
550
    }
551
552
    /**
553
     * insert Batch Files
554
     *
555
     * @param string|string[] $fileNames
556
     * @param string[]        $columns
557
     * @param string          $format ['TabSeparated','TabSeparatedWithNames','CSV','CSVWithNames']
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
558
     * @return Statement[]
559
     * @throws Exception\TransportException
560
     */
561 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...
562
    {
563 8
        if (is_string($fileNames)) {
564
            $fileNames = [$fileNames];
565
        }
566 8
        if ($this->getCountPendingQueue() > 0) {
567
            throw new QueryException('Queue must be empty, before insertBatch, need executeAsync');
568
        }
569
570 8
        if (! in_array($format, self::SUPPORTED_FORMATS, true)) {
571
            throw new QueryException('Format not support in insertBatchFiles');
572
        }
573
574 8
        $result = [];
575
576 8
        foreach ($fileNames as $fileName) {
577 8
            if (! is_file($fileName) || ! is_readable($fileName)) {
578
                throw  new QueryException('Cant read file: ' . $fileName . ' ' . (is_file($fileName) ? '' : ' is not file'));
579
            }
580
581 8
            if (empty($columns)) {
582
                $sql = 'INSERT INTO ' . $tableName . ' FORMAT ' . $format;
583
            } else {
584 8
                $sql = 'INSERT INTO ' . $tableName . ' ( ' . implode(',', $columns) . ' ) FORMAT ' . $format;
585
            }
586 8
            $result[$fileName] = $this->transport()->writeAsyncCSV($sql, $fileName);
587
        }
588
589
        // exec
590 8
        $this->executeAsync();
591
592
        // fetch resutl
593 8
        foreach ($fileNames as $fileName) {
594 8
            if (! $result[$fileName]->isError()) {
595 6
                continue;
596
            }
597
598 2
            $result[$fileName]->error();
599
        }
600
601 6
        return $result;
602
    }
603
604
    /**
605
     * insert Batch Stream
606
     *
607
     * @param string[] $columns
608
     * @param string   $format ['TabSeparated','TabSeparatedWithNames','CSV','CSVWithNames']
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
609
     * @return Transport\CurlerRequest
610
     */
611 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...
612
    {
613 2
        if ($this->getCountPendingQueue() > 0) {
614
            throw new QueryException('Queue must be empty, before insertBatch, need executeAsync');
615
        }
616
617 2
        if (! in_array($format, self::SUPPORTED_FORMATS, true)) {
618
            throw new QueryException('Format not support in insertBatchFiles');
619
        }
620
621 2
        if (empty($columns)) {
622
            $sql = 'INSERT INTO ' . $tableName . ' FORMAT ' . $format;
623
        } else {
624 2
            $sql = 'INSERT INTO ' . $tableName . ' ( ' . implode(',', $columns) . ' ) FORMAT ' . $format;
625
        }
626
627 2
        return $this->transport()->writeStreamData($sql);
628
    }
629
630
    /**
631
     * stream Write
632
     *
633
     * @param string[] $bind
634
     * @return Statement
635
     * @throws Exception\TransportException
636
     */
637 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...
638
    {
639 1
        if ($this->getCountPendingQueue() > 0) {
640
            throw new QueryException('Queue must be empty, before streamWrite');
641
        }
642
643 1
        return $this->transport()->streamWrite($stream, $sql, $bind);
644
    }
645
646
    /**
647
     * stream Read
648
     *
649
     * @param string[] $bind
650
     * @return Statement
651
     */
652 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...
653
    {
654 1
        if ($this->getCountPendingQueue() > 0) {
655
            throw new QueryException('Queue must be empty, before streamWrite');
656
        }
657
658 1
        return $this->transport()->streamRead($streamRead, $sql, $bind);
659
    }
660
661
    /**
662
     * Size of database
663
     *
664
     * @return mixed|null
665
     */
666
    public function databaseSize()
667
    {
668
        $b = $this->settings()->getDatabase();
669
670
        return $this->select(
671
            '
672
            SELECT database,formatReadableSize(sum(bytes)) as size
673
            FROM system.parts
674
            WHERE active AND database=:database
675
            GROUP BY database
676
            ',
677
            ['database' => $b]
678
        )->fetchOne();
679
    }
680
681
    /**
682
     * Size of tables
683
     *
684
     * @return mixed
685
     */
686 1
    public function tableSize(string $tableName)
687
    {
688 1
        $tables = $this->tablesSize();
689
690 1
        if (isset($tables[$tableName])) {
691 1
            return $tables[$tableName];
692
        }
693
694
        return null;
695
    }
696
697
    /**
698
     * Ping server
699
     *
700
     * @return bool
701
     */
702 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...
703
    {
704 37
        return $this->transport()->ping();
705
    }
706
707
    /**
708
     * Tables sizes
709
     *
710
     * @param bool $flatList
711
     * @return mixed[][]
712
     */
713 1
    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...
714
    {
715 1
        $result = $this->select('
716
        SELECT name as table,database,
717
            max(sizebytes) as sizebytes,
718
            max(size) as size,
719
            min(min_date) as min_date,
720
            max(max_date) as max_date
721
            FROM system.tables
722
            ANY LEFT JOIN 
723
            (
724
            SELECT table,database,
725
                        formatReadableSize(sum(bytes)) as size,
726
                        sum(bytes) as sizebytes,
727
                        min(min_date) as min_date,
728
                        max(max_date) as max_date
729
                        FROM system.parts 
730
                        WHERE active AND database=:database
731
                        GROUP BY table,database
732
            ) USING ( table,database )
733
            WHERE database=:database
734
            GROUP BY table,database
735
        ',
736 1
            ['database' => $this->settings()->getDatabase()]);
737
738 1
        if ($flatList) {
739
            return $result->rows();
740
        }
741
742 1
        return $result->rowsAsTree('table');
743
    }
744
745
    /**
746
     * isExists
747
     *
748
     * @return array
0 ignored issues
show
introduced by
@return annotation of method \ClickHouseDB\Client::isExists() does not specify type hint for items of its traversable return value.
Loading history...
749
     */
750
    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...
751
    {
752
        return $this->select(
753
            '
754
            SELECT *
755
            FROM system.tables 
756
            WHERE name=\'' . $table . '\' AND database=\'' . $database . '\''
757
        )->rowsAsTree('name');
758
    }
759
760
    /**
761
     * List of partitions
762
     *
763
     * @return mixed[][]
764
     */
765
    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...
766
    {
767
        $database          = $this->settings()->getDatabase();
768
        $whereActiveClause = $active === null ? '' : sprintf(' AND active = %s', (int) $active);
769
        $limitClause       = $limit !== null ? ' LIMIT ' . $limit : '';
770
771
        return $this->select(<<<CLICKHOUSE
772
SELECT *
773
FROM system.parts 
774
WHERE like(table,'%$table%') AND database='$database'$whereActiveClause
775
ORDER BY max_date $limitClause
776
CLICKHOUSE
777
        )->rowsAsTree('name');
778
    }
779
780
    /**
781
     * dropPartition
782
     * @deprecated
783
     * @return Statement
784
     */
785
    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...
786
    {
0 ignored issues
show
Coding Style introduced by
Expected 0 blank lines after opening function brace; 1 found
Loading history...
787
788
        $partition_id = trim($partition_id, '\'');
789
        $this->settings()->set('replication_alter_partitions_sync', 2);
790
        $state = $this->write('ALTER TABLE {dataBaseTableName} DROP PARTITION :partion_id',
791
            [
792
                'dataBaseTableName' => $dataBaseTableName,
793
                'partion_id'        => $partition_id,
794
            ]);
795
796
        return $state;
797
    }
798
799
    /**
800
     * Truncate ( drop all partitions )
801
     * @deprecated
802
     * @return array
0 ignored issues
show
introduced by
@return annotation of method \ClickHouseDB\Client::truncateTable() does not specify type hint for items of its traversable return value.
Loading history...
803
     */
804
    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...
805
    {
806
        $partions = $this->partitions($tableName);
807
        $out      = [];
808
        foreach ($partions as $part_key => $part) {
809
            $part_id       = $part['partition'];
810
            $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

810
            $out[$part_id] = /** @scrutinizer ignore-deprecated */ $this->dropPartition($tableName, $part_id);
Loading history...
811
        }
812
813
        return $out;
814
    }
815
816
    /**
817
     * Returns the server's uptime in seconds.
818
     *
819
     * @return int
820
     * @throws Exception\TransportException
821
     */
822 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...
823
    {
824 1
        return $this->select('SELECT uptime() as uptime')->fetchOne('uptime');
825
    }
826
827
    /**
828
     * Returns string with the server version.
829
     */
830 1
    public function getServerVersion() : string
831
    {
832 1
        return (string) $this->select('SELECT version() as version')->fetchOne('version');
833
    }
834
835
    /**
836
     * Read system.settings table
837
     *
838
     * @return mixed[][]
839
     */
840 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...
841
    {
842 1
        $l    = [];
843 1
        $list = $this->select('SELECT * FROM system.settings' . ($like ? ' WHERE name LIKE :like' : ''),
844 1
            ['like' => '%' . $like . '%'])->rows();
845 1
        foreach ($list as $row) {
846 1
            if (isset($row['name'])) {
0 ignored issues
show
introduced by
Use early exit to reduce code nesting.
Loading history...
847 1
                $n = $row['name'];
848 1
                unset($row['name']);
849 1
                $l[$n] = $row;
850
            }
851
        }
852
853 1
        return $l;
854
    }
855
856
    /**
857
     * dropOldPartitions by day_ago
858
     * @deprecated
859
     *
860
     * @return array
0 ignored issues
show
introduced by
@return annotation of method \ClickHouseDB\Client::dropOldPartitions() does not specify type hint for items of its traversable return value.
Loading history...
861
     * @throws Exception\TransportException
862
     * @throws \Exception
863
     */
864
    public function dropOldPartitions(string $table_name, int $days_ago, int $count_partitons_per_one = 100)
0 ignored issues
show
introduced by
Method \ClickHouseDB\Client::dropOldPartitions() 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...
865
    {
866
        $days_ago = strtotime(date('Y-m-d 00:00:00', strtotime('-' . $days_ago . ' day')));
867
868
        $drop           = [];
869
        $list_patitions = $this->partitions($table_name, $count_partitons_per_one);
870
871
        foreach ($list_patitions as $partion_id => $partition) {
872
            if (stripos($partition['engine'], 'mergetree') === false) {
873
                continue;
874
            }
875
876
            // $min_date = strtotime($partition['min_date']);
877
            $max_date = strtotime($partition['max_date']);
878
879
            if ($max_date < $days_ago) {
0 ignored issues
show
introduced by
Use early exit to reduce code nesting.
Loading history...
880
                $drop[] = $partition['partition'];
881
            }
882
        }
883
884
        $result = [];
885
        foreach ($drop as $partition_id) {
886
            $result[$partition_id] = $this->dropPartition($table_name, $partition_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

886
            $result[$partition_id] = /** @scrutinizer ignore-deprecated */ $this->dropPartition($table_name, $partition_id);
Loading history...
887
        }
888
889
        return $result;
890
    }
891
}
892