Skip to content

Commit e2ea1dd

Browse files
authored
Task/allow using existing connection (#18)
* Add support for SQLite and using existing PDO connection * Rename methods to be consistent across connection adapters * Cleanup to use readonly properties
1 parent 9ae4ea4 commit e2ea1dd

File tree

9 files changed

+84
-26
lines changed

9 files changed

+84
-26
lines changed

docker/php/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM php:8.2.1-zts-bullseye AS php
1+
FROM php:8.3-zts-bullseye AS php
22

33
RUN apt-get update -y \
44
&& apt-get upgrade -y

resources/schemas/sqlite.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CREATE TABLE my_table (
2+
id INTEGER PRIMARY KEY,
3+
name VARCHAR(255),
4+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
5+
);

src/AmpPostgresConnectionAdapter.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ private function __construct(
2020
private readonly Closure $connectionFactory
2121
) {}
2222

23-
public static function newConnectionFromConfig(ConnectionAdapterConfig $config) : self {
23+
public static function fromConnectionConfig(ConnectionAdapterConfig $config) : self {
2424
return new self(fn() => connect(
2525
PostgresConfig::fromString(sprintf(
2626
'db=%s host=%s port=%d user=%s pass=%s',
@@ -33,7 +33,7 @@ public static function newConnectionFromConfig(ConnectionAdapterConfig $config)
3333
));
3434
}
3535

36-
public static function existingConnection(PostgresLink $link) : self {
36+
public static function fromExistingConnection(PostgresLink $link) : self {
3737
return new self(fn() => $link);
3838
}
3939

src/PdoConnectionAdapter.php

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22

33
namespace Cspray\DatabaseTestCase;
44

5-
use Cspray\DatabaseTestCase\DatabaseRepresentation\Row;
6-
use Cspray\DatabaseTestCase\DatabaseRepresentation\Table;
7-
use Cspray\DatabaseTestCase\Exception\UnableToGetTable;
5+
use Closure;
86
use Cspray\DatabaseTestCase\Exception\MissingRequiredExtension;
97
use PDO;
10-
use PDOException;
118

129
if (! extension_loaded('pdo')) {
1310
throw new MissingRequiredExtension('You must enable ext-pdo to use the ' . PdoConnectionAdapter::class);
@@ -17,27 +14,25 @@ final class PdoConnectionAdapter extends AbstractConnectionAdapter {
1714

1815
private ?PDO $connection = null;
1916

20-
public function __construct(
21-
private readonly ConnectionAdapterConfig $adapterConfig,
17+
private function __construct(
18+
private readonly Closure $pdoSupplier,
2219
private readonly PdoDriver $pdoDriver
2320
) {}
2421

22+
public static function fromConnectionConfig(ConnectionAdapterConfig $adapterConfig, PdoDriver $pdoDriver) : self {
23+
return self::fromExistingConnection(new PDO($pdoDriver->dsn($adapterConfig)), $pdoDriver);
24+
}
25+
26+
public static function fromExistingConnection(PDO $pdo, PdoDriver $pdoDriver) : self {
27+
return new self(static fn() => $pdo, $pdoDriver);
28+
}
29+
2530
public function establishConnection() : void {
26-
$this->connection = new PDO(
27-
sprintf(
28-
'%s:host=%s;port=%d;dbname=%s;user=%s;password=%s',
29-
$this->pdoDriver->getDsnIdentifier(),
30-
$this->adapterConfig->host,
31-
$this->adapterConfig->port,
32-
$this->adapterConfig->database,
33-
$this->adapterConfig->user,
34-
$this->adapterConfig->password
35-
)
36-
);
31+
$this->connection = ($this->pdoSupplier)();
3732
}
3833

3934
public function onTestStart() : void {
40-
$this->connection->query('START TRANSACTION');
35+
$this->connection->query($this->pdoDriver->startTransactionSql());
4136
}
4237

4338
public function onTestStop() : void {

src/PdoDriver.php

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,39 @@
55
enum PdoDriver : string{
66
case Postgresql = 'pdo_pgsql';
77
case Mysql = 'pdo_mysql';
8+
case Sqlite = 'pdo_sqlite';
89

9-
public function getDsnIdentifier() : string {
10+
public function dsn(ConnectionAdapterConfig $adapterConfig) : string {
11+
return match ($this) {
12+
self::Sqlite => sprintf(
13+
'sqlite:%s',
14+
$adapterConfig->host
15+
),
16+
default => sprintf(
17+
'%s:host=%s;port=%d;dbname=%s;user=%s;password=%s',
18+
$this->dsnIdentifier(),
19+
$adapterConfig->host,
20+
$adapterConfig->port,
21+
$adapterConfig->database,
22+
$adapterConfig->user,
23+
$adapterConfig->password
24+
),
25+
};
26+
27+
}
28+
29+
private function dsnIdentifier() : string {
1030
return match ($this) {
1131
self::Postgresql => 'pgsql',
12-
self::Mysql => 'mysql'
32+
self::Mysql => 'mysql',
33+
self::Sqlite => 'sqlite',
34+
};
35+
}
36+
37+
public function startTransactionSql() : string {
38+
return match ($this) {
39+
self::Sqlite => 'BEGIN TRANSACTION',
40+
default => 'START TRANSACTION',
1341
};
1442
}
1543
}

tests/Integration/AmpPostgresConnectionAdapterTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ protected function executeCountSql(string $table) : int {
2222
}
2323

2424
protected static function getConnectionAdapter() : ConnectionAdapter {
25-
return AmpPostgresConnectionAdapter::newConnectionFromConfig(new PostgresConnectionConfig());
25+
return AmpPostgresConnectionAdapter::fromConnectionConfig(new PostgresConnectionConfig());
2626
}
2727
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Cspray\DatabaseTestCase\Tests\Integration;
4+
5+
use Cspray\DatabaseTestCase\ConnectionAdapter;
6+
use Cspray\DatabaseTestCase\PdoConnectionAdapter;
7+
use Cspray\DatabaseTestCase\PdoDriver;
8+
use PDO;
9+
use PHPUnit\Framework\Attributes\CoversClass;
10+
11+
#[CoversClass(PdoConnectionAdapter::class)]
12+
class ExistingPdoConnectionAdapterTest extends ConnectionAdapterTestCase {
13+
14+
protected function getExpectedUnderlyingConnectionClassName() : string {
15+
return PDO::class;
16+
}
17+
18+
protected function executeCountSql(string $table) : int {
19+
$connection = self::getUnderlyingConnection();
20+
assert($connection instanceof PDO);
21+
return $connection->query('SELECT COUNT(*) AS "count" FROM ' . $table)
22+
->fetch(PDO::FETCH_ASSOC)['count'];
23+
}
24+
25+
protected static function getConnectionAdapter() : ConnectionAdapter {
26+
$pdo = new PDO('sqlite::memory:');
27+
$pdo->query(file_get_contents(dirname(__DIR__, 2) . '/resources/schemas/sqlite.sql'));
28+
return PdoConnectionAdapter::fromExistingConnection($pdo, PdoDriver::Sqlite);
29+
}
30+
}

tests/Integration/MysqlPdoConnectionAdapterTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ protected function executeCountSql(string $table) : int {
2424
}
2525

2626
protected static function getConnectionAdapter() : ConnectionAdapter {
27-
return new PdoConnectionAdapter(
27+
return PdoConnectionAdapter::fromConnectionConfig(
2828
new ConnectionAdapterConfig(
2929
'mysql',
3030
'mysql',

tests/Integration/PostgresPdoConnectionAdapterTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
class PostgresPdoConnectionAdapterTest extends ConnectionAdapterTestCase {
1515

1616
protected static function getConnectionAdapter() : ConnectionAdapter {
17-
return new PdoConnectionAdapter(
17+
return PdoConnectionAdapter::fromConnectionConfig(
1818
new PostgresConnectionConfig(),
1919
PdoDriver::Postgresql
2020
);

0 commit comments

Comments
 (0)