Blame | Letzte Änderung | Log anzeigen | RSS feed
<?phpnamespace Doctrine\DBAL\Platforms;use Doctrine\DBAL\Connection;use Doctrine\DBAL\Exception;use Doctrine\DBAL\Schema\ForeignKeyConstraint;use Doctrine\DBAL\Schema\Identifier;use Doctrine\DBAL\Schema\Index;use Doctrine\DBAL\Schema\OracleSchemaManager;use Doctrine\DBAL\Schema\Sequence;use Doctrine\DBAL\Schema\Table;use Doctrine\DBAL\Schema\TableDiff;use Doctrine\DBAL\TransactionIsolationLevel;use Doctrine\DBAL\Types\BinaryType;use Doctrine\Deprecations\Deprecation;use InvalidArgumentException;use function array_merge;use function count;use function explode;use function func_get_arg;use function func_num_args;use function implode;use function preg_match;use function sprintf;use function strlen;use function strpos;use function strtoupper;use function substr;/*** OraclePlatform.*/class OraclePlatform extends AbstractPlatform{/*** Assertion for Oracle identifiers.** @deprecated** @link http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements008.htm** @param string $identifier** @return void** @throws Exception*/public static function assertValidIdentifier($identifier){if (preg_match('(^(([a-zA-Z]{1}[a-zA-Z0-9_$#]{0,})|("[^"]+"))$)', $identifier) === 0) {throw new Exception('Invalid Oracle identifier');}}/*** {@inheritDoc}*/public function getSubstringExpression($string, $start, $length = null){if ($length !== null) {return sprintf('SUBSTR(%s, %d, %d)', $string, $start, $length);}return sprintf('SUBSTR(%s, %d)', $string, $start);}/*** @deprecated Generate dates within the application.** @param string $type** @return string*/public function getNowExpression($type = 'timestamp'){Deprecation::trigger('doctrine/dbal','https://github.com/doctrine/dbal/pull/4753','OraclePlatform::getNowExpression() is deprecated. Generate dates within the application.',);switch ($type) {case 'date':case 'time':case 'timestamp':default:return 'TO_CHAR(CURRENT_TIMESTAMP, \'YYYY-MM-DD HH24:MI:SS\')';}}/*** {@inheritDoc}*/public function getLocateExpression($str, $substr, $startPos = false){if ($startPos === false) {return 'INSTR(' . $str . ', ' . $substr . ')';}return 'INSTR(' . $str . ', ' . $substr . ', ' . $startPos . ')';}/*** {@inheritdoc}*/protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit){switch ($unit) {case DateIntervalUnit::MONTH:case DateIntervalUnit::QUARTER:case DateIntervalUnit::YEAR:switch ($unit) {case DateIntervalUnit::QUARTER:$interval *= 3;break;case DateIntervalUnit::YEAR:$interval *= 12;break;}return 'ADD_MONTHS(' . $date . ', ' . $operator . $interval . ')';default:$calculationClause = '';switch ($unit) {case DateIntervalUnit::SECOND:$calculationClause = '/24/60/60';break;case DateIntervalUnit::MINUTE:$calculationClause = '/24/60';break;case DateIntervalUnit::HOUR:$calculationClause = '/24';break;case DateIntervalUnit::WEEK:$calculationClause = '*7';break;}return '(' . $date . $operator . $interval . $calculationClause . ')';}}/*** {@inheritDoc}*/public function getDateDiffExpression($date1, $date2){return sprintf('TRUNC(%s) - TRUNC(%s)', $date1, $date2);}/*** {@inheritDoc}*/public function getBitAndComparisonExpression($value1, $value2){return 'BITAND(' . $value1 . ', ' . $value2 . ')';}public function getCurrentDatabaseExpression(): string{return "SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA')";}/*** {@inheritDoc}*/public function getBitOrComparisonExpression($value1, $value2){return '(' . $value1 . '-' .$this->getBitAndComparisonExpression($value1, $value2). '+' . $value2 . ')';}/*** {@inheritDoc}*/public function getCreatePrimaryKeySQL(Index $index, $table): string{if ($table instanceof Table) {Deprecation::trigger('doctrine/dbal','https://github.com/doctrine/dbal/issues/4798','Passing $table as a Table object to %s is deprecated. Pass it as a quoted name instead.',__METHOD__,);$table = $table->getQuotedName($this);}return 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $index->getQuotedName($this). ' PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index) . ')';}/*** {@inheritDoc}** Need to specifiy minvalue, since start with is hidden in the system and MINVALUE <= START WITH.* Therefore we can use MINVALUE to be able to get a hint what START WITH was for later introspection* in {@see listSequences()}*/public function getCreateSequenceSQL(Sequence $sequence){return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) .' START WITH ' . $sequence->getInitialValue() .' MINVALUE ' . $sequence->getInitialValue() .' INCREMENT BY ' . $sequence->getAllocationSize() .$this->getSequenceCacheSQL($sequence);}/*** {@inheritDoc}*/public function getAlterSequenceSQL(Sequence $sequence){return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) .' INCREMENT BY ' . $sequence->getAllocationSize(). $this->getSequenceCacheSQL($sequence);}/*** Cache definition for sequences*/private function getSequenceCacheSQL(Sequence $sequence): string{if ($sequence->getCache() === 0) {return ' NOCACHE';}if ($sequence->getCache() === 1) {return ' NOCACHE';}if ($sequence->getCache() > 1) {return ' CACHE ' . $sequence->getCache();}return '';}/*** {@inheritDoc}*/public function getSequenceNextValSQL($sequence){return 'SELECT ' . $sequence . '.nextval FROM DUAL';}/*** {@inheritDoc}*/public function getSetTransactionIsolationSQL($level){return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level);}/*** {@inheritDoc}*/protected function _getTransactionIsolationLevelSQL($level){switch ($level) {case TransactionIsolationLevel::READ_UNCOMMITTED:return 'READ UNCOMMITTED';case TransactionIsolationLevel::READ_COMMITTED:return 'READ COMMITTED';case TransactionIsolationLevel::REPEATABLE_READ:case TransactionIsolationLevel::SERIALIZABLE:return 'SERIALIZABLE';default:return parent::_getTransactionIsolationLevelSQL($level);}}/*** {@inheritDoc}*/public function getBooleanTypeDeclarationSQL(array $column){return 'NUMBER(1)';}/*** {@inheritDoc}*/public function getIntegerTypeDeclarationSQL(array $column){return 'NUMBER(10)';}/*** {@inheritDoc}*/public function getBigIntTypeDeclarationSQL(array $column){return 'NUMBER(20)';}/*** {@inheritDoc}*/public function getSmallIntTypeDeclarationSQL(array $column){return 'NUMBER(5)';}/*** {@inheritDoc}*/public function getDateTimeTypeDeclarationSQL(array $column){return 'TIMESTAMP(0)';}/*** {@inheritDoc}*/public function getDateTimeTzTypeDeclarationSQL(array $column){return 'TIMESTAMP(0) WITH TIME ZONE';}/*** {@inheritDoc}*/public function getDateTypeDeclarationSQL(array $column){return 'DATE';}/*** {@inheritDoc}*/public function getTimeTypeDeclarationSQL(array $column){return 'DATE';}/*** {@inheritDoc}*/protected function _getCommonIntegerTypeDeclarationSQL(array $column){return '';}/*** {@inheritDoc}*/protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed/*, $lengthOmitted = false*/){if ($length <= 0 || (func_num_args() > 2 && func_get_arg(2))) {Deprecation::trigger('doctrine/dbal','https://github.com/doctrine/dbal/issues/3263','Relying on the default string column length on Oracle is deprecated'. ', specify the length explicitly.',);}return $fixed ? ($length > 0 ? 'CHAR(' . $length . ')' : 'CHAR(2000)'): ($length > 0 ? 'VARCHAR2(' . $length . ')' : 'VARCHAR2(4000)');}/*** {@inheritdoc}*/protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed/*, $lengthOmitted = false*/){if ($length <= 0 || (func_num_args() > 2 && func_get_arg(2))) {Deprecation::trigger('doctrine/dbal','https://github.com/doctrine/dbal/issues/3263','Relying on the default binary column length on Oracle is deprecated'. ', specify the length explicitly.',);}return 'RAW(' . ($length > 0 ? $length : $this->getBinaryMaxLength()) . ')';}/*** {@inheritdoc}** @deprecated*/public function getBinaryMaxLength(){Deprecation::triggerIfCalledFromOutside('doctrine/dbal','https://github.com/doctrine/dbal/issues/3263','OraclePlatform::getBinaryMaxLength() is deprecated.',);return 2000;}/*** {@inheritDoc}*/public function getClobTypeDeclarationSQL(array $column){return 'CLOB';}/*** {@inheritDoc}** @internal The method should be only used from within the {@see AbstractSchemaManager} class hierarchy.*/public function getListDatabasesSQL(){return 'SELECT username FROM all_users';}/*** {@inheritDoc}** @internal The method should be only used from within the {@see AbstractSchemaManager} class hierarchy.*/public function getListSequencesSQL($database){$database = $this->normalizeIdentifier($database);$database = $this->quoteStringLiteral($database->getName());return 'SELECT sequence_name, min_value, increment_by FROM sys.all_sequences ' .'WHERE SEQUENCE_OWNER = ' . $database;}/*** {@inheritDoc}*/protected function _getCreateTableSQL($name, array $columns, array $options = []){$indexes = $options['indexes'] ?? [];$options['indexes'] = [];$sql = parent::_getCreateTableSQL($name, $columns, $options);foreach ($columns as $columnName => $column) {if (isset($column['sequence'])) {$sql[] = $this->getCreateSequenceSQL($column['sequence']);}if (! isset($column['autoincrement']) || ! $column['autoincrement'] &&(! isset($column['autoinc']) || ! $column['autoinc'])) {continue;}$sql = array_merge($sql, $this->getCreateAutoincrementSql($columnName, $name));}foreach ($indexes as $index) {$sql[] = $this->getCreateIndexSQL($index, $name);}return $sql;}/*** @deprecated The SQL used for schema introspection is an implementation detail and should not be relied upon.** {@inheritDoc}** @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaOracleReader.html*/public function getListTableIndexesSQL($table, $database = null){$table = $this->normalizeIdentifier($table);$table = $this->quoteStringLiteral($table->getName());return "SELECT uind_col.index_name AS name,(SELECT uind.index_typeFROM user_indexes uindWHERE uind.index_name = uind_col.index_name) AS type,decode((SELECT uind.uniquenessFROM user_indexes uindWHERE uind.index_name = uind_col.index_name),'NONUNIQUE',0,'UNIQUE',1) AS is_unique,uind_col.column_name AS column_name,uind_col.column_position AS column_pos,(SELECT ucon.constraint_typeFROM user_constraints uconWHERE ucon.index_name = uind_col.index_nameAND ucon.table_name = uind_col.table_name) AS is_primaryFROM user_ind_columns uind_colWHERE uind_col.table_name = " . $table . 'ORDER BY uind_col.column_position ASC';}/*** @deprecated The SQL used for schema introspection is an implementation detail and should not be relied upon.** {@inheritDoc}*/public function getListTablesSQL(){return 'SELECT * FROM sys.user_tables';}/*** {@inheritDoc}** @internal The method should be only used from within the {@see AbstractSchemaManager} class hierarchy.*/public function getListViewsSQL($database){return 'SELECT view_name, text FROM sys.user_views';}/*** @internal The method should be only used from within the OraclePlatform class hierarchy.** @param string $name* @param string $table* @param int $start** @return string[]*/public function getCreateAutoincrementSql($name, $table, $start = 1){$tableIdentifier = $this->normalizeIdentifier($table);$quotedTableName = $tableIdentifier->getQuotedName($this);$unquotedTableName = $tableIdentifier->getName();$nameIdentifier = $this->normalizeIdentifier($name);$quotedName = $nameIdentifier->getQuotedName($this);$unquotedName = $nameIdentifier->getName();$sql = [];$autoincrementIdentifierName = $this->getAutoincrementIdentifierName($tableIdentifier);$idx = new Index($autoincrementIdentifierName, [$quotedName], true, true);$sql[] = "DECLAREconstraints_Count NUMBER;BEGINSELECT COUNT(CONSTRAINT_NAME) INTO constraints_CountFROM USER_CONSTRAINTSWHERE TABLE_NAME = '" . $unquotedTableName . "'AND CONSTRAINT_TYPE = 'P';IF constraints_Count = 0 OR constraints_Count = '' THENEXECUTE IMMEDIATE '" . $this->getCreateConstraintSQL($idx, $quotedTableName) . "';END IF;END;";$sequenceName = $this->getIdentitySequenceName($tableIdentifier->isQuoted() ? $quotedTableName : $unquotedTableName,$nameIdentifier->isQuoted() ? $quotedName : $unquotedName,);$sequence = new Sequence($sequenceName, $start);$sql[] = $this->getCreateSequenceSQL($sequence);$sql[] = 'CREATE TRIGGER ' . $autoincrementIdentifierName . 'BEFORE INSERTON ' . $quotedTableName . 'FOR EACH ROWDECLARElast_Sequence NUMBER;last_InsertID NUMBER;BEGINIF (:NEW.' . $quotedName . ' IS NULL OR :NEW.' . $quotedName . ' = 0) THENSELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $quotedName . ' FROM DUAL;ELSESELECT NVL(Last_Number, 0) INTO last_SequenceFROM User_SequencesWHERE Sequence_Name = \'' . $sequence->getName() . '\';SELECT :NEW.' . $quotedName . ' INTO last_InsertID FROM DUAL;WHILE (last_InsertID > last_Sequence) LOOPSELECT ' . $sequenceName . '.NEXTVAL INTO last_Sequence FROM DUAL;END LOOP;SELECT ' . $sequenceName . '.NEXTVAL INTO last_Sequence FROM DUAL;END IF;END;';return $sql;}/*** @internal The method should be only used from within the OracleSchemaManager class hierarchy.** Returns the SQL statements to drop the autoincrement for the given table name.** @param string $table The table name to drop the autoincrement for.** @return string[]*/public function getDropAutoincrementSql($table){$table = $this->normalizeIdentifier($table);$autoincrementIdentifierName = $this->getAutoincrementIdentifierName($table);$identitySequenceName = $this->getIdentitySequenceName($table->isQuoted() ? $table->getQuotedName($this) : $table->getName(),'',);return ['DROP TRIGGER ' . $autoincrementIdentifierName,$this->getDropSequenceSQL($identitySequenceName),$this->getDropConstraintSQL($autoincrementIdentifierName, $table->getQuotedName($this)),];}/*** Normalizes the given identifier.** Uppercases the given identifier if it is not quoted by intention* to reflect Oracle's internal auto uppercasing strategy of unquoted identifiers.** @param string $name The identifier to normalize.*/private function normalizeIdentifier($name): Identifier{$identifier = new Identifier($name);return $identifier->isQuoted() ? $identifier : new Identifier(strtoupper($name));}/*** Adds suffix to identifier,** if the new string exceeds max identifier length,* keeps $suffix, cuts from $identifier as much as the part exceeding.*/private function addSuffix(string $identifier, string $suffix): string{$maxPossibleLengthWithoutSuffix = $this->getMaxIdentifierLength() - strlen($suffix);if (strlen($identifier) > $maxPossibleLengthWithoutSuffix) {$identifier = substr($identifier, 0, $maxPossibleLengthWithoutSuffix);}return $identifier . $suffix;}/*** Returns the autoincrement primary key identifier name for the given table identifier.** Quotes the autoincrement primary key identifier name* if the given table name is quoted by intention.*/private function getAutoincrementIdentifierName(Identifier $table): string{$identifierName = $this->addSuffix($table->getName(), '_AI_PK');return $table->isQuoted()? $this->quoteSingleIdentifier($identifierName): $identifierName;}/*** @deprecated The SQL used for schema introspection is an implementation detail and should not be relied upon.** {@inheritDoc}*/public function getListTableForeignKeysSQL($table){$table = $this->normalizeIdentifier($table);$table = $this->quoteStringLiteral($table->getName());return "SELECT alc.constraint_name,alc.DELETE_RULE,cols.column_name \"local_column\",cols.position,(SELECT r_cols.table_nameFROM user_cons_columns r_colsWHERE alc.r_constraint_name = r_cols.constraint_nameAND r_cols.position = cols.position) AS \"references_table\",(SELECT r_cols.column_nameFROM user_cons_columns r_colsWHERE alc.r_constraint_name = r_cols.constraint_nameAND r_cols.position = cols.position) AS \"foreign_column\"FROM user_cons_columns colsJOIN user_constraints alcON alc.constraint_name = cols.constraint_nameAND alc.constraint_type = 'R'AND alc.table_name = " . $table . 'ORDER BY cols.constraint_name ASC, cols.position ASC';}/*** @deprecated** {@inheritDoc}*/public function getListTableConstraintsSQL($table){$table = $this->normalizeIdentifier($table);$table = $this->quoteStringLiteral($table->getName());return 'SELECT * FROM user_constraints WHERE table_name = ' . $table;}/*** @deprecated The SQL used for schema introspection is an implementation detail and should not be relied upon.** {@inheritDoc}*/public function getListTableColumnsSQL($table, $database = null){$table = $this->normalizeIdentifier($table);$table = $this->quoteStringLiteral($table->getName());$tabColumnsTableName = 'user_tab_columns';$colCommentsTableName = 'user_col_comments';$tabColumnsOwnerCondition = '';$colCommentsOwnerCondition = '';if ($database !== null && $database !== '/') {$database = $this->normalizeIdentifier($database);$database = $this->quoteStringLiteral($database->getName());$tabColumnsTableName = 'all_tab_columns';$colCommentsTableName = 'all_col_comments';$tabColumnsOwnerCondition = ' AND c.owner = ' . $database;$colCommentsOwnerCondition = ' AND d.OWNER = c.OWNER';}return sprintf(<<<'SQL'SELECT c.*,(SELECT d.commentsFROM %s dWHERE d.TABLE_NAME = c.TABLE_NAME%sAND d.COLUMN_NAME = c.COLUMN_NAME) AS commentsFROM %s cWHERE c.table_name = %s%sORDER BY c.column_idSQL,$colCommentsTableName,$colCommentsOwnerCondition,$tabColumnsTableName,$table,$tabColumnsOwnerCondition,);}/*** {@inheritDoc}*/public function getDropForeignKeySQL($foreignKey, $table){if ($foreignKey instanceof ForeignKeyConstraint) {Deprecation::trigger('doctrine/dbal','https://github.com/doctrine/dbal/issues/4798','Passing $foreignKey as a ForeignKeyConstraint object to %s is deprecated.'. ' Pass it as a quoted name instead.',__METHOD__,);} else {$foreignKey = new Identifier($foreignKey);}if ($table instanceof Table) {Deprecation::trigger('doctrine/dbal','https://github.com/doctrine/dbal/issues/4798','Passing $table as a Table object to %s is deprecated. Pass it as a quoted name instead.',__METHOD__,);} else {$table = new Identifier($table);}$foreignKey = $foreignKey->getQuotedName($this);$table = $table->getQuotedName($this);return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey;}/*** {@inheritdoc}** @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy.*/public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey){$referentialAction = '';if ($foreignKey->hasOption('onDelete')) {$referentialAction = $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete'));}if ($referentialAction !== '') {return ' ON DELETE ' . $referentialAction;}return '';}/*** {@inheritdoc}** @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy.*/public function getForeignKeyReferentialActionSQL($action){$action = strtoupper($action);switch ($action) {case 'RESTRICT': // RESTRICT is not supported, therefore falling back to NO ACTION.case 'NO ACTION':// NO ACTION cannot be declared explicitly,// therefore returning empty string to indicate to OMIT the referential clause.return '';case 'CASCADE':case 'SET NULL':return $action;default:// SET DEFAULT is not supported, throw exception instead.throw new InvalidArgumentException('Invalid foreign key action: ' . $action);}}/*** {@inheritDoc}*/public function getCreateDatabaseSQL($name){return 'CREATE USER ' . $name;}/*** {@inheritDoc}*/public function getDropDatabaseSQL($name){return 'DROP USER ' . $name . ' CASCADE';}/*** {@inheritDoc}*/public function getAlterTableSQL(TableDiff $diff){$sql = [];$commentsSQL = [];$columnSql = [];$fields = [];$tableNameSQL = ($diff->getOldTable() ?? $diff->getName($this))->getQuotedName($this);foreach ($diff->getAddedColumns() as $column) {if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {continue;}$fields[] = $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray());$comment = $this->getColumnComment($column);if ($comment === null || $comment === '') {continue;}$commentsSQL[] = $this->getCommentOnColumnSQL($tableNameSQL,$column->getQuotedName($this),$comment,);}if (count($fields) > 0) {$sql[] = 'ALTER TABLE ' . $tableNameSQL . ' ADD (' . implode(', ', $fields) . ')';}$fields = [];foreach ($diff->getModifiedColumns() as $columnDiff) {if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) {continue;}$newColumn = $columnDiff->getNewColumn();// Do not generate column alteration clause if type is binary and only fixed property has changed.// Oracle only supports binary type columns with variable length.// Avoids unnecessary table alteration statements.if ($newColumn->getType() instanceof BinaryType &&$columnDiff->hasFixedChanged() &&count($columnDiff->changedProperties) === 1) {continue;}$columnHasChangedComment = $columnDiff->hasCommentChanged();/*** Do not add query part if only comment has changed*/if (! ($columnHasChangedComment && count($columnDiff->changedProperties) === 1)) {$newColumnProperties = $newColumn->toArray();if (! $columnDiff->hasNotNullChanged()) {unset($newColumnProperties['notnull']);}$fields[] = $newColumn->getQuotedName($this) . $this->getColumnDeclarationSQL('', $newColumnProperties);}if (! $columnHasChangedComment) {continue;}$commentsSQL[] = $this->getCommentOnColumnSQL($tableNameSQL,$newColumn->getQuotedName($this),$this->getColumnComment($newColumn),);}if (count($fields) > 0) {$sql[] = 'ALTER TABLE ' . $tableNameSQL . ' MODIFY (' . implode(', ', $fields) . ')';}foreach ($diff->getRenamedColumns() as $oldColumnName => $column) {if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) {continue;}$oldColumnName = new Identifier($oldColumnName);$sql[] = 'ALTER TABLE ' . $tableNameSQL . ' RENAME COLUMN ' . $oldColumnName->getQuotedName($this). ' TO ' . $column->getQuotedName($this);}$fields = [];foreach ($diff->getDroppedColumns() as $column) {if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) {continue;}$fields[] = $column->getQuotedName($this);}if (count($fields) > 0) {$sql[] = 'ALTER TABLE ' . $tableNameSQL . ' DROP (' . implode(', ', $fields) . ')';}$tableSql = [];if (! $this->onSchemaAlterTable($diff, $tableSql)) {$sql = array_merge($sql, $commentsSQL);$newName = $diff->getNewName();if ($newName !== false) {Deprecation::trigger('doctrine/dbal','https://github.com/doctrine/dbal/pull/5663','Generation of "rename table" SQL using %s is deprecated. Use getRenameTableSQL() instead.',__METHOD__,);$sql[] = sprintf('ALTER TABLE %s RENAME TO %s',$tableNameSQL,$newName->getQuotedName($this),);}$sql = array_merge($this->getPreAlterTableIndexForeignKeySQL($diff),$sql,$this->getPostAlterTableIndexForeignKeySQL($diff),);}return array_merge($sql, $tableSql, $columnSql);}/*** {@inheritdoc}** @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy.*/public function getColumnDeclarationSQL($name, array $column){if (isset($column['columnDefinition'])) {$columnDef = $this->getCustomTypeDeclarationSQL($column);} else {$default = $this->getDefaultValueDeclarationSQL($column);$notnull = '';if (isset($column['notnull'])) {$notnull = $column['notnull'] ? ' NOT NULL' : ' NULL';}if (! empty($column['unique'])) {Deprecation::trigger('doctrine/dbal','https://github.com/doctrine/dbal/pull/5656','The usage of the "unique" column property is deprecated. Use unique constraints instead.',);$unique = ' ' . $this->getUniqueFieldDeclarationSQL();} else {$unique = '';}if (! empty($column['check'])) {Deprecation::trigger('doctrine/dbal','https://github.com/doctrine/dbal/pull/5656','The usage of the "check" column property is deprecated.',);$check = ' ' . $column['check'];} else {$check = '';}$typeDecl = $column['type']->getSQLDeclaration($column, $this);$columnDef = $typeDecl . $default . $notnull . $unique . $check;}return $name . ' ' . $columnDef;}/*** {@inheritdoc}*/protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName){if (strpos($tableName, '.') !== false) {[$schema] = explode('.', $tableName);$oldIndexName = $schema . '.' . $oldIndexName;}return ['ALTER INDEX ' . $oldIndexName . ' RENAME TO ' . $index->getQuotedName($this)];}/*** {@inheritdoc}** @deprecated*/public function usesSequenceEmulatedIdentityColumns(){Deprecation::trigger('doctrine/dbal','https://github.com/doctrine/dbal/pull/5513','%s is deprecated.',__METHOD__,);return true;}/*** {@inheritdoc}** @internal The method should be only used from within the OraclePlatform class hierarchy.*/public function getIdentitySequenceName($tableName, $columnName){$table = new Identifier($tableName);// No usage of column name to preserve BC compatibility with <2.5$identitySequenceName = $this->addSuffix($table->getName(), '_SEQ');if ($table->isQuoted()) {$identitySequenceName = '"' . $identitySequenceName . '"';}$identitySequenceIdentifier = $this->normalizeIdentifier($identitySequenceName);return $identitySequenceIdentifier->getQuotedName($this);}/*** {@inheritDoc}** @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy.*/public function supportsCommentOnStatement(){return true;}/*** {@inheritDoc}*/public function getName(){Deprecation::triggerIfCalledFromOutside('doctrine/dbal','https://github.com/doctrine/dbal/issues/4749','OraclePlatform::getName() is deprecated. Identify platforms by their class.',);return 'oracle';}/*** {@inheritDoc}*/protected function doModifyLimitQuery($query, $limit, $offset){if ($limit === null && $offset <= 0) {return $query;}if (preg_match('/^\s*SELECT/i', $query) === 1) {if (preg_match('/\sFROM\s/i', $query) === 0) {$query .= ' FROM dual';}$columns = ['a.*'];if ($offset > 0) {$columns[] = 'ROWNUM AS doctrine_rownum';}$query = sprintf('SELECT %s FROM (%s) a', implode(', ', $columns), $query);if ($limit !== null) {$query .= sprintf(' WHERE ROWNUM <= %d', $offset + $limit);}if ($offset > 0) {$query = sprintf('SELECT * FROM (%s) WHERE doctrine_rownum >= %d', $query, $offset + 1);}}return $query;}/*** {@inheritDoc}*/public function getCreateTemporaryTableSnippetSQL(){return 'CREATE GLOBAL TEMPORARY TABLE';}/*** {@inheritDoc}*/public function getDateTimeTzFormatString(){return 'Y-m-d H:i:sP';}/*** {@inheritDoc}*/public function getDateFormatString(){return 'Y-m-d 00:00:00';}/*** {@inheritDoc}*/public function getTimeFormatString(){return '1900-01-01 H:i:s';}/*** {@inheritDoc}*/public function getMaxIdentifierLength(){return 30;}/*** {@inheritDoc}*/public function supportsSequences(){return true;}/*** {@inheritDoc}*/public function supportsReleaseSavepoints(){return false;}/*** {@inheritDoc}*/public function getTruncateTableSQL($tableName, $cascade = false){$tableIdentifier = new Identifier($tableName);return 'TRUNCATE TABLE ' . $tableIdentifier->getQuotedName($this);}/*** {@inheritDoc}*/public function getDummySelectSQL(){$expression = func_num_args() > 0 ? func_get_arg(0) : '1';return sprintf('SELECT %s FROM DUAL', $expression);}/*** {@inheritDoc}*/protected function initializeDoctrineTypeMappings(){$this->doctrineTypeMapping = ['binary_double' => 'float','binary_float' => 'float','binary_integer' => 'boolean','blob' => 'blob','char' => 'string','clob' => 'text','date' => 'date','float' => 'float','integer' => 'integer','long' => 'string','long raw' => 'blob','nchar' => 'string','nclob' => 'text','number' => 'integer','nvarchar2' => 'string','pls_integer' => 'boolean','raw' => 'binary','rowid' => 'string','timestamp' => 'datetime','timestamptz' => 'datetimetz','urowid' => 'string','varchar' => 'string','varchar2' => 'string',];}/*** {@inheritDoc}*/public function releaseSavePoint($savepoint){return '';}/*** {@inheritDoc}** @deprecated Implement {@see createReservedKeywordsList()} instead.*/protected function getReservedKeywordsClass(){Deprecation::triggerIfCalledFromOutside('doctrine/dbal','https://github.com/doctrine/dbal/issues/4510','OraclePlatform::getReservedKeywordsClass() is deprecated,'. ' use OraclePlatform::createReservedKeywordsList() instead.',);return Keywords\OracleKeywords::class;}/*** {@inheritDoc}*/public function getBlobTypeDeclarationSQL(array $column){return 'BLOB';}/** @deprecated The SQL used for schema introspection is an implementation detail and should not be relied upon. */public function getListTableCommentsSQL(string $table, ?string $database = null): string{$tableCommentsName = 'user_tab_comments';$ownerCondition = '';if ($database !== null && $database !== '/') {$tableCommentsName = 'all_tab_comments';$ownerCondition = ' AND owner = ' . $this->quoteStringLiteral($this->normalizeIdentifier($database)->getName(),);}return sprintf(<<<'SQL'SELECT comments FROM %s WHERE table_name = %s%sSQL,$tableCommentsName,$this->quoteStringLiteral($this->normalizeIdentifier($table)->getName()),$ownerCondition,);}public function createSchemaManager(Connection $connection): OracleSchemaManager{return new OracleSchemaManager($connection, $this);}}