Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
94.44% covered (success)
94.44%
34 / 36
91.67% covered (success)
91.67%
22 / 24
CRAP
0.00% covered (danger)
0.00%
0 / 1
SqlServerDialect
94.44% covered (success)
94.44%
34 / 36
91.67% covered (success)
91.67%
22 / 24
26.12
0.00% covered (danger)
0.00%
0 / 1
 getType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 integer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 bigInteger
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 smallInteger
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 varchar
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 text
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 longText
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 blob
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 boolean
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 timestamp
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 date
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 char
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 currentTimestamp
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 currentDate
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 autoIncrement
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createTablePrefix
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 createTableSuffix
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addColumn
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 modifyColumn
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createIndex
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 dropIndex
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 supportsColumnPositioning
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 supportsCombinedAlter
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 quoteIdentifier
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3/**
4 * SQL Server specific SQL dialect.
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public License,
7 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
8 * obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * @package   phpMyFAQ
11 * @author    Thorsten Rinne <thorsten@phpmyfaq.de>
12 * @copyright 2023-2026 phpMyFAQ Team
13 * @license   https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
14 * @link      https://www.phpmyfaq.de
15 * @since     2026-01-25
16 */
17
18declare(strict_types=1);
19
20namespace phpMyFAQ\Setup\Migration\QueryBuilder\Dialect;
21
22use phpMyFAQ\Setup\Migration\QueryBuilder\DialectInterface;
23
24class SqlServerDialect implements DialectInterface
25{
26    public function getType(): string
27    {
28        return 'sqlsrv';
29    }
30
31    public function integer(): string
32    {
33        return 'INT';
34    }
35
36    public function bigInteger(): string
37    {
38        return 'BIGINT';
39    }
40
41    public function smallInteger(): string
42    {
43        return 'SMALLINT';
44    }
45
46    public function varchar(int $length): string
47    {
48        return "NVARCHAR({$length})";
49    }
50
51    public function text(): string
52    {
53        return 'NVARCHAR(MAX)';
54    }
55
56    public function longText(): string
57    {
58        return 'NVARCHAR(MAX)';
59    }
60
61    public function blob(): string
62    {
63        return 'VARBINARY(MAX)';
64    }
65
66    public function boolean(): string
67    {
68        return 'TINYINT';
69    }
70
71    public function timestamp(): string
72    {
73        return 'DATETIME';
74    }
75
76    public function date(): string
77    {
78        return 'DATE';
79    }
80
81    public function char(int $length): string
82    {
83        return "NCHAR({$length})";
84    }
85
86    public function currentTimestamp(): string
87    {
88        return 'GETDATE()';
89    }
90
91    public function currentDate(): string
92    {
93        return 'GETDATE()';
94    }
95
96    public function autoIncrement(string $columnName): string
97    {
98        return "{$columnName} INT IDENTITY(1,1) NOT NULL";
99    }
100
101    public function createTablePrefix(string $tableName, bool $ifNotExists = false): string
102    {
103        if ($ifNotExists) {
104            return (
105                "IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='{$tableName}' AND xtype='U') "
106                . "CREATE TABLE {$tableName}"
107            );
108        }
109        return "CREATE TABLE {$tableName}";
110    }
111
112    public function createTableSuffix(): string
113    {
114        return '';
115    }
116
117    public function addColumn(string $tableName, string $columnName, string $type, ?string $after = null): string
118    {
119        // SQL Server doesn't support AFTER clause, and uses different syntax
120        return "ALTER TABLE {$tableName} ADD {$columnName} {$type}";
121    }
122
123    public function modifyColumn(string $tableName, string $columnName, string $newType): string
124    {
125        return "ALTER TABLE {$tableName} ALTER COLUMN {$columnName} {$newType}";
126    }
127
128    /**
129     * @param string[] $columns
130     */
131    public function createIndex(string $indexName, string $tableName, array $columns, bool $ifNotExists = false): string
132    {
133        $columnList = implode(', ', $columns);
134        if ($ifNotExists) {
135            return (
136                "IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = '{$indexName}'"
137                . " AND object_id = OBJECT_ID(N'{$tableName}')) "
138                . "CREATE INDEX {$indexName} ON {$tableName} ({$columnList})"
139            );
140        }
141        return "CREATE INDEX {$indexName} ON {$tableName} ({$columnList})";
142    }
143
144    public function dropIndex(string $indexName, string $tableName): string
145    {
146        return "DROP INDEX {$indexName} ON {$tableName}";
147    }
148
149    public function supportsColumnPositioning(): bool
150    {
151        return false;
152    }
153
154    public function supportsCombinedAlter(): bool
155    {
156        return false;
157    }
158
159    public function quoteIdentifier(string $identifier): string
160    {
161        return '[' . str_replace(search: ']', replace: ']]', subject: $identifier) . ']';
162    }
163}