Skip to content

Commit

Permalink
Task/allow using existing connection (#18)
Browse files Browse the repository at this point in the history
* Add support for SQLite and using existing PDO connection

* Rename methods to be consistent across connection adapters

* Cleanup to use readonly properties
  • Loading branch information
cspray authored Apr 5, 2024
1 parent 9ae4ea4 commit e2ea1dd
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 26 deletions.
2 changes: 1 addition & 1 deletion docker/php/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM php:8.2.1-zts-bullseye AS php
FROM php:8.3-zts-bullseye AS php

RUN apt-get update -y \
&& apt-get upgrade -y
Expand Down
5 changes: 5 additions & 0 deletions resources/schemas/sqlite.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CREATE TABLE my_table (
id INTEGER PRIMARY KEY,
name VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
);
4 changes: 2 additions & 2 deletions src/AmpPostgresConnectionAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ private function __construct(
private readonly Closure $connectionFactory
) {}

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

public static function existingConnection(PostgresLink $link) : self {
public static function fromExistingConnection(PostgresLink $link) : self {
return new self(fn() => $link);
}

Expand Down
31 changes: 13 additions & 18 deletions src/PdoConnectionAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@

namespace Cspray\DatabaseTestCase;

use Cspray\DatabaseTestCase\DatabaseRepresentation\Row;
use Cspray\DatabaseTestCase\DatabaseRepresentation\Table;
use Cspray\DatabaseTestCase\Exception\UnableToGetTable;
use Closure;
use Cspray\DatabaseTestCase\Exception\MissingRequiredExtension;
use PDO;
use PDOException;

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

private ?PDO $connection = null;

public function __construct(
private readonly ConnectionAdapterConfig $adapterConfig,
private function __construct(
private readonly Closure $pdoSupplier,
private readonly PdoDriver $pdoDriver
) {}

public static function fromConnectionConfig(ConnectionAdapterConfig $adapterConfig, PdoDriver $pdoDriver) : self {
return self::fromExistingConnection(new PDO($pdoDriver->dsn($adapterConfig)), $pdoDriver);
}

public static function fromExistingConnection(PDO $pdo, PdoDriver $pdoDriver) : self {
return new self(static fn() => $pdo, $pdoDriver);
}

public function establishConnection() : void {
$this->connection = new PDO(
sprintf(
'%s:host=%s;port=%d;dbname=%s;user=%s;password=%s',
$this->pdoDriver->getDsnIdentifier(),
$this->adapterConfig->host,
$this->adapterConfig->port,
$this->adapterConfig->database,
$this->adapterConfig->user,
$this->adapterConfig->password
)
);
$this->connection = ($this->pdoSupplier)();
}

public function onTestStart() : void {
$this->connection->query('START TRANSACTION');
$this->connection->query($this->pdoDriver->startTransactionSql());
}

public function onTestStop() : void {
Expand Down
32 changes: 30 additions & 2 deletions src/PdoDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,39 @@
enum PdoDriver : string{
case Postgresql = 'pdo_pgsql';
case Mysql = 'pdo_mysql';
case Sqlite = 'pdo_sqlite';

public function getDsnIdentifier() : string {
public function dsn(ConnectionAdapterConfig $adapterConfig) : string {
return match ($this) {
self::Sqlite => sprintf(
'sqlite:%s',
$adapterConfig->host
),
default => sprintf(
'%s:host=%s;port=%d;dbname=%s;user=%s;password=%s',
$this->dsnIdentifier(),
$adapterConfig->host,
$adapterConfig->port,
$adapterConfig->database,
$adapterConfig->user,
$adapterConfig->password
),
};

}

private function dsnIdentifier() : string {
return match ($this) {
self::Postgresql => 'pgsql',
self::Mysql => 'mysql'
self::Mysql => 'mysql',
self::Sqlite => 'sqlite',
};
}

public function startTransactionSql() : string {
return match ($this) {
self::Sqlite => 'BEGIN TRANSACTION',
default => 'START TRANSACTION',
};
}
}
2 changes: 1 addition & 1 deletion tests/Integration/AmpPostgresConnectionAdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ protected function executeCountSql(string $table) : int {
}

protected static function getConnectionAdapter() : ConnectionAdapter {
return AmpPostgresConnectionAdapter::newConnectionFromConfig(new PostgresConnectionConfig());
return AmpPostgresConnectionAdapter::fromConnectionConfig(new PostgresConnectionConfig());
}
}
30 changes: 30 additions & 0 deletions tests/Integration/ExistingPdoConnectionAdapterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php declare(strict_types=1);

namespace Cspray\DatabaseTestCase\Tests\Integration;

use Cspray\DatabaseTestCase\ConnectionAdapter;
use Cspray\DatabaseTestCase\PdoConnectionAdapter;
use Cspray\DatabaseTestCase\PdoDriver;
use PDO;
use PHPUnit\Framework\Attributes\CoversClass;

#[CoversClass(PdoConnectionAdapter::class)]
class ExistingPdoConnectionAdapterTest extends ConnectionAdapterTestCase {

protected function getExpectedUnderlyingConnectionClassName() : string {
return PDO::class;
}

protected function executeCountSql(string $table) : int {
$connection = self::getUnderlyingConnection();
assert($connection instanceof PDO);
return $connection->query('SELECT COUNT(*) AS "count" FROM ' . $table)
->fetch(PDO::FETCH_ASSOC)['count'];
}

protected static function getConnectionAdapter() : ConnectionAdapter {
$pdo = new PDO('sqlite::memory:');
$pdo->query(file_get_contents(dirname(__DIR__, 2) . '/resources/schemas/sqlite.sql'));
return PdoConnectionAdapter::fromExistingConnection($pdo, PdoDriver::Sqlite);
}
}
2 changes: 1 addition & 1 deletion tests/Integration/MysqlPdoConnectionAdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ protected function executeCountSql(string $table) : int {
}

protected static function getConnectionAdapter() : ConnectionAdapter {
return new PdoConnectionAdapter(
return PdoConnectionAdapter::fromConnectionConfig(
new ConnectionAdapterConfig(
'mysql',
'mysql',
Expand Down
2 changes: 1 addition & 1 deletion tests/Integration/PostgresPdoConnectionAdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
class PostgresPdoConnectionAdapterTest extends ConnectionAdapterTestCase {

protected static function getConnectionAdapter() : ConnectionAdapter {
return new PdoConnectionAdapter(
return PdoConnectionAdapter::fromConnectionConfig(
new PostgresConnectionConfig(),
PdoDriver::Postgresql
);
Expand Down

0 comments on commit e2ea1dd

Please sign in to comment.