summaryrefslogtreecommitdiff
path: root/vendor/doctrine/dbal/src/Platforms/OraclePlatform.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/doctrine/dbal/src/Platforms/OraclePlatform.php')
-rw-r--r--vendor/doctrine/dbal/src/Platforms/OraclePlatform.php784
1 files changed, 784 insertions, 0 deletions
diff --git a/vendor/doctrine/dbal/src/Platforms/OraclePlatform.php b/vendor/doctrine/dbal/src/Platforms/OraclePlatform.php
new file mode 100644
index 0000000..314f6ee
--- /dev/null
+++ b/vendor/doctrine/dbal/src/Platforms/OraclePlatform.php
@@ -0,0 +1,784 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\DBAL\Platforms;
6
7use Doctrine\DBAL\Connection;
8use Doctrine\DBAL\Exception\InvalidColumnType\ColumnLengthRequired;
9use Doctrine\DBAL\Platforms\Keywords\KeywordList;
10use Doctrine\DBAL\Platforms\Keywords\OracleKeywords;
11use Doctrine\DBAL\Schema\ForeignKeyConstraint;
12use Doctrine\DBAL\Schema\Identifier;
13use Doctrine\DBAL\Schema\Index;
14use Doctrine\DBAL\Schema\OracleSchemaManager;
15use Doctrine\DBAL\Schema\Sequence;
16use Doctrine\DBAL\Schema\TableDiff;
17use Doctrine\DBAL\TransactionIsolationLevel;
18use Doctrine\DBAL\Types\Types;
19use InvalidArgumentException;
20
21use function array_merge;
22use function count;
23use function explode;
24use function implode;
25use function sprintf;
26use function str_contains;
27use function strlen;
28use function strtoupper;
29use function substr;
30
31/**
32 * OraclePlatform.
33 */
34class OraclePlatform extends AbstractPlatform
35{
36 public function getSubstringExpression(string $string, string $start, ?string $length = null): string
37 {
38 if ($length === null) {
39 return sprintf('SUBSTR(%s, %s)', $string, $start);
40 }
41
42 return sprintf('SUBSTR(%s, %s, %s)', $string, $start, $length);
43 }
44
45 public function getLocateExpression(string $string, string $substring, ?string $start = null): string
46 {
47 if ($start === null) {
48 return sprintf('INSTR(%s, %s)', $string, $substring);
49 }
50
51 return sprintf('INSTR(%s, %s, %s)', $string, $substring, $start);
52 }
53
54 protected function getDateArithmeticIntervalExpression(
55 string $date,
56 string $operator,
57 string $interval,
58 DateIntervalUnit $unit,
59 ): string {
60 switch ($unit) {
61 case DateIntervalUnit::MONTH:
62 case DateIntervalUnit::QUARTER:
63 case DateIntervalUnit::YEAR:
64 switch ($unit) {
65 case DateIntervalUnit::QUARTER:
66 $interval = $this->multiplyInterval($interval, 3);
67 break;
68
69 case DateIntervalUnit::YEAR:
70 $interval = $this->multiplyInterval($interval, 12);
71 break;
72 }
73
74 return 'ADD_MONTHS(' . $date . ', ' . $operator . $interval . ')';
75
76 default:
77 $calculationClause = '';
78
79 switch ($unit) {
80 case DateIntervalUnit::SECOND:
81 $calculationClause = '/24/60/60';
82 break;
83
84 case DateIntervalUnit::MINUTE:
85 $calculationClause = '/24/60';
86 break;
87
88 case DateIntervalUnit::HOUR:
89 $calculationClause = '/24';
90 break;
91
92 case DateIntervalUnit::WEEK:
93 $calculationClause = '*7';
94 break;
95 }
96
97 return '(' . $date . $operator . $interval . $calculationClause . ')';
98 }
99 }
100
101 public function getDateDiffExpression(string $date1, string $date2): string
102 {
103 return sprintf('TRUNC(%s) - TRUNC(%s)', $date1, $date2);
104 }
105
106 public function getBitAndComparisonExpression(string $value1, string $value2): string
107 {
108 return 'BITAND(' . $value1 . ', ' . $value2 . ')';
109 }
110
111 public function getCurrentDatabaseExpression(): string
112 {
113 return "SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA')";
114 }
115
116 public function getBitOrComparisonExpression(string $value1, string $value2): string
117 {
118 return '(' . $value1 . '-' .
119 $this->getBitAndComparisonExpression($value1, $value2)
120 . '+' . $value2 . ')';
121 }
122
123 public function getCreatePrimaryKeySQL(Index $index, string $table): string
124 {
125 return 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $index->getQuotedName($this)
126 . ' PRIMARY KEY (' . implode(', ', $index->getQuotedColumns($this)) . ')';
127 }
128
129 /**
130 * {@inheritDoc}
131 *
132 * Need to specifiy minvalue, since start with is hidden in the system and MINVALUE <= START WITH.
133 * Therefore we can use MINVALUE to be able to get a hint what START WITH was for later introspection
134 * in {@see listSequences()}
135 */
136 public function getCreateSequenceSQL(Sequence $sequence): string
137 {
138 return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) .
139 ' START WITH ' . $sequence->getInitialValue() .
140 ' MINVALUE ' . $sequence->getInitialValue() .
141 ' INCREMENT BY ' . $sequence->getAllocationSize() .
142 $this->getSequenceCacheSQL($sequence);
143 }
144
145 public function getAlterSequenceSQL(Sequence $sequence): string
146 {
147 return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) .
148 ' INCREMENT BY ' . $sequence->getAllocationSize()
149 . $this->getSequenceCacheSQL($sequence);
150 }
151
152 /**
153 * Cache definition for sequences
154 */
155 private function getSequenceCacheSQL(Sequence $sequence): string
156 {
157 if ($sequence->getCache() === 0) {
158 return ' NOCACHE';
159 }
160
161 if ($sequence->getCache() === 1) {
162 return ' NOCACHE';
163 }
164
165 if ($sequence->getCache() > 1) {
166 return ' CACHE ' . $sequence->getCache();
167 }
168
169 return '';
170 }
171
172 public function getSequenceNextValSQL(string $sequence): string
173 {
174 return 'SELECT ' . $sequence . '.nextval FROM DUAL';
175 }
176
177 public function getSetTransactionIsolationSQL(TransactionIsolationLevel $level): string
178 {
179 return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level);
180 }
181
182 protected function _getTransactionIsolationLevelSQL(TransactionIsolationLevel $level): string
183 {
184 return match ($level) {
185 TransactionIsolationLevel::READ_UNCOMMITTED => 'READ UNCOMMITTED',
186 TransactionIsolationLevel::READ_COMMITTED => 'READ COMMITTED',
187 TransactionIsolationLevel::REPEATABLE_READ,
188 TransactionIsolationLevel::SERIALIZABLE => 'SERIALIZABLE',
189 };
190 }
191
192 /**
193 * {@inheritDoc}
194 */
195 public function getBooleanTypeDeclarationSQL(array $column): string
196 {
197 return 'NUMBER(1)';
198 }
199
200 /**
201 * {@inheritDoc}
202 */
203 public function getIntegerTypeDeclarationSQL(array $column): string
204 {
205 return 'NUMBER(10)';
206 }
207
208 /**
209 * {@inheritDoc}
210 */
211 public function getBigIntTypeDeclarationSQL(array $column): string
212 {
213 return 'NUMBER(20)';
214 }
215
216 /**
217 * {@inheritDoc}
218 */
219 public function getSmallIntTypeDeclarationSQL(array $column): string
220 {
221 return 'NUMBER(5)';
222 }
223
224 /**
225 * {@inheritDoc}
226 */
227 public function getDateTimeTypeDeclarationSQL(array $column): string
228 {
229 return 'TIMESTAMP(0)';
230 }
231
232 /**
233 * {@inheritDoc}
234 */
235 public function getDateTimeTzTypeDeclarationSQL(array $column): string
236 {
237 return 'TIMESTAMP(0) WITH TIME ZONE';
238 }
239
240 /**
241 * {@inheritDoc}
242 */
243 public function getDateTypeDeclarationSQL(array $column): string
244 {
245 return 'DATE';
246 }
247
248 /**
249 * {@inheritDoc}
250 */
251 public function getTimeTypeDeclarationSQL(array $column): string
252 {
253 return 'DATE';
254 }
255
256 /**
257 * {@inheritDoc}
258 */
259 protected function _getCommonIntegerTypeDeclarationSQL(array $column): string
260 {
261 return '';
262 }
263
264 protected function getVarcharTypeDeclarationSQLSnippet(?int $length): string
265 {
266 if ($length === null) {
267 throw ColumnLengthRequired::new($this, 'VARCHAR2');
268 }
269
270 return sprintf('VARCHAR2(%d)', $length);
271 }
272
273 protected function getBinaryTypeDeclarationSQLSnippet(?int $length): string
274 {
275 if ($length === null) {
276 throw ColumnLengthRequired::new($this, 'RAW');
277 }
278
279 return sprintf('RAW(%d)', $length);
280 }
281
282 protected function getVarbinaryTypeDeclarationSQLSnippet(?int $length): string
283 {
284 return $this->getBinaryTypeDeclarationSQLSnippet($length);
285 }
286
287 /**
288 * {@inheritDoc}
289 */
290 public function getClobTypeDeclarationSQL(array $column): string
291 {
292 return 'CLOB';
293 }
294
295 /** @internal The method should be only used from within the {@see AbstractSchemaManager} class hierarchy. */
296 public function getListDatabasesSQL(): string
297 {
298 return 'SELECT username FROM all_users';
299 }
300
301 /** @internal The method should be only used from within the {@see AbstractSchemaManager} class hierarchy. */
302 public function getListSequencesSQL(string $database): string
303 {
304 return 'SELECT SEQUENCE_NAME, MIN_VALUE, INCREMENT_BY FROM SYS.ALL_SEQUENCES WHERE SEQUENCE_OWNER = '
305 . $this->quoteStringLiteral(
306 $this->normalizeIdentifier($database)->getName(),
307 );
308 }
309
310 /**
311 * {@inheritDoc}
312 */
313 protected function _getCreateTableSQL(string $name, array $columns, array $options = []): array
314 {
315 $indexes = $options['indexes'] ?? [];
316 $options['indexes'] = [];
317 $sql = parent::_getCreateTableSQL($name, $columns, $options);
318
319 foreach ($columns as $column) {
320 if (isset($column['sequence'])) {
321 $sql[] = $this->getCreateSequenceSQL($column['sequence']);
322 }
323
324 if (
325 empty($column['autoincrement'])
326 ) {
327 continue;
328 }
329
330 $sql = array_merge($sql, $this->getCreateAutoincrementSql($column['name'], $name));
331 }
332
333 foreach ($indexes as $index) {
334 $sql[] = $this->getCreateIndexSQL($index, $name);
335 }
336
337 return $sql;
338 }
339
340 /** @internal The method should be only used from within the {@see AbstractSchemaManager} class hierarchy. */
341 public function getListViewsSQL(string $database): string
342 {
343 return 'SELECT view_name, text FROM sys.user_views';
344 }
345
346 /** @return array<int, string> */
347 protected function getCreateAutoincrementSql(string $name, string $table, int $start = 1): array
348 {
349 $tableIdentifier = $this->normalizeIdentifier($table);
350 $quotedTableName = $tableIdentifier->getQuotedName($this);
351 $unquotedTableName = $tableIdentifier->getName();
352
353 $nameIdentifier = $this->normalizeIdentifier($name);
354 $quotedName = $nameIdentifier->getQuotedName($this);
355 $unquotedName = $nameIdentifier->getName();
356
357 $sql = [];
358
359 $autoincrementIdentifierName = $this->getAutoincrementIdentifierName($tableIdentifier);
360
361 $idx = new Index($autoincrementIdentifierName, [$quotedName], true, true);
362
363 $sql[] = "DECLARE
364 constraints_Count NUMBER;
365BEGIN
366 SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count
367 FROM USER_CONSTRAINTS
368 WHERE TABLE_NAME = '" . $unquotedTableName . "'
369 AND CONSTRAINT_TYPE = 'P';
370 IF constraints_Count = 0 OR constraints_Count = '' THEN
371 EXECUTE IMMEDIATE '" . $this->getCreateIndexSQL($idx, $quotedTableName) . "';
372 END IF;
373END;";
374
375 $sequenceName = $this->getIdentitySequenceName(
376 $tableIdentifier->isQuoted() ? $quotedTableName : $unquotedTableName,
377 );
378 $sequence = new Sequence($sequenceName, $start);
379 $sql[] = $this->getCreateSequenceSQL($sequence);
380
381 $sql[] = 'CREATE TRIGGER ' . $autoincrementIdentifierName . '
382 BEFORE INSERT
383 ON ' . $quotedTableName . '
384 FOR EACH ROW
385DECLARE
386 last_Sequence NUMBER;
387 last_InsertID NUMBER;
388BEGIN
389 IF (:NEW.' . $quotedName . ' IS NULL OR :NEW.' . $quotedName . ' = 0) THEN
390 SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $quotedName . ' FROM DUAL;
391 ELSE
392 SELECT NVL(Last_Number, 0) INTO last_Sequence
393 FROM User_Sequences
394 WHERE Sequence_Name = \'' . $sequence->getName() . '\';
395 SELECT :NEW.' . $quotedName . ' INTO last_InsertID FROM DUAL;
396 WHILE (last_InsertID > last_Sequence) LOOP
397 SELECT ' . $sequenceName . '.NEXTVAL INTO last_Sequence FROM DUAL;
398 END LOOP;
399 SELECT ' . $sequenceName . '.NEXTVAL INTO last_Sequence FROM DUAL;
400 END IF;
401END;';
402
403 return $sql;
404 }
405
406 /**
407 * @internal The method should be only used from within the OracleSchemaManager class hierarchy.
408 *
409 * Returns the SQL statements to drop the autoincrement for the given table name.
410 *
411 * @param string $table The table name to drop the autoincrement for.
412 *
413 * @return string[]
414 */
415 public function getDropAutoincrementSql(string $table): array
416 {
417 $table = $this->normalizeIdentifier($table);
418 $autoincrementIdentifierName = $this->getAutoincrementIdentifierName($table);
419 $identitySequenceName = $this->getIdentitySequenceName(
420 $table->isQuoted() ? $table->getQuotedName($this) : $table->getName(),
421 );
422
423 return [
424 'DROP TRIGGER ' . $autoincrementIdentifierName,
425 $this->getDropSequenceSQL($identitySequenceName),
426 $this->getDropConstraintSQL($autoincrementIdentifierName, $table->getQuotedName($this)),
427 ];
428 }
429
430 /**
431 * Normalizes the given identifier.
432 *
433 * Uppercases the given identifier if it is not quoted by intention
434 * to reflect Oracle's internal auto uppercasing strategy of unquoted identifiers.
435 *
436 * @param string $name The identifier to normalize.
437 */
438 private function normalizeIdentifier(string $name): Identifier
439 {
440 $identifier = new Identifier($name);
441
442 return $identifier->isQuoted() ? $identifier : new Identifier(strtoupper($name));
443 }
444
445 /**
446 * Adds suffix to identifier,
447 *
448 * if the new string exceeds max identifier length,
449 * keeps $suffix, cuts from $identifier as much as the part exceeding.
450 */
451 private function addSuffix(string $identifier, string $suffix): string
452 {
453 $maxPossibleLengthWithoutSuffix = $this->getMaxIdentifierLength() - strlen($suffix);
454 if (strlen($identifier) > $maxPossibleLengthWithoutSuffix) {
455 $identifier = substr($identifier, 0, $maxPossibleLengthWithoutSuffix);
456 }
457
458 return $identifier . $suffix;
459 }
460
461 /**
462 * Returns the autoincrement primary key identifier name for the given table identifier.
463 *
464 * Quotes the autoincrement primary key identifier name
465 * if the given table name is quoted by intention.
466 */
467 private function getAutoincrementIdentifierName(Identifier $table): string
468 {
469 $identifierName = $this->addSuffix($table->getName(), '_AI_PK');
470
471 return $table->isQuoted()
472 ? $this->quoteSingleIdentifier($identifierName)
473 : $identifierName;
474 }
475
476 public function getDropForeignKeySQL(string $foreignKey, string $table): string
477 {
478 return $this->getDropConstraintSQL($foreignKey, $table);
479 }
480
481 /** @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy. */
482 public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey): string
483 {
484 $referentialAction = '';
485
486 if ($foreignKey->hasOption('onDelete')) {
487 $referentialAction = $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete'));
488 }
489
490 if ($referentialAction !== '') {
491 return ' ON DELETE ' . $referentialAction;
492 }
493
494 return '';
495 }
496
497 /** @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy. */
498 public function getForeignKeyReferentialActionSQL(string $action): string
499 {
500 $action = strtoupper($action);
501
502 return match ($action) {
503 'RESTRICT',
504 'NO ACTION' => '',
505 'CASCADE',
506 'SET NULL' => $action,
507 default => throw new InvalidArgumentException(sprintf('Invalid foreign key action "%s".', $action)),
508 };
509 }
510
511 public function getCreateDatabaseSQL(string $name): string
512 {
513 return 'CREATE USER ' . $name;
514 }
515
516 public function getDropDatabaseSQL(string $name): string
517 {
518 return 'DROP USER ' . $name . ' CASCADE';
519 }
520
521 /**
522 * {@inheritDoc}
523 */
524 public function getAlterTableSQL(TableDiff $diff): array
525 {
526 $sql = [];
527 $commentsSQL = [];
528 $columnSql = [];
529
530 $addColumnSQL = [];
531
532 $tableNameSQL = $diff->getOldTable()->getQuotedName($this);
533
534 foreach ($diff->getAddedColumns() as $column) {
535 $addColumnSQL[] = $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());
536 $comment = $column->getComment();
537
538 if ($comment === '') {
539 continue;
540 }
541
542 $commentsSQL[] = $this->getCommentOnColumnSQL(
543 $tableNameSQL,
544 $column->getQuotedName($this),
545 $comment,
546 );
547 }
548
549 if (count($addColumnSQL) > 0) {
550 $sql[] = 'ALTER TABLE ' . $tableNameSQL . ' ADD (' . implode(', ', $addColumnSQL) . ')';
551 }
552
553 $modifyColumnSQL = [];
554 foreach ($diff->getModifiedColumns() as $columnDiff) {
555 $newColumn = $columnDiff->getNewColumn();
556 $oldColumn = $columnDiff->getOldColumn();
557
558 $newColumnProperties = $newColumn->toArray();
559 $oldColumnProperties = $oldColumn->toArray();
560
561 $oldSQL = $this->getColumnDeclarationSQL('', $oldColumnProperties);
562 $newSQL = $this->getColumnDeclarationSQL('', $newColumnProperties);
563
564 if ($newSQL !== $oldSQL) {
565 if (! $columnDiff->hasNotNullChanged()) {
566 unset($newColumnProperties['notnull']);
567 $newSQL = $this->getColumnDeclarationSQL('', $newColumnProperties);
568 }
569
570 $modifyColumnSQL[] = $newColumn->getQuotedName($this) . $newSQL;
571 }
572
573 if (! $columnDiff->hasCommentChanged()) {
574 continue;
575 }
576
577 $commentsSQL[] = $this->getCommentOnColumnSQL(
578 $tableNameSQL,
579 $newColumn->getQuotedName($this),
580 $newColumn->getComment(),
581 );
582 }
583
584 if (count($modifyColumnSQL) > 0) {
585 $sql[] = 'ALTER TABLE ' . $tableNameSQL . ' MODIFY (' . implode(', ', $modifyColumnSQL) . ')';
586 }
587
588 foreach ($diff->getRenamedColumns() as $oldColumnName => $column) {
589 $oldColumnName = new Identifier($oldColumnName);
590
591 $sql[] = 'ALTER TABLE ' . $tableNameSQL . ' RENAME COLUMN ' . $oldColumnName->getQuotedName($this)
592 . ' TO ' . $column->getQuotedName($this);
593 }
594
595 $dropColumnSQL = [];
596 foreach ($diff->getDroppedColumns() as $column) {
597 $dropColumnSQL[] = $column->getQuotedName($this);
598 }
599
600 if (count($dropColumnSQL) > 0) {
601 $sql[] = 'ALTER TABLE ' . $tableNameSQL . ' DROP (' . implode(', ', $dropColumnSQL) . ')';
602 }
603
604 return array_merge(
605 $this->getPreAlterTableIndexForeignKeySQL($diff),
606 $sql,
607 $commentsSQL,
608 $this->getPostAlterTableIndexForeignKeySQL($diff),
609 $columnSql,
610 );
611 }
612
613 /**
614 * {@inheritDoc}
615 *
616 * @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy.
617 */
618 public function getColumnDeclarationSQL(string $name, array $column): string
619 {
620 if (isset($column['columnDefinition'])) {
621 $declaration = $column['columnDefinition'];
622 } else {
623 $default = $this->getDefaultValueDeclarationSQL($column);
624
625 $notnull = '';
626
627 if (isset($column['notnull'])) {
628 $notnull = $column['notnull'] ? ' NOT NULL' : ' NULL';
629 }
630
631 $typeDecl = $column['type']->getSQLDeclaration($column, $this);
632 $declaration = $typeDecl . $default . $notnull;
633 }
634
635 return $name . ' ' . $declaration;
636 }
637
638 /**
639 * {@inheritDoc}
640 */
641 protected function getRenameIndexSQL(string $oldIndexName, Index $index, string $tableName): array
642 {
643 if (str_contains($tableName, '.')) {
644 [$schema] = explode('.', $tableName);
645 $oldIndexName = $schema . '.' . $oldIndexName;
646 }
647
648 return ['ALTER INDEX ' . $oldIndexName . ' RENAME TO ' . $index->getQuotedName($this)];
649 }
650
651 protected function getIdentitySequenceName(string $tableName): string
652 {
653 $table = new Identifier($tableName);
654
655 // No usage of column name to preserve BC compatibility with <2.5
656 $identitySequenceName = $this->addSuffix($table->getName(), '_SEQ');
657
658 if ($table->isQuoted()) {
659 $identitySequenceName = '"' . $identitySequenceName . '"';
660 }
661
662 $identitySequenceIdentifier = $this->normalizeIdentifier($identitySequenceName);
663
664 return $identitySequenceIdentifier->getQuotedName($this);
665 }
666
667 /** @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy. */
668 public function supportsCommentOnStatement(): bool
669 {
670 return true;
671 }
672
673 protected function doModifyLimitQuery(string $query, ?int $limit, int $offset): string
674 {
675 if ($offset > 0) {
676 $query .= sprintf(' OFFSET %d ROWS', $offset);
677 }
678
679 if ($limit !== null) {
680 $query .= sprintf(' FETCH NEXT %d ROWS ONLY', $limit);
681 }
682
683 return $query;
684 }
685
686 public function getCreateTemporaryTableSnippetSQL(): string
687 {
688 return 'CREATE GLOBAL TEMPORARY TABLE';
689 }
690
691 public function getDateTimeTzFormatString(): string
692 {
693 return 'Y-m-d H:i:sP';
694 }
695
696 public function getDateFormatString(): string
697 {
698 return 'Y-m-d 00:00:00';
699 }
700
701 public function getTimeFormatString(): string
702 {
703 return '1900-01-01 H:i:s';
704 }
705
706 public function getMaxIdentifierLength(): int
707 {
708 return 128;
709 }
710
711 public function supportsSequences(): bool
712 {
713 return true;
714 }
715
716 public function supportsReleaseSavepoints(): bool
717 {
718 return false;
719 }
720
721 public function getTruncateTableSQL(string $tableName, bool $cascade = false): string
722 {
723 $tableIdentifier = new Identifier($tableName);
724
725 return 'TRUNCATE TABLE ' . $tableIdentifier->getQuotedName($this);
726 }
727
728 public function getDummySelectSQL(string $expression = '1'): string
729 {
730 return sprintf('SELECT %s FROM DUAL', $expression);
731 }
732
733 protected function initializeDoctrineTypeMappings(): void
734 {
735 $this->doctrineTypeMapping = [
736 'binary_double' => Types::FLOAT,
737 'binary_float' => Types::FLOAT,
738 'binary_integer' => Types::BOOLEAN,
739 'blob' => Types::BLOB,
740 'char' => Types::STRING,
741 'clob' => Types::TEXT,
742 'date' => Types::DATE_MUTABLE,
743 'float' => Types::FLOAT,
744 'integer' => Types::INTEGER,
745 'long' => Types::STRING,
746 'long raw' => Types::BLOB,
747 'nchar' => Types::STRING,
748 'nclob' => Types::TEXT,
749 'number' => Types::INTEGER,
750 'nvarchar2' => Types::STRING,
751 'pls_integer' => Types::BOOLEAN,
752 'raw' => Types::BINARY,
753 'rowid' => Types::STRING,
754 'timestamp' => Types::DATETIME_MUTABLE,
755 'timestamptz' => Types::DATETIMETZ_MUTABLE,
756 'urowid' => Types::STRING,
757 'varchar' => Types::STRING,
758 'varchar2' => Types::STRING,
759 ];
760 }
761
762 public function releaseSavePoint(string $savepoint): string
763 {
764 return '';
765 }
766
767 protected function createReservedKeywordsList(): KeywordList
768 {
769 return new OracleKeywords();
770 }
771
772 /**
773 * {@inheritDoc}
774 */
775 public function getBlobTypeDeclarationSQL(array $column): string
776 {
777 return 'BLOB';
778 }
779
780 public function createSchemaManager(Connection $connection): OracleSchemaManager
781 {
782 return new OracleSchemaManager($connection, $this);
783 }
784}