Passed
Push — master ( e718b7...0c5c50 )
by Def
32:40 queued 28:42
created

DDLQueryBuilder::getColumnDefinition()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5.025

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 9
c 1
b 0
f 0
dl 0
loc 19
ccs 9
cts 10
cp 0.9
rs 9.6111
cc 5
nc 3
nop 2
crap 5.025
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Mysql;
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\AbstractDDLQueryBuilder;
12
use Yiisoft\Db\QueryBuilder\QueryBuilderInterface;
13
use Yiisoft\Db\Schema\QuoterInterface;
14
use Yiisoft\Db\Schema\SchemaInterface;
15
16
use function preg_match;
17
use function preg_replace;
18
use function trim;
19
20
final class DDLQueryBuilder extends AbstractDDLQueryBuilder
21
{
22 498
    public function __construct(
23
        private QueryBuilderInterface $queryBuilder,
24
        private QuoterInterface $quoter,
25
        private SchemaInterface $schema
26
    ) {
27 498
        parent::__construct($queryBuilder, $quoter, $schema);
28
    }
29
30
    /**
31
     * @throws NotSupportedException
32
     */
33 2
    public function addCheck(string $name, string $table, string $expression): string
34
    {
35 2
        throw new NotSupportedException(__METHOD__ . ' is not supported by MySQL.');
36
    }
37
38
    /**
39
     * @throws Exception|Throwable
40
     */
41 5
    public function addCommentOnColumn(string $table, string $column, string $comment): string
42
    {
43
        /* Strip existing comment which may include escaped quotes */
44 5
        $definition = trim(
45 5
            preg_replace(
46 5
                "/COMMENT '(?:''|[^'])*'/i",
47 5
                '',
48 5
                $this->getColumnDefinition($table, $column)
49 5
            )
50 5
        );
51
52 5
        $checkRegex = '/CHECK *(\(([^()]|(?-2))*\))/';
53 5
        $check = preg_match($checkRegex, $definition, $checkMatches);
54
55 5
        if ($check === 1) {
56
            $definition = preg_replace($checkRegex, '', $definition);
57
        }
58
59 5
        $alterSql = 'ALTER TABLE '
60 5
            . $this->quoter->quoteTableName($table)
61 5
            . ' CHANGE '
62 5
            . $this->quoter->quoteColumnName($column)
63 5
            . ' '
64 5
            . $this->quoter->quoteColumnName($column)
65 5
            . (empty($definition) ? '' : ' ' . $definition)
66 5
            . ' COMMENT '
67 5
            . (string) $this->quoter->quoteValue($comment);
68
69 5
        if ($check === 1) {
70
            $alterSql .= ' ' . $checkMatches[0];
71
        }
72
73 5
        return $alterSql;
74
    }
75
76
    /**
77
     * @throws \Exception
78
     */
79 4
    public function addCommentOnTable(string $table, string $comment): string
80
    {
81 4
        return 'ALTER TABLE '
82 4
            . $this->quoter->quoteTableName($table)
83 4
            . ' COMMENT '
84 4
            . (string) $this->quoter->quoteValue($comment);
85
    }
86
87
    /**
88
     * @throws NotSupportedException
89
     */
90 2
    public function addDefaultValue(string $name, string $table, string $column, mixed $value): string
91
    {
92 2
        throw new NotSupportedException(__METHOD__ . ' is not supported by MySQL.');
93
    }
94
95
    /**
96
     * @throws Exception
97
     * @throws InvalidArgumentException
98
     */
99 10
    public function createIndex(
100
        string $name,
101
        string $table,
102
        array|string $columns,
103
        string $indexType = null,
104
        string $indexMethod = null
105
    ): string {
106 10
        return 'CREATE ' . ($indexType ? ($indexType . ' ') : '') . 'INDEX '
107 10
            . $this->quoter->quoteTableName($name)
108 10
            . ($indexMethod !== null ? " USING $indexMethod" : '')
109 10
            . ' ON ' . $this->quoter->quoteTableName($table)
110 10
            . ' (' . $this->queryBuilder->buildColumns($columns) . ')';
111
    }
112
113 1
    public function checkIntegrity(string $schema = '', string $table = '', bool $check = true): string
114
    {
115 1
        return 'SET FOREIGN_KEY_CHECKS = ' . ($check ? 1 : 0);
116
    }
117
118
    /**
119
     * @throws NotSupportedException
120
     */
121 1
    public function dropCheck(string $name, string $table): string
122
    {
123 1
        throw new NotSupportedException(__METHOD__ . ' is not supported by MySQL.');
124
    }
125
126
    /**
127
     * @throws Exception|Throwable
128
     */
129 2
    public function dropCommentFromColumn(string $table, string $column): string
130
    {
131 2
        return $this->addCommentOnColumn($table, $column, '');
132
    }
133
134
    /**
135
     * @throws \Exception
136
     */
137 2
    public function dropCommentFromTable(string $table): string
138
    {
139 2
        return $this->addCommentOnTable($table, '');
140
    }
141
142
    /**
143
     * @throws NotSupportedException
144
     */
145 1
    public function dropDefaultValue(string $name, string $table): string
146
    {
147 1
        throw new NotSupportedException(__METHOD__ . ' is not supported by MySQL.');
148
    }
149
150 2
    public function dropForeignKey(string $name, string $table): string
151
    {
152 2
        return 'ALTER TABLE '
153 2
            . $this->quoter->quoteTableName($table)
154 2
            . ' DROP FOREIGN KEY '
155 2
            . $this->quoter->quoteColumnName($name);
156
    }
157
158 3
    public function dropPrimaryKey(string $name, string $table): string
159
    {
160 3
        return 'ALTER TABLE ' . $this->quoter->quoteTableName($table) . ' DROP PRIMARY KEY';
161
    }
162
163 3
    public function dropUnique(string $name, string $table): string
164
    {
165 3
        return $this->dropIndex($name, $table);
166
    }
167
168
    /**
169
     * @throws Exception
170
     * @throws Throwable
171
     */
172 2
    public function renameColumn(string $table, string $oldName, string $newName): string
173
    {
174 2
        $quotedTable = $this->quoter->quoteTableName($table);
175
176 2
        $columnDefinition = $this->getColumnDefinition($table, $oldName);
177
178
        /* try to give back a SQL anyway */
179 2
        return "ALTER TABLE $quotedTable CHANGE "
180 2
            . $this->quoter->quoteColumnName($oldName) . ' '
181 2
            . $this->quoter->quoteColumnName($newName)
182 2
            . (!empty($columnDefinition) ? ' ' . $columnDefinition : '');
183
    }
184
185
    /**
186
     * Gets column definition.
187
     *
188
     * @param string $table table name.
189
     * @param string $column column name.
190
     *
191
     * @throws Throwable in case when table does not contain column.
192
     *
193
     * @return string the column definition.
194
     */
195 7
    public function getColumnDefinition(string $table, string $column): string
196
    {
197 7
        $result = '';
198
199 7
        $sql = $this->schema->getTableSchema($table)?->getCreateSql();
200
201 7
        if (empty($sql)) {
202
            return '';
203
        }
204
205 7
        if (preg_match_all('/^\s*`(.*?)`\s+(.*?),?$/m', $sql, $matches)) {
206 7
            foreach ($matches[1] as $i => $c) {
207 7
                if ($c === $column) {
208 7
                    $result = $matches[2][$i];
209
                }
210
            }
211
        }
212
213 7
        return $result;
214
    }
215
}
216