Skip to content

Commit c41bd8e

Browse files
czPechydg
authored andcommitted
MsSql support for tables, columns, indexes, foreign keys (#215)
1 parent 3d7522b commit c41bd8e

File tree

1 file changed

+107
-4
lines changed

1 file changed

+107
-4
lines changed

src/Database/Drivers/MsSqlDriver.php

Lines changed: 107 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,13 @@ class MsSqlDriver implements Nette\Database\ISupplementalDriver
1919
{
2020
use Nette\SmartObject;
2121

22+
/** @var Nette\Database\Connection */
23+
private $connection;
24+
25+
2226
public function initialize(Nette\Database\Connection $connection, array $options): void
2327
{
28+
$this->connection = $connection;
2429
}
2530

2631

@@ -81,25 +86,123 @@ public function applyLimit(string &$sql, ?int $limit, ?int $offset): void
8186

8287
public function getTables(): array
8388
{
84-
throw new Nette\NotImplementedException;
89+
$tables = [];
90+
foreach ($this->connection->query('SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES') as $row) {
91+
$tables[] = [
92+
'name' => $row['TABLE_SCHEMA'] . '.' . $row['TABLE_NAME'],
93+
'view' => ($row['TABLE_TYPE'] ?? null) === 'VIEW',
94+
];
95+
}
96+
return $tables;
8597
}
8698

8799

88100
public function getColumns(string $table): array
89101
{
90-
throw new Nette\NotImplementedException;
102+
[$table_schema, $table_name] = explode('.', $table);
103+
$columns = [];
104+
105+
$query = "
106+
SELECT
107+
COLUMN_NAME,
108+
DATA_TYPE,
109+
CHARACTER_MAXIMUM_LENGTH,
110+
NUMERIC_PRECISION,
111+
IS_NULLABLE,
112+
COLUMN_DEFAULT,
113+
DOMAIN_NAME
114+
FROM
115+
INFORMATION_SCHEMA.COLUMNS
116+
WHERE
117+
TABLE_SCHEMA = {$this->connection->quote($table_schema)}
118+
AND TABLE_NAME = {$this->connection->quote($table_name)}";
119+
120+
foreach ($this->connection->query($query) as $row) {
121+
$columns[] = [
122+
'name' => $row['COLUMN_NAME'],
123+
'table' => $table,
124+
'nativetype' => strtoupper($row['DATA_TYPE']),
125+
'size' => $row['CHARACTER_MAXIMUM_LENGTH'] ?? ($row['NUMERIC_PRECISION'] ?? null),
126+
'unsigned' => false,
127+
'nullable' => $row['IS_NULLABLE'] === 'YES',
128+
'default' => $row['COLUMN_DEFAULT'],
129+
'autoincrement' => $row['DOMAIN_NAME'] === 'COUNTER',
130+
'primary' => $row['COLUMN_NAME'] === 'ID',
131+
'vendor' => (array) $row,
132+
];
133+
}
134+
return $columns;
91135
}
92136

93137

94138
public function getIndexes(string $table): array
95139
{
96-
throw new Nette\NotImplementedException;
140+
[, $table_name] = explode('.', $table);
141+
$indexes = [];
142+
143+
$query = "
144+
SELECT
145+
name_index = ind.name,
146+
id_column = ic.index_column_id,
147+
name_column = col.name,
148+
ind.is_unique,
149+
ind.is_primary_key
150+
FROM
151+
sys.indexes ind
152+
INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id
153+
INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id
154+
INNER JOIN sys.tables t ON ind.object_id = t.object_id
155+
WHERE
156+
t.name = {$this->connection->quote($table_name)}
157+
ORDER BY
158+
t.name, ind.name, ind.index_id, ic.index_column_id";
159+
160+
foreach ($this->connection->query($query) as $row) {
161+
$indexes[$row['name_index']]['name'] = $row['name_index'];
162+
$indexes[$row['name_index']]['unique'] = $row['is_unique'] !== 'False';
163+
$indexes[$row['name_index']]['primary'] = $row['is_primary_key'] !== 'False';
164+
$indexes[$row['name_index']]['columns'][$row['id_column'] - 1] = $row['name_column'];
165+
}
166+
return array_values($indexes);
97167
}
98168

99169

100170
public function getForeignKeys(string $table): array
101171
{
102-
throw new Nette\NotImplementedException;
172+
[$table_schema, $table_name] = explode('.', $table);
173+
$keys = [];
174+
175+
$query = "
176+
SELECT
177+
obj.name AS [fk_name],
178+
col1.name AS [column],
179+
tab2.name AS [referenced_table],
180+
col2.name AS [referenced_column]
181+
FROM
182+
sys.foreign_key_columns fkc
183+
INNER JOIN sys.objects obj
184+
ON obj.object_id = fkc.constraint_object_id
185+
INNER JOIN sys.tables tab1
186+
ON tab1.object_id = fkc.parent_object_id
187+
INNER JOIN sys.schemas sch
188+
ON tab1.schema_id = sch.schema_id
189+
INNER JOIN sys.columns col1
190+
ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
191+
INNER JOIN sys.tables tab2
192+
ON tab2.object_id = fkc.referenced_object_id
193+
INNER JOIN sys.columns col2
194+
ON col2.column_id = referenced_column_id AND col2.object_id = tab2.object_id
195+
WHERE
196+
tab1.name = {$this->connection->quote($table_name)}";
197+
198+
foreach ($this->connection->query($query) as $id => $row) {
199+
$keys[$id]['name'] = $row['fk_name'];
200+
$keys[$id]['local'] = $row['column'];
201+
$keys[$id]['table'] = $table_schema . '.' . $row['referenced_table'];
202+
$keys[$id]['foreign'] = $row['referenced_column'];
203+
}
204+
205+
return array_values($keys);
103206
}
104207

105208

0 commit comments

Comments
 (0)