Passed
Pull Request — master (#319)
by Sergei
04:01
created

DDLQueryBuilder   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 170
Duplicated Lines 0 %

Test Coverage

Coverage 97.26%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 24
eloc 56
c 2
b 0
f 0
dl 0
loc 170
ccs 71
cts 73
cp 0.9726
rs 10

15 Methods

Rating   Name   Duplication   Size   Complexity  
A dropUnique() 0 3 1
A dropPrimaryKey() 0 3 1
A dropCommentFromTable() 0 3 1
A createIndex() 0 12 3
A dropDefaultValue() 0 3 1
A addCommentOnTable() 0 6 1
A addCheck() 0 3 1
A addCommentOnColumn() 0 33 4
A getColumnDefinition() 0 15 3
A addDefaultValue() 0 3 1
A dropForeignKey() 0 6 1
A dropCommentFromColumn() 0 3 1
A checkIntegrity() 0 3 2
A dropCheck() 0 3 1
A renameColumn() 0 11 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Mysql;
6
7
use InvalidArgumentException;
8
use Throwable;
9
use Yiisoft\Db\Exception\Exception;
10
use Yiisoft\Db\Exception\NotSupportedException;
11
use Yiisoft\Db\QueryBuilder\AbstractDDLQueryBuilder;
12
13
use function preg_match;
14
use function preg_quote;
15
use function preg_replace;
16
use function trim;
17
18
/**
19
 * Implements a (Data Definition Language) SQL statements for MySQL, MariaDB.
20
 */
21
final class DDLQueryBuilder extends AbstractDDLQueryBuilder
22
{
23
    /**
24
     * @throws NotSupportedException
25
     */
26 2
    public function addCheck(string $table, string $name, string $expression): string
27
    {
28 2
        throw new NotSupportedException(__METHOD__ . ' is not supported by MySQL.');
29
    }
30
31
    /**
32
     * @throws Throwable
33
     */
34 5
    public function addCommentOnColumn(string $table, string $column, string $comment): string
35
    {
36
        /* Strip existing comment which may include escaped quotes */
37 5
        $definition = trim(
38 5
            preg_replace(
39 5
                "/COMMENT '(?:''|[^'])*'/i",
40 5
                '',
41 5
                $this->getColumnDefinition($table, $column)
42 5
            )
43 5
        );
44
45 5
        $checkRegex = '/CHECK *(\(([^()]|(?-2))*\))/';
46 5
        $check = preg_match($checkRegex, $definition, $checkMatches);
47
48 5
        if ($check === 1) {
49
            $definition = preg_replace($checkRegex, '', $definition);
50
        }
51
52 5
        $alterSql = 'ALTER TABLE '
53 5
            . $this->quoter->quoteTableName($table)
54 5
            . ' CHANGE '
55 5
            . $this->quoter->quoteColumnName($column)
56 5
            . ' '
57 5
            . $this->quoter->quoteColumnName($column)
58 5
            . (empty($definition) ? '' : ' ' . $definition)
59 5
            . ' COMMENT '
60 5
            . (string) $this->quoter->quoteValue($comment);
61
62 5
        if ($check === 1) {
63
            $alterSql .= ' ' . $checkMatches[0];
64
        }
65
66 5
        return $alterSql;
67
    }
68
69 4
    public function addCommentOnTable(string $table, string $comment): string
70
    {
71 4
        return 'ALTER TABLE '
72 4
            . $this->quoter->quoteTableName($table)
73 4
            . ' COMMENT '
74 4
            . (string) $this->quoter->quoteValue($comment);
75
    }
76
77 2
    public function addDefaultValue(string $table, string $name, string $column, mixed $value): string
78
    {
79 2
        throw new NotSupportedException(__METHOD__ . ' is not supported by MySQL.');
80
    }
81
82 10
    public function createIndex(
83
        string $table,
84
        string $name,
85
        array|string $columns,
86
        string $indexType = null,
87
        string $indexMethod = null
88
    ): string {
89 10
        return 'CREATE ' . (!empty($indexType) ? $indexType . ' ' : '') . 'INDEX '
90 10
            . $this->quoter->quoteTableName($name)
91 10
            . (!empty($indexMethod) ? " USING $indexMethod" : '')
92 10
            . ' ON ' . $this->quoter->quoteTableName($table)
93 10
            . ' (' . $this->queryBuilder->buildColumns($columns) . ')';
94
    }
95
96 1
    public function checkIntegrity(string $schema = '', string $table = '', bool $check = true): string
97
    {
98 1
        return 'SET FOREIGN_KEY_CHECKS = ' . ($check ? 1 : 0);
99
    }
100
101
    /**
102
     * @throws NotSupportedException
103
     */
104 1
    public function dropCheck(string $table, string $name): string
105
    {
106 1
        throw new NotSupportedException(__METHOD__ . ' is not supported by MySQL.');
107
    }
108
109
    /**
110
     * @throws Exception
111
     * @throws Throwable
112
     */
113 2
    public function dropCommentFromColumn(string $table, string $column): string
114
    {
115 2
        return $this->addCommentOnColumn($table, $column, '');
116
    }
117
118
    /**
119
     * @throws \Exception
120
     */
121 2
    public function dropCommentFromTable(string $table): string
122
    {
123 2
        return $this->addCommentOnTable($table, '');
124
    }
125
126 1
    public function dropDefaultValue(string $table, string $name): string
127
    {
128 1
        throw new NotSupportedException(__METHOD__ . ' is not supported by MySQL.');
129
    }
130
131 2
    public function dropForeignKey(string $table, string $name): string
132
    {
133 2
        return 'ALTER TABLE '
134 2
            . $this->quoter->quoteTableName($table)
135 2
            . ' DROP FOREIGN KEY '
136 2
            . $this->quoter->quoteColumnName($name);
137
    }
138
139 3
    public function dropPrimaryKey(string $table, string $name): string
140
    {
141 3
        return 'ALTER TABLE ' . $this->quoter->quoteTableName($table) . ' DROP PRIMARY KEY';
142
    }
143
144 3
    public function dropUnique(string $table, string $name): string
145
    {
146 3
        return $this->dropIndex($table, $name);
147
    }
148
149
    /**
150
     * @throws Exception
151
     * @throws Throwable
152
     */
153 4
    public function renameColumn(string $table, string $oldName, string $newName): string
154
    {
155 4
        $quotedTable = $this->quoter->quoteTableName($table);
156
157 4
        $columnDefinition = $this->getColumnDefinition($table, $oldName);
158
159
        /* try to give back an SQL anyway */
160 2
        return "ALTER TABLE $quotedTable CHANGE "
161 2
            . $this->quoter->quoteColumnName($oldName) . ' '
162 2
            . $this->quoter->quoteColumnName($newName)
163 2
            . (!empty($columnDefinition) ? ' ' . $columnDefinition : '');
164
    }
165
166
    /**
167
     * Gets column definition.
168
     *
169
     * @param string $table The table name.
170
     * @param string $column The column name.
171
     *
172
     * @throws Throwable In case when table doesn't contain a column.
173
     *
174
     * @return string The column definition.
175
     */
176 9
    public function getColumnDefinition(string $table, string $column): string
177
    {
178 9
        $sql = $this->schema->getTableSchema($table)?->getCreateSql();
179
180 9
        if (empty($sql)) {
181 1
            throw new InvalidArgumentException("Table \"$table\" does not exist.");
182
        }
183
184 8
        $quotedColumn = preg_quote($column, '/');
185
186 8
        if (preg_match("/^\s*([`\"])$quotedColumn\\1\s+(.*?),?$/m", $sql, $matches) !== 1) {
187 1
            throw new InvalidArgumentException("Column \"$column\" does not exist in table \"$table\".");
188
        }
189
190 7
        return $matches[2];
191
    }
192
}
193