master

laravel/framework

Last updated at: 29/12/2023 09:21

PostgresConnector.php

TLDR

This file is the PostgresConnector class in the Illuminate\Database\Connectors namespace. It extends the Connector class and implements the ConnectorInterface. The class provides methods to establish a database connection, configure the connection settings, and create a DSN string.

Methods (5)

connect

This method is responsible for establishing a database connection. It takes an array of configuration options as a parameter and returns a PDO object representing the connection.

configureIsolationLevel

This method sets the connection transaction isolation level. It takes a PDO object representing the connection and an array of configuration options as parameters. If the isolation_level configuration option is set, it prepares and executes a statement to set the session characteristics as the specified isolation level.

configureEncoding

This method sets the connection character set and collation. It takes a PDO object representing the connection and an array of configuration options as parameters. If the charset configuration option is set, it prepares and executes a statement to set the names to the specified character set.

configureTimezone

This method sets the timezone on the connection. It takes a PDO object representing the connection and an array of configuration options as parameters. If the timezone configuration option is set, it prepares and executes a statement to set the time zone to the specified timezone.

configureSearchPath

This method sets the "search_path" on the database connection. It takes a PDO object representing the connection and an array of configuration options as parameters. If either the search_path or schema configuration option is set, it prepares and executes a statement to set the search path to the specified value.

configureApplicationName

This method sets the application name on the connection. It takes a PDO object representing the connection and an array of configuration options as parameters. If the application_name configuration option is set, it prepares and executes a statement to set the application name to the specified value.

getDsn

This method creates a DSN string from a configuration. It takes an array of configuration options as a parameter. It extracts the host, database, and port from the configuration options and constructs the basic DSN string. If a port is specified, it adds it to the DSN string. Finally, it calls the addSslOptions method to add any SSL options specified in the configuration and returns the complete DSN string.

addSslOptions

This method adds SSL options to the DSN string. It takes the current DSN string and an array of configuration options as parameters. It iterates over the sslmode, sslcert, sslkey, and sslrootcert configuration options and, if they are set, appends them to the DSN string. It returns the updated DSN string.

configureSynchronousCommit

This method configures the synchronous_commit setting on the connection. It takes a PDO object representing the connection and an array of configuration options as parameters. If the synchronous_commit configuration option is set, it prepares and executes a statement to set the synchronous commit to the specified value.

Classes

No classes in this file

<?php

namespace Illuminate\Database\Connectors;

use Illuminate\Database\Concerns\ParsesSearchPath;
use PDO;

class PostgresConnector extends Connector implements ConnectorInterface
{
    use ParsesSearchPath;

    /**
     * The default PDO connection options.
     *
     * @var array
     */
    protected $options = [
        PDO::ATTR_CASE => PDO::CASE_NATURAL,
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
        PDO::ATTR_STRINGIFY_FETCHES => false,
    ];

    /**
     * Establish a database connection.
     *
     * @param  array  $config
     * @return \PDO
     */
    public function connect(array $config)
    {
        // First we'll create the basic DSN and connection instance connecting to the
        // using the configuration option specified by the developer. We will also
        // set the default character set on the connections to UTF-8 by default.
        $connection = $this->createConnection(
            $this->getDsn($config), $config, $this->getOptions($config)
        );

        $this->configureIsolationLevel($connection, $config);

        $this->configureEncoding($connection, $config);

        // Next, we will check to see if a timezone has been specified in this config
        // and if it has we will issue a statement to modify the timezone with the
        // database. Setting this DB timezone is an optional configuration item.
        $this->configureTimezone($connection, $config);

        $this->configureSearchPath($connection, $config);

        // Postgres allows an application_name to be set by the user and this name is
        // used to when monitoring the application with pg_stat_activity. So we'll
        // determine if the option has been specified and run a statement if so.
        $this->configureApplicationName($connection, $config);

        $this->configureSynchronousCommit($connection, $config);

        return $connection;
    }

    /**
     * Set the connection transaction isolation level.
     *
     * @param  \PDO  $connection
     * @param  array  $config
     * @return void
     */
    protected function configureIsolationLevel($connection, array $config)
    {
        if (isset($config['isolation_level'])) {
            $connection->prepare("set session characteristics as transaction isolation level {$config['isolation_level']}")->execute();
        }
    }

    /**
     * Set the connection character set and collation.
     *
     * @param  \PDO  $connection
     * @param  array  $config
     * @return void
     */
    protected function configureEncoding($connection, $config)
    {
        if (! isset($config['charset'])) {
            return;
        }

        $connection->prepare("set names '{$config['charset']}'")->execute();
    }

    /**
     * Set the timezone on the connection.
     *
     * @param  \PDO  $connection
     * @param  array  $config
     * @return void
     */
    protected function configureTimezone($connection, array $config)
    {
        if (isset($config['timezone'])) {
            $timezone = $config['timezone'];

            $connection->prepare("set time zone '{$timezone}'")->execute();
        }
    }

    /**
     * Set the "search_path" on the database connection.
     *
     * @param  \PDO  $connection
     * @param  array  $config
     * @return void
     */
    protected function configureSearchPath($connection, $config)
    {
        if (isset($config['search_path']) || isset($config['schema'])) {
            $searchPath = $this->quoteSearchPath(
                $this->parseSearchPath($config['search_path'] ?? $config['schema'])
            );

            $connection->prepare("set search_path to {$searchPath}")->execute();
        }
    }

    /**
     * Format the search path for the DSN.
     *
     * @param  array  $searchPath
     * @return string
     */
    protected function quoteSearchPath($searchPath)
    {
        return count($searchPath) === 1 ? '"'.$searchPath[0].'"' : '"'.implode('", "', $searchPath).'"';
    }

    /**
     * Set the application name on the connection.
     *
     * @param  \PDO  $connection
     * @param  array  $config
     * @return void
     */
    protected function configureApplicationName($connection, $config)
    {
        if (isset($config['application_name'])) {
            $applicationName = $config['application_name'];

            $connection->prepare("set application_name to '$applicationName'")->execute();
        }
    }

    /**
     * Create a DSN string from a configuration.
     *
     * @param  array  $config
     * @return string
     */
    protected function getDsn(array $config)
    {
        // First we will create the basic DSN setup as well as the port if it is in
        // in the configuration options. This will give us the basic DSN we will
        // need to establish the PDO connections and return them back for use.
        extract($config, EXTR_SKIP);

        $host = isset($host) ? "host={$host};" : '';

        // Sometimes - users may need to connect to a database that has a different
        // name than the database used for "information_schema" queries. This is
        // typically the case if using "pgbouncer" type software when pooling.
        $database = $connect_via_database ?? $database;
        $port = $connect_via_port ?? $port ?? null;

        $dsn = "pgsql:{$host}dbname='{$database}'";

        // If a port was specified, we will add it to this Postgres DSN connections
        // format. Once we have done that we are ready to return this connection
        // string back out for usage, as this has been fully constructed here.
        if (! is_null($port)) {
            $dsn .= ";port={$port}";
        }

        return $this->addSslOptions($dsn, $config);
    }

    /**
     * Add the SSL options to the DSN.
     *
     * @param  string  $dsn
     * @param  array  $config
     * @return string
     */
    protected function addSslOptions($dsn, array $config)
    {
        foreach (['sslmode', 'sslcert', 'sslkey', 'sslrootcert'] as $option) {
            if (isset($config[$option])) {
                $dsn .= ";{$option}={$config[$option]}";
            }
        }

        return $dsn;
    }

    /**
     * Configure the synchronous_commit setting.
     *
     * @param  \PDO  $connection
     * @param  array  $config
     * @return void
     */
    protected function configureSynchronousCommit($connection, array $config)
    {
        if (! isset($config['synchronous_commit'])) {
            return;
        }

        $connection->prepare("set synchronous_commit to '{$config['synchronous_commit']}'")->execute();
    }
}