Skip to content

Commit 76f204e

Browse files
committed
wip
1 parent b0d6cee commit 76f204e

30 files changed

+341
-132
lines changed

packages/database/src/Connection/PDOConnection.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ final class PDOConnection implements Connection
1313
{
1414
private ?PDO $pdo = null;
1515

16-
private int|string|null $lastInsertId = null;
17-
1816
public function __construct(
1917
private(set) readonly DatabaseConfig $config,
2018
) {}

packages/database/src/GenericDatabase.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,18 @@ public function execute(Query $query): void
3131
$bindings = $this->resolveBindings($query);
3232

3333
try {
34-
$statement = $this->connection->prepare($query->toSql());
34+
foreach (explode(';', $query->toSql()) as $sql) {
35+
if (! $sql) {
36+
continue;
37+
}
3538

36-
$statement->execute($bindings);
39+
$statement = $this->connection->prepare($sql . ';');
3740

38-
$this->lastStatement = $statement;
39-
$this->lastQuery = $query;
41+
$statement->execute($bindings);
42+
43+
$this->lastStatement = $statement;
44+
$this->lastQuery = $query;
45+
}
4046
} catch (PDOException $pdoException) {
4147
throw new QueryException($query, $bindings, $pdoException);
4248
}
@@ -46,6 +52,7 @@ public function getLastInsertId(): Id|null
4652
{
4753
$sql = $this->lastQuery->toSql();
4854

55+
// TODO: properly determine whether a query is an insert or not
4956
if (! str_starts_with($sql, 'INSERT')) {
5057
return null;
5158
}
@@ -57,7 +64,7 @@ public function getLastInsertId(): Id|null
5764
$lastInsertId = $this->connection->lastInsertId();
5865
}
5966

60-
return new Id($lastInsertId);
67+
return Id::tryFrom($lastInsertId);
6168
}
6269

6370
public function fetch(Query $query): array

packages/database/src/Id.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@
1313
{
1414
public string|int $id;
1515

16+
public static function tryFrom(string|int|self|null $id): self|null
17+
{
18+
if ($id === null) {
19+
return null;
20+
}
21+
22+
return new self($id);
23+
}
24+
1625
public function __construct(string|int|self $id)
1726
{
1827
$id = ($id instanceof self) ? $id->id : $id;

packages/database/src/IsDatabaseModel.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,15 @@ public static function create(mixed ...$params): self
7272

7373
$model = self::new(...$params);
7474

75-
$model->id = query(self::class)
75+
$id = query(self::class)
7676
->insert($model)
7777
->build()
7878
->execute();
7979

80+
if ($id !== null) {
81+
$model->id = new Id($id);
82+
}
83+
8084
return $model;
8185
}
8286

packages/database/src/QueryStatements/BooleanStatement.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,19 @@ public function __construct(
1717

1818
public function compile(DatabaseDialect $dialect): string
1919
{
20+
$default = null;
21+
22+
if ($this->default !== null) {
23+
$default = match ($dialect) {
24+
DatabaseDialect::POSTGRESQL => $this->default ? 'true' : 'false',
25+
default => $this->default ? '1' : '0',
26+
};
27+
}
28+
2029
return sprintf(
2130
'`%s` BOOLEAN %s %s',
2231
$this->name,
23-
$this->default ? "DEFAULT {$this->default}" : '',
32+
$default !== null ? "DEFAULT {$default}" : '',
2433
$this->nullable ? '' : 'NOT NULL',
2534
);
2635
}

packages/database/src/QueryStatements/CharStatement.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function compile(DatabaseDialect $dialect): string
2020
return sprintf(
2121
'`%s` CHAR %s %s',
2222
$this->name,
23-
$this->default !== null ? "DEFAULT \"{$this->default}\"" : '',
23+
$this->default !== null ? "DEFAULT '{$this->default}'" : '',
2424
$this->nullable ? '' : 'NOT NULL',
2525
);
2626
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Database\QueryStatements;
6+
7+
use Tempest\Database\Config\DatabaseDialect;
8+
use Tempest\Database\QueryStatement;
9+
10+
use function Tempest\Support\arr;
11+
12+
final readonly class CompoundStatement implements QueryStatement
13+
{
14+
private array $statements;
15+
16+
public function __construct(QueryStatement ...$statements)
17+
{
18+
$this->statements = $statements;
19+
}
20+
21+
public function compile(DatabaseDialect $dialect): string
22+
{
23+
return arr($this->statements)
24+
->map(fn (QueryStatement $statement) => $statement->compile($dialect))
25+
->implode(';' . PHP_EOL)
26+
->append(';')
27+
->toString();
28+
}
29+
}

packages/database/src/QueryStatements/CountStatement.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,21 @@ public function __construct(
2121

2222
public function compile(DatabaseDialect $dialect): string
2323
{
24+
$countField = new FieldStatement(sprintf(
25+
'COUNT(%s) AS %s',
26+
$this->getCountArgument(),
27+
$this->getKey(),
28+
));
29+
2430
$query = arr([
25-
sprintf(
26-
'SELECT COUNT(%s)',
27-
$this->getCountArgument(),
28-
),
31+
sprintf('SELECT %s', $countField->compile($dialect)),
2932
sprintf('FROM `%s`', $this->table->name),
3033
]);
3134

3235
if ($this->where->isNotEmpty()) {
3336
$query[] = 'WHERE ' . $this->where
34-
->map(fn (WhereStatement $where) => $where->compile($dialect))
35-
->implode(PHP_EOL);
37+
->map(fn (WhereStatement $where) => $where->compile($dialect))
38+
->implode(PHP_EOL);
3639
}
3740

3841
return $query->implode(PHP_EOL);
@@ -51,6 +54,6 @@ public function getCountArgument(): string
5154

5255
public function getKey(): string
5356
{
54-
return "COUNT({$this->getCountArgument()})";
57+
return 'count';
5558
}
5659
}

packages/database/src/QueryStatements/CreateEnumTypeStatement.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,8 @@ public function compile(DatabaseDialect $dialect): string
2929
return match ($dialect) {
3030
DatabaseDialect::MYSQL, DatabaseDialect::SQLITE => '',
3131
DatabaseDialect::POSTGRESQL => sprintf(
32-
<<<PSQL
33-
DO $$ BEGIN
34-
CREATE TYPE %s AS (%s);
35-
EXCEPTION
36-
WHEN duplicate_object THEN null;
37-
END $$;
32+
<<<'PSQL'
33+
CREATE TYPE "%s" AS ENUM (%s);
3834
PSQL,
3935
str($this->enumClass)->replace('\\\\', '_'),
4036
$cases->implode(', '),

packages/database/src/QueryStatements/CreateTableStatement.php

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace Tempest\Database\QueryStatements;
66

77
use BackedEnum;
8-
use Symfony\Component\VarDumper\Cloner\Data;
98
use Tempest\Database\Builder\ModelDefinition;
109
use Tempest\Database\Builder\TableDefinition;
1110
use Tempest\Database\Config\DatabaseDialect;
@@ -43,7 +42,8 @@ public function belongsTo(
4342
OnDelete $onDelete = OnDelete::RESTRICT,
4443
OnUpdate $onUpdate = OnUpdate::NO_ACTION,
4544
bool $nullable = false,
46-
): self {
45+
): self
46+
{
4747
[, $localKey] = explode('.', $local);
4848

4949
$this->integer($localKey, nullable: $nullable);
@@ -62,7 +62,8 @@ public function text(
6262
string $name,
6363
bool $nullable = false,
6464
?string $default = null,
65-
): self {
65+
): self
66+
{
6667
$this->statements[] = new TextStatement(
6768
name: $name,
6869
nullable: $nullable,
@@ -77,7 +78,8 @@ public function varchar(
7778
int $length = 255,
7879
bool $nullable = false,
7980
?string $default = null,
80-
): self {
81+
): self
82+
{
8183
$this->statements[] = new VarcharStatement(
8284
name: $name,
8385
size: $length,
@@ -92,7 +94,8 @@ public function char(
9294
string $name,
9395
bool $nullable = false,
9496
?string $default = null,
95-
): self {
97+
): self
98+
{
9699
$this->statements[] = new CharStatement(
97100
name: $name,
98101
nullable: $nullable,
@@ -107,7 +110,8 @@ public function integer(
107110
bool $unsigned = false,
108111
bool $nullable = false,
109112
?int $default = null,
110-
): self {
113+
): self
114+
{
111115
$this->statements[] = new IntegerStatement(
112116
name: $name,
113117
unsigned: $unsigned,
@@ -122,7 +126,8 @@ public function float(
122126
string $name,
123127
bool $nullable = false,
124128
?float $default = null,
125-
): self {
129+
): self
130+
{
126131
$this->statements[] = new FloatStatement(
127132
name: $name,
128133
nullable: $nullable,
@@ -136,7 +141,8 @@ public function datetime(
136141
string $name,
137142
bool $nullable = false,
138143
?string $default = null,
139-
): self {
144+
): self
145+
{
140146
$this->statements[] = new DatetimeStatement(
141147
name: $name,
142148
nullable: $nullable,
@@ -150,7 +156,8 @@ public function date(
150156
string $name,
151157
bool $nullable = false,
152158
?string $default = null,
153-
): self {
159+
): self
160+
{
154161
$this->statements[] = new DateStatement(
155162
name: $name,
156163
nullable: $nullable,
@@ -164,7 +171,8 @@ public function boolean(
164171
string $name,
165172
bool $nullable = false,
166173
?bool $default = null,
167-
): self {
174+
): self
175+
{
168176
$this->statements[] = new BooleanStatement(
169177
name: $name,
170178
nullable: $nullable,
@@ -178,7 +186,8 @@ public function json(
178186
string $name,
179187
bool $nullable = false,
180188
?string $default = null,
181-
): self {
189+
): self
190+
{
182191
$this->statements[] = new JsonStatement(
183192
name: $name,
184193
nullable: $nullable,
@@ -192,7 +201,8 @@ public function array(
192201
string $name,
193202
bool $nullable = false,
194203
array $default = [],
195-
): self {
204+
): self
205+
{
196206
$this->statements[] = new JsonStatement(
197207
name: $name,
198208
nullable: $nullable,
@@ -207,9 +217,8 @@ public function enum(
207217
string $enumClass,
208218
bool $nullable = false,
209219
null|UnitEnum|BackedEnum $default = null,
210-
): self {
211-
$this->statements[] = new CreateEnumTypeStatement($enumClass);
212-
220+
): self
221+
{
213222
$this->statements[] = new EnumStatement(
214223
name: $name,
215224
enumClass: $enumClass,
@@ -225,7 +234,8 @@ public function set(
225234
array $values,
226235
bool $nullable = false,
227236
?string $default = null,
228-
): self {
237+
): self
238+
{
229239
$this->statements[] = new SetStatement(
230240
name: $name,
231241
values: $values,
@@ -280,9 +290,9 @@ public function compile(DatabaseDialect $dialect): string
280290

281291
if ($this->indexStatements !== []) {
282292
$createIndices = PHP_EOL . arr($this->indexStatements)
283-
->map(fn (QueryStatement $queryStatement) => str($queryStatement->compile($dialect))->trim()->replace(' ', ' '))
284-
->implode(';' . PHP_EOL)
285-
->append(';');
293+
->map(fn (QueryStatement $queryStatement) => str($queryStatement->compile($dialect))->trim()->replace(' ', ' '))
294+
->implode(';' . PHP_EOL)
295+
->append(';');
286296
} else {
287297
$createIndices = '';
288298
}

0 commit comments

Comments
 (0)