diff options
Diffstat (limited to 'vendor/doctrine/dbal/src/Platforms/DB2Platform.php')
-rw-r--r-- | vendor/doctrine/dbal/src/Platforms/DB2Platform.php | 593 |
1 files changed, 593 insertions, 0 deletions
diff --git a/vendor/doctrine/dbal/src/Platforms/DB2Platform.php b/vendor/doctrine/dbal/src/Platforms/DB2Platform.php new file mode 100644 index 0000000..a00b24b --- /dev/null +++ b/vendor/doctrine/dbal/src/Platforms/DB2Platform.php | |||
@@ -0,0 +1,593 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Platforms; | ||
6 | |||
7 | use Doctrine\DBAL\Connection; | ||
8 | use Doctrine\DBAL\Platforms\Exception\NotSupported; | ||
9 | use Doctrine\DBAL\Platforms\Keywords\DB2Keywords; | ||
10 | use Doctrine\DBAL\Platforms\Keywords\KeywordList; | ||
11 | use Doctrine\DBAL\Schema\ColumnDiff; | ||
12 | use Doctrine\DBAL\Schema\DB2SchemaManager; | ||
13 | use Doctrine\DBAL\Schema\Identifier; | ||
14 | use Doctrine\DBAL\Schema\Index; | ||
15 | use Doctrine\DBAL\Schema\TableDiff; | ||
16 | use Doctrine\DBAL\SQL\Builder\DefaultSelectSQLBuilder; | ||
17 | use Doctrine\DBAL\SQL\Builder\SelectSQLBuilder; | ||
18 | use Doctrine\DBAL\TransactionIsolationLevel; | ||
19 | use Doctrine\DBAL\Types\Types; | ||
20 | |||
21 | use function array_merge; | ||
22 | use function count; | ||
23 | use function current; | ||
24 | use function explode; | ||
25 | use function implode; | ||
26 | use function sprintf; | ||
27 | use function str_contains; | ||
28 | |||
29 | /** | ||
30 | * Provides the behavior, features and SQL dialect of the IBM DB2 database platform of the oldest supported version. | ||
31 | */ | ||
32 | class DB2Platform extends AbstractPlatform | ||
33 | { | ||
34 | /** | ||
35 | * {@inheritDoc} | ||
36 | */ | ||
37 | public function getBlobTypeDeclarationSQL(array $column): string | ||
38 | { | ||
39 | // todo blob(n) with $column['length']; | ||
40 | return 'BLOB(1M)'; | ||
41 | } | ||
42 | |||
43 | protected function initializeDoctrineTypeMappings(): void | ||
44 | { | ||
45 | $this->doctrineTypeMapping = [ | ||
46 | 'bigint' => Types::BIGINT, | ||
47 | 'binary' => Types::BINARY, | ||
48 | 'blob' => Types::BLOB, | ||
49 | 'character' => Types::STRING, | ||
50 | 'clob' => Types::TEXT, | ||
51 | 'date' => Types::DATE_MUTABLE, | ||
52 | 'decimal' => Types::DECIMAL, | ||
53 | 'double' => Types::FLOAT, | ||
54 | 'integer' => Types::INTEGER, | ||
55 | 'real' => Types::FLOAT, | ||
56 | 'smallint' => Types::SMALLINT, | ||
57 | 'time' => Types::TIME_MUTABLE, | ||
58 | 'timestamp' => Types::DATETIME_MUTABLE, | ||
59 | 'varbinary' => Types::BINARY, | ||
60 | 'varchar' => Types::STRING, | ||
61 | ]; | ||
62 | } | ||
63 | |||
64 | protected function getBinaryTypeDeclarationSQLSnippet(?int $length): string | ||
65 | { | ||
66 | return $this->getCharTypeDeclarationSQLSnippet($length) . ' FOR BIT DATA'; | ||
67 | } | ||
68 | |||
69 | protected function getVarbinaryTypeDeclarationSQLSnippet(?int $length): string | ||
70 | { | ||
71 | return $this->getVarcharTypeDeclarationSQLSnippet($length) . ' FOR BIT DATA'; | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * {@inheritDoc} | ||
76 | */ | ||
77 | public function getClobTypeDeclarationSQL(array $column): string | ||
78 | { | ||
79 | // todo clob(n) with $column['length']; | ||
80 | return 'CLOB(1M)'; | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * {@inheritDoc} | ||
85 | */ | ||
86 | public function getBooleanTypeDeclarationSQL(array $column): string | ||
87 | { | ||
88 | return 'SMALLINT'; | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * {@inheritDoc} | ||
93 | */ | ||
94 | public function getIntegerTypeDeclarationSQL(array $column): string | ||
95 | { | ||
96 | return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($column); | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * {@inheritDoc} | ||
101 | */ | ||
102 | public function getBigIntTypeDeclarationSQL(array $column): string | ||
103 | { | ||
104 | return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($column); | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * {@inheritDoc} | ||
109 | */ | ||
110 | public function getSmallIntTypeDeclarationSQL(array $column): string | ||
111 | { | ||
112 | return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($column); | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * {@inheritDoc} | ||
117 | */ | ||
118 | protected function _getCommonIntegerTypeDeclarationSQL(array $column): string | ||
119 | { | ||
120 | $autoinc = ''; | ||
121 | if (! empty($column['autoincrement'])) { | ||
122 | $autoinc = ' GENERATED BY DEFAULT AS IDENTITY'; | ||
123 | } | ||
124 | |||
125 | return $autoinc; | ||
126 | } | ||
127 | |||
128 | public function getBitAndComparisonExpression(string $value1, string $value2): string | ||
129 | { | ||
130 | return 'BITAND(' . $value1 . ', ' . $value2 . ')'; | ||
131 | } | ||
132 | |||
133 | public function getBitOrComparisonExpression(string $value1, string $value2): string | ||
134 | { | ||
135 | return 'BITOR(' . $value1 . ', ' . $value2 . ')'; | ||
136 | } | ||
137 | |||
138 | protected function getDateArithmeticIntervalExpression( | ||
139 | string $date, | ||
140 | string $operator, | ||
141 | string $interval, | ||
142 | DateIntervalUnit $unit, | ||
143 | ): string { | ||
144 | switch ($unit) { | ||
145 | case DateIntervalUnit::WEEK: | ||
146 | $interval = $this->multiplyInterval($interval, 7); | ||
147 | $unit = DateIntervalUnit::DAY; | ||
148 | break; | ||
149 | |||
150 | case DateIntervalUnit::QUARTER: | ||
151 | $interval = $this->multiplyInterval($interval, 3); | ||
152 | $unit = DateIntervalUnit::MONTH; | ||
153 | break; | ||
154 | } | ||
155 | |||
156 | return $date . ' ' . $operator . ' ' . $interval . ' ' . $unit->value; | ||
157 | } | ||
158 | |||
159 | public function getDateDiffExpression(string $date1, string $date2): string | ||
160 | { | ||
161 | return 'DAYS(' . $date1 . ') - DAYS(' . $date2 . ')'; | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * {@inheritDoc} | ||
166 | */ | ||
167 | public function getDateTimeTypeDeclarationSQL(array $column): string | ||
168 | { | ||
169 | if (isset($column['version']) && $column['version'] === true) { | ||
170 | return 'TIMESTAMP(0) WITH DEFAULT'; | ||
171 | } | ||
172 | |||
173 | return 'TIMESTAMP(0)'; | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * {@inheritDoc} | ||
178 | */ | ||
179 | public function getDateTypeDeclarationSQL(array $column): string | ||
180 | { | ||
181 | return 'DATE'; | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * {@inheritDoc} | ||
186 | */ | ||
187 | public function getTimeTypeDeclarationSQL(array $column): string | ||
188 | { | ||
189 | return 'TIME'; | ||
190 | } | ||
191 | |||
192 | public function getTruncateTableSQL(string $tableName, bool $cascade = false): string | ||
193 | { | ||
194 | $tableIdentifier = new Identifier($tableName); | ||
195 | |||
196 | return 'TRUNCATE ' . $tableIdentifier->getQuotedName($this) . ' IMMEDIATE'; | ||
197 | } | ||
198 | |||
199 | public function getSetTransactionIsolationSQL(TransactionIsolationLevel $level): string | ||
200 | { | ||
201 | throw NotSupported::new(__METHOD__); | ||
202 | } | ||
203 | |||
204 | /** @internal The method should be only used from within the {@see AbstractSchemaManager} class hierarchy. */ | ||
205 | public function getListViewsSQL(string $database): string | ||
206 | { | ||
207 | return 'SELECT NAME, TEXT FROM SYSIBM.SYSVIEWS'; | ||
208 | } | ||
209 | |||
210 | /** @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy. */ | ||
211 | public function supportsCommentOnStatement(): bool | ||
212 | { | ||
213 | return true; | ||
214 | } | ||
215 | |||
216 | public function getCurrentDateSQL(): string | ||
217 | { | ||
218 | return 'CURRENT DATE'; | ||
219 | } | ||
220 | |||
221 | public function getCurrentTimeSQL(): string | ||
222 | { | ||
223 | return 'CURRENT TIME'; | ||
224 | } | ||
225 | |||
226 | public function getCurrentTimestampSQL(): string | ||
227 | { | ||
228 | return 'CURRENT TIMESTAMP'; | ||
229 | } | ||
230 | |||
231 | /** @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy. */ | ||
232 | public function getIndexDeclarationSQL(Index $index): string | ||
233 | { | ||
234 | // Index declaration in statements like CREATE TABLE is not supported. | ||
235 | throw NotSupported::new(__METHOD__); | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * {@inheritDoc} | ||
240 | */ | ||
241 | protected function _getCreateTableSQL(string $name, array $columns, array $options = []): array | ||
242 | { | ||
243 | $indexes = []; | ||
244 | if (isset($options['indexes'])) { | ||
245 | $indexes = $options['indexes']; | ||
246 | } | ||
247 | |||
248 | $options['indexes'] = []; | ||
249 | |||
250 | $sqls = parent::_getCreateTableSQL($name, $columns, $options); | ||
251 | |||
252 | foreach ($indexes as $definition) { | ||
253 | $sqls[] = $this->getCreateIndexSQL($definition, $name); | ||
254 | } | ||
255 | |||
256 | return $sqls; | ||
257 | } | ||
258 | |||
259 | /** | ||
260 | * {@inheritDoc} | ||
261 | */ | ||
262 | public function getAlterTableSQL(TableDiff $diff): array | ||
263 | { | ||
264 | $sql = []; | ||
265 | $columnSql = []; | ||
266 | $commentsSQL = []; | ||
267 | |||
268 | $tableNameSQL = $diff->getOldTable()->getQuotedName($this); | ||
269 | |||
270 | $queryParts = []; | ||
271 | foreach ($diff->getAddedColumns() as $column) { | ||
272 | $columnDef = $column->toArray(); | ||
273 | $queryPart = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); | ||
274 | |||
275 | // Adding non-nullable columns to a table requires a default value to be specified. | ||
276 | if ( | ||
277 | ! empty($columnDef['notnull']) && | ||
278 | ! isset($columnDef['default']) && | ||
279 | empty($columnDef['autoincrement']) | ||
280 | ) { | ||
281 | $queryPart .= ' WITH DEFAULT'; | ||
282 | } | ||
283 | |||
284 | $queryParts[] = $queryPart; | ||
285 | |||
286 | $comment = $column->getComment(); | ||
287 | |||
288 | if ($comment === '') { | ||
289 | continue; | ||
290 | } | ||
291 | |||
292 | $commentsSQL[] = $this->getCommentOnColumnSQL( | ||
293 | $tableNameSQL, | ||
294 | $column->getQuotedName($this), | ||
295 | $comment, | ||
296 | ); | ||
297 | } | ||
298 | |||
299 | foreach ($diff->getDroppedColumns() as $column) { | ||
300 | $queryParts[] = 'DROP COLUMN ' . $column->getQuotedName($this); | ||
301 | } | ||
302 | |||
303 | foreach ($diff->getModifiedColumns() as $columnDiff) { | ||
304 | if ($columnDiff->hasCommentChanged()) { | ||
305 | $newColumn = $columnDiff->getNewColumn(); | ||
306 | $commentsSQL[] = $this->getCommentOnColumnSQL( | ||
307 | $tableNameSQL, | ||
308 | $newColumn->getQuotedName($this), | ||
309 | $newColumn->getComment(), | ||
310 | ); | ||
311 | } | ||
312 | |||
313 | $this->gatherAlterColumnSQL( | ||
314 | $tableNameSQL, | ||
315 | $columnDiff, | ||
316 | $sql, | ||
317 | $queryParts, | ||
318 | ); | ||
319 | } | ||
320 | |||
321 | foreach ($diff->getRenamedColumns() as $oldColumnName => $column) { | ||
322 | $oldColumnName = new Identifier($oldColumnName); | ||
323 | |||
324 | $queryParts[] = 'RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . | ||
325 | ' TO ' . $column->getQuotedName($this); | ||
326 | } | ||
327 | |||
328 | if (count($queryParts) > 0) { | ||
329 | $sql[] = 'ALTER TABLE ' . $tableNameSQL . ' ' . implode(' ', $queryParts); | ||
330 | } | ||
331 | |||
332 | // Some table alteration operations require a table reorganization. | ||
333 | if (count($diff->getDroppedColumns()) > 0 || count($diff->getModifiedColumns()) > 0) { | ||
334 | $sql[] = "CALL SYSPROC.ADMIN_CMD ('REORG TABLE " . $tableNameSQL . "')"; | ||
335 | } | ||
336 | |||
337 | $sql = array_merge( | ||
338 | $this->getPreAlterTableIndexForeignKeySQL($diff), | ||
339 | $sql, | ||
340 | $commentsSQL, | ||
341 | $this->getPostAlterTableIndexForeignKeySQL($diff), | ||
342 | ); | ||
343 | |||
344 | return array_merge($sql, $columnSql); | ||
345 | } | ||
346 | |||
347 | public function getRenameTableSQL(string $oldName, string $newName): string | ||
348 | { | ||
349 | return sprintf('RENAME TABLE %s TO %s', $oldName, $newName); | ||
350 | } | ||
351 | |||
352 | /** | ||
353 | * Gathers the table alteration SQL for a given column diff. | ||
354 | * | ||
355 | * @param string $table The table to gather the SQL for. | ||
356 | * @param ColumnDiff $columnDiff The column diff to evaluate. | ||
357 | * @param list<string> $sql The sequence of table alteration statements to fill. | ||
358 | * @param list<string> $queryParts The sequence of column alteration clauses to fill. | ||
359 | */ | ||
360 | private function gatherAlterColumnSQL( | ||
361 | string $table, | ||
362 | ColumnDiff $columnDiff, | ||
363 | array &$sql, | ||
364 | array &$queryParts, | ||
365 | ): void { | ||
366 | $alterColumnClauses = $this->getAlterColumnClausesSQL($columnDiff); | ||
367 | |||
368 | if (empty($alterColumnClauses)) { | ||
369 | return; | ||
370 | } | ||
371 | |||
372 | // If we have a single column alteration, we can append the clause to the main query. | ||
373 | if (count($alterColumnClauses) === 1) { | ||
374 | $queryParts[] = current($alterColumnClauses); | ||
375 | |||
376 | return; | ||
377 | } | ||
378 | |||
379 | // We have multiple alterations for the same column, | ||
380 | // so we need to trigger a complete ALTER TABLE statement | ||
381 | // for each ALTER COLUMN clause. | ||
382 | foreach ($alterColumnClauses as $alterColumnClause) { | ||
383 | $sql[] = 'ALTER TABLE ' . $table . ' ' . $alterColumnClause; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | /** | ||
388 | * Returns the ALTER COLUMN SQL clauses for altering a column described by the given column diff. | ||
389 | * | ||
390 | * @return string[] | ||
391 | */ | ||
392 | private function getAlterColumnClausesSQL(ColumnDiff $columnDiff): array | ||
393 | { | ||
394 | $newColumn = $columnDiff->getNewColumn()->toArray(); | ||
395 | |||
396 | $alterClause = 'ALTER COLUMN ' . $columnDiff->getNewColumn()->getQuotedName($this); | ||
397 | |||
398 | if ($newColumn['columnDefinition'] !== null) { | ||
399 | return [$alterClause . ' ' . $newColumn['columnDefinition']]; | ||
400 | } | ||
401 | |||
402 | $clauses = []; | ||
403 | |||
404 | if ( | ||
405 | $columnDiff->hasTypeChanged() || | ||
406 | $columnDiff->hasLengthChanged() || | ||
407 | $columnDiff->hasPrecisionChanged() || | ||
408 | $columnDiff->hasScaleChanged() || | ||
409 | $columnDiff->hasFixedChanged() | ||
410 | ) { | ||
411 | $clauses[] = $alterClause . ' SET DATA TYPE ' . $newColumn['type']->getSQLDeclaration($newColumn, $this); | ||
412 | } | ||
413 | |||
414 | if ($columnDiff->hasNotNullChanged()) { | ||
415 | $clauses[] = $newColumn['notnull'] ? $alterClause . ' SET NOT NULL' : $alterClause . ' DROP NOT NULL'; | ||
416 | } | ||
417 | |||
418 | if ($columnDiff->hasDefaultChanged()) { | ||
419 | if (isset($newColumn['default'])) { | ||
420 | $defaultClause = $this->getDefaultValueDeclarationSQL($newColumn); | ||
421 | |||
422 | if ($defaultClause !== '') { | ||
423 | $clauses[] = $alterClause . ' SET' . $defaultClause; | ||
424 | } | ||
425 | } else { | ||
426 | $clauses[] = $alterClause . ' DROP DEFAULT'; | ||
427 | } | ||
428 | } | ||
429 | |||
430 | return $clauses; | ||
431 | } | ||
432 | |||
433 | /** | ||
434 | * {@inheritDoc} | ||
435 | */ | ||
436 | protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff): array | ||
437 | { | ||
438 | $sql = []; | ||
439 | |||
440 | $tableNameSQL = $diff->getOldTable()->getQuotedName($this); | ||
441 | |||
442 | foreach ($diff->getDroppedIndexes() as $droppedIndex) { | ||
443 | foreach ($diff->getAddedIndexes() as $addedIndex) { | ||
444 | if ($droppedIndex->getColumns() !== $addedIndex->getColumns()) { | ||
445 | continue; | ||
446 | } | ||
447 | |||
448 | if ($droppedIndex->isPrimary()) { | ||
449 | $sql[] = 'ALTER TABLE ' . $tableNameSQL . ' DROP PRIMARY KEY'; | ||
450 | } elseif ($droppedIndex->isUnique()) { | ||
451 | $sql[] = 'ALTER TABLE ' . $tableNameSQL . ' DROP UNIQUE ' . $droppedIndex->getQuotedName($this); | ||
452 | } else { | ||
453 | $sql[] = $this->getDropIndexSQL($droppedIndex->getQuotedName($this), $tableNameSQL); | ||
454 | } | ||
455 | |||
456 | $sql[] = $this->getCreateIndexSQL($addedIndex, $tableNameSQL); | ||
457 | |||
458 | $diff->unsetAddedIndex($addedIndex); | ||
459 | $diff->unsetDroppedIndex($droppedIndex); | ||
460 | |||
461 | break; | ||
462 | } | ||
463 | } | ||
464 | |||
465 | return array_merge($sql, parent::getPreAlterTableIndexForeignKeySQL($diff)); | ||
466 | } | ||
467 | |||
468 | /** | ||
469 | * {@inheritDoc} | ||
470 | */ | ||
471 | protected function getRenameIndexSQL(string $oldIndexName, Index $index, string $tableName): array | ||
472 | { | ||
473 | if (str_contains($tableName, '.')) { | ||
474 | [$schema] = explode('.', $tableName); | ||
475 | $oldIndexName = $schema . '.' . $oldIndexName; | ||
476 | } | ||
477 | |||
478 | return ['RENAME INDEX ' . $oldIndexName . ' TO ' . $index->getQuotedName($this)]; | ||
479 | } | ||
480 | |||
481 | /** | ||
482 | * {@inheritDoc} | ||
483 | * | ||
484 | * @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy. | ||
485 | */ | ||
486 | public function getDefaultValueDeclarationSQL(array $column): string | ||
487 | { | ||
488 | if (! empty($column['autoincrement'])) { | ||
489 | return ''; | ||
490 | } | ||
491 | |||
492 | if (! empty($column['version'])) { | ||
493 | if ((string) $column['type'] !== 'DateTime') { | ||
494 | $column['default'] = '1'; | ||
495 | } | ||
496 | } | ||
497 | |||
498 | return parent::getDefaultValueDeclarationSQL($column); | ||
499 | } | ||
500 | |||
501 | public function getEmptyIdentityInsertSQL(string $quotedTableName, string $quotedIdentifierColumnName): string | ||
502 | { | ||
503 | return 'INSERT INTO ' . $quotedTableName . ' (' . $quotedIdentifierColumnName . ') VALUES (DEFAULT)'; | ||
504 | } | ||
505 | |||
506 | public function getCreateTemporaryTableSnippetSQL(): string | ||
507 | { | ||
508 | return 'DECLARE GLOBAL TEMPORARY TABLE'; | ||
509 | } | ||
510 | |||
511 | public function getTemporaryTableName(string $tableName): string | ||
512 | { | ||
513 | return 'SESSION.' . $tableName; | ||
514 | } | ||
515 | |||
516 | protected function doModifyLimitQuery(string $query, ?int $limit, int $offset): string | ||
517 | { | ||
518 | if ($offset > 0) { | ||
519 | $query .= sprintf(' OFFSET %d ROWS', $offset); | ||
520 | } | ||
521 | |||
522 | if ($limit !== null) { | ||
523 | $query .= sprintf(' FETCH NEXT %d ROWS ONLY', $limit); | ||
524 | } | ||
525 | |||
526 | return $query; | ||
527 | } | ||
528 | |||
529 | public function getLocateExpression(string $string, string $substring, ?string $start = null): string | ||
530 | { | ||
531 | if ($start === null) { | ||
532 | return sprintf('LOCATE(%s, %s)', $substring, $string); | ||
533 | } | ||
534 | |||
535 | return sprintf('LOCATE(%s, %s, %s)', $substring, $string, $start); | ||
536 | } | ||
537 | |||
538 | public function getSubstringExpression(string $string, string $start, ?string $length = null): string | ||
539 | { | ||
540 | if ($length === null) { | ||
541 | return sprintf('SUBSTR(%s, %s)', $string, $start); | ||
542 | } | ||
543 | |||
544 | return sprintf('SUBSTR(%s, %s, %s)', $string, $start, $length); | ||
545 | } | ||
546 | |||
547 | public function getLengthExpression(string $string): string | ||
548 | { | ||
549 | return 'LENGTH(' . $string . ', CODEUNITS32)'; | ||
550 | } | ||
551 | |||
552 | public function getCurrentDatabaseExpression(): string | ||
553 | { | ||
554 | return 'CURRENT_USER'; | ||
555 | } | ||
556 | |||
557 | public function supportsIdentityColumns(): bool | ||
558 | { | ||
559 | return true; | ||
560 | } | ||
561 | |||
562 | public function createSelectSQLBuilder(): SelectSQLBuilder | ||
563 | { | ||
564 | return new DefaultSelectSQLBuilder($this, 'WITH RR USE AND KEEP UPDATE LOCKS', null); | ||
565 | } | ||
566 | |||
567 | public function getDummySelectSQL(string $expression = '1'): string | ||
568 | { | ||
569 | return sprintf('SELECT %s FROM sysibm.sysdummy1', $expression); | ||
570 | } | ||
571 | |||
572 | /** | ||
573 | * {@inheritDoc} | ||
574 | * | ||
575 | * DB2 supports savepoints, but they work semantically different than on other vendor platforms. | ||
576 | * | ||
577 | * TODO: We have to investigate how to get DB2 up and running with savepoints. | ||
578 | */ | ||
579 | public function supportsSavepoints(): bool | ||
580 | { | ||
581 | return false; | ||
582 | } | ||
583 | |||
584 | protected function createReservedKeywordsList(): KeywordList | ||
585 | { | ||
586 | return new DB2Keywords(); | ||
587 | } | ||
588 | |||
589 | public function createSchemaManager(Connection $connection): DB2SchemaManager | ||
590 | { | ||
591 | return new DB2SchemaManager($connection, $this); | ||
592 | } | ||
593 | } | ||