Skip to content

Commit f34ad57

Browse files
authored
fix(database): postgres support (#1259)
1 parent 5b9d8ff commit f34ad57

File tree

69 files changed

+742
-321
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+742
-321
lines changed

.github/workflows/integration-tests.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ on:
55
workflow_dispatch:
66
schedule:
77
- cron: '0 0 * * *'
8+
env:
9+
POSTGRES_USER: runner
10+
POSTGRES_PASSWORD: ''
11+
POSTGRES_DB: postgres
812

913
jobs:
1014
vitest:
@@ -28,7 +32,7 @@ jobs:
2832
uses: shivammathur/setup-php@v2
2933
with:
3034
php-version: ${{ matrix.php }}
31-
extensions: dom, curl, libxml, mbstring, pcntl, fileinfo, pdo, sqlite, pdo_sqlite, pdo_mysql, intl, ftp, zip
35+
extensions: dom, curl, libxml, mbstring, pcntl, fileinfo, pdo, sqlite, pdo_sqlite, pdo_mysql, pdo_pgsql intl, ftp, zip
3236
coverage: pcov
3337

3438
- name: Setup Bun
@@ -60,6 +64,9 @@ jobs:
6064
stability:
6165
- prefer-stable
6266
- prefer-lowest
67+
exclude:
68+
- os: windows-latest
69+
database: postgres
6370

6471
name: "Run tests: PHP ${{ matrix.php }} - ${{ matrix.database }} - ${{ matrix.stability }} - ${{ matrix.os }}"
6572

@@ -94,7 +101,10 @@ jobs:
94101
uses: ankane/setup-postgres@v1
95102

96103
- name: Set database config - ${{ matrix.database }}
97-
run: php -r "file_exists('tests/Fixtures/Config/database.config.php') || copy('tests/Fixtures/Config/database.${{ matrix.database }}.php', 'tests/Fixtures/Config/database.config.php');"
104+
run: php -r "copy('tests/Fixtures/Config/database.${{ matrix.database }}.php', 'tests/Fixtures/Config/database.config.php');"
105+
106+
- name: Tempest about
107+
run: php ./tempest about
98108

99109
- name: List discovered locations
100110
run: php ./tempest discovery:status

packages/container/src/GenericContainer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function __construct(
3030
private ArrayIterator $singletons = new ArrayIterator(),
3131

3232
/** @var ArrayIterator<array-key, class-string> $initializers */
33-
private ArrayIterator $initializers = new ArrayIterator(),
33+
public ArrayIterator $initializers = new ArrayIterator(),
3434

3535
/** @var ArrayIterator<array-key, class-string> $dynamicInitializers */
3636
private ArrayIterator $dynamicInitializers = new ArrayIterator(),

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
3838
{
3939
return $this->build()->execute(...$bindings);
4040
}

packages/database/src/Config/DatabaseDialect.php

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

55
namespace Tempest\Database\Config;
66

7+
use PDOException;
8+
79
enum DatabaseDialect: string
810
{
911
case SQLITE = 'sqlite';
@@ -18,4 +20,13 @@ public function tableNotFoundCode(): string
1820
self::SQLITE => 'HY000',
1921
};
2022
}
23+
24+
public function isTableNotFoundError(PDOException $exception): bool
25+
{
26+
return match ($this) {
27+
self::MYSQL => $exception->getCode() === '42S02' && str_contains($exception->getMessage(), 'table'),
28+
self::SQLITE => $exception->getCode() === 'HY000' && str_contains($exception->getMessage(), 'table'),
29+
self::POSTGRESQL => $exception->getCode() === '42P01' && str_contains($exception->getMessage(), 'relation'),
30+
};
31+
}
2132
}

packages/database/src/Config/PostgresConfig.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public function __construct(
3232
#[SensitiveParameter]
3333
public string $port = '5432',
3434
#[SensitiveParameter]
35-
public string $username = '',
35+
public string $username = 'postgres',
3636
#[SensitiveParameter]
3737
public string $password = '',
3838
#[SensitiveParameter]

packages/database/src/Connection/CachedConnectionInitializer.php

Lines changed: 0 additions & 35 deletions
This file was deleted.

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: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PDOStatement;
99
use Tempest\Database\Config\DatabaseConfig;
1010
use Tempest\Database\Exceptions\ConnectionClosed;
11+
use Throwable;
1112

1213
final class PDOConnection implements Connection
1314
{
@@ -53,13 +54,37 @@ public function lastInsertId(): false|string
5354
return $this->pdo->lastInsertId();
5455
}
5556

56-
public function prepare(string $sql): false|PDOStatement
57+
public function prepare(string $sql): PDOStatement
5758
{
5859
if ($this->pdo === null) {
5960
throw new ConnectionClosed();
6061
}
6162

62-
return $this->pdo->prepare($sql);
63+
$statement = $this->pdo->prepare($sql);
64+
65+
if ($statement === false) {
66+
throw new ConnectionClosed();
67+
}
68+
69+
return $statement;
70+
}
71+
72+
public function ping(): bool
73+
{
74+
try {
75+
$statement = $this->prepare('SELECT 1');
76+
$statement->execute();
77+
78+
return true;
79+
} catch (Throwable) {
80+
return false;
81+
}
82+
}
83+
84+
public function reconnect(): void
85+
{
86+
$this->close();
87+
$this->connect();
6388
}
6489

6590
public function close(): void
@@ -74,9 +99,9 @@ public function connect(): void
7499
}
75100

76101
$this->pdo = new PDO(
77-
$this->config->dsn,
78-
$this->config->username,
79-
$this->config->password,
102+
dsn: $this->config->dsn,
103+
username: $this->config->username,
104+
password: $this->config->password,
80105
);
81106
}
82107
}

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;
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+
}

0 commit comments

Comments
 (0)