Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Exception Types

php-sqlx uses a hierarchy of exceptions to provide detailed error information.

Exception Hierarchy

SqlxException (base)
├── ConnectionException
├── QueryException
├── TransactionException
├── ParseException
├── ParameterException
├── ConfigurationException
├── ValidationException
├── NotPermittedException
├── TimeoutException
└── PoolExhaustedException

All exceptions extend Sqlx\Exceptions\SqlxException.

SqlxException

The base exception class for all php-sqlx errors.

use Sqlx\Exceptions\SqlxException;

try {
    $driver->queryRow("SELECT * FROM users");
} catch (SqlxException $e) {
    echo "Error: " . $e->getMessage();
    echo "Code: " . $e->getCode();

    if ($e->isTransient()) {
        // Can retry this operation
    }
}

Methods

MethodReturnsDescription
getMessage()stringError message
getCode()intError code constant
isTransient()boolWhether error is temporary/retriable
getSql()?stringThe SQL that caused the error (if applicable)

ConnectionException

Thrown when connection to the database fails.

use Sqlx\Exceptions\ConnectionException;

try {
    $driver = DriverFactory::make("postgres://invalid-host/mydb");
} catch (ConnectionException $e) {
    echo "Could not connect: " . $e->getMessage();
}

Common causes:

  • Invalid hostname or port
  • Authentication failure
  • Network issues
  • Database server down
  • SSL/TLS configuration errors

QueryException

Thrown when a query fails to execute.

use Sqlx\Exceptions\QueryException;

try {
    $driver->queryRow("SELECT * FROM nonexistent_table");
} catch (QueryException $e) {
    echo "Query failed: " . $e->getMessage();
    echo "SQL: " . $e->getSql();
}

Common causes:

  • Table or column doesn’t exist
  • Syntax errors
  • Constraint violations
  • Permission denied
  • Lock timeouts

TransactionException

Thrown for transaction-related errors.

use Sqlx\Exceptions\TransactionException;

try {
    $driver->begin(function($driver) {
        // ... operations that cause deadlock
        return true;
    });
} catch (TransactionException $e) {
    if ($e->isTransient()) {
        // Deadlock or serialization failure - can retry
    }
}

Common causes:

  • Deadlocks
  • Serialization failures
  • Lock wait timeouts
  • Transaction already in progress

ParseException

Thrown when SQL parsing fails (before sending to database).

use Sqlx\Exceptions\ParseException;

try {
    $driver->queryAll("SELECT * FROM users {{ AND status = }}");  // Incomplete block
} catch (ParseException $e) {
    echo "Parse error: " . $e->getMessage();
}

Common causes:

  • Malformed conditional blocks {{ }}
  • Invalid placeholder syntax
  • Unmatched quotes or brackets

ParameterException

Thrown when parameter validation fails.

use Sqlx\Exceptions\ParameterException;

try {
    $driver->queryAll("SELECT * FROM users WHERE age = ?u", [-5]);  // Negative unsigned
} catch (ParameterException $e) {
    echo "Invalid parameter: " . $e->getMessage();
}

Common causes:

  • Type mismatch with type-safe placeholders
  • Missing required parameters
  • Wrong number of parameters
  • Invalid parameter format

ConfigurationException

Thrown for configuration errors.

use Sqlx\Exceptions\ConfigurationException;

try {
    $driver = DriverFactory::make([
        // Missing OPT_URL
        DriverOptions::OPT_MAX_CONNECTIONS => 10,
    ]);
} catch (ConfigurationException $e) {
    echo "Config error: " . $e->getMessage();
}

Common causes:

  • Missing required options
  • Invalid option values
  • Conflicting options

ValidationException

Thrown when input validation fails.

use Sqlx\Exceptions\ValidationException;

try {
    $driver->insert('users', [
        'email' => 'not-an-email',  // Invalid format
    ]);
} catch (ValidationException $e) {
    echo "Validation failed: " . $e->getMessage();
}

NotPermittedException

Thrown when an operation is not allowed.

use Sqlx\Exceptions\NotPermittedException;

$readOnlyDriver = DriverFactory::make([
    DriverOptions::OPT_URL => "postgres://localhost/mydb",
    DriverOptions::OPT_READONLY => true,
]);

try {
    $readOnlyDriver->execute("INSERT INTO users ...", [...]);
} catch (NotPermittedException $e) {
    echo "Write not allowed on read-only connection";
}

TimeoutException

Thrown when an operation times out.

use Sqlx\Exceptions\TimeoutException;

try {
    $driver->queryAll("SELECT * FROM huge_table");  // Takes too long
} catch (TimeoutException $e) {
    echo "Query timed out: " . $e->getMessage();
}

PoolExhaustedException

Thrown when no connection is available from the pool.

use Sqlx\Exceptions\PoolExhaustedException;

try {
    $result = $driver->queryAll("SELECT ...");
} catch (PoolExhaustedException $e) {
    echo "All connections busy, try again later";
}

Common causes:

  • All connections in use
  • Acquire timeout exceeded
  • Slow queries holding connections

Catching Multiple Types

try {
    $user = $driver->queryRow("SELECT * FROM users WHERE id = ?", [$id]);
} catch (ConnectionException $e) {
    // Handle connection issues
    log_error("Database unavailable: " . $e->getMessage());
    show_maintenance_page();
} catch (QueryException $e) {
    // Handle query issues
    log_error("Query failed: " . $e->getSql());
    show_error_page();
} catch (SqlxException $e) {
    // Catch-all for other php-sqlx errors
    log_error("Database error: " . $e->getMessage());
    show_error_page();
}

Best Practices

Log Full Details

try {
    $driver->execute($sql, $params);
} catch (SqlxException $e) {
    $logger->error('Database error', [
        'message' => $e->getMessage(),
        'code' => $e->getCode(),
        'sql' => $e->getSql(),
        'transient' => $e->isTransient(),
        'trace' => $e->getTraceAsString(),
    ]);
    throw $e;
}

Retry Transient Errors

try {
    $result = $driver->queryAll($sql, $params);
} catch (SqlxException $e) {
    if ($e->isTransient()) {
        // Retry logic
        usleep(100000);
        $result = $driver->queryAll($sql, $params);
    } else {
        throw $e;
    }
}

Convert to Domain Exceptions

try {
    return $this->driver->queryRow(
        "SELECT * FROM users WHERE id = ?",
        [$id]
    );
} catch (QueryException $e) {
    throw new UserNotFoundException("User $id not found", 0, $e);
}