php-pg / pgconn
低级 PostgreSQL 数据库驱动程序
Requires
- php: >=8.1
- amphp/amp: ^v3.0.0
- amphp/socket: ^v2.0.0
- php-pg/pgpassfile: ^0.0.1
- php-pg/pgproto3: ^v0.0.9
- php-pg/pgservicefile: ^0.0.1
- psr/log: ^3.0
Requires (Dev)
- amphp/log: ^v2.0.0
- phpstan/phpstan: ^1.4
- phpstan/phpstan-strict-rules: ^1.1
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.6
README
包 pgconn 是一个低级 PostgreSQL 数据库驱动程序。它几乎与 C 库 libpq 在同一级别上运行。应用程序应使用高级库来处理常规查询,并在需要直接访问 PostgreSQL 功能时才使用 pgconn。
连接
此库尽可能遵循 libpq
的行为。这意味着您可以使用几乎所有的 libpq
连接选项和两种连接字符串格式。
支持的 libpq
功能
- .pgpass 文件
- .pg_service.conf 文件
- 环境变量
- 多个连接主机
使用连接字符串
有关 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