Passed
Branch dev (d14b82)
by Wilmer
12:57
created

DDLQueryBuilder   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Test Coverage

Coverage 97.1%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 69
c 1
b 0
f 0
dl 0
loc 141
ccs 67
cts 69
cp 0.971
rs 10
wmc 26

7 Methods

Rating   Name   Duplication   Size   Complexity  
B alterColumn() 0 49 7
A createIndex() 0 15 5
A truncateTable() 0 3 1
A __construct() 0 3 1
A checkIntegrity() 0 27 6
A dropIndex() 0 18 5
A renameTable() 0 6 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Pgsql;
6
7
use Throwable;
8
use Yiisoft\Db\Exception\Exception;
9
use Yiisoft\Db\Exception\InvalidArgumentException;
10
use Yiisoft\Db\Exception\InvalidConfigException;
11
use Yiisoft\Db\Exception\NotSupportedException;
12
use Yiisoft\Db\Pgsql\PDO\SchemaPDOPgsql;
13
use Yiisoft\Db\Query\DDLQueryBuilder as AbstractDDLQueryBuilder;
14
use Yiisoft\Db\Query\QueryBuilderInterface;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Query\QueryBuilderInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
16
final class DDLQueryBuilder extends AbstractDDLQueryBuilder
17
{
18 401
    public function __construct(private QueryBuilderInterface $queryBuilder)
19
    {
20 401
        parent::__construct($queryBuilder);
21
    }
22
23 2
    public function alterColumn(string $table, string $column, $type): string
24
    {
25 2
        $columnName = $this->queryBuilder->quoter()->quoteColumnName($column);
26 2
        $tableName = $this->queryBuilder->quoter()->quoteTableName($table);
27
28
        /**
29
         * {@see https://github.com/yiisoft/yii2/issues/4492}
30
         * {@see http://www.postgresql.org/docs/9.1/static/sql-altertable.html}
31
         */
32 2
        if (preg_match('/^(DROP|SET|RESET|USING)\s+/i', (string) $type)) {
33 1
            return "ALTER TABLE $tableName ALTER COLUMN $columnName $type";
34
        }
35
36 2
        $type = 'TYPE ' . $this->queryBuilder->getColumnType($type);
37 2
        $multiAlterStatement = [];
38 2
        $constraintPrefix = preg_replace('/[^a-z0-9_]/i', '', $table . '_' . $column);
39
40 2
        if (preg_match('/\s+DEFAULT\s+(["\']?\w*["\']?)/i', $type, $matches)) {
41 1
            $type = preg_replace('/\s+DEFAULT\s+(["\']?\w*["\']?)/i', '', $type);
42 1
            $multiAlterStatement[] = "ALTER COLUMN $columnName SET DEFAULT $matches[1]";
43
        }
44
45 2
        $type = preg_replace('/\s+NOT\s+NULL/i', '', $type, -1, $count);
46
47 2
        if ($count) {
48 1
            $multiAlterStatement[] = "ALTER COLUMN $columnName SET NOT NULL";
49
        } else {
50
            /** remove additional null if any */
51 2
            $type = preg_replace('/\s+NULL/i', '', $type, -1, $count);
52 2
            if ($count) {
53 1
                $multiAlterStatement[] = "ALTER COLUMN $columnName DROP NOT NULL";
54
            }
55
        }
56
57 2
        if (preg_match('/\s+CHECK\s+\((.+)\)/i', $type, $matches)) {
58 1
            $type = preg_replace('/\s+CHECK\s+\((.+)\)/i', '', $type);
59 1
            $multiAlterStatement[] = "ADD CONSTRAINT {$constraintPrefix}_check CHECK ($matches[1])";
60
        }
61
62 2
        $type = preg_replace('/\s+UNIQUE/i', '', $type, -1, $count);
63
64 2
        if ($count) {
65 1
            $multiAlterStatement[] = "ADD UNIQUE ($columnName)";
66
        }
67
68
        /** add what's left at the beginning */
69 2
        array_unshift($multiAlterStatement, "ALTER COLUMN $columnName $type");
70
71 2
        return 'ALTER TABLE ' . $tableName . ' ' . implode(', ', $multiAlterStatement);
72
    }
73
74
    /**
75
     * @throws Exception|InvalidConfigException|NotSupportedException|Throwable
76
     */
77 1
    public function checkIntegrity(string $schema = '', string $table = '', bool $check = true): string
78
    {
79
        /** @var SchemaPDOPgsql */
80 1
        $schemaInstance = $this->queryBuilder->schema();
81 1
        $enable = $check ? 'ENABLE' : 'DISABLE';
82 1
        $schema = $schema ?: $schemaInstance->getDefaultSchema();
83 1
        $tableNames = [];
84 1
        $viewNames = [];
85
86 1
        if ($schema !== null) {
87 1
            $tableNames = $table ? [$table] : $schemaInstance->getTableNames($schema);
88 1
            $viewNames = $schemaInstance->getViewNames($schema);
89
        }
90
91 1
        $tableNames = array_diff($tableNames, $viewNames);
92 1
        $command = '';
93
94 1
        foreach ($tableNames as $tableName) {
95 1
            $tableName = $this->queryBuilder->quoter()->quoteTableName("$schema.$tableName");
96 1
            $command .= "ALTER TABLE $tableName $enable TRIGGER ALL; ";
97
        }
98
99
        /** enable to have ability to alter several tables */
100
        //$pdo = $db->getSlavePdo();
101
        //$pdo?->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
102
103 1
        return $command;
104
    }
105
106
    /**
107
     * @throws Exception|InvalidArgumentException
108
     */
109 6
    public function createIndex(string $name, string $table, array|string $columns, $unique = false): string
110
    {
111 6
        if ($unique === $this->queryBuilder::INDEX_UNIQUE || $unique === true) {
112 4
            $index = false;
113 4
            $unique = true;
114
        } else {
115 3
            $index = $unique;
116 3
            $unique = false;
117
        }
118
119 6
        return ($unique ? 'CREATE UNIQUE INDEX ' : 'CREATE INDEX ')
120 6
            . $this->queryBuilder->quoter()->quoteTableName($name) . ' ON '
121 6
            . $this->queryBuilder->quoter()->quoteTableName($table)
122 6
            . ($index !== false ? " USING $index" : '')
123 6
            . ' (' . $this->queryBuilder->buildColumns($columns) . ')';
124
    }
125
126 3
    public function dropIndex(string $name, string $table): string
127
    {
128 3
        if (str_contains($table, '.') && !str_contains($name, '.')) {
129 1
            if (str_contains($table, '{{')) {
130 1
                $table = preg_replace('/{{(.*?)}}/', '\1', $table);
131 1
                [$schema, $table] = explode('.', $table);
132 1
                if (!str_contains($schema, '%')) {
133 1
                    $name = $schema . '.' . $name;
134
                } else {
135 1
                    $name = '{{' . $schema . '.' . $name . '}}';
136
                }
137
            } else {
138
                [$schema] = explode('.', $table);
139
                $name = $schema . '.' . $name;
140
            }
141
        }
142
143 3
        return 'DROP INDEX ' . $this->queryBuilder->quoter()->quoteTableName($name);
144
    }
145
146 2
    public function renameTable(string $oldName, string $newName): string
147
    {
148
        return 'ALTER TABLE '
149 2
            . $this->queryBuilder->quoter()->quoteTableName($oldName)
150
            . ' RENAME TO '
151 2
            . $this->queryBuilder->quoter()->quoteTableName($newName);
152
    }
153
154 1
    public function truncateTable(string $table): string
155
    {
156 1
        return 'TRUNCATE TABLE ' . $this->queryBuilder->quoter()->quoteTableName($table) . ' RESTART IDENTITY';
157
    }
158
}
159