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

Практическое применение pg_send_query_params в PHP для работы с PostgreSQL
Раздел: Базы данных (PostgreSQL)
pg_send_query_params(PgSql\Connection $connection, string $query, array $params): int|bool

Основные сведения о функции

Назначение и описание

Функция pg_send_query_params отправляет команду и отдельные параметры на сервер PostgreSQL для асинхронного выполнения, не дожидаясь возвращения результата. Она используется для безопасного выполнения параметризованных SQL-запросов, минимизируя риск SQL-инъекций. Функция полезна в сценариях, требующих неблокирующего взаимодействия с базой данных.

Синтаксис и аргументы

Функция имеет следующую сигнатуру:

pg_send_query_params(PgSql\Connection $connection = ?, string $query = ?, array $params = ?): int|bool

Аргументы:

  • $connection (PgSql\Connection). Обязательный. Ресурс соединения с PostgreSQL, возвращенный функциями pg_connect() или pg_pconnect().
  • $query (string). Обязательный. SQL-запрос, содержащий плейсхолдеры ($1, $2 и т.д.). В одном запросе может быть несколько команд, разделенных точкой с запятой.
  • $params (array). Массив значений параметров для подстановки вместо плейсхолдеров в запросе. Количество элементов должно соответствовать количеству плейсхолдеров. Все значения обрабатываются как строки.

Возвращаемое значение: Возвращает true в случае успешной отправки, false при неудаче. Для получения результатов запроса необходимо использовать функции pg_get_result().

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

Простой параметризованный запрос
<?
$conn = pg_connect("host=localhost dbname=test user=postgres");
$sql = 'SELECT * FROM users WHERE id = $1';
$params = [42];
$result = pg_send_query_params($conn, $sql, $params);
if ($result) {
    $res = pg_get_result($conn);
    $rows = pg_fetch_all($res);
    print_r($rows);
}
?>
Array
(
    [0] => Array
        (
            [id] => 42
            [name] => Иван
        )
)
Запрос с несколькими параметрами
<?
$sql = 'INSERT INTO products (name, price) VALUES ($1, $2) RETURNING id';
$params = ['Монитор', 15000];
if (pg_send_query_params($conn, $sql, $params)) {
    $res = pg_get_result($conn);
    $newId = pg_fetch_result($res, 0, 'id');
    echo "Добавлен товар с ID: $newId";
}
?>
Добавлен товар с ID: 101

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

Синхронный аналог, который сразу возвращает результат. Используется, когда не требуется асинхронность, и нужно упростить код.

Отправляет запрос асинхронно, но без поддержки раздельных параметров. Значения необходимо экранировать вручную с помощью pg_escape_string(). Менее безопасный вариант.

PDO::prepare и PDOStatement::execute

Альтернативный подход через расширение PDO. Поддерживает именованные плейсхолдеры и более унифицированный API для работы с разными СУБД. Для асинхронных операций в PDO требуется дополнительная настройка.

Аналоги в других языках

Python (psycopg2)
import psycopg2
conn = psycopg2.connect("dbname=test")
cur = conn.cursor()
cur.execute("SELECT * FROM users WHERE id = %s", (42,))
rows = cur.fetchall()
print(rows)
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', [42]);
console.log(res.rows);
MySQL (PHP PDO)
// Вместо pg_send_query_params для MySQL через PDO
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([42]);
$rows = $stmt->fetchAll();

Основное отличие от PHP-функции заключается в синтаксисе плейсхолдеров и синхронной/асинхронной модели работы по умолчанию.

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

Несоответствие количества параметров
<?
$sql = 'SELECT * FROM users WHERE id = $1 AND status = $2';
$params = [5]; // Только один параметр вместо двух
$sent = pg_send_query_params($conn, $sql, $params);
if ($sent) {
    $res = pg_get_result($conn);
    echo pg_result_error($res);
}
?>
Warning: pg_send_query_params(): Query failed: ERROR:  bind message supplies 1 parameters, but prepared statement "pdo_stmt_00000001" requires 2
Использование некорректного типа соединения
<?
$conn = 'localhost'; // Строка вместо ресурса соединения
$sent = pg_send_query_params($conn, 'SELECT 1', []);
var_dump($sent);
?>
Warning: pg_send_query_params(): supplied resource is not a valid PostgreSQL link resource in ...
bool(false)
Отсутствие проверки результата отправки
<?
pg_send_query_params($conn, 'INVALID SQL', []);
// Сразу пытаемся получить результат без проверки успешности отправки
$res = pg_get_result($conn);
if ($res) {
    echo pg_result_error($res);
}
?>
ERROR:  syntax error at or near "INVALID"

Изменения в версиях PHP

Функция была добавлена в PHP 5.1.0. Специфичных изменений в поведении функции в последних мажорных версиях PHP (7.x, 8.x) не было. Важным изменением в PHP 8.1.0 стал переход на объектно-ориентированный API: вместо ресурсов (resource) теперь используется объект PgSql\Connection. Старый синтаксис с ресурсами по-прежнему работает, но выдает предупреждения о устаревании.

<?
// До PHP 8.1.0
$conn = pg_connect(...); // тип: resource
// Начиная с PHP 8.1.0
$conn = pg_connect(...); // тип: PgSql\Connection
?>

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

Асинхронное выполнение нескольких запросов
Пример php
<?
$conn = pg_connect(...);
// Отправляем первый запрос
pg_send_query_params($conn,
    'INSERT INTO log (message) VALUES ($1) RETURNING id',
    ['Старт операции']
);
// Не дожидаясь завершения, отправляем второй
pg_send_query_params($conn,
    'SELECT expensive_calculation($1)',
    ['123']
);
// Получаем результаты в порядке отправки
$res1 = pg_get_result($conn);
$insertId = pg_fetch_result($res1, 0, 0);
echo "Логирование ID: $insertId\n";
$res2 = pg_get_result($conn);
$calcResult = pg_fetch_result($res2, 0, 0);
echo "Результат вычисления: $calcResult\n";
?>
Работа с NULL-значениями
Пример php
<?
$sql = 'UPDATE users SET phone = $1 WHERE id = $2';
$params = [null, 10]; // Явное указание NULL
pg_send_query_params($conn, $sql, $params);
$res = pg_get_result($conn);
echo "Затронуто строк: " . pg_affected_rows($res);
?>
Использование в цикле с разными параметрами
Пример php
<?
$conn = pg_connect(...);
$sql = 'UPDATE orders SET processed = true WHERE id = $1';
$orderIds = [101, 102, 103];
foreach ($orderIds as $id) {
    // Все запросы ставятся в очередь
    pg_send_query_params($conn, $sql, [$id]);
}
// Затем результаты обрабатываются
while ($res = pg_get_result($conn)) {
    $affected = pg_affected_rows($res);
    echo "Обработан заказ, затронуто строк: $affected\n";
}
?>
Комбинирование с pg_connection_busy для управления потоком
Пример php
<?
// Проверка, свободно ли соединение для нового запроса
while (pg_connection_busy($conn)) {
    usleep(10000); // Ждем 10ms, если соединение занято обработкой предыдущего запроса
}
$sent = pg_send_query_params($conn, 'SELECT pg_sleep(1)', []);
echo "Длинный запрос отправлен";
// Соединение теперь будет занято, pg_connection_busy вернет true
?>

PHP pg_send_query_params function comments

En
Pg send query params Submits a command and separate parameters to the server without waiting for the result(s)