amphp/sql-common
Shared interfaces and abstractions for asynchronous SQL database clients in Amp, including connection pools, query result interfaces, and common SQL exceptions. It forms the foundation for amphp/mysql and amphp/postgres.
amphp/sql-common is an interface/abstraction package. It cannot open a database connection by itself.composer require amphp/mysql
# or
composer require amphp/postgres
Add amphp/sql-common explicitly only when you type-hint its interfaces, build a custom driver, or write reusable database-agnostic code.src/SqlExecutor.php — the core query/prepare/execute contract.src/SqlConnectionPool.php — pooling, transactions, connection lifecycle.src/SqlConnection.php — a single connection.src/SqlResult.php / SqlStatement.php / SqlTransaction.php — result, prepared statement, transaction contracts.src/ConnectionConfig.php — driver configuration base.src/Common/ — shared pool implementation helpers used by the MySQL/Postgres drivers.Amp\Sql\SqlConnectionPool and run a query through the common interface.
use Amp\Sql\SqlConnectionPool;
final class UserRepository
{
public function __construct(private SqlConnectionPool $pool) {}
public function find(int $id): ?array
{
$result = $this->pool->execute(
'SELECT * FROM users WHERE id = ?', // Postgres uses $1
[$id],
);
foreach ($result as $row) {
return $row;
}
return null;
}
}
Amp\Sql\SqlExecutor. Use SqlConnectionPool only when you need transactions, connection acquisition, pool stats, or shutdown control.execute() for one-shot queries. It acquires and releases a connection for you. Use getConnection() only for explicit transactions or session-level state.SqlStatement; do not share a statement across pool connections because it is bound to its originating connection.$transaction = $pool->beginTransaction();
try {
$transaction->execute('UPDATE accounts SET balance = balance - ? WHERE id = ?', [$amount, $from]);
$transaction->execute('UPDATE accounts SET balance = balance + ? WHERE id = ?', [$amount, $to]);
$transaction->commit();
} catch (\Throwable $e) {
$transaction->rollback();
throw $e;
}
Keep the transaction scope small and never share a SqlTransaction across concurrent coroutines.Amp\Sql\SqlTransactionIsolation) when the driver supports them, rather than driver-specific constants.SqlExecutor for cross-cutting concerns. Logging, metrics, retry policies, and query timing can be implemented by decorating the shared interface without coupling to MySQL or Postgres.SqlExecutor, but keep dialect-specific SQL in the driver-specific implementation or configuration layer. The shared package does not normalize SQL dialects or placeholders.SqlConnection, SqlStatement, SqlResult, and SqlTransaction; provide a SqlConnector; and reuse the Amp\Sql\Common\* pool helpers where possible.SqlExecutor, SqlStatement, and SqlResult for unit tests. Use real driver integration tests for SQL correctness, pooling, and transaction behavior.amphp/mysql commonly uses ?; amphp/postgres commonly uses $1, $2, etc. Do not assume SQL written against one driver will run unchanged on the other.getConnection() and then wait on another pooled connection in the same logical operation.SqlResult before reusing the connection. Some metadata such as row count may not be available until the result is consumed.commit() or rollback(). Relying on destructor behavior is fragile, especially under cancellation and long-running workers.Amp\Sql\SqlException, ConnectionException, QueryError, TransactionError) rather than only driver-specific exception classes. Inspect available query/error context when debugging failed statements.sleep(), blocking file/network I/O) stall the event loop. In Amp v3/fiber-based code, synchronous-looking code still runs cooperatively; do not introduce blocking operations.amphp/sql-common on a major version compatible with your MySQL/Postgres driver. Mixing major versions can produce interface mismatches.SqlExecutor/SqlConnectionPool if you need query logs, timings, or metrics.withDatabase()-style helpers where provided instead of mutating shared config. Never log connection configs containing passwords.SqlConnector and extend the shared Common pool classes for custom transports or test doubles; use decorators rather than modifying vendor code for observability.How can I help you explore Laravel packages today?