summaryrefslogtreecommitdiff
path: root/vendor/doctrine/dbal/src/Schema/DB2SchemaManager.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/doctrine/dbal/src/Schema/DB2SchemaManager.php')
-rw-r--r--vendor/doctrine/dbal/src/Schema/DB2SchemaManager.php371
1 files changed, 371 insertions, 0 deletions
diff --git a/vendor/doctrine/dbal/src/Schema/DB2SchemaManager.php b/vendor/doctrine/dbal/src/Schema/DB2SchemaManager.php
new file mode 100644
index 0000000..f2ed089
--- /dev/null
+++ b/vendor/doctrine/dbal/src/Schema/DB2SchemaManager.php
@@ -0,0 +1,371 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\DBAL\Schema;
6
7use Doctrine\DBAL\Exception;
8use Doctrine\DBAL\Platforms\DB2Platform;
9use Doctrine\DBAL\Result;
10use Doctrine\DBAL\Types\Type;
11use Doctrine\DBAL\Types\Types;
12
13use function array_change_key_case;
14use function implode;
15use function preg_match;
16use function str_replace;
17use function strpos;
18use function strtolower;
19use function strtoupper;
20use function substr;
21
22use const CASE_LOWER;
23
24/**
25 * IBM Db2 Schema Manager.
26 *
27 * @extends AbstractSchemaManager<DB2Platform>
28 */
29class DB2SchemaManager extends AbstractSchemaManager
30{
31 /**
32 * {@inheritDoc}
33 *
34 * @throws Exception
35 */
36 protected function _getPortableTableColumnDefinition(array $tableColumn): Column
37 {
38 $tableColumn = array_change_key_case($tableColumn, CASE_LOWER);
39
40 $length = $precision = $default = null;
41 $scale = 0;
42 $fixed = false;
43
44 if ($tableColumn['default'] !== null && $tableColumn['default'] !== 'NULL') {
45 $default = $tableColumn['default'];
46
47 if (preg_match('/^\'(.*)\'$/s', $default, $matches) === 1) {
48 $default = str_replace("''", "'", $matches[1]);
49 }
50 }
51
52 $type = $this->platform->getDoctrineTypeMapping($tableColumn['typename']);
53
54 switch (strtolower($tableColumn['typename'])) {
55 case 'varchar':
56 if ($tableColumn['codepage'] === 0) {
57 $type = Types::BINARY;
58 }
59
60 $length = $tableColumn['length'];
61 break;
62
63 case 'character':
64 if ($tableColumn['codepage'] === 0) {
65 $type = Types::BINARY;
66 }
67
68 $length = $tableColumn['length'];
69 $fixed = true;
70 break;
71
72 case 'clob':
73 $length = $tableColumn['length'];
74 break;
75
76 case 'decimal':
77 case 'double':
78 case 'real':
79 $scale = $tableColumn['scale'];
80 $precision = $tableColumn['length'];
81 break;
82 }
83
84 $options = [
85 'length' => $length,
86 'unsigned' => false,
87 'fixed' => $fixed,
88 'default' => $default,
89 'autoincrement' => (bool) $tableColumn['autoincrement'],
90 'notnull' => $tableColumn['nulls'] === 'N',
91 'platformOptions' => [],
92 ];
93
94 if (isset($tableColumn['comment'])) {
95 $options['comment'] = $tableColumn['comment'];
96 }
97
98 if ($scale !== null && $precision !== null) {
99 $options['scale'] = $scale;
100 $options['precision'] = $precision;
101 }
102
103 return new Column($tableColumn['colname'], Type::getType($type), $options);
104 }
105
106 /**
107 * {@inheritDoc}
108 */
109 protected function _getPortableTableDefinition(array $table): string
110 {
111 $table = array_change_key_case($table, CASE_LOWER);
112
113 return $table['name'];
114 }
115
116 /**
117 * {@inheritDoc}
118 */
119 protected function _getPortableTableIndexesList(array $tableIndexes, string $tableName): array
120 {
121 foreach ($tableIndexes as &$tableIndexRow) {
122 $tableIndexRow = array_change_key_case($tableIndexRow, CASE_LOWER);
123 $tableIndexRow['primary'] = (bool) $tableIndexRow['primary'];
124 }
125
126 return parent::_getPortableTableIndexesList($tableIndexes, $tableName);
127 }
128
129 /**
130 * {@inheritDoc}
131 */
132 protected function _getPortableTableForeignKeyDefinition(array $tableForeignKey): ForeignKeyConstraint
133 {
134 return new ForeignKeyConstraint(
135 $tableForeignKey['local_columns'],
136 $tableForeignKey['foreign_table'],
137 $tableForeignKey['foreign_columns'],
138 $tableForeignKey['name'],
139 $tableForeignKey['options'],
140 );
141 }
142
143 /**
144 * {@inheritDoc}
145 */
146 protected function _getPortableTableForeignKeysList(array $tableForeignKeys): array
147 {
148 $foreignKeys = [];
149
150 foreach ($tableForeignKeys as $tableForeignKey) {
151 $tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER);
152
153 if (! isset($foreignKeys[$tableForeignKey['index_name']])) {
154 $foreignKeys[$tableForeignKey['index_name']] = [
155 'local_columns' => [$tableForeignKey['local_column']],
156 'foreign_table' => $tableForeignKey['foreign_table'],
157 'foreign_columns' => [$tableForeignKey['foreign_column']],
158 'name' => $tableForeignKey['index_name'],
159 'options' => [
160 'onUpdate' => $tableForeignKey['on_update'],
161 'onDelete' => $tableForeignKey['on_delete'],
162 ],
163 ];
164 } else {
165 $foreignKeys[$tableForeignKey['index_name']]['local_columns'][] = $tableForeignKey['local_column'];
166 $foreignKeys[$tableForeignKey['index_name']]['foreign_columns'][] = $tableForeignKey['foreign_column'];
167 }
168 }
169
170 return parent::_getPortableTableForeignKeysList($foreignKeys);
171 }
172
173 /**
174 * {@inheritDoc}
175 */
176 protected function _getPortableViewDefinition(array $view): View
177 {
178 $view = array_change_key_case($view, CASE_LOWER);
179
180 $sql = '';
181 $pos = strpos($view['text'], ' AS ');
182
183 if ($pos !== false) {
184 $sql = substr($view['text'], $pos + 4);
185 }
186
187 return new View($view['name'], $sql);
188 }
189
190 protected function normalizeName(string $name): string
191 {
192 $identifier = new Identifier($name);
193
194 return $identifier->isQuoted() ? $identifier->getName() : strtoupper($name);
195 }
196
197 protected function selectTableNames(string $databaseName): Result
198 {
199 $sql = <<<'SQL'
200SELECT NAME
201FROM SYSIBM.SYSTABLES
202WHERE TYPE = 'T'
203 AND CREATOR = ?
204SQL;
205
206 return $this->connection->executeQuery($sql, [$databaseName]);
207 }
208
209 protected function selectTableColumns(string $databaseName, ?string $tableName = null): Result
210 {
211 $sql = 'SELECT';
212
213 if ($tableName === null) {
214 $sql .= ' C.TABNAME AS NAME,';
215 }
216
217 $sql .= <<<'SQL'
218 C.COLNAME,
219 C.TYPENAME,
220 C.CODEPAGE,
221 C.NULLS,
222 C.LENGTH,
223 C.SCALE,
224 C.REMARKS AS COMMENT,
225 CASE
226 WHEN C.GENERATED = 'D' THEN 1
227 ELSE 0
228 END AS AUTOINCREMENT,
229 C.DEFAULT
230FROM SYSCAT.COLUMNS C
231 JOIN SYSCAT.TABLES AS T
232 ON T.TABSCHEMA = C.TABSCHEMA
233 AND T.TABNAME = C.TABNAME
234SQL;
235
236 $conditions = ['C.TABSCHEMA = ?', "T.TYPE = 'T'"];
237 $params = [$databaseName];
238
239 if ($tableName !== null) {
240 $conditions[] = 'C.TABNAME = ?';
241 $params[] = $tableName;
242 }
243
244 $sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY C.TABNAME, C.COLNO';
245
246 return $this->connection->executeQuery($sql, $params);
247 }
248
249 protected function selectIndexColumns(string $databaseName, ?string $tableName = null): Result
250 {
251 $sql = 'SELECT';
252
253 if ($tableName === null) {
254 $sql .= ' IDX.TABNAME AS NAME,';
255 }
256
257 $sql .= <<<'SQL'
258 IDX.INDNAME AS KEY_NAME,
259 IDXCOL.COLNAME AS COLUMN_NAME,
260 CASE
261 WHEN IDX.UNIQUERULE = 'P' THEN 1
262 ELSE 0
263 END AS PRIMARY,
264 CASE
265 WHEN IDX.UNIQUERULE = 'D' THEN 1
266 ELSE 0
267 END AS NON_UNIQUE
268 FROM SYSCAT.INDEXES AS IDX
269 JOIN SYSCAT.TABLES AS T
270 ON IDX.TABSCHEMA = T.TABSCHEMA AND IDX.TABNAME = T.TABNAME
271 JOIN SYSCAT.INDEXCOLUSE AS IDXCOL
272 ON IDX.INDSCHEMA = IDXCOL.INDSCHEMA AND IDX.INDNAME = IDXCOL.INDNAME
273SQL;
274
275 $conditions = ['IDX.TABSCHEMA = ?', "T.TYPE = 'T'"];
276 $params = [$databaseName];
277
278 if ($tableName !== null) {
279 $conditions[] = 'IDX.TABNAME = ?';
280 $params[] = $tableName;
281 }
282
283 $sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY IDX.INDNAME, IDXCOL.COLSEQ';
284
285 return $this->connection->executeQuery($sql, $params);
286 }
287
288 protected function selectForeignKeyColumns(string $databaseName, ?string $tableName = null): Result
289 {
290 $sql = 'SELECT';
291
292 if ($tableName === null) {
293 $sql .= ' R.TABNAME AS NAME,';
294 }
295
296 $sql .= <<<'SQL'
297 FKCOL.COLNAME AS LOCAL_COLUMN,
298 R.REFTABNAME AS FOREIGN_TABLE,
299 PKCOL.COLNAME AS FOREIGN_COLUMN,
300 R.CONSTNAME AS INDEX_NAME,
301 CASE
302 WHEN R.UPDATERULE = 'R' THEN 'RESTRICT'
303 END AS ON_UPDATE,
304 CASE
305 WHEN R.DELETERULE = 'C' THEN 'CASCADE'
306 WHEN R.DELETERULE = 'N' THEN 'SET NULL'
307 WHEN R.DELETERULE = 'R' THEN 'RESTRICT'
308 END AS ON_DELETE
309 FROM SYSCAT.REFERENCES AS R
310 JOIN SYSCAT.TABLES AS T
311 ON T.TABSCHEMA = R.TABSCHEMA
312 AND T.TABNAME = R.TABNAME
313 JOIN SYSCAT.KEYCOLUSE AS FKCOL
314 ON FKCOL.CONSTNAME = R.CONSTNAME
315 AND FKCOL.TABSCHEMA = R.TABSCHEMA
316 AND FKCOL.TABNAME = R.TABNAME
317 JOIN SYSCAT.KEYCOLUSE AS PKCOL
318 ON PKCOL.CONSTNAME = R.REFKEYNAME
319 AND PKCOL.TABSCHEMA = R.REFTABSCHEMA
320 AND PKCOL.TABNAME = R.REFTABNAME
321 AND PKCOL.COLSEQ = FKCOL.COLSEQ
322SQL;
323
324 $conditions = ['R.TABSCHEMA = ?', "T.TYPE = 'T'"];
325 $params = [$databaseName];
326
327 if ($tableName !== null) {
328 $conditions[] = 'R.TABNAME = ?';
329 $params[] = $tableName;
330 }
331
332 $sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY R.CONSTNAME, FKCOL.COLSEQ';
333
334 return $this->connection->executeQuery($sql, $params);
335 }
336
337 /**
338 * {@inheritDoc}
339 */
340 protected function fetchTableOptionsByTable(string $databaseName, ?string $tableName = null): array
341 {
342 $sql = 'SELECT NAME, REMARKS';
343
344 $conditions = [];
345 $params = [];
346
347 if ($tableName !== null) {
348 $conditions[] = 'NAME = ?';
349 $params[] = $tableName;
350 }
351
352 $sql .= ' FROM SYSIBM.SYSTABLES';
353
354 if ($conditions !== []) {
355 $sql .= ' WHERE ' . implode(' AND ', $conditions);
356 }
357
358 /** @var array<string,array<string,mixed>> $metadata */
359 $metadata = $this->connection->executeQuery($sql, $params)
360 ->fetchAllAssociativeIndexed();
361
362 $tableOptions = [];
363 foreach ($metadata as $table => $data) {
364 $data = array_change_key_case($data, CASE_LOWER);
365
366 $tableOptions[$table] = ['comment' => $data['remarks']];
367 }
368
369 return $tableOptions;
370 }
371}