Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/Platforms/AbstractPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -1652,6 +1652,32 @@ public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey
return $query;
}

/**
* Returns the SQL fragment representing the deferrability of a constraint.
*/
protected function getConstraintDeferrabilitySQL(ForeignKeyConstraint $foreignKey): string
{
$sql = '';

if ($foreignKey->hasOption('deferrable')) {
if ($foreignKey->getOption('deferrable') !== false) {
$sql .= ' DEFERRABLE';
} else {
$sql .= ' NOT DEFERRABLE';
}
}

if ($foreignKey->hasOption('deferred')) {
if ($foreignKey->getOption('deferred') !== false) {
$sql .= ' INITIALLY DEFERRED';
} else {
$sql .= ' INITIALLY IMMEDIATE';
}
}

return $sql;
}

/**
* Returns the given referential action in uppercase if valid, otherwise throws an exception.
*
Expand Down
14 changes: 10 additions & 4 deletions src/Platforms/OraclePlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -483,17 +483,23 @@ public function getDropForeignKeySQL(string $foreignKey, string $table): string
/** @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy. */
public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey): string
{
$referentialAction = '';
$sql = '';

if ($foreignKey->hasOption('onDelete')) {
$referentialAction = $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete'));

if ($referentialAction !== '') {
$sql .= ' ON DELETE ' . $referentialAction;
}
}

if ($referentialAction !== '') {
return ' ON DELETE ' . $referentialAction;
$deferrabilitySQL = $this->getConstraintDeferrabilitySQL($foreignKey);

if ($deferrabilitySQL !== '') {
$sql .= $deferrabilitySQL;
}

return '';
return $sql;
}

/** @internal The method should be only used from within the {@see AbstractPlatform} class hierarchy. */
Expand Down
16 changes: 3 additions & 13 deletions src/Platforms/PostgreSQLPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,20 +182,10 @@ public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey

$query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey);

if ($foreignKey->hasOption('deferrable')) {
if ($foreignKey->getOption('deferrable') !== false) {
$query .= ' DEFERRABLE';
} else {
$query .= ' NOT DEFERRABLE';
}
}
$deferrabilitySQL = $this->getConstraintDeferrabilitySQL($foreignKey);

if ($foreignKey->hasOption('deferred')) {
if ($foreignKey->getOption('deferred') !== false) {
$query .= ' INITIALLY DEFERRED';
} else {
$query .= ' INITIALLY IMMEDIATE';
}
if ($deferrabilitySQL !== '') {
$query .= $deferrabilitySQL;
}

return $query;
Expand Down
10 changes: 9 additions & 1 deletion src/Schema/OracleSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ protected function _getPortableTableForeignKeysList(array $tableForeignKeys): ar
'foreign' => [],
'foreignTable' => $value['references_table'],
'onDelete' => $value['delete_rule'],
'deferrable' => $value['deferrable'] === 'DEFERRABLE',
'deferred' => $value['deferred'] === 'DEFERRED',
];
}

Expand All @@ -230,7 +232,11 @@ protected function _getPortableTableForeignKeyDefinition(array $tableForeignKey)
$this->getQuotedIdentifierName($tableForeignKey['foreignTable']),
$tableForeignKey['foreign'],
$this->getQuotedIdentifierName($tableForeignKey['name']),
['onDelete' => $tableForeignKey['onDelete']],
[
'onDelete' => $tableForeignKey['onDelete'],
'deferrable' => $tableForeignKey['deferrable'],
'deferred' => $tableForeignKey['deferred'],
],
);
}

Expand Down Expand Up @@ -412,6 +418,8 @@ protected function selectForeignKeyColumns(string $databaseName, ?string $tableN
$sql .= <<<'SQL'
ALC.CONSTRAINT_NAME,
ALC.DELETE_RULE,
ALC.DEFERRABLE,
ALC.DEFERRED,
COLS.COLUMN_NAME LOCAL_COLUMN,
COLS.POSITION,
R_COLS.TABLE_NAME REFERENCES_TABLE,
Expand Down
2 changes: 1 addition & 1 deletion tests/Functional/Schema/ForeignKeyConstraintTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ public function testDeferrabilityIntrospection(array $options, array $expectedOp

if ($platform instanceof SQLitePlatform) {
self::markTestIncomplete('Not all combinations of options are currently properly introspected on SQLite.');
} elseif (! $platform instanceof PostgreSQLPlatform) {
} elseif (! $platform instanceof PostgreSQLPlatform && ! $platform instanceof OraclePlatform) {
self::markTestSkipped(sprintf(
'Introspection of constraint deferrability is currently unsupported on %s.',
$platform::class,
Expand Down