Pg send execute: примеры (PHP)

Использование pg_send_execute для асинхронных запросов PostgreSQL
Раздел: Базы данных (PostgreSQL)
pg_send_execute(PgSql\Connection $connection, string $stmtname, array $params): int|bool

Функция pg_send_execute() в PHP выполняет асинхронную отправку подготовленного запроса с параметрами на сервер PostgreSQL. Она не ожидает завершения выполнения запроса, позволяя скрипту продолжить работу. Функция возвращает true при успешной отправке, false при ошибке и 0, если необходимо дождаться сокета.

Аргументы функции
  • connection (ресурс) — ресурс соединения с базой данных PostgreSQL.
  • stmtname (string) — имя подготовленного запроса. Если передана пустая строка, выполняется безымянный подготовленный запрос.
  • params (array) — массив значений параметров для подстановки в подготовленный запрос. Все значения приводятся к строковому типу.
Базовый пример
// Подготовка запроса
pg_prepare($conn, 'user_query', 'SELECT * FROM users WHERE id = $1');

// Асинхронная отправка с параметром
$result = pg_send_execute($conn, 'user_query', [42]);
echo $result ? 'Запрос отправлен' : 'Ошибка отправки';
Запрос отправлен
Пример с несколькими параметрами
pg_prepare($conn, 'insert_data', 'INSERT INTO logs (message, level) VALUES ($1, $2)');
$send = pg_send_execute($conn, 'insert_data', ['Тестовое сообщение', 'INFO']);
if ($send) {
    echo 'Данные поставлены в очередь на вставку';
}
Данные поставлены в очередь на вставку

В PHP существуют альтернативные функции для работы с PostgreSQL:

  • pg_execute() — синхронное выполнение подготовленного запроса. Блокирует выполнение скрипта до получения результата.
  • pg_send_query_params() — асинхронная отправка параметризованного запроса без предварительной подготовки.
  • pg_send_query() — асинхронная отправка обычного SQL-запроса.

Функцию pg_send_execute() предпочтительно использовать при необходимости асинхронного выполнения уже подготовленных запросов с параметрами, особенно в циклах или при обработке множества запросов.

Передача несуществующего имени запроса
$result = pg_send_execute($conn, 'nonexistent', [1]);
if ($result === false) {
    echo 'Ошибка: подготовленный запрос не найден';
}
Ошибка: подготовленный запрос не найден
Неверное количество параметров
pg_prepare($conn, 'query', 'SELECT $1, $2');
$result = pg_send_execute($conn, 'query', [1]); // Только один параметр вместо двух
if (!$result) {
    echo 'Ошибка: несоответствие количества параметров';
}
Ошибка: несоответствие количества параметров

В PHP 8.1 добавлена поддержка PgSql\Connection как альтернативы ресурсу соединения. С версии PHP 8.0 улучшена обработка ошибок.

// PHP 8.1+ с объектом PgSql\Connection
$conn = pg_connect("...");
$result = pg_send_execute($conn, 'stmtname', [1]); // $conn теперь объект
Асинхронная обработка нескольких запросов
Пример php
pg_prepare($conn, 'get_user', 'SELECT * FROM users WHERE id = $1');

$ids = [1, 2, 3];
$pending = [];

foreach ($ids as $id) {
    if (pg_send_execute($conn, 'get_user', [$id])) {
        $pending[] = $id;
    }
}

while (!empty($pending)) {
    foreach ($pending as $key => $id) {
        if (pg_connection_busy($conn)) {
            usleep(10000); // Ждем 10 мс
            continue;
        }
        $res = pg_get_result($conn);
        if ($res) {
            echo "Результат для ID $id: " . pg_fetch_assoc($res)['username'] . "\n";
            unset($pending[$key]);
        }
    }
}
Использование с безымянными подготовленными запросами
Пример php
// Безымянный подготовленный запрос
pg_prepare($conn, '', 'SELECT NOW() - $1::interval');
$sent = pg_send_execute($conn, '', ['1 day']);
if ($sent) {
    $res = pg_get_result($conn);
    print_r(pg_fetch_row($res));
}
Array
(
    [0] => 2023-12-31 10:00:00
)
Комбинирование с pg_get_result
Пример php
pg_prepare($conn, 'multi', 'SELECT $1, $2');

if (pg_send_execute($conn, 'multi', ['A', 'B'])) {
    while (pg_connection_busy($conn)) {
        usleep(1000);
    }
    $result = pg_get_result($conn);
    if ($result) {
        print_r(pg_fetch_all($result));
    }
}
Python (psycopg2)
import psycopg2
from psycopg2.extras import execute_batch

conn = psycopg2.connect("dbname=test")
cur = conn.cursor()
cur.execute("PREPARE user_query AS SELECT * FROM users WHERE id = %s")
cur.execute("EXECUTE user_query (%s)", (42,))
Node.js (pg)
const { Client } = require('pg');
const client = new Client();
await client.connect();
await client.query('PREPARE user_query AS SELECT * FROM users WHERE id = $1');
const res = await client.query('EXECUTE user_query(42)');
MySQL (подготовленные запросы)
// В MySQL нет прямой асинхронной альтернативы
$stmt = $mysql_conn->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", 42);
$stmt->execute();

PHP pg_send_execute function comments

En
Pg send execute Sends a request to execute a prepared statement with given parameters, without waiting for the result(s)