Skip to content

Commit 1ddbc7c

Browse files
committed
feat(database): support inserting and updating relationships
1 parent faf11b4 commit 1ddbc7c

File tree

10 files changed

+2089
-187
lines changed

10 files changed

+2089
-187
lines changed

packages/database/src/Builder/QueryBuilders/InsertQueryBuilder.php

Lines changed: 316 additions & 66 deletions
Large diffs are not rendered by default.

packages/database/src/Builder/QueryBuilders/UpdateQueryBuilder.php

Lines changed: 431 additions & 45 deletions
Large diffs are not rendered by default.

packages/database/src/Builder/TableDefinition.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace Tempest\Database\Builder;
66

77
use Stringable;
8-
use Tempest\Reflection\ClassReflector;
98

109
final readonly class TableDefinition implements Stringable
1110
{
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Database\Exceptions;
6+
7+
use Exception;
8+
use Tempest\Database\Builder\ModelInspector;
9+
10+
final class CouldNotUpdateRelation extends Exception implements DatabaseException
11+
{
12+
public static function requiresSingleRecord(ModelInspector $model): self
13+
{
14+
return new self(sprintf(
15+
'Attempted to update a relation on %s without targeting a single record by primary key. Use `where(%s, $id)` to update relations.',
16+
$model->getName(),
17+
$model->getPrimaryKey(),
18+
));
19+
}
20+
21+
public static function requiresPrimaryKey(ModelInspector $model): self
22+
{
23+
return new self(sprintf('Attempted to update a relation on %s, but it does not have a primary key.', $model->getName()));
24+
}
25+
}

packages/database/src/GenericDatabase.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ public function execute(BuildsQuery|Query $query): void
4545

4646
try {
4747
$statement = $this->connection->prepare($query->toSql()->toString());
48-
4948
$statement->execute($bindings);
5049

5150
$this->lastStatement = $statement;
@@ -90,7 +89,6 @@ public function fetch(BuildsQuery|Query $query): array
9089

9190
try {
9291
$pdoQuery = $this->connection->prepare($query->toSql()->toString());
93-
9492
$pdoQuery->execute($bindings);
9593

9694
return $pdoQuery->fetchAll(PDO::FETCH_NAMED);

tests/Integration/Database/Builder/InsertQueryBuilderTest.php

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
use Tempest\Database\Config\DatabaseDialect;
66
use Tempest\Database\Database;
7-
use Tempest\Database\Exceptions\HasManyRelationCouldNotBeInsterted;
8-
use Tempest\Database\Exceptions\HasOneRelationCouldNotBeInserted;
97
use Tempest\Database\Migrations\CreateMigrationsTable;
108
use Tempest\Database\PrimaryKey;
119
use Tempest\Database\Query;
@@ -26,10 +24,7 @@ final class InsertQueryBuilderTest extends FrameworkIntegrationTestCase
2624
public function test_insert_on_plain_table(): void
2725
{
2826
$query = query('chapters')
29-
->insert(
30-
title: 'Chapter 01',
31-
index: 1,
32-
)
27+
->insert(title: 'Chapter 01', index: 1)
3328
->build();
3429

3530
$expected = $this->buildExpectedInsert('INSERT INTO `chapters` (`title`, `index`) VALUES (?, ?)');
@@ -72,11 +67,7 @@ public function test_insert_with_batch(): void
7267

7368
public function test_insert_on_model_table(): void
7469
{
75-
$author = new Author(
76-
name: 'brent',
77-
type: AuthorType::A,
78-
);
79-
70+
$author = new Author(name: 'brent', type: AuthorType::A);
8071
$query = query(Author::class)
8172
->insert(
8273
$author,
@@ -94,15 +85,11 @@ public function test_insert_on_model_table_with_new_relation(): void
9485
{
9586
$book = Book::new(
9687
title: 'Timeline Taxi',
97-
author: Author::new(
98-
name: 'Brent',
99-
),
88+
author: Author::new(name: 'Brent'),
10089
);
10190

10291
$bookQuery = query(Book::class)
103-
->insert(
104-
$book,
105-
)
92+
->insert($book)
10693
->build();
10794

10895
$expectedBookQuery = $this->buildExpectedInsert('INSERT INTO `books` (`title`, `author_id`) VALUES (?, ?)');
@@ -130,9 +117,7 @@ public function test_insert_on_model_table_with_existing_relation(): void
130117
);
131118

132119
$bookQuery = query(Book::class)
133-
->insert(
134-
$book,
135-
)
120+
->insert($book)
136121
->build();
137122

138123
$expectedBookQuery = $this->buildExpectedInsert('INSERT INTO `books` (`title`, `author_id`) VALUES (?, ?)');
@@ -142,30 +127,6 @@ public function test_insert_on_model_table_with_existing_relation(): void
142127
$this->assertSame(10, $bookQuery->bindings[1]);
143128
}
144129

145-
public function test_inserting_has_many_via_parent_model_throws_exception(): void
146-
{
147-
$this->assertException(HasManyRelationCouldNotBeInsterted::class, function (): void {
148-
query(Book::class)
149-
->insert(
150-
title: 'Timeline Taxi',
151-
chapters: ['title' => 'Chapter 01'],
152-
)
153-
->build();
154-
});
155-
}
156-
157-
public function test_inserting_has_one_via_parent_model_throws_exception(): void
158-
{
159-
$this->assertException(HasOneRelationCouldNotBeInserted::class, function (): void {
160-
query(Book::class)
161-
->insert(
162-
title: 'Timeline Taxi',
163-
isbn: ['value' => '979-8344313764'],
164-
)
165-
->build();
166-
});
167-
}
168-
169130
public function test_then_method(): void
170131
{
171132
$this->migrate(CreateMigrationsTable::class, CreatePublishersTable::class, CreateAuthorTable::class, CreateBookTable::class, CreateChapterTable::class);
@@ -218,7 +179,9 @@ public function test_insert_mapping(): void
218179
{
219180
$author = Author::new(name: 'test');
220181

221-
$query = query(Author::class)->insert($author)->build();
182+
$query = query(Author::class)
183+
->insert($author)
184+
->build();
222185

223186
$dialect = $this->container->get(Database::class)->dialect;
224187

0 commit comments

Comments
 (0)