Passed
Branch dev (c92037)
by Wilmer
05:05 queued 02:25
created

DDLQueryBuilder::dropCommentFromTable()   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 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Mysql;
6
7
use Throwable;
8
use Yiisoft\Db\Command\CommandInterface;
9
use Yiisoft\Db\Exception\Exception;
10
use Yiisoft\Db\Exception\InvalidArgumentException;
11
use Yiisoft\Db\Exception\NotSupportedException;
12
use Yiisoft\Db\Query\DDLQueryBuilder as AbstractDDLQueryBuilder;
13
use Yiisoft\Db\Query\QueryBuilderInterface;
14
use Yiisoft\Db\Schema\QuoterInterface;
15
use Yiisoft\Db\Schema\SchemaInterface;
16
17
use function array_values;
18
use function preg_match;
19
use function preg_replace;
20
use function trim;
21
22
final class DDLQueryBuilder extends AbstractDDLQueryBuilder
23
{
24 355
    public function __construct(
25
        private CommandInterface $command,
26
        private QueryBuilderInterface $queryBuilder,
27
        private QuoterInterface $quoter,
28
        SchemaInterface $schema
29
    ) {
30 355
        parent::__construct($queryBuilder, $quoter, $schema);
31
    }
32
33
    /**
34
     * @throws NotSupportedException
35
     */
36 1
    public function addCheck(string $name, string $table, string $expression): string
37
    {
38 1
        throw new NotSupportedException(__METHOD__ . ' is not supported by MySQL.');
39
    }
40
41
    /**
42
     * @throws Exception|Throwable
43
     */
44 1
    public function addCommentOnColumn(string $table, string $column, string $comment): string
45
    {
46
        /* Strip existing comment which may include escaped quotes */
47 1
        $definition = trim(
48 1
            preg_replace(
49
                "/COMMENT '(?:''|[^'])*'/i",
50
                '',
51 1
                $this->getColumnDefinition($table, $column)
52
            )
53
        );
54
55 1
        $checkRegex = '/CHECK *(\(([^()]|(?-2))*\))/';
56 1
        $check = preg_match($checkRegex, $definition, $checkMatches);
57
58 1
        if ($check === 1) {
59
            $definition = preg_replace($checkRegex, '', $definition);
60
        }
61
62 1
        $alterSql = 'ALTER TABLE '
63 1
            . $this->quoter->quoteTableName($table)
64
            . ' CHANGE '
65 1
            . $this->quoter->quoteColumnName($column)
66
            . ' '
67 1
            . $this->quoter->quoteColumnName($column)
68 1
            . (empty($definition) ? '' : ' ' . $definition)
69
            . ' COMMENT '
70 1
            . (string) $this->quoter->quoteValue($comment);
71
72 1
        if ($check === 1) {
73
            $alterSql .= ' ' . $checkMatches[0];
74
        }
75
76 1
        return $alterSql;
77
    }
78
79
    /**
80
     * @throws \Exception
81
     */
82 1
    public function addCommentOnTable(string $table, string $comment): string
83
    {
84
        return 'ALTER TABLE '
85 1
            . $this->quoter->quoteTableName($table)
86
            . ' COMMENT '
87 1
            . (string) $this->quoter->quoteValue($comment);
88
    }
89
90
    /**
91
     * @throws Exception|InvalidArgumentException
92
     */
93 6
    public function createIndex(string $name, string $table, array|string $columns, bool $unique = false): string
94
    {
95
        return 'ALTER TABLE '
96 6
            . $this->quoter->quoteTableName($table)
97 6
            . ($unique ? ' ADD UNIQUE INDEX ' : ' ADD INDEX ')
98 6
            . $this->quoter->quoteTableName($name)
99 6
            . ' (' . $this->queryBuilder->buildColumns($columns) . ')';
100
    }
101
102 1
    public function checkIntegrity(string $schema = '', string $table = '', bool $check = true): string
103
    {
104 1
        return 'SET FOREIGN_KEY_CHECKS = ' . ($check ? 1 : 0);
105
    }
106
107
    /**
108
     * @throws NotSupportedException
109
     */
110 1
    public function dropCheck(string $name, string $table): string
111
    {
112 1
        throw new NotSupportedException(__METHOD__ . ' is not supported by MySQL.');
113
    }
114
115
    /**
116
     * @throws Exception|Throwable
117
     */
118 1
    public function dropCommentFromColumn(string $table, string $column): string
119
    {
120 1
        return $this->addCommentOnColumn($table, $column, '');
121
    }
122
123
    /**
124
     * @throws \Exception
125
     */
126 1
    public function dropCommentFromTable(string $table): string
127
    {
128 1
        return $this->addCommentOnTable($table, '');
129
    }
130
131 2
    public function dropForeignKey(string $name, string $table): string
132
    {
133
        return 'ALTER TABLE '
134 2
            . $this->quoter->quoteTableName($table)
135
            . ' DROP FOREIGN KEY '
136 2
            . $this->quoter->quoteColumnName($name);
137
    }
138
139 2
    public function dropPrimaryKey(string $name, string $table): string
140
    {
141 2
        return 'ALTER TABLE ' . $this->quoter->quoteTableName($table) . ' DROP PRIMARY KEY';
142
    }
143
144 2
    public function dropUnique(string $name, string $table): string
145
    {
146 2
        return $this->dropIndex($name, $table);
147
    }
148
149
    /**
150
     * @throws Exception|Throwable
151
     */
152 2
    public function renameColumn(string $table, string $oldName, string $newName): string
153
    {
154 2
        $quotedTable = $this->quoter->quoteTableName($table);
155
156 2
        $columnDefinition = $this->getColumnDefinition($table, $oldName);
157
158
        /* try to give back a SQL anyway */
159 1
        return "ALTER TABLE $quotedTable CHANGE "
160 1
            . $this->quoter->quoteColumnName($oldName) . ' '
161 1
            . $this->quoter->quoteColumnName($newName)
162 1
            . (!empty($columnDefinition) ? ' ' . $columnDefinition : '');
163
    }
164
165
    /**
166
     * @todo need work with bit, tinybit and other new not suppoerted types (v.5.7 and later)
167
     */
168
//    public function getColumnDefinitionFromSchema($table, $oldName): string
169
//    {
170
//        $schema = $this->schema;
171
//        $tableSchema = $schema->getTableSchema($table, true);
172
//        if ($tableSchema === null) {
173
//            throw new InvalidArgumentException("Table not found: $table");
174
//        }
175
//
176
//        $oldColumnSchema = $tableSchema->getColumn($oldName);
177
//        if ($oldColumnSchema === null) {
178
//            return '';
179
//        }
180
//
181
//        $columnSchemaBuilder = $this->schema->createColumnSchemaBuilder(
182
//            $oldColumnSchema->getType(),
183
//            $oldColumnSchema->getPrecision() ?? $oldColumnSchema->getSize()
184
//        );
185
//
186
//        $defaultValue = $oldColumnSchema->getDefaultValue();
187
//
188
//        if ($oldColumnSchema->isAllowNull()) {
189
//            if ($defaultValue === null) {
190
//                if (!in_array($oldColumnSchema->getType(), [Schema::TYPE_TEXT, Schema::TYPE_BINARY], true)) {
191
//                    $columnSchemaBuilder->defaultValue('NULL');
192
//                }
193
//                if ($oldColumnSchema->getType() === Schema::TYPE_TIMESTAMP) {
194
//                    $columnSchemaBuilder->null();
195
//                }
196
//            } elseif ($oldColumnSchema->getType() !== Schema::TYPE_BINARY) {
197
//                $columnSchemaBuilder->defaultValue($defaultValue);
198
//            }
199
//        } else {
200
//            $columnSchemaBuilder->notNull();
201
//            if ($defaultValue !== null && ($oldColumnSchema->getDbType() !== 'bit(1)' || !empty($defaultValue))) {
202
//                $columnSchemaBuilder->defaultValue($defaultValue);
203
//            }
204
//        }
205
//
206
//        if (!empty($oldColumnSchema->getComment())) {
207
//            $columnSchemaBuilder->comment($oldColumnSchema->getComment());
208
//        }
209
//
210
//        if ($oldColumnSchema->isUnsigned()) {
211
//            $columnSchemaBuilder->unsigned();
212
//        }
213
//
214
//        if ($oldColumnSchema->isAutoIncrement()) {
215
//            $columnSchemaBuilder->append('AUTO_INCREMENT');
216
//        } elseif (!empty($oldColumnSchema->getExtra())) {
217
//            $columnSchemaBuilder->append($oldColumnSchema->getExtra());
218
//        }
219
//
220
//        return $this->queryBuilder->getColumnType($columnSchemaBuilder);
221
//    }
222
223
    /**
224
     * Gets column definition.
225
     *
226
     * @param string $table table name.
227
     * @param string $column column name.
228
     *
229
     * @throws Exception|Throwable in case when table does not contain column.
230
     *
231
     * @return string the column definition.
232
     *
233
     * @todo need change to getColumnDefinitionFromSchema with deep research
234
     */
235 3
    public function getColumnDefinition(string $table, string $column): string
236
    {
237 3
        $result = '';
238 3
        $quotedTable = $this->quoter->quoteTableName($table);
239
240
        /** @var array<array-key, string> $row */
241 3
        $row = $this->command->setSql('SHOW CREATE TABLE ' . $quotedTable)->queryOne();
242
243 2
        if (!isset($row['Create Table'])) {
244
            $row = array_values($row);
0 ignored issues
show
Bug introduced by
$row of type false is incompatible with the type array expected by parameter $array of array_values(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

244
            $row = array_values(/** @scrutinizer ignore-type */ $row);
Loading history...
245
            $sql = $row[1];
246
        } else {
247 2
            $sql = $row['Create Table'];
248
        }
249
250 2
        if (preg_match_all('/^\s*`(.*?)`\s+(.*?),?$/m', $sql, $matches)) {
251 2
            foreach ($matches[1] as $i => $c) {
252 2
                if ($c === $column) {
253 2
                    $result = $matches[2][$i];
254
                }
255
            }
256
        }
257
258 2
        return $result;
259
    }
260
}
261