Skip to content

Commit b0d6cee

Browse files
committed
wip
1 parent 8b02466 commit b0d6cee

22 files changed

+193
-56
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function __construct(
3434
);
3535
}
3636

37-
public function execute(mixed ...$bindings): Id
37+
public function execute(mixed ...$bindings): Id|null
3838
{
3939
return $this->build()->execute(...$bindings);
4040
}

packages/database/src/Connection/Connection.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function rollback(): bool;
1616

1717
public function lastInsertId(): false|string;
1818

19-
public function prepare(string $sql): false|PDOStatement;
19+
public function prepare(string $sql): PDOStatement;
2020

2121
public function close(): void;
2222

packages/database/src/Connection/PDOConnection.php

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

16+
private int|string|null $lastInsertId = null;
17+
1618
public function __construct(
1719
private(set) readonly DatabaseConfig $config,
1820
) {}
@@ -53,13 +55,19 @@ public function lastInsertId(): false|string
5355
return $this->pdo->lastInsertId();
5456
}
5557

56-
public function prepare(string $sql): false|PDOStatement
58+
public function prepare(string $sql): PDOStatement
5759
{
5860
if ($this->pdo === null) {
5961
throw new ConnectionClosed();
6062
}
6163

62-
return $this->pdo->prepare($sql);
64+
$statement = $this->pdo->prepare($sql);
65+
66+
if ($statement === false) {
67+
throw new ConnectionClosed();
68+
}
69+
70+
return $statement;
6371
}
6472

6573
public function close(): void

packages/database/src/Database.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface Database
88
{
99
public function execute(Query $query): void;
1010

11-
public function getLastInsertId(): Id;
11+
public function getLastInsertId(): Id|null;
1212

1313
public function fetch(Query $query): array;
1414

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Tempest\Database;
4+
5+
use Tempest\Container\Container;
6+
use Tempest\Container\Initializer;
7+
use Tempest\Database\Config\DatabaseConfig;
8+
use Tempest\Database\Config\DatabaseDialect;
9+
10+
final class DatabaseDialectInitializer implements Initializer
11+
{
12+
public function initialize(Container $container): DatabaseDialect
13+
{
14+
return $container->get(DatabaseConfig::class)->dialect;
15+
}
16+
}

packages/database/src/DatabaseInitializer.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public function initialize(ClassReflector $class, ?string $tag, Container $conta
3737
return new GenericDatabase(
3838
$connection,
3939
new GenericTransactionManager($connection),
40+
$container->get(DatabaseConfig::class)->dialect,
4041
);
4142
}
4243
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Tempest\Database\Exceptions;
4+
5+
use Exception;
6+
7+
final class NoLastInsertIdAvailable extends Exception
8+
{
9+
public function __construct()
10+
{
11+
parent::__construct("No last insert id available.");
12+
}
13+
}

packages/database/src/GenericDatabase.php

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,56 @@
88
use DateTimeInterface;
99
use PDO;
1010
use PDOException;
11+
use PDOStatement;
12+
use Tempest\Database\Config\DatabaseDialect;
1113
use Tempest\Database\Connection\Connection;
1214
use Tempest\Database\Exceptions\QueryException;
1315
use Tempest\Database\Transactions\TransactionManager;
1416
use Throwable;
1517

16-
final readonly class GenericDatabase implements Database
18+
final class GenericDatabase implements Database
1719
{
20+
private PDOStatement|null $lastStatement = null;
21+
private Query|null $lastQuery = null;
22+
1823
public function __construct(
19-
private(set) Connection $connection,
20-
private(set) TransactionManager $transactionManager,
24+
private(set) readonly Connection $connection,
25+
private(set) readonly TransactionManager $transactionManager,
26+
private(set) readonly DatabaseDialect $dialect,
2127
) {}
2228

2329
public function execute(Query $query): void
2430
{
2531
$bindings = $this->resolveBindings($query);
2632

2733
try {
28-
$this->connection
29-
->prepare($query->toSql())
30-
->execute($bindings);
34+
$statement = $this->connection->prepare($query->toSql());
35+
36+
$statement->execute($bindings);
37+
38+
$this->lastStatement = $statement;
39+
$this->lastQuery = $query;
3140
} catch (PDOException $pdoException) {
3241
throw new QueryException($query, $bindings, $pdoException);
3342
}
3443
}
3544

36-
public function getLastInsertId(): Id
45+
public function getLastInsertId(): Id|null
3746
{
38-
return new Id($this->connection->lastInsertId());
47+
$sql = $this->lastQuery->toSql();
48+
49+
if (! str_starts_with($sql, 'INSERT')) {
50+
return null;
51+
}
52+
53+
if ($this->dialect === DatabaseDialect::POSTGRESQL) {
54+
$data = $this->lastStatement->fetch(PDO::FETCH_ASSOC);
55+
$lastInsertId = $data['id'] ?? null;
56+
} else {
57+
$lastInsertId = $this->connection->lastInsertId();
58+
}
59+
60+
return new Id($lastInsertId);
3961
}
4062

4163
public function fetch(Query $query): array

packages/database/src/Migrations/MigrationManager.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ private function getTableDefinitions(DatabaseDialect $dialect): array
258258
return array_map(
259259
fn (array $item) => match ($dialect) {
260260
DatabaseDialect::SQLITE => new TableMigrationDefinition($item['name']),
261-
default => new TableMigrationDefinition(array_values($item)[0]),
261+
DatabaseDialect::POSTGRESQL => new TableMigrationDefinition($item['table_name']),
262+
DatabaseDialect::MYSQL => new TableMigrationDefinition(array_values($item)[0]),
262263
},
263264
new ShowTablesStatement()->fetch($dialect),
264265
);

packages/database/src/Query.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Tempest\Database\Config\DatabaseConfig;
88

9+
use Tempest\Database\Config\DatabaseDialect;
910
use function Tempest\get;
1011

1112
final class Query
@@ -17,7 +18,7 @@ public function __construct(
1718
public array $executeAfter = [],
1819
) {}
1920

20-
public function execute(mixed ...$bindings): Id
21+
public function execute(mixed ...$bindings): Id|null
2122
{
2223
$this->bindings = [...$this->bindings, ...$bindings];
2324

@@ -48,8 +49,14 @@ public function toSql(): string
4849
{
4950
$sql = $this->sql;
5051

52+
$dialect = $this->getDatabaseConfig()->dialect;
53+
5154
if ($sql instanceof QueryStatement) {
52-
return $sql->compile($this->getDatabaseConfig()->dialect);
55+
$sql = $sql->compile($dialect);
56+
}
57+
58+
if ($dialect === DatabaseDialect::POSTGRESQL) {
59+
$sql = str_replace('`', '', $sql);
5360
}
5461

5562
return $sql;

0 commit comments

Comments
 (0)