Skip to content

Commit

Permalink
Add ReferentialAction class
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov committed Feb 10, 2025
1 parent 06670a6 commit c161161
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 63 deletions.
5 changes: 3 additions & 2 deletions docs/guide/en/command/ddl.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ method:

```php
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Constant\ReferentialAction;

/** @var ConnectionInterface $db */
$db->createCommand()->addForeignKey(
Expand All @@ -189,8 +190,8 @@ $db->createCommand()->addForeignKey(
'profile_id',
'{{%profile}}',
'id',
'CASCADE',
'CASCADE'
ReferentialAction::CASCADE,
ReferentialAction::CASCADE
)->execute();
```

Expand Down
5 changes: 3 additions & 2 deletions docs/guide/pt-BR/command/ddl.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ Para adicionar uma chave estrangeira a uma tabela existente, você pode usar o m

```php
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Constant\ReferentialAction;

/** @var ConnectionInterface $db */
$db->createCommand()->addForeignKey(
Expand All @@ -185,8 +186,8 @@ $db->createCommand()->addForeignKey(
'profile_id',
'{{%profile}}',
'id',
'CASCADE',
'CASCADE'
ReferentialAction::CASCADE,
ReferentialAction::CASCADE
)->execute();
```

Expand Down
18 changes: 8 additions & 10 deletions src/Command/CommandInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Yiisoft\Db\Constant\DataType;
use Yiisoft\Db\Constant\IndexType;
use Yiisoft\Db\Constant\PseudoType;
use Yiisoft\Db\Constant\ReferentialAction;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidArgumentException;
use Yiisoft\Db\Exception\InvalidCallException;
Expand Down Expand Up @@ -99,8 +100,7 @@ public function addDefaultValue(string $table, string $name, string $column, mix

/**
* Creates an SQL command for adding a foreign key constraint to an existing table.
*
* The method will quote the table and column names.
* The method will quote the `name`, `table`, `referenceTable` parameters before using them in the generated SQL.
*
* @param string $table The name of the table to add foreign key constraint to.
* @param string $name The name of the foreign key constraint.
Expand All @@ -109,25 +109,23 @@ public function addDefaultValue(string $table, string $name, string $column, mix
* @param string $referenceTable The name of the table that the foreign key references to.
* @param array|string $referenceColumns The name of the column that the foreign key references to. If there are
* many columns, separate them with commas.
* @param string|null $delete The `ON DELETE` option. Most DBMS support these options: `RESTRICT`, `CASCADE`, `NO ACTION`,
* `SET DEFAULT`, `SET NULL`.
* @param string|null $update The `ON UPDATE` option. Most DBMS support these options: `RESTRICT`, `CASCADE`, `NO ACTION`,
* `SET DEFAULT`, `SET NULL`.
* @param string|null $delete The `ON DELETE` option. See {@see ReferentialAction} class for possible values.
* @param string|null $update The `ON UPDATE` option. See {@see ReferentialAction} class for possible values.
*
* @throws Exception
* @throws InvalidArgumentException
*
* Note: The method will quote the `name`, `table`, `referenceTable` parameters before using them in the generated
* SQL.
* @psalm-param ReferentialAction::*|null $delete
* @psalm-param ReferentialAction::*|null $update
*/
public function addForeignKey(
string $table,
string $name,
array|string $columns,
string $referenceTable,
array|string $referenceColumns,
string $delete = null,
string $update = null
string|null $delete = null,
string|null $update = null
): static;

/**
Expand Down
46 changes: 46 additions & 0 deletions src/Constant/ReferentialAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Constant;

/**
* `ReferentialAction` represents the possible actions that can be performed on the referenced table.
*
* The constants are used to specify `ON DELETE` and `ON UPDATE` actions by {@see ForeignKeyConstraint::onDelete()},
* {@see ForeignKeyConstraint::onUpdate()}, {@see DDLQueryBuilderInterface::addForeignKey()}
* and {@see CommandInterface::addForeignKey()}.
*
* MSSQL does not support `RESTRICT` key world but uses this behavior by default (if no action is specified).
*
* Oracle supports only `CASCADE` and `SET NULL` key worlds and only `ON DELETE` clause.
* `NO ACTION` is used by default for `ON DELETE` and `ON UPDATE` (if no action is specified).
*/
final class ReferentialAction
{
/**
* @var string Used when the referenced rows are not deleted or updated. If rows of the referenced table are used
* by rows of the referencing table, an error is thrown. This is the default behavior.
*/
public const NO_ACTION = 'NO ACTION';
/**
* @var string Used when the referenced rows cannot be deleted or updated. For example, if rows of the referenced
* table are used by rows of the referencing table, it is not permitted to delete those rows from the referenced table.
* This is similar to {@see NO_ACTION}, but is not used by some DBMSs.
*/
public const RESTRICT = 'RESTRICT';
/**
* @var string Used when the referenced row is deleted or updated and all rows that reference it are deleted
* or updated accordingly.
*/
public const CASCADE = 'CASCADE';
/**
* @var string Used when the rows that refer to the deleted or updated row are set to `NULL`.
* If columns are defined as `NOT NULL`, an error is thrown.
*/
public const SET_NULL = 'SET NULL';
/**
* @var string Used when the rows that refer to the deleted or updated row are set to their default values.
*/
public const SET_DEFAULT = 'SET DEFAULT';
}
14 changes: 14 additions & 0 deletions src/Constraint/ForeignKeyConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Yiisoft\Db\Constraint;

use Yiisoft\Db\Constant\ReferentialAction;

/**
* Represents a foreign key constraint in a database.
*
Expand All @@ -17,7 +19,9 @@ final class ForeignKeyConstraint extends Constraint
private string|null $foreignSchemaName = null;
private string|null $foreignTableName = null;
private array $foreignColumnNames = [];
/** @psalm-var ReferentialAction::*|null */
private string|null $onUpdate = null;
/** @psalm-var ReferentialAction::*|null */
private string|null $onDelete = null;

/**
Expand Down Expand Up @@ -46,6 +50,8 @@ public function getForeignColumnNames(): array

/**
* @return string|null The referential action if rows in a referenced table are to be updated.
*
* @psalm-return ReferentialAction::*|null
*/
public function getOnUpdate(): string|null
{
Expand All @@ -54,6 +60,8 @@ public function getOnUpdate(): string|null

/**
* @return string|null The referential action if rows in a referenced table are to be deleted.
*
* @psalm-return ReferentialAction::*|null
*/
public function getOnDelete(): string|null
{
Expand Down Expand Up @@ -97,6 +105,9 @@ public function foreignColumnNames(array $value): self
* Set the referential action if rows in a referenced table are to be updated.
*
* @param string|null $value The referential action if rows in a referenced table are to be updated.
* See {@see ReferentialAction} class for possible values.
*
* @psalm-param ReferentialAction::*|null $value
*/
public function onUpdate(string|null $value): self
{
Expand All @@ -108,6 +119,9 @@ public function onUpdate(string|null $value): self
* Set the referential action if rows in a referenced table are to be deleted.
*
* @param string|null $value The referential action if rows in a referenced table are to be deleted.
* See {@see ReferentialAction} class for possible values.
*
* @psalm-param ReferentialAction::*|null $value
*/
public function onDelete(string|null $value): self
{
Expand Down
5 changes: 5 additions & 0 deletions src/QueryBuilder/AbstractColumnDefinitionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Yiisoft\Db\QueryBuilder;

use Yiisoft\Db\Constant\ColumnType;
use Yiisoft\Db\Constant\ReferentialAction;
use Yiisoft\Db\Schema\Column\ColumnInterface;

use function in_array;
Expand Down Expand Up @@ -231,6 +232,8 @@ protected function buildReferenceDefinition(ColumnInterface $column): string|nul

/**
* Builds the ON DELETE clause for the column reference.
*
* @psalm-param ReferentialAction::* $onDelete
*/
protected function buildOnDelete(string $onDelete): string
{
Expand All @@ -239,6 +242,8 @@ protected function buildOnDelete(string $onDelete): string

/**
* Builds the ON UPDATE clause for the column reference.
*
* @psalm-param ReferentialAction::* $onUpdate
*/
protected function buildOnUpdate(string $onUpdate): string
{
Expand Down
11 changes: 6 additions & 5 deletions src/QueryBuilder/DDLQueryBuilderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Yiisoft\Db\QueryBuilder;

use Yiisoft\Db\Constant\IndexType;
use Yiisoft\Db\Constant\ReferentialAction;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidArgumentException;
use Yiisoft\Db\Exception\InvalidConfigException;
Expand Down Expand Up @@ -103,6 +104,7 @@ public function addDefaultValue(string $table, string $name, string $column, mix

/**
* Builds an SQL statement for adding a foreign key constraint to an existing table.
* The method will quote the `name`, `table`, `referenceTable` parameters before using them in the generated SQL.
*
* @param string $table The table to add the foreign key constraint will to.
* @param string $name The name of the foreign key constraint.
Expand All @@ -111,17 +113,16 @@ public function addDefaultValue(string $table, string $name, string $column, mix
* @param string $referenceTable The table that the foreign key references to.
* @param array|string $referenceColumns The name of the column that the foreign key references to.
* If there are many columns, separate them with commas or use an array to represent them.
* @param string|null $delete The `ON DELETE` option. Most DBMS support these options: `RESTRICT`, `CASCADE`, `NO ACTION`,
* `SET DEFAULT`, `SET NULL`.
* @param string|null $update The `ON UPDATE` option. Most DBMS support these options: `RESTRICT`, `CASCADE`, `NO ACTION`,
* `SET DEFAULT`, `SET NULL`.
* @param string|null $delete The `ON DELETE` option. See {@see ReferentialAction} class for possible values.
* @param string|null $update The `ON UPDATE` option. See {@see ReferentialAction} class for possible values.
*
* @throws Exception
* @throws InvalidArgumentException
*
* @return string The SQL statement for adding a foreign key constraint to an existing table.
*
* Note: The method will quote the `name`, `table`, `referenceTable` parameters before using them in the generated SQL.
* @psalm-param ReferentialAction::*|null $delete
* @psalm-param ReferentialAction::*|null $update
*/
public function addForeignKey(
string $table,
Expand Down
14 changes: 8 additions & 6 deletions tests/Db/Command/CommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,18 +117,20 @@ public function testAddDefaultValue(): void
* @dataProvider \Yiisoft\Db\Tests\Provider\CommandProvider::addForeignKeySql
*/
public function testAddForeignKeySql(
string $name,
string $tableName,
array|string $column1,
array|string $column2,
array|string $columns,
array|string $referenceColumns,
string|null $delete,
string|null $update,
string $expected
): void {
$db = $this->getConnection();

$command = $db->createCommand();
$sql = $command->addForeignKey($tableName, $name, $column1, $tableName, $column2, $delete, $update)->getSql();

$name = '{{fk_constraint}}';
$tableName = '{{fk_table}}';
$referenceTable = '{{fk_referenced_table}}';

$sql = $command->addForeignKey($tableName, $name, $columns, $referenceTable, $referenceColumns, $delete, $update)->getSql();

$this->assertSame($expected, $sql);
}
Expand Down
Loading

0 comments on commit c161161

Please sign in to comment.