Failed Conditions
Push — master ( 20fa9e...5a0a45 )
by Igor
03:28 queued 10s
created

src/Client.php (45 issues)

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
/**
35
 * Class Client
36
 * @package ClickHouseDB
37
 */
38
class Client
39
{
40
    const SUPPORTED_FORMATS = ['TabSeparated', 'TabSeparatedWithNames', 'CSV', 'CSVWithNames', 'JSONEachRow'];
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 67
    public function __construct(array $connectParams, array $settings = [])
65
    {
66 67
        if (!isset($connectParams['username'])) {
0 ignored issues
show
Expected 1 space(s) after NOT operator; 0 found
Loading history...
67
            throw  new \InvalidArgumentException('not set username');
68
        }
69
70 67
        if (!isset($connectParams['password'])) {
0 ignored issues
show
Expected 1 space(s) after NOT operator; 0 found
Loading history...
71
            throw  new \InvalidArgumentException('not set password');
72
        }
73
74 67
        if (!isset($connectParams['port'])) {
0 ignored issues
show
Expected 1 space(s) after NOT operator; 0 found
Loading history...
75
            throw  new \InvalidArgumentException('not set port');
76
        }
77
78 67
        if (!isset($connectParams['host'])) {
0 ignored issues
show
Expected 1 space(s) after NOT operator; 0 found
Loading history...
79
            throw  new \InvalidArgumentException('not set host');
80
        }
81
82 67
        $this->connectUsername = $connectParams['username'];
83 67
        $this->connectPassword = $connectParams['password'];
84 67
        $this->connectPort = $connectParams['port'];
0 ignored issues
show
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 67
        $this->connectHost = $connectParams['host'];
0 ignored issues
show
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 67
        $this->transport = new Http(
89 67
            $this->connectHost,
90 67
            $this->connectPort,
91 67
            $this->connectUsername,
92 67
            $this->connectPassword
93
        );
94
95 67
        $this->transport->addQueryDegeneration(new Bindings());
96
97
        // apply settings to transport class
98 67
        $this->settings()->database('default');
99 67
        if (!empty($settings)) {
0 ignored issues
show
Expected 1 space(s) after NOT operator; 0 found
Loading history...
100 1
            $this->settings()->apply($settings);
101
        }
102
103 67
        if (isset($connectParams['readonly'])) {
104
            $this->setReadOnlyUser($connectParams['readonly']);
105
        }
106
107 67
        if (isset($connectParams['https'])) {
108
            $this->https($connectParams['https']);
109
        }
110
111 67
        if (isset($connectParams['sslCA'])) {
112
            $this->transport->setSslCA($connectParams['sslCA']);
113
        }
114
115 67
        $this->enableHttpCompression();
116 67
    }
117
118
    /**
119
     * if the user has only read in the config file
120
     */
121
    public function setReadOnlyUser(bool $flag)
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()
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)
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()
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)
163
    {
164
        $this->connectHost = $host;
165
        $this->transport()->setHost($host);
166
    }
167
168
    /**
169
     * @return Settings
170
     */
171 2
    public function setTimeout(float $timeout)
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)
188
    {
189 2
        $this->transport()->setConnectTimeOut($connectTimeOut);
190 2
    }
191
192
    /**
193
     * @return int
194
     */
195 1
    public function getConnectTimeOut()
196
    {
197 1
        return $this->transport()->getConnectTimeOut();
198
    }
199
200
    /**
201
     * @return Http
202
     */
203 67
    public function transport()
204
    {
205 67
        if (!$this->transport) {
0 ignored issues
show
Expected 1 space(s) after NOT operator; 0 found
Loading history...
206
            throw  new \InvalidArgumentException('Empty transport class');
207
        }
208
209 67
        return $this->transport;
210
    }
211
212
    /**
213
     * @return string
214
     */
215
    public function getConnectHost()
216
    {
217
        return $this->connectHost;
218
    }
219
220
    /**
221
     * @return string
222
     */
223
    public function getConnectPassword()
224
    {
225
        return $this->connectPassword;
226
    }
227
228
    /**
229
     * @return string
230
     */
231
    public function getConnectPort()
232
    {
233
        return $this->connectPort;
234
    }
235
236
    /**
237
     * @return string
238
     */
239
    public function getConnectUsername()
240
    {
241
        return $this->connectUsername;
242
    }
243
244
    /**
245
     * @return Http
246
     */
247
    public function getTransport()
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 67
    public function settings()
264
    {
265 67
        return $this->transport()->settings();
266
    }
267
268
    /**
269
     * @param string|null $useSessionId
270
     * @return $this
271
     */
272 2
    public function useSession(string $useSessionId = null)
273
    {
274 2
        if (!$this->settings()->getSessionId()) {
0 ignored issues
show
Expected 1 space(s) after NOT operator; 0 found
Loading history...
275 2
            if (!$useSessionId) {
0 ignored issues
show
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
296
     * @return Statement
297
     */
298 26
    public function write(string $sql, array $bindings = [], bool $exception = true)
299
    {
300 26
        return $this->transport()->write($sql, $bindings, $exception);
301
    }
302
303
    /**
304
     * set db name
305
     * @return static
306
     */
307 67
    public function database(string $db)
308
    {
309 67
        $this->settings()->database($db);
310
311 67
        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
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 67
    public function enableHttpCompression(bool $flag = true)
332
    {
333 67
        $this->settings()->enableHttpCompression($flag);
334
335 67
        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
Expected 1 space(s) after cast statement; 0 found
Loading history...
358
359 2
        return $this;
360
    }
361
362
    /**
363
     * @param mixed[] $bindings
364
     * @return Statement
365
     */
366 31
    public function select(
367
        string $sql,
368
        array $bindings = [],
369
        WhereInFile $whereInFile = null,
370
        WriteToFile $writeToFile = null
371
    )
372
    {
0 ignored issues
show
The closing parenthesis and the opening brace of a multi-line function declaration must be on the same line
Loading history...
373 31
        return $this->transport()->select($sql, $bindings, $whereInFile, $writeToFile);
374
    }
375
376
    /**
377
     * @return bool
378
     */
379 10
    public function executeAsync()
380
    {
381 10
        return $this->transport()->executeAsync();
382
    }
383
384
    public function maxTimeExecutionAllAsync()
385
    {
386
387
    }
388
389
    /**
390
     * set progressFunction
391
     */
392 1
    public function progressFunction(callable $callback)
393
    {
394 1
        if (!is_callable($callback)) {
0 ignored issues
show
Expected 1 space(s) after NOT operator; 0 found
Loading history...
395
            throw new \InvalidArgumentException('Not is_callable progressFunction');
396
        }
397
398 1
        if (!$this->settings()->is('send_progress_in_http_headers')) {
0 ignored issues
show
Expected 1 space(s) after NOT operator; 0 found
Loading history...
399 1
            $this->settings()->set('send_progress_in_http_headers', 1);
400
        }
401 1
        if (!$this->settings()->is('http_headers_progress_interval_ms')) {
0 ignored issues
show
Expected 1 space(s) after NOT operator; 0 found
Loading history...
402 1
            $this->settings()->set('http_headers_progress_interval_ms', 100);
403
        }
404
405 1
        $this->transport()->setProgressFunction($callback);
406 1
    }
407
408
    /**
409
     * prepare select
410
     *
411
     * @param mixed[] $bindings
412
     * @return Statement
413
     */
414 7
    public function selectAsync(
415
        string $sql,
416
        array $bindings = [],
417
        WhereInFile $whereInFile = null,
418
        WriteToFile $writeToFile = null
419
    )
420
    {
0 ignored issues
show
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
428
     */
429
    public function showProcesslist()
430
    {
431
        return $this->select('SHOW PROCESSLIST')->rows();
432
    }
433
434
    /**
435
     * show databases
436
     *
437
     * @return array
438
     */
439
    public function showDatabases()
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()
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()
470
    {
471 12
        return $this->transport()->getCountPendingQueue();
472
    }
473
474
    /**
475
     * @param mixed[][] $values
476
     * @param string[] $columns
0 ignored issues
show
Expected 2 spaces after parameter type; 1 found
Loading history...
477
     * @return Statement
478
     * @throws Exception\TransportException
479
     */
480 9
    public function insert(string $table, array $values, array $columns = []): Statement
0 ignored issues
show
There must be exactly 1 whitespace between closing parenthesis and return type colon.
Loading history...
481
    {
482 9
        if (empty($values)) {
483 1
            throw QueryException::cannotInsertEmptyValues();
484
        }
485
486 8
        if (stripos($table, '`') === false && stripos($table, '.') === false) {
487 5
            $table = '`' . $table . '`'; //quote table name for dot names
488
        }
489 8
        $sql = 'INSERT INTO ' . $table;
490
491 8
        if (count($columns) !== 0) {
492 7
            $sql .= ' (`' . implode('`,`', $columns) . '`) ';
493
        }
494
495 8
        $sql .= ' VALUES ';
496
497 8
        foreach ($values as $row) {
498 8
            $sql .= ' (' . FormatLine::Insert($row) . '), ';
499
        }
500 8
        $sql = trim($sql, ', ');
501
502 8
        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)
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
544
     * @return Statement
545
     */
546
    public function insertAssocBulk(string $tableName, array $values)
547
    {
548
        list($columns, $vals) = $this->prepareInsertAssocBulk($values);
549
550
        return $this->insert($tableName, $vals, $columns);
551
    }
552
553
    /**
554
     * insert TabSeparated files
555
     *
556
     * @param string|string[] $fileNames
557
     * @param string[] $columns
0 ignored issues
show
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
569
     * @param string[] $columns
0 ignored issues
show
Expected 8 spaces after parameter type; 1 found
Loading history...
570
     * @param string $format ['TabSeparated','TabSeparatedWithNames','CSV','CSVWithNames']
0 ignored issues
show
Expected 10 spaces after parameter type; 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')
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
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
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
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
621
     * @param string $format ['TabSeparated','TabSeparatedWithNames','CSV','CSVWithNames']
0 ignored issues
show
Expected 3 spaces after parameter type; 1 found
Loading history...
622
     * @return Transport\CurlerRequest
623
     */
624 2
    public function insertBatchStream(string $tableName, array $columns = [], string $format = 'CSV')
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
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
647
     * @return Statement
648
     * @throws Exception\TransportException
649
     */
650 1
    public function streamWrite(Stream $stream, string $sql, array $bind = [])
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
663
     * @return Statement
664
     */
665 1
    public function streamRead(Stream $streamRead, string $sql, array $bind = [])
666
    {
667 1
        if ($this->getCountPendingQueue() > 0) {
668
            throw new QueryException('Queue must be empty, before streamWrite');
669
        }
670
671 1
        return $this->transport()->streamRead($streamRead, $sql, $bind);
672
    }
673
674
    /**
675
     * Size of database
676
     *
677
     * @return mixed|null
678
     */
679
    public function databaseSize()
680
    {
681
        $b = $this->settings()->getDatabase();
682
683
        return $this->select(
684
            '
685
            SELECT database,formatReadableSize(sum(bytes)) as size
686
            FROM system.parts
687
            WHERE active AND database=:database
688
            GROUP BY database
689
            ',
690
            ['database' => $b]
691
        )->fetchOne();
692
    }
693
694
    /**
695
     * Size of tables
696
     *
697
     * @return mixed
698
     */
699 1
    public function tableSize(string $tableName)
700
    {
701 1
        $tables = $this->tablesSize();
702
703 1
        if (isset($tables[$tableName])) {
704 1
            return $tables[$tableName];
705
        }
706
707
        return null;
708
    }
709
710
    /**
711
     * Ping server
712
     *
713
     * @return bool
714
     */
715 37
    public function ping()
716
    {
717 37
        return $this->transport()->ping();
718
    }
719
720
    /**
721
     * Tables sizes
722
     *
723
     * @param bool $flatList
724
     * @return mixed[][]
725
     */
726 1
    public function tablesSize($flatList = false)
727
    {
728 1
        $result = $this->select('
729
        SELECT name as table,database,
730
            max(sizebytes) as sizebytes,
731
            max(size) as size,
732
            min(min_date) as min_date,
733
            max(max_date) as max_date
734
            FROM system.tables
735
            ANY LEFT JOIN 
736
            (
737
            SELECT table,database,
738
                        formatReadableSize(sum(bytes)) as size,
739
                        sum(bytes) as sizebytes,
740
                        min(min_date) as min_date,
741
                        max(max_date) as max_date
742
                        FROM system.parts 
743
                        WHERE active AND database=:database
744
                        GROUP BY table,database
745
            ) USING ( table,database )
746
            WHERE database=:database
747
            GROUP BY table,database
748
        ',
749 1
            ['database' => $this->settings()->getDatabase()]);
750
751 1
        if ($flatList) {
752
            return $result->rows();
753
        }
754
755 1
        return $result->rowsAsTree('table');
756
    }
757
758
    /**
759
     * isExists
760
     *
761
     * @return array
762
     */
763
    public function isExists(string $database, string $table)
764
    {
765
        return $this->select(
766
            '
767
            SELECT *
768
            FROM system.tables 
769
            WHERE name=\'' . $table . '\' AND database=\'' . $database . '\''
770
        )->rowsAsTree('name');
771
    }
772
773
    /**
774
     * List of partitions
775
     *
776
     * @return mixed[][]
777
     */
778
    public function partitions(string $table, int $limit = null, bool $active = null)
779
    {
780
        $database = $this->settings()->getDatabase();
0 ignored issues
show
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...
781
        $whereActiveClause = $active === null ? '' : sprintf(' AND active = %s', (int)$active);
0 ignored issues
show
Expected 1 space(s) after cast statement; 0 found
Loading history...
782
        $limitClause = $limit !== null ? ' LIMIT ' . $limit : '';
0 ignored issues
show
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...
783
784
        return $this->select(<<<CLICKHOUSE
785
SELECT *
786
FROM system.parts 
787
WHERE like(table,'%$table%') AND database='$database'$whereActiveClause
788
ORDER BY max_date $limitClause
789
CLICKHOUSE
790
        )->rowsAsTree('name');
791
    }
792
793
    /**
794
     * dropPartition
795
     * @return Statement
0 ignored issues
show
Expected 1 lines between description and annotations, found 0.
Loading history...
Incorrect annotations group.
Loading history...
796
     * @deprecated
797
     */
798
    public function dropPartition(string $dataBaseTableName, string $partition_id)
799
    {
800
801
        $partition_id = trim($partition_id, '\'');
802
        $this->settings()->set('replication_alter_partitions_sync', 2);
803
        $state = $this->write('ALTER TABLE {dataBaseTableName} DROP PARTITION :partion_id',
804
            [
805
                'dataBaseTableName' => $dataBaseTableName,
806
                'partion_id' => $partition_id,
807
            ]);
808
809
        return $state;
810
    }
811
812
    /**
813
     * Truncate ( drop all partitions )
814
     * @return array
0 ignored issues
show
Expected 1 lines between description and annotations, found 0.
Loading history...
Incorrect annotations group.
Loading history...
@return annotation of method \ClickHouseDB\Client::truncateTable() does not specify type hint for items of its traversable return value.
Loading history...
815
     * @deprecated
816
     */
817
    public function truncateTable(string $tableName)
818
    {
819
        $partions = $this->partitions($tableName);
820
        $out = [];
0 ignored issues
show
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...
821
        foreach ($partions as $part_key => $part) {
822
            $part_id = $part['partition'];
0 ignored issues
show
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...
823
            $out[$part_id] = $this->dropPartition($tableName, $part_id);
824
        }
825
826
        return $out;
827
    }
828
829
    /**
830
     * Returns the server's uptime in seconds.
831
     *
832
     * @return int
833
     * @throws Exception\TransportException
834
     */
835 1
    public function getServerUptime()
836
    {
837 1
        return $this->select('SELECT uptime() as uptime')->fetchOne('uptime');
838
    }
839
840
    /**
841
     * Returns string with the server version.
842
     */
843 1
    public function getServerVersion(): string
0 ignored issues
show
There must be exactly 1 whitespace between closing parenthesis and return type colon.
Loading history...
844
    {
845 1
        return (string)$this->select('SELECT version() as version')->fetchOne('version');
0 ignored issues
show
Expected 1 space(s) after cast statement; 0 found
Loading history...
846
    }
847
848
    /**
849
     * Read system.settings table
850
     *
851
     * @return mixed[][]
852
     */
853 1
    public function getServerSystemSettings(string $like = '')
854
    {
855 1
        $l = [];
0 ignored issues
show
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...
856 1
        $list = $this->select('SELECT * FROM system.settings' . ($like ? ' WHERE name LIKE :like' : ''),
857 1
            ['like' => '%' . $like . '%'])->rows();
858 1
        foreach ($list as $row) {
859 1
            if (isset($row['name'])) {
860 1
                $n = $row['name'];
861 1
                unset($row['name']);
862 1
                $l[$n] = $row;
863
            }
864
        }
865
866 1
        return $l;
867
    }
868
869
    /**
870
     * dropOldPartitions by day_ago
871
     * @return array
0 ignored issues
show
Expected 1 lines between description and annotations, found 0.
Loading history...
Incorrect annotations group.
Loading history...
@return annotation of method \ClickHouseDB\Client::dropOldPartitions() does not specify type hint for items of its traversable return value.
Loading history...
872
     * @throws Exception\TransportException
873
     * @throws \Exception
874
     * @deprecated
0 ignored issues
show
Expected 0 lines after last content, found 1.
Loading history...
875
     *
876
     */
877
    public function dropOldPartitions(string $table_name, int $days_ago, int $count_partitons_per_one = 100)
878
    {
879
        $days_ago = strtotime(date('Y-m-d 00:00:00', strtotime('-' . $days_ago . ' day')));
880
881
        $drop = [];
0 ignored issues
show
Equals sign not aligned with surrounding assignments; expected 11 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...
882
        $list_patitions = $this->partitions($table_name, $count_partitons_per_one);
883
884
        foreach ($list_patitions as $partion_id => $partition) {
885
            if (stripos($partition['engine'], 'mergetree') === false) {
886
                continue;
887
            }
888
889
            // $min_date = strtotime($partition['min_date']);
890
            $max_date = strtotime($partition['max_date']);
891
892
            if ($max_date < $days_ago) {
893
                $drop[] = $partition['partition'];
894
            }
895
        }
896
897
        $result = [];
898
        foreach ($drop as $partition_id) {
899
            $result[$partition_id] = $this->dropPartition($table_name, $partition_id);
900
        }
901
902
        return $result;
903
    }
904
}
905