Skip to content

Commit 2a8b2d5

Browse files
committed
feat(database): add foreign key support for sqlite dialect
1 parent 16655b4 commit 2a8b2d5

File tree

5 files changed

+24
-34
lines changed

5 files changed

+24
-34
lines changed

packages/database/src/QueryStatements/BelongsToStatement.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public function compile(DatabaseDialect $dialect): string
4444
'ON UPDATE ' . $this->onUpdate->value,
4545
)),
4646
),
47-
DatabaseDialect::POSTGRESQL => new ConstraintStatement(
47+
DatabaseDialect::POSTGRESQL , DatabaseDialect::SQLITE => new ConstraintStatement(
4848
$constraintName,
4949
new RawStatement(sprintf(
5050
'FOREIGN KEY(%s) REFERENCES %s(%s) %s %s',
@@ -55,7 +55,6 @@ public function compile(DatabaseDialect $dialect): string
5555
'ON UPDATE ' . $this->onUpdate->value,
5656
)),
5757
),
58-
DatabaseDialect::SQLITE => throw new DialectWasNotSupported(),
5958
};
6059

6160
return $statement->compile($dialect);

packages/database/src/QueryStatements/ConstraintNameStatement.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public function __construct(
2222
public function compile(DatabaseDialect $dialect): string
2323
{
2424
return match ($dialect) {
25-
DatabaseDialect::MYSQL, DatabaseDialect::POSTGRESQL => sprintf('CONSTRAINT %s', $this->name->compile($dialect)),
25+
DatabaseDialect::MYSQL, DatabaseDialect::POSTGRESQL, DatabaseDialect::SQLITE => sprintf('CONSTRAINT %s', $this->name->compile($dialect)),
2626
default => throw new DialectWasNotSupported(),
2727
};
2828
}

packages/database/src/QueryStatements/CreateTableStatement.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,14 @@ public function compile(DatabaseDialect $dialect): string
378378
'CREATE TABLE %s (%s);',
379379
new TableDefinition($this->tableName),
380380
arr($this->statements)
381-
// Remove BelongsTo for sqlLite as it does not support those queries
382-
->filter(fn (QueryStatement $queryStatement) => ! ($dialect === DatabaseDialect::SQLITE && $queryStatement instanceof BelongsToStatement))
381+
->sortByCallback(function (QueryStatement $a, QueryStatement $b) {
382+
// Foreign keys must be defined last in SQLite
383+
if ($a instanceof BelongsToStatement && $b instanceof BelongsToStatement) {
384+
return 0;
385+
}
386+
387+
return $a instanceof BelongsToStatement ? 1 : -1;
388+
})
383389
->map(fn (QueryStatement $queryStatement) => str($queryStatement->compile($dialect))->trim()->replace(' ', ' '))
384390
->filter(fn (ImmutableString $str) => $str->isNotEmpty())
385391
->implode(', ' . PHP_EOL . ' ')

packages/database/tests/QueryStatements/AlterTableStatementTest.php

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public function test_alter_add_belongs_to_mysql(DatabaseDialect $dialect): void
5959
}
6060

6161
#[TestWith([DatabaseDialect::POSTGRESQL])]
62+
#[TestWith([DatabaseDialect::SQLITE])]
6263
public function test_alter_add_belongs_to_postgresql(DatabaseDialect $dialect): void
6364
{
6465
$expected = 'ALTER TABLE `table` ADD CONSTRAINT `fk_parent_table_foo` FOREIGN KEY(foo) REFERENCES parent(bar) ON DELETE RESTRICT ON UPDATE NO ACTION ;';
@@ -71,16 +72,6 @@ public function test_alter_add_belongs_to_postgresql(DatabaseDialect $dialect):
7172
$this->assertEqualsIgnoringCase($expected, $normalized);
7273
}
7374

74-
#[TestWith([DatabaseDialect::SQLITE])]
75-
public function test_alter_add_belongs_to_unsupported(DatabaseDialect $dialect): void
76-
{
77-
$this->expectException(DialectWasNotSupported::class);
78-
79-
new AlterTableStatement('table')
80-
->add(new BelongsToStatement('table.foo', 'parent.bar'))
81-
->compile($dialect);
82-
}
83-
8475
#[TestWith([DatabaseDialect::MYSQL])]
8576
#[TestWith([DatabaseDialect::POSTGRESQL])]
8677
#[TestWith([DatabaseDialect::SQLITE])]
@@ -98,6 +89,7 @@ public function test_alter_table_drop_column(DatabaseDialect $dialect): void
9889

9990
#[TestWith([DatabaseDialect::MYSQL, 'ALTER TABLE `table` DROP CONSTRAINT `foo` ;'])]
10091
#[TestWith([DatabaseDialect::POSTGRESQL, 'ALTER TABLE `table` DROP CONSTRAINT `foo` ;'])]
92+
#[TestWith([DatabaseDialect::SQLITE, 'ALTER TABLE `table` DROP CONSTRAINT `foo` ;'])]
10193
public function test_alter_table_drop_constraint(DatabaseDialect $dialect, string $expected): void
10294
{
10395
$statement = new AlterTableStatement('table')
@@ -109,15 +101,6 @@ public function test_alter_table_drop_constraint(DatabaseDialect $dialect, strin
109101
$this->assertEqualsIgnoringCase($expected, $normalized);
110102
}
111103

112-
#[TestWith([DatabaseDialect::SQLITE])]
113-
public function test_alter_table_drop_constraint_unsupported_dialects(DatabaseDialect $dialect): void
114-
{
115-
$this->expectException(DialectWasNotSupported::class);
116-
new AlterTableStatement('table')
117-
->dropConstraint('foo')
118-
->compile($dialect);
119-
}
120-
121104
#[TestWith([DatabaseDialect::MYSQL, 'ALTER TABLE `table` ADD `foo` VARCHAR(42) DEFAULT \'bar\' NOT NULL ;'])]
122105
#[TestWith([
123106
DatabaseDialect::POSTGRESQL,

packages/database/tests/QueryStatements/CreateTableStatementTest.php

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ public static function provide_fk_create_table_database_drivers(): Generator
9898
CREATE TABLE `books` (
9999
`id` INTEGER PRIMARY KEY AUTO_INCREMENT,
100100
`author_id` INTEGER NOT NULL,
101-
CONSTRAINT `fk_authors_books_author_id` FOREIGN KEY books(author_id) REFERENCES authors(id) ON DELETE CASCADE ON UPDATE NO ACTION,
102-
`name` VARCHAR(255) NOT NULL
101+
`name` VARCHAR(255) NOT NULL,
102+
CONSTRAINT `fk_authors_books_author_id` FOREIGN KEY books(author_id) REFERENCES authors(id) ON DELETE CASCADE ON UPDATE NO ACTION
103103
);
104104
SQL,
105105
];
@@ -110,8 +110,8 @@ public static function provide_fk_create_table_database_drivers(): Generator
110110
CREATE TABLE `books` (
111111
`id` SERIAL PRIMARY KEY,
112112
`author_id` INTEGER NOT NULL,
113-
CONSTRAINT `fk_authors_books_author_id` FOREIGN KEY(author_id) REFERENCES authors(id) ON DELETE CASCADE ON UPDATE NO ACTION,
114-
`name` VARCHAR(255) NOT NULL
113+
`name` VARCHAR(255) NOT NULL,
114+
CONSTRAINT `fk_authors_books_author_id` FOREIGN KEY(author_id) REFERENCES authors(id) ON DELETE CASCADE ON UPDATE NO ACTION
115115
);
116116
SQL,
117117
];
@@ -122,7 +122,8 @@ public static function provide_fk_create_table_database_drivers(): Generator
122122
CREATE TABLE `books` (
123123
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
124124
`author_id` INTEGER NOT NULL,
125-
`name` VARCHAR(255) NOT NULL
125+
`name` VARCHAR(255) NOT NULL,
126+
CONSTRAINT `fk_authors_books_author_id` FOREIGN KEY(author_id) REFERENCES authors(id) ON DELETE CASCADE ON UPDATE NO ACTION
126127
);
127128
SQL,
128129
];
@@ -149,8 +150,8 @@ public static function provide_fk_create_table_database_drivers_explicit(): Gene
149150
CREATE TABLE `books` (
150151
`id` INTEGER PRIMARY KEY AUTO_INCREMENT,
151152
`author_id` INTEGER NOT NULL,
152-
CONSTRAINT `fk_authors_books_author_id` FOREIGN KEY books(author_id) REFERENCES authors(id) ON DELETE CASCADE ON UPDATE NO ACTION,
153-
`name` VARCHAR(255) NOT NULL
153+
`name` VARCHAR(255) NOT NULL,
154+
CONSTRAINT `fk_authors_books_author_id` FOREIGN KEY books(author_id) REFERENCES authors(id) ON DELETE CASCADE ON UPDATE NO ACTION
154155
);
155156
SQL,
156157
];
@@ -161,8 +162,8 @@ public static function provide_fk_create_table_database_drivers_explicit(): Gene
161162
CREATE TABLE `books` (
162163
`id` SERIAL PRIMARY KEY,
163164
`author_id` INTEGER NOT NULL,
164-
CONSTRAINT `fk_authors_books_author_id` FOREIGN KEY(author_id) REFERENCES authors(id) ON DELETE CASCADE ON UPDATE NO ACTION,
165-
`name` VARCHAR(255) NOT NULL
165+
`name` VARCHAR(255) NOT NULL,
166+
CONSTRAINT `fk_authors_books_author_id` FOREIGN KEY(author_id) REFERENCES authors(id) ON DELETE CASCADE ON UPDATE NO ACTION
166167
);
167168
SQL,
168169
];
@@ -173,7 +174,8 @@ public static function provide_fk_create_table_database_drivers_explicit(): Gene
173174
CREATE TABLE `books` (
174175
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
175176
`author_id` INTEGER NOT NULL,
176-
`name` VARCHAR(255) NOT NULL
177+
`name` VARCHAR(255) NOT NULL,
178+
CONSTRAINT `fk_authors_books_author_id` FOREIGN KEY(author_id) REFERENCES authors(id) ON DELETE CASCADE ON UPDATE NO ACTION
177179
);
178180
SQL,
179181
];

0 commit comments

Comments
 (0)