Skip to content

Commit c1561e0

Browse files
authored
fix(database): prevent non-object model queries from trying to use the model class (#1239)
1 parent 975b49a commit c1561e0

File tree

5 files changed

+113
-2
lines changed

5 files changed

+113
-2
lines changed

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

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ public function first(mixed ...$bindings): mixed
5959
{
6060
$query = $this->build(...$bindings);
6161

62+
if (! $this->modelDefinition) {
63+
return $query->fetchFirst();
64+
}
65+
6266
$result = map($query)->collection()->to($this->modelClass);
6367

6468
if ($result === []) {
@@ -79,7 +83,13 @@ public function get(Id $id): mixed
7983
/** @return TModelClass[] */
8084
public function all(mixed ...$bindings): array
8185
{
82-
return map($this->build(...$bindings))->collection()->to($this->modelClass);
86+
$query = $this->build(...$bindings);
87+
88+
if (! $this->modelDefinition) {
89+
return $query->fetch();
90+
}
91+
92+
return map($query)->collection()->to($this->modelClass);
8393
}
8494

8595
/**
@@ -124,7 +134,14 @@ public function orWhere(string $where, mixed ...$bindings): self
124134
/** @return self<TModelClass> */
125135
public function whereField(string $field, mixed $value): self
126136
{
127-
$field = $this->modelDefinition->getFieldDefinition($field);
137+
if ($this->modelDefinition) {
138+
$field = $this->modelDefinition->getFieldDefinition($field);
139+
} else {
140+
$field = new FieldDefinition(
141+
$this->resolveTable($this->modelClass),
142+
$field,
143+
);
144+
}
128145

129146
return $this->where("{$field} = :{$field->name}", ...[$field->name => $value]);
130147
}

tests/Integration/Database/Builder/DeleteQueryBuilderTest.php

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

55
use Tempest\Database\Builder\QueryBuilders\DeleteQueryBuilder;
66
use Tempest\Database\Id;
7+
use Tempest\Database\Migrations\CreateMigrationsTable;
8+
use Tests\Tempest\Fixtures\Migrations\CreateAuthorTable;
79
use Tests\Tempest\Fixtures\Modules\Books\Models\Author;
810
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;
911

@@ -97,4 +99,20 @@ public function test_delete_on_plain_table_with_conditions(): void
9799
$query->bindings[0],
98100
);
99101
}
102+
103+
public function test_delete_with_non_object_model(): void
104+
{
105+
$this->migrate(CreateMigrationsTable::class, CreateAuthorTable::class);
106+
107+
query('authors')->insert(
108+
['id' => 1, 'name' => 'Brent'],
109+
['id' => 2, 'name' => 'Other'],
110+
)->execute();
111+
112+
query('authors')->delete()->where('id = ?', 1)->execute();
113+
114+
$count = query('authors')->count()->where('id = ?', 1)->execute();
115+
116+
$this->assertSame(0, $count);
117+
}
100118
}

tests/Integration/Database/Builder/InsertQueryBuilderTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,18 @@ public function test_then_method(): void
205205
$this->assertSame('Chapter 02', $book->chapters[2]->title);
206206
$this->assertSame('Chapter 03', $book->chapters[3]->title);
207207
}
208+
209+
public function test_insert_with_non_object_model(): void
210+
{
211+
$this->migrate(CreateMigrationsTable::class, CreateAuthorTable::class);
212+
213+
query('authors')->insert(
214+
['id' => 1, 'name' => 'Brent'],
215+
['id' => 2, 'name' => 'Other'],
216+
)->execute();
217+
218+
$count = query('authors')->count()->execute();
219+
220+
$this->assertSame(2, $count);
221+
}
208222
}

tests/Integration/Database/Builder/SelectQueryBuilderTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
namespace Tests\Tempest\Integration\Database\Builder;
66

77
use Tempest\Database\Builder\QueryBuilders\SelectQueryBuilder;
8+
use Tempest\Database\Database;
89
use Tempest\Database\Migrations\CreateMigrationsTable;
10+
use Tempest\Database\Query;
11+
use Tempest\Database\QueryStatements\CreateTableStatement;
912
use Tests\Tempest\Fixtures\Migrations\CreateAuthorTable;
1013
use Tests\Tempest\Fixtures\Migrations\CreateBookTable;
1114
use Tests\Tempest\Fixtures\Modules\Books\Models\Author;
15+
use Tests\Tempest\Fixtures\Modules\Books\Models\AuthorType;
1216
use Tests\Tempest\Fixtures\Modules\Books\Models\Book;
1317
use Tests\Tempest\Integration\FrameworkIntegrationTestCase;
1418

@@ -230,4 +234,42 @@ public function test_select_query_with_conditions(): void
230234
$this->assertSame($expected, $sql);
231235
$this->assertSame(['Timeline Taxi', '1', '2025-01-01'], $bindings);
232236
}
237+
238+
public function test_select_first_with_non_object_model(): void
239+
{
240+
$this->migrate(CreateMigrationsTable::class, CreateAuthorTable::class);
241+
242+
query('authors')->insert(
243+
['id' => 1, 'name' => 'Brent'],
244+
['id' => 2, 'name' => 'Other'],
245+
)->execute();
246+
247+
$author = query('authors')
248+
->select()
249+
->whereField('id', 2)
250+
->first();
251+
252+
$this->assertSame(['id' => 2, 'name' => 'Other', 'type' => null], $author);
253+
}
254+
255+
public function test_select_all_with_non_object_model(): void
256+
{
257+
$this->migrate(CreateMigrationsTable::class, CreateAuthorTable::class);
258+
259+
query('authors')->insert(
260+
['id' => 1, 'name' => 'Brent', 'type' => AuthorType::B],
261+
['id' => 2, 'name' => 'Other', 'type' => null],
262+
['id' => 3, 'name' => 'Another', 'type' => AuthorType::A],
263+
)->execute();
264+
265+
$authors = query('authors')
266+
->select()
267+
->where('name <> ?', 'Brent')
268+
->all();
269+
270+
$this->assertSame(
271+
[['id' => 2, 'name' => 'Other', 'type' => null], ['id' => 3, 'name' => 'Another', 'type' => 'a']],
272+
$authors,
273+
);
274+
}
233275
}

tests/Integration/Database/Builder/UpdateQueryBuilderTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
use Tempest\Database\Exceptions\CannotUpdateHasOneRelation;
99
use Tempest\Database\Exceptions\InvalidUpdateStatement;
1010
use Tempest\Database\Id;
11+
use Tempest\Database\Migrations\CreateMigrationsTable;
1112
use Tempest\Database\Query;
13+
use Tests\Tempest\Fixtures\Migrations\CreateAuthorTable;
1214
use Tests\Tempest\Fixtures\Modules\Books\Models\Author;
1315
use Tests\Tempest\Fixtures\Modules\Books\Models\AuthorType;
1416
use Tests\Tempest\Fixtures\Modules\Books\Models\Book;
@@ -260,4 +262,22 @@ public function test_update_on_plain_table_with_conditions(): void
260262
$query->bindings,
261263
);
262264
}
265+
266+
public function test_update_with_non_object_model(): void
267+
{
268+
$this->migrate(CreateMigrationsTable::class, CreateAuthorTable::class);
269+
270+
query('authors')->insert(
271+
['id' => 1, 'name' => 'Brent'],
272+
['id' => 2, 'name' => 'Other'],
273+
)->execute();
274+
275+
query('authors')->update(
276+
name: 'Brendt',
277+
)->where('id = ?', 1)->execute();
278+
279+
$count = query('authors')->count()->where('name = ?', 'Brendt')->execute();
280+
281+
$this->assertSame(1, $count);
282+
}
263283
}

0 commit comments

Comments
 (0)