Test Failed
Pull Request — master (#66)
by Wilmer
18:24 queued 07:05
created

DDLQueryBuilder   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 183
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 65
c 1
b 0
f 0
dl 0
loc 183
rs 10
wmc 25

11 Methods

Rating   Name   Duplication   Size   Complexity  
A alterColumn() 0 8 1
A dropCommentFromTable() 0 3 1
A addCommentOnTable() 0 3 1
A dropCommentFromColumn() 0 3 1
A addCommentOnColumn() 0 3 1
A addDefaultValue() 0 8 1
A __construct() 0 3 1
A buildRemoveCommentSql() 0 27 6
A checkIntegrity() 0 19 5
A dropDefaultValue() 0 6 1
A buildAddCommentSql() 0 32 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Mssql;
6
7
use Exception;
8
use Yiisoft\Db\Exception\InvalidArgumentException;
9
use Yiisoft\Db\Exception\NotSupportedException;
10
use Yiisoft\Db\Mssql\PDO\SchemaPDOMssql;
11
use Yiisoft\Db\Query\DDLQueryBuilder as AbstractDDLQueryBuilder;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Query\DDLQueryBuilder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Yiisoft\Db\Query\QueryBuilderInterface;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Query\QueryBuilderInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
14
final class DDLQueryBuilder extends AbstractDDLQueryBuilder
15
{
16
    public function __construct(private QueryBuilderInterface $queryBuilder)
17
    {
18
        parent::__construct($queryBuilder);
19
    }
20
21
    /**
22
     * @throws InvalidArgumentException
23
     */
24
    public function addCommentOnColumn(string $table, string $column, string $comment): string
25
    {
26
        return $this->buildAddCommentSql($comment, $table, $column);
27
    }
28
29
    /**
30
     * @throws InvalidArgumentException
31
     */
32
    public function addCommentOnTable(string $table, string $comment): string
33
    {
34
        return $this->buildAddCommentSql($comment, $table);
35
    }
36
37
    /**
38
     * @throws Exception
39
     */
40
    public function addDefaultValue(string $name, string $table, string $column, mixed $value): string
41
    {
42
        return 'ALTER TABLE '
43
            . $this->queryBuilder->quoter()->quoteTableName($table)
44
            . ' ADD CONSTRAINT '
45
            . $this->queryBuilder->quoter()->quoteColumnName($name)
46
            . ' DEFAULT ' . $this->queryBuilder->quoter()->quoteValue($value)
47
            . ' FOR ' . $this->queryBuilder->quoter()->quoteColumnName($column);
48
    }
49
50
    public function alterColumn(string $table, string $column, string $type): string
51
    {
52
        return 'ALTER TABLE '
53
            . $this->queryBuilder->quoter()->quoteTableName($table)
54
            . ' ALTER COLUMN '
55
            . $this->queryBuilder->quoter()->quoteColumnName($column)
56
            . ' '
57
            . $this->queryBuilder->getColumnType($type);
58
    }
59
60
    /**
61
     * @throws NotSupportedException
62
     */
63
    public function checkIntegrity(string $schema = '', string $table = '', bool $check = true): string
64
    {
65
        $enable = $check ? 'CHECK' : 'NOCHECK';
66
67
        /** @var SchemaPDOMssql */
68
        $schemaInstance = $this->queryBuilder->schema();
69
        $defaultSchema = $schema ?: $schemaInstance->getDefaultSchema();
70
        $tableNames =  $schemaInstance->getTableSchema($table)
71
             ? [$table] : $schemaInstance->getTableNames($defaultSchema);
72
        $viewNames = $schemaInstance->getViewNames($defaultSchema);
73
        $tableNames = array_diff($tableNames, $viewNames);
74
        $command = '';
75
76
        foreach ($tableNames as $tableName) {
77
            $tableName = $this->queryBuilder->quoter()->quoteTableName("$defaultSchema.$tableName");
78
            $command .= "ALTER TABLE $tableName $enable CONSTRAINT ALL; ";
79
        }
80
81
        return $command;
82
    }
83
84
    /**
85
     * @throws InvalidArgumentException
86
     */
87
    public function dropCommentFromColumn(string $table, string $column): string
88
    {
89
        return $this->buildRemoveCommentSql($table, $column);
90
    }
91
92
    /**
93
     * @throws InvalidArgumentException
94
     */
95
    public function dropCommentFromTable(string $table): string
96
    {
97
        return $this->buildRemoveCommentSql($table);
98
    }
99
100
    public function dropDefaultValue(string $name, string $table): string
101
    {
102
        return 'ALTER TABLE '
103
            . $this->queryBuilder->quoter()->quoteTableName($table)
104
            . ' DROP CONSTRAINT '
105
            . $this->queryBuilder->quoter()->quoteColumnName($name);
106
    }
107
108
    /**
109
     * Builds a SQL command for adding or updating a comment to a table or a column. The command built will check if a
110
     * comment already exists. If so, it will be updated, otherwise, it will be added.
111
     *
112
     * @param string $comment the text of the comment to be added. The comment will be properly quoted by the method.
113
     * @param string $table the table to be commented or whose column is to be commented. The table name will be
114
     * properly quoted by the method.
115
     * @param string|null $column optional. The name of the column to be commented. If empty, the command will add the
116
     * comment to the table instead. The column name will be properly quoted by the method.
117
     *
118
     * @throws Exception|InvalidArgumentException if the table does not exist.
119
     *
120
     * @return string the SQL statement for adding a comment.
121
     */
122
    private function buildAddCommentSql(string $comment, string $table, ?string $column = null): string
123
    {
124
        $tableSchema = $this->queryBuilder->schema()->getTableSchema($table);
125
126
        if ($tableSchema === null) {
127
            throw new InvalidArgumentException("Table not found: $table");
128
        }
129
130
        $schemaName = $tableSchema->getSchemaName() ? "N'" . $tableSchema->getSchemaName() . "'" : 'SCHEMA_NAME()';
131
        $tableName = 'N' . $this->queryBuilder->quoter()->quoteValue($tableSchema->getName());
132
        $columnName = $column ? 'N' . $this->queryBuilder->quoter()->quoteValue($column) : null;
133
        $comment = 'N' . $this->queryBuilder->quoter()->quoteValue($comment);
134
        $functionParams = "
135
            @name = N'MS_description',
136
            @value = $comment,
137
            @level0type = N'SCHEMA', @level0name = $schemaName,
138
            @level1type = N'TABLE', @level1name = $tableName"
139
            . ($column ? ", @level2type = N'COLUMN', @level2name = $columnName" : '') . ';';
140
141
        return "
142
            IF NOT EXISTS (
143
                    SELECT 1
144
                    FROM fn_listextendedproperty (
145
                        N'MS_description',
146
                        'SCHEMA', $schemaName,
147
                        'TABLE', $tableName,
148
                        " . ($column ? "'COLUMN', $columnName " : ' DEFAULT, DEFAULT ') . "
149
                    )
150
            )
151
                EXEC sys.sp_addextendedproperty $functionParams
152
            ELSE
153
                EXEC sys.sp_updateextendedproperty $functionParams
154
        ";
155
    }
156
157
    /**
158
     * Builds a SQL command for removing a comment from a table or a column. The command built will check if a comment
159
     * already exists before trying to perform the removal.
160
     *
161
     * @param string $table the table that will have the comment removed or whose column will have the comment removed.
162
     * The table name will be properly quoted by the method.
163
     * @param string|null $column optional. The name of the column whose comment will be removed. If empty, the command
164
     * will remove the comment from the table instead. The column name will be properly quoted by the method.
165
     *
166
     * @throws Exception|InvalidArgumentException if the table does not exist.
167
     *
168
     * @return string the SQL statement for removing the comment.
169
     */
170
    private function buildRemoveCommentSql(string $table, ?string $column = null): string
171
    {
172
        $tableSchema = $this->queryBuilder->schema()->getTableSchema($table);
173
174
        if ($tableSchema === null) {
175
            throw new InvalidArgumentException("Table not found: $table");
176
        }
177
178
        $schemaName = $tableSchema->getSchemaName() ? "N'" . $tableSchema->getSchemaName() . "'" : 'SCHEMA_NAME()';
179
        $tableName = 'N' . $this->queryBuilder->quoter()->quoteValue($tableSchema->getName());
180
        $columnName = $column ? 'N' . $this->queryBuilder->quoter()->quoteValue($column) : null;
181
182
        return "
183
            IF EXISTS (
184
                    SELECT 1
185
                    FROM fn_listextendedproperty (
186
                        N'MS_description',
187
                        'SCHEMA', $schemaName,
188
                        'TABLE', $tableName,
189
                        " . ($column ? "'COLUMN', $columnName " : ' DEFAULT, DEFAULT ') . "
190
                    )
191
            )
192
                EXEC sys.sp_dropextendedproperty
193
                    @name = N'MS_description',
194
                    @level0type = N'SCHEMA', @level0name = $schemaName,
195
                    @level1type = N'TABLE', @level1name = $tableName"
196
                    . ($column ? ", @level2type = N'COLUMN', @level2name = $columnName" : '') . ';';
197
    }
198
}
199