Passed
Pull Request — dev (#128)
by Def
38:26 queued 25:50
created

DDLQueryBuilder::truncateTable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

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