Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(database): add closable connection wrapper for PDO connection #875

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/Tempest/Database/src/Connection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Tempest\Database;

use PDOStatement;

interface Connection
{
public function beginTransaction(): bool;

public function commit(): bool;

public function rollback(): bool;

public function lastInsertId(): false|string;

public function prepare(string $sql): false|PDOStatement;

public function close(): void;

public function connect(): void;
}
32 changes: 32 additions & 0 deletions src/Tempest/Database/src/ConnectionInitializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Tempest\Database;

use Tempest\Container\Container;
use Tempest\Container\Initializer;
use Tempest\Container\Singleton;

final class ConnectionInitializer implements Initializer
{
private static Connection|null $instance = null;

#[Singleton]
public function initialize(Container $container): Connection
{
// Reuse same connection instance in unit tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is only meant to be used in tests, can we ensure we are actually running in tests? We can check the current environment from the Kernel I believe

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a cary over from the PDOInitializer which had the same. But yeah, good suggestion. I will make it such that it only "caches" when in testing. This is more of a test speed+memory improvement than anything else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented the check.

if (self::$instance !== null) {
return self::$instance;
}

$databaseConfig = $container->get(DatabaseConfig::class);

$connection = new PDOConnection($databaseConfig->connection());
$connection->connect();

self::$instance = $connection;

return $connection;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

declare(strict_types=1);

namespace Tempest\Database;
namespace Tempest\Database\Connections;

use Tempest\Database\DatabaseDialect;
use Tempest\Database\Tables\NamingStrategy;

interface DatabaseConnection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

declare(strict_types=1);

namespace Tempest\Database;
namespace Tempest\Database\Connections;

use Tempest\Container\Container;
use Tempest\Container\Initializer;
use Tempest\Container\Singleton;
use Tempest\Database\DatabaseConfig;

final class DatabaseConnectionInitializer implements Initializer
{
Expand Down
1 change: 0 additions & 1 deletion src/Tempest/Database/src/Connections/MySqlConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace Tempest\Database\Connections;

use SensitiveParameter;
use Tempest\Database\DatabaseConnection;
use Tempest\Database\DatabaseDialect;
use Tempest\Database\Tables\NamingStrategy;
use Tempest\Database\Tables\PluralizedSnakeCaseStrategy;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace Tempest\Database\Connections;

use SensitiveParameter;
use Tempest\Database\DatabaseConnection;
use Tempest\Database\DatabaseDialect;
use Tempest\Database\Tables\NamingStrategy;
use Tempest\Database\Tables\PluralizedSnakeCaseStrategy;
Expand Down
1 change: 0 additions & 1 deletion src/Tempest/Database/src/Connections/SQLiteConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace Tempest\Database\Connections;

use SensitiveParameter;
use Tempest\Database\DatabaseConnection;
use Tempest\Database\DatabaseDialect;
use Tempest\Database\Tables\NamingStrategy;
use Tempest\Database\Tables\PluralizedSnakeCaseStrategy;
Expand Down
2 changes: 2 additions & 0 deletions src/Tempest/Database/src/DatabaseConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Tempest\Database;

use Tempest\Database\Connections\DatabaseConnection;

final class DatabaseConfig
{
private array $migrations = [];
Expand Down
1 change: 1 addition & 0 deletions src/Tempest/Database/src/DatabaseDialectInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Tempest\Container\Container;
use Tempest\Container\Initializer;
use Tempest\Database\Connections\DatabaseConnection;

final readonly class DatabaseDialectInitializer implements Initializer
{
Expand Down
3 changes: 1 addition & 2 deletions src/Tempest/Database/src/DatabaseInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace Tempest\Database;

use PDO;
use Tempest\Container\Container;
use Tempest\Container\Initializer;
use Tempest\Container\Singleton;
Expand All @@ -16,7 +15,7 @@
public function initialize(Container $container): Database
{
return new GenericDatabase(
$container->get(PDO::class),
$container->get(Connection::class),
$container->get(TransactionManager::class),
);
}
Expand Down
12 changes: 6 additions & 6 deletions src/Tempest/Database/src/GenericDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
use Tempest\Database\Transactions\TransactionManager;
use Throwable;

final class GenericDatabase implements Database
final readonly class GenericDatabase implements Database
{
public function __construct(
private PDO $pdo,
private readonly TransactionManager $transactionManager,
private Connection $connection,
private TransactionManager $transactionManager,
) {
}

Expand All @@ -25,7 +25,7 @@ public function execute(Query $query): void
$bindings = $this->resolveBindings($query);

try {
$this->pdo
$this->connection
->prepare($query->getSql())
->execute($bindings);
} catch (PDOException $pdoException) {
Expand All @@ -35,12 +35,12 @@ public function execute(Query $query): void

public function getLastInsertId(): Id
{
return new Id($this->pdo->lastInsertId());
return new Id($this->connection->lastInsertId());
}

public function fetch(Query $query): array
{
$pdoQuery = $this->pdo->prepare($query->getSql());
$pdoQuery = $this->connection->prepare($query->getSql());

$pdoQuery->execute($this->resolveBindings($query));

Expand Down
61 changes: 61 additions & 0 deletions src/Tempest/Database/src/PDOConnection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);

namespace Tempest\Database;

use PDO;
use PDOStatement;
use Tempest\Database\Connections\DatabaseConnection;

final class PDOConnection implements Connection
{
private PDO|null $pdo = null;

public function __construct(private readonly DatabaseConnection $connection)
{
}

public function beginTransaction(): bool
{
return $this->pdo->beginTransaction();
}

public function commit(): bool
{
return $this->pdo->commit();
}

public function rollback(): bool
{
return $this->pdo->rollBack();
}

public function lastInsertId(): false|string
{
return $this->pdo->lastInsertId();
}

public function prepare(string $sql): false|PDOStatement
{
return $this->pdo->prepare($sql);
}

public function close(): void
{
$this->pdo = null;
}

public function connect(): void
{
if ($this->pdo !== null) {
return;
}

$this->pdo = new PDO(
$this->connection->getDsn(),
$this->connection->getUsername(),
$this->connection->getPassword(),
);
}
}
35 changes: 0 additions & 35 deletions src/Tempest/Database/src/PDOInitializer.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@

namespace Tempest\Database\Transactions;

use PDO;
use Tempest\Database\Connection;
use Tempest\Database\Exceptions\CouldNotBeginTransaction;
use Tempest\Database\Exceptions\CouldNotCommitTransaction;
use Tempest\Database\Exceptions\CouldNotRollbackTransaction;

final class GenericTransactionManager implements TransactionManager
{
public function __construct(private PDO $pdo)
public function __construct(private Connection $connection)
{
}

public function begin(): void
{
$transactionBegun = $this->pdo->beginTransaction();
$transactionBegun = $this->connection->beginTransaction();

if (! $transactionBegun) {
throw new CouldNotBeginTransaction();
Expand All @@ -26,7 +26,7 @@ public function begin(): void

public function commit(): void
{
$transactionCommitted = $this->pdo->commit();
$transactionCommitted = $this->connection->commit();

if (! $transactionCommitted) {
throw new CouldNotCommitTransaction();
Expand All @@ -35,7 +35,7 @@ public function commit(): void

public function rollback(): void
{
$transactionRolledBack = $this->pdo->rollBack();
$transactionRolledBack = $this->connection->rollBack();

if (! $transactionRolledBack) {
throw new CouldNotRollbackTransaction();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@

namespace Tempest\Database\Transactions;

use PDO;
use Tempest\Container\Container;
use Tempest\Container\Initializer;
use Tempest\Container\Singleton;
use Tempest\Database\Connection;

final readonly class TransactionManagerInitializer implements Initializer
{
#[Singleton]
public function initialize(Container $container): TransactionManager
{
return new GenericTransactionManager($container->get(PDO::class));
return new GenericTransactionManager($container->get(Connection::class));
}
}
2 changes: 1 addition & 1 deletion src/Tempest/Database/tests/DatabaseDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Tempest\Database\Connections\DatabaseConnection;
use Tempest\Database\Connections\MySqlConnection;
use Tempest\Database\Connections\PostgresConnection;
use Tempest\Database\Connections\SQLiteConnection;
use Tempest\Database\DatabaseConnection;

/**
* @internal
Expand Down
2 changes: 1 addition & 1 deletion src/Tempest/Database/tests/DatabaseQueryStatementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Tempest\Database\Connections\DatabaseConnection;
use Tempest\Database\Connections\MySqlConnection;
use Tempest\Database\Connections\PostgresConnection;
use Tempest\Database\Connections\SQLiteConnection;
use Tempest\Database\DatabaseConnection;
use Tempest\Database\QueryStatements\CreateTableStatement;
use Tempest\Database\QueryStatements\OnDelete;
use Tempest\Database\QueryStatements\PrimaryKeyStatement;
Expand Down
Loading
Loading