php-pg/pgconn

低级 PostgreSQL 数据库驱动程序

v0.0.1 2022-02-12 03:40 UTC

This package is auto-updated.

Last update: 2024-09-12 09:06:24 UTC


README

包 pgconn 是一个低级 PostgreSQL 数据库驱动程序。它几乎与 C 库 libpq 在同一级别上运行。应用程序应使用高级库来处理常规查询,并在需要直接访问 PostgreSQL 功能时才使用 pgconn。

连接

此库尽可能遵循 libpq 的行为。这意味着您可以使用几乎所有的 libpq 连接选项和两种连接字符串格式。

支持的 libpq 功能

使用连接字符串

有关 libpq 连接字符串格式的详细信息,请参阅 34.1.1. 连接字符串

支持的连接字符串

  • 关键字/值,例如:host=localhost port=5432 user=user password=secret dbname=mydb connect_timeout=10
    • 多主机,例如:host=localhost,otherhost port=5432,5433 user=user password=secret dbname=mydb connect_timeout=10
  • URI,例如:postgresql://user:secret@localhost:5432/mydb?connect_timeout=10
    • 多主机,例如:postgresql://user:secret@localhost:5432,otherhost:5433/mydb?connect_timeout=10
$connString = 'host=localhost port=5432 user=user password=secret dbname=mydb connect_timeout=10';
// or
$connString = 'postgresql://user:secret@localhost:5432/mydb?connect_timeout=10';

$conf = \PhpPg\PgConn\Config\Internal\parseConfig($connString);

$pgConnector = new \PhpPg\PgConn\PgConnector();
$conn = $pgConnector->connect($conf);

有关支持连接选项的详细信息,请参阅 34.1.2. 参数关键字

通过手动实例化配置

$conf = new \PhpPg\PgConn\Config\Config(
    hosts: [
        new \PhpPg\PgConn\Config\HostConfig(
            host: '127.0.0.1',
            port: 5432,
            password: 'secret',
            tlsConfig: null,
        ),
        new \PhpPg\PgConn\Config\HostConfig(
            host: '127.0.0.1',
            port: 5433,
            password: 'secret_pass',
            tlsConfig: new \PhpPg\PgConn\Config\TlsConfig(
                tlsContext: (new \Amp\Socket\ClientTlsContext(''))
                    ->withoutPeerVerification()
                    ->withCaFile('path to CA')
                    ->withCertificate(new \Amp\Socket\Certificate('path to public key', 'path to private key')),
                sslMode: \PhpPg\PgConn\Config\SslMode::PREFER,
            )
        ),
    ],
    user: 'postgres',
    database: 'mydb',
    connectTimeout: 1,
    // and other params
);

// Also, fluent interface supported
$conf = $conf
    ->withRuntimeParam('application_name', 'My Application')
    ->withOnNotice(new class implements \PhpPg\PgConn\Config\NoticeHandlerInterface {
        public function __invoke(\PhpPg\PgConn\Notice $notice): void {
            // do something with notice
        }
    })
    ->withOnNotification(new class implements \PhpPg\PgConn\Config\NotificationHandlerInterface {
        public function __invoke(\PhpPg\PgConn\Notification $notice): void {
            // do something with notification
        }
    })
    // Any PSR compatible logger for debugging purposes
    ->withLogger($logger);

$pgConnector = new \PhpPg\PgConn\PgConnector();
$conn = $pgConnector->connect($conf);

API

PgConn 不是并发安全的,应在连接池中使用。

方法

  • PgConn::close(): void - 与服务器断开连接

  • PgConn::getConfig(): Config - 获取用于建立连接的配置

  • PgConn::getHostConfig(): HostConfig - 获取当前连接主机的配置

  • PgConn::getSocket(): Socket - 获取底层的套接字连接

  • PgConn::getStatus(): PgConnStatus - 获取当前连接状态

  • PgConn::getPid(): int - 获取后端进程 ID

  • PgConn::getSecretKey(): int - 获取取消请求的秘密密钥

  • PgConn::getTxStatus(): string (1 byte) - 获取事务状态(有关详细信息,请参阅 ReadyForQuery 消息)

  • PgConn::getParameterStatuses(): array<string, string> - 获取当前会话运行时参数

  • PgConn::getParameterStatus(string $paramName): string - 获取当前会话运行时参数

  • PgConn::cancelRequest - 取消正在进行的请求(可能没有效果,请参阅“取消 API 调用”部分)

  • PgConn::exec - 使用简单协议执行查询(一次可以指定多个查询)。

    请参阅示例
    /** @var \PhpPg\PgConn\PgConn $conn */
    $sql = "SELECT 'Hello World' AS msg, 322 AS num; SELECT * FROM table; UPDATE table SET idx = idx + 1";
    
    /**
    * If the query contains a syntax error or contains invalid data, no exception will be thrown,
    * an exception will be thrown when the results are received.
    */
    $mrr = $conn->exec($sql);
    
    // Fetch all results at once
    $results = $mrr->readAll();
    
    $results[0]; // query 1 results
    $results[1]; // query 2 results
    $results[2]; // query 3 results
    
    $results[0]->getCommandTag(); // query 1 execution result (e.g. SELECT 1)
    $rows = $results[0]->getRows(); // query 1 returned rows (multidimensional array)
    $rows[0]; // query 1 row 1
    $rows[0][0] // query 1 row 1 column 1
    $rows[0][0] // query 1 row 1 column 2
    
    $results[0]->getFieldDescriptions(); // query 1 returned rows format information (binary/text, data type, column name, etc)
    
    // Fetch results in iterative way
    while ($mrr->nextResult()) {
        $rr = $mrr->getResultReader();
        $fieldDescriptions = $rr->getFieldDescriptions()
        
        while ($rr->nextRow()) {
            $result = $rr->getResult();
    
            $rows = $result->getRows();
            foreach ($rows as $rowIdx => $row) {
                foreach ($row as $colIdx => $colValue) {
                    // Do something with returned data
                }
            }
        }
        
        $commandTag = $rr->getCommandTag();
    }
  • PgConn::execParams - 使用扩展协议执行查询(允许参数绑定),不允许多个查询

    请参阅示例
    /** @var \PhpPg\PgConn\PgConn $conn */
    $rr = $conn->execParams(
        sql: 'SELECT $1::int, $2::text',
        paramValues: ['100', 'Hello world'],
        // param formats (binary/text)
        paramFormats: [],
        // param data types
        paramOIDs: [],
        // return rows format (binary/text)
        resultFormats: [],
    );
    
    $result = $rr->getResult();
    
    $result->getFieldDescriptions(); // returned rows format information (binary/text, data type, column name, etc)
    $result->getRows(); // returned rows
    $result->getCommandTag(); // command execution result
  • PgConn::prepare - 准备语句

    请参阅示例
    /** @var \PhpPg\PgConn\PgConn $conn */
    $stmtDesc = $conn->prepare(
        name: 'my_stmt_1',
        sql: "INSERT INTO my_table (col1, col2) VALUES ($1::int, $2::text)"
    );
    $stmtDesc->name; // prepared statement name
    $stmtDesc->fields; // prepared statement return rows format description
    $stmtDesc->paramOIDs; // prepared statement bind parameter types
    $stmtDesc->sql; // prepared statement query
  • PgConn:execPrepared - 执行预处理语句

    请参阅示例
    /** @var \PhpPg\PgConn\PgConn $conn */
    $rr = $conn->execPrepared(
        stmtName: 'my_stmt_1',
        paramValues: ['100', 'Hello World'],
        // parameter formats (1 - text; 0 - binary
        // One item per each paramValue or one item for all paramValues
        paramFormats: [],
        // desired format of returned rows, such as paramFormats
        resultFormats: [],
    );
    $result = $rr->getResult();
    
    $result->getFieldDescriptions(); // returned rows format information (binary/text, data type, column name, etc)
    $result->getRows(); // returned rows
    $result->getCommandTag(); // command execution result
  • PgConn::copyFrom - 从可读流复制数据到 PostgreSQL 服务器

    请参阅示例
    /** @var \PhpPg\PgConn\PgConn $conn */
    $genData = static function (): \Generator {
        for ($i = 0; $i < 1000; $i++) {
            yield "{$i}, \"foo {$i} bar\"\n";
        }
    };
    $stream = new \Amp\ByteStream\ReadableIterableStream($genData());
    
    $ct = $conn->copyFrom('COPY foo FROM STDIN WITH (FORMAT csv)', $stream);
    echo "Rows affected: {$ct->rowsAffected()}\n";
  • PgConn::copyTo - 从 PostgreSQL 服务器复制数据到可写流

    请参阅示例
    /** @var \PhpPg\PgConn\PgConn $conn */
    $stream = new \Amp\ByteStream\WritableIterableStream(0);
    
    \Amp\async(static function () use ($stream) {
    foreach ($stream->getIterator() as $row) {
    // Process row copied from postgres
    }
    });
    
    $ct = $conn->copyTo('COPY foo TO STDOUT', $stream);
    echo "Rows affected: {$ct->rowsAffected()}\n";

取消 API 调用

可以使用 AMPHP 取消对象取消任何 API 调用。
当取消发生时,库向 PostgreSQL 服务器发送 CancelRequest 消息。

但是,PostgreSQL 协议流程有一个重要的说明

取消信号可能或 可能不会 有任何效果——例如,如果它在后端完成处理查询之后到达,则它将没有效果。
如果取消有效,则会导致当前命令提前终止并显示错误信息。

综上所述,出于安全和效率的考虑,前端没有直接的方法来判断取消请求是否成功。
它必须继续等待后端对查询的响应。
发出取消请求仅仅提高了当前查询尽快完成的可能性,并提高了它将以错误信息而不是成功结束的可能性。

这意味着取消对象可能不会立即取消正在运行的查询。

有关更多信息,请参阅53.2.7. 取消进行中的请求

灵感来源于Golang包jackc/pgconn