Test Failed
Push — remove-test-query-builder-trai... ( 73573f...54249c )
by Wilmer
21:16 queued 18:04
created

DDLQueryBuilder::truncateTable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
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\NotSupportedException;
11
use Yiisoft\Db\QueryBuilder\DDLQueryBuilder as AbstractDDLQueryBuilder;
12
use Yiisoft\Db\QueryBuilder\QueryBuilderInterface;
13
use Yiisoft\Db\Schema\ColumnSchemaBuilder;
14
use Yiisoft\Db\Schema\QuoterInterface;
15
use Yiisoft\Db\Schema\SchemaInterface;
16
17
use function array_diff;
18
use function array_unshift;
19
use function explode;
20
use function implode;
21
use function preg_match;
22
use function preg_replace;
23
use function str_contains;
24
25
final class DDLQueryBuilder extends AbstractDDLQueryBuilder
26
{
27
    public function __construct(
28
        private QueryBuilderInterface $queryBuilder,
29
        private QuoterInterface $quoter,
30
        private SchemaInterface $schema
31
    ) {
32
        parent::__construct($queryBuilder, $quoter, $schema);
33
    }
34
35
    /**
36
     * @throws NotSupportedException
37
     */
38
    public function addDefaultValue(string $name, string $table, string $column, mixed $value): string
39
    {
40
        throw new NotSupportedException(__METHOD__ . ' is not supported by PostgreSQL.');
41
    }
42
43
    public function alterColumn(string $table, string $column, ColumnSchemaBuilder|string $type): string
44
    {
45
        $columnName = $this->quoter->quoteColumnName($column);
46
        $tableName = $this->quoter->quoteTableName($table);
47
48
        /**
49
         * {@see https://github.com/yiisoft/yii2/issues/4492}
50
         * {@see http://www.postgresql.org/docs/9.1/static/sql-altertable.html}
51
         */
52
        if (preg_match('/^(DROP|SET|RESET|USING)\s+/i', (string) $type)) {
53
            return "ALTER TABLE $tableName ALTER COLUMN $columnName $type";
54
        }
55
56
        $type = 'TYPE ' . $this->queryBuilder->getColumnType($type);
57
        $multiAlterStatement = [];
58
        $constraintPrefix = preg_replace('/[^a-z0-9_]/i', '', $table . '_' . $column);
59
60
        if (preg_match('/\s+DEFAULT\s+(["\']?\w*["\']?)/i', $type, $matches)) {
61
            $type = preg_replace('/\s+DEFAULT\s+(["\']?\w*["\']?)/i', '', $type);
62
            $multiAlterStatement[] = "ALTER COLUMN $columnName SET DEFAULT $matches[1]";
63
        }
64
65
        $type = preg_replace('/\s+NOT\s+NULL/i', '', $type, -1, $count);
66
67
        if ($count) {
68
            $multiAlterStatement[] = "ALTER COLUMN $columnName SET NOT NULL";
69
        } else {
70
            /** remove additional null if any */
71
            $type = preg_replace('/\s+NULL/i', '', $type, -1, $count);
72
            if ($count) {
73
                $multiAlterStatement[] = "ALTER COLUMN $columnName DROP NOT NULL";
74
            }
75
        }
76
77
        if (preg_match('/\s+CHECK\s+\((.+)\)/i', $type, $matches)) {
78
            $type = preg_replace('/\s+CHECK\s+\((.+)\)/i', '', $type);
79
            $multiAlterStatement[] = "ADD CONSTRAINT {$constraintPrefix}_check CHECK ($matches[1])";
80
        }
81
82
        $type = preg_replace('/\s+UNIQUE/i', '', $type, -1, $count);
83
84
        if ($count) {
85
            $multiAlterStatement[] = "ADD UNIQUE ($columnName)";
86
        }
87
88
        /** add what's left at the beginning */
89
        array_unshift($multiAlterStatement, "ALTER COLUMN $columnName $type");
90
91
        return 'ALTER TABLE ' . $tableName . ' ' . implode(', ', $multiAlterStatement);
92
    }
93
94
    /**
95
     * @throws Exception|NotSupportedException|Throwable
96
     */
97
    public function checkIntegrity(string $schema = '', string $table = '', bool $check = true): string
98
    {
99
        /** @var Schema $schemaInstance */
100
        $schemaInstance = $this->schema;
101
        $enable = $check ? 'ENABLE' : 'DISABLE';
102
        $schema = $schema ?: $schemaInstance->getDefaultSchema();
103
        $tableNames = [];
104
        $viewNames = [];
105
106
        if ($schema !== null) {
107
            $tableNames = $table ? [$table] : $schemaInstance->getTableNames($schema);
108
            $viewNames = $schemaInstance->getViewNames($schema);
109
        }
110
111
        $tableNames = array_diff($tableNames, $viewNames);
112
        $command = '';
113
114
        /** @psalm-var string[] $tableNames */
115
        foreach ($tableNames as $tableName) {
116
            $tableName = $this->quoter->quoteTableName("$schema.$tableName");
117
            $command .= "ALTER TABLE $tableName $enable TRIGGER ALL; ";
118
        }
119
120
        /** enable to have ability to alter several tables */
121
        //$pdo = $db->getSlavePdo();
122
        //$pdo?->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
123
124
        return $command;
125
    }
126
127
    /**
128
     * @throws Exception|InvalidArgumentException
129
     */
130
    public function createIndex(string $name, string $table, array|string $columns, ?string $indexType = null, ?string $indexMethod = null): string
131
    {
132
        return 'CREATE ' . ($indexType ? ($indexType . ' ') : '') . 'INDEX '
133
            . $this->quoter->quoteTableName($name) . ' ON '
134
            . $this->quoter->quoteTableName($table)
135
            . ($indexMethod !== null ? " USING $indexMethod" : '')
136
            . ' (' . $this->queryBuilder->buildColumns($columns) . ')';
137
    }
138
139
    /**
140
     * @throws NotSupportedException
141
     */
142
    public function dropDefaultValue(string $name, string $table): string
143
    {
144
        throw new NotSupportedException(__METHOD__ . ' is not supported by PostgreSQL.');
145
    }
146
147
    public function dropIndex(string $name, string $table): string
148
    {
149
        if (str_contains($table, '.') && !str_contains($name, '.')) {
150
            if (str_contains($table, '{{')) {
151
                $table = preg_replace('/{{(.*?)}}/', '\1', $table);
152
                [$schema] = explode('.', $table);
153
                if (!str_contains($schema, '%')) {
154
                    $name = $schema . '.' . $name;
155
                } else {
156
                    $name = '{{' . $schema . '.' . $name . '}}';
157
                }
158
            } else {
159
                [$schema] = explode('.', $table);
160
                $name = $schema . '.' . $name;
161
            }
162
        }
163
164
        return 'DROP INDEX ' . $this->quoter->quoteTableName($name);
165
    }
166
167
    public function truncateTable(string $table): string
168
    {
169
        return 'TRUNCATE TABLE ' . $this->quoter->quoteTableName($table) . ' RESTART IDENTITY';
170
    }
171
172
    public function renameTable(string $oldName, string $newName): string
173
    {
174
        return 'ALTER TABLE '
175
            . $this->quoter->quoteTableName($oldName)
176
            . ' RENAME TO '
177
            . $this->quoter->quoteTableName($newName);
178
    }
179
}
180