diff options
Diffstat (limited to 'vendor/doctrine/dbal/src/Schema/DB2SchemaManager.php')
-rw-r--r-- | vendor/doctrine/dbal/src/Schema/DB2SchemaManager.php | 371 |
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 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Schema; | ||
6 | |||
7 | use Doctrine\DBAL\Exception; | ||
8 | use Doctrine\DBAL\Platforms\DB2Platform; | ||
9 | use Doctrine\DBAL\Result; | ||
10 | use Doctrine\DBAL\Types\Type; | ||
11 | use Doctrine\DBAL\Types\Types; | ||
12 | |||
13 | use function array_change_key_case; | ||
14 | use function implode; | ||
15 | use function preg_match; | ||
16 | use function str_replace; | ||
17 | use function strpos; | ||
18 | use function strtolower; | ||
19 | use function strtoupper; | ||
20 | use function substr; | ||
21 | |||
22 | use const CASE_LOWER; | ||
23 | |||
24 | /** | ||
25 | * IBM Db2 Schema Manager. | ||
26 | * | ||
27 | * @extends AbstractSchemaManager<DB2Platform> | ||
28 | */ | ||
29 | class 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' | ||
200 | SELECT NAME | ||
201 | FROM SYSIBM.SYSTABLES | ||
202 | WHERE TYPE = 'T' | ||
203 | AND CREATOR = ? | ||
204 | SQL; | ||
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 | ||
230 | FROM SYSCAT.COLUMNS C | ||
231 | JOIN SYSCAT.TABLES AS T | ||
232 | ON T.TABSCHEMA = C.TABSCHEMA | ||
233 | AND T.TABNAME = C.TABNAME | ||
234 | SQL; | ||
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 | ||
273 | SQL; | ||
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 | ||
322 | SQL; | ||
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 | } | ||