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

Асинхронная подготовка запросов: работа с pg_send_prepare в PHP
Раздел: Базы данных (PostgreSQL)
pg_send_prepare(PgSql\Connection $connection, string $stmtname, string $query): int|bool

Описание функции pg_send_prepare

Функция pg_send_prepare в PHP предназначена для асинхронной отправки запроса на создание подготовленного выражения (prepared statement) на сервер PostgreSQL. Она не дожидается завершения подготовки, что позволяет продолжить выполнение скрипта. Функция используется для оптимизации выполнения повторяющихся запросов и защиты от SQL-инъекций.

Аргументы функции
  • connection (ресурс) — обязательный аргумент, представляет собой соединение с базой данных PostgreSQL, полученное через pg_connect.
  • statement_name (строка) — уникальное имя подготовленного выражения в рамках соединения.
  • query (строка) — SQL-запрос с плейсхолдерами ($1, $2 и т.д.), который будет подготовлен.

Функция возвращает true при успешной отправке запроса, false в случае ошибки. Для проверки результата подготовки используется функция pg_get_result.

Примеры использования pg_send_prepare

Базовый пример подготовки выражения
$conn = pg_connect("dbname=test user=postgres");
$stmt_name = "my_select";
$query = "SELECT * FROM users WHERE id = $1";

// Асинхронная отправка запроса на подготовку
if (pg_send_prepare($conn, $stmt_name, $query)) {
    // Дожидаемся результата подготовки
    $result = pg_get_result($conn);
    if (pg_result_error($result)) {
        echo "Ошибка подготовки: " . pg_result_error($result);
    } else {
        echo "Подготовка успешна";
    }
} else {
    echo "Не удалось отправить запрос на подготовку";
}
Подготовка успешна
Пример с несколькими параметрами
$conn = pg_connect("dbname=test");
$stmt_name = "user_insert";
$query = "INSERT INTO users (name, age) VALUES ($1, $2)";

if (pg_send_prepare($conn, $stmt_name, $query)) {
    $result = pg_get_result($conn);
    if (!pg_result_error($result)) {
        // Теперь можно выполнить подготовленное выражение с параметрами
        pg_send_execute($conn, $stmt_name, array("Иван", 30));
        $exec_result = pg_get_result($conn);
        echo "Запись добавлена";
    }
}
Запись добавлена

Похожие функции в PHP

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

PDO::prepare

В расширении PDO метод prepare создает объект подготовленного выражения. Этот подход более универсален, так как работает с различными СУБД, и часто используется в современных приложениях.

Функция pg_query_params выполняет запрос с параметрами без явного создания именованного подготовленного выражения. Удобна для однократного выполнения параметризованных запросов.

Альтернативы в других языках

Python (psycopg2)
import psycopg2
conn = psycopg2.connect("dbname=test")
cursor = conn.cursor()
cursor.execute("PREPARE my_select AS SELECT * FROM users WHERE id = %s")
# Или использование параметризованных запросов напрямую:
cursor.execute("SELECT * FROM users WHERE id = %s", (1,))
JavaScript (node-postgres)
const { Client } = require('pg');
const client = new Client();
await client.connect();
// Подготовленные выражения создаются автоматически при именованных параметрах
const res = await client.query('SELECT * FROM users WHERE id = $1', [1]);
MySQL (подготовленные выражения)
-- В MySQL подготовленные выражения создаются на уровне протокола
PREPARE stmt FROM 'SELECT * FROM users WHERE id = ?';
SET @id = 1;
EXECUTE stmt USING @id;

Типичные ошибки

Использование неверного типа соединения
$conn = "not a connection";
$result = pg_send_prepare($conn, "stmt", "SELECT 1");
var_dump($result);
bool(false)
Повторное использование имени подготовленного выражения
$conn = pg_connect("dbname=test");
pg_send_prepare($conn, "my_stmt", "SELECT 1");
pg_get_result($conn);
// Повторное использование того же имени без освобождения может вызвать ошибку
pg_send_prepare($conn, "my_stmt", "SELECT 2");
$result = pg_get_result($conn);
echo pg_result_error($result);
ERROR: prepared statement "my_stmt" already exists
Некорректные плейсхолдеры в запросе
$conn = pg_connect("dbname=test");
pg_send_prepare($conn, "stmt", "SELECT $a, $b");
$result = pg_get_result($conn);
echo pg_result_error($result);
ERROR: there is no parameter $a

Изменения в последних версиях PHP

В PHP 8.1 функция pg_send_prepare не претерпела значительных изменений. Однако, начиная с PHP 8.0, многие функции расширения PgSQL были улучшены для лучшей интеграции с современными практиками программирования, такими как более строгая типизация. В PHP 8.2 добавлены предупреждения о нерекомендуемых способах использования, но они не затрагивают непосредственно pg_send_prepare.

Расширенные примеры

Асинхронная подготовка и выполнение в цикле
Пример php
$conn = pg_connect("dbname=test");
$stmt_name = "batch_insert";
$query = "INSERT INTO logs(level, message) VALUES ($1, $2)";

// Подготавливаем выражение
pg_send_prepare($conn, $stmt_name, $query);
$prep_result = pg_get_result($conn);
if (pg_result_error($prep_result)) die(pg_result_error($prep_result));

$logs = [
    ['INFO', 'Запись 1'],
    ['ERROR', 'Запись 2'],
    ['DEBUG', 'Запись 3']
];

// Асинхронно выполняем подготовленное выражение для каждого набора параметров
foreach ($logs as $log) {
    pg_send_execute($conn, $stmt_name, $log);
}
// Получаем все результаты
foreach ($logs as $log) {
    $res = pg_get_result($conn);
    if (pg_result_error($res)) {
        echo "Ошибка: " . pg_result_error($res);
    }
}
echo "Все записи добавлены";
Использование с pg_connect_poll для неблокирующих операций
Пример php
$conn = pg_connect("host=localhost dbname=test", PGSQL_CONNECT_ASYNC);
// Ждем подключения
while (true) {
    $status = pg_connect_poll($conn);
    if ($status === PGSQL_POLLING_OK) break;
    usleep(1000);
}
// Теперь можно асинхронно подготовить выражение
pg_send_prepare($conn, "async_stmt", "SELECT pg_sleep($1), $2");
// Делаем что-то полезное, пока запрос отправляется
// ...
// Затем проверяем результат
$result = pg_get_result($conn);
if (!pg_result_error($result)) {
    echo "Подготовка завершена";
}
Очистка подготовленных выражений
Пример php
$conn = pg_connect("dbname=test");
pg_send_prepare($conn, "temp_stmt", "SELECT $1");
pg_get_result($conn);
// Явное освобождение подготовленного выражения
pg_send_query($conn, "DEALLOCATE temp_stmt");
pg_get_result($conn);
echo "Выражение освобождено";

PHP pg_send_prepare function comments

En
Pg send prepare Sends a request to create a prepared statement with the given parameters, without waiting for completion