Pg put line: примеры (PHP)

Функция pg_put_line и передача данных в PostgreSQL
Раздел: Базы данных (PostgreSQL)
pg_put_line(PgSql\Connection $connection, string $data): bool
Функция pg_put_line в PHP

Функция pg_put_line отправляет строку данных на сервер PostgreSQL в режиме копирования. Она применяется при выполнении операций COPY FROM или COPY TO для передачи данных построчно, что эффективно для массовой загрузки или выгрузки информации.

Аргументы функции
  • connection – ресурс соединения с базой данных PostgreSQL.
  • data – строка для отправки на сервер. Должна заканчиваться символом новой строки, который добавляется автоматически, если отсутствует.

Функция возвращает true после успешной отправки строки или false при возникновении ошибки.

Простые примеры применения
Базовый пример копирования данных
<?
$conn = pg_connect("host=localhost dbname=test");
pg_query($conn, "COPY mytable FROM STDIN");
pg_put_line($conn, "1\tЗначение 1\n");
pg_put_line($conn, "2\tЗначение 2\n");
pg_put_line($conn, "3\tЗначение 3\n");
pg_put_line($conn, "\\.\n");
pg_end_copy($conn);
?>
Результат: данные успешно загружены в таблицу mytable.
Пример с автоматическим добавлением новой строки
<?
pg_query($conn, "COPY logs FROM STDIN");
// Символ новой строки не добавлен в строку
pg_put_line($conn, "2023-10-01\tОшибка подключения");
// Функция автоматически добавит \n
pg_put_line($conn, "\\.");
pg_end_copy($conn);
?>
Результат: строка '2023-10-01\tОшибка подключения\n' отправлена на сервер.
Альтернативные функции PHP

Для работы с данными PostgreSQL доступны несколько функций:

  • pg_copy_from – загружает массив данных в таблицу с помощью команды COPY. Позволяет передать все данные одним вызовом.
  • pg_copy_to – выгружает данные из таблицы в массив. Обе функции работают с массивами, что удобно для небольших объемов информации.
  • pg_query с INSERT – подходит для единичных вставок, но менее эффективен при массовой загрузке.

Функция pg_put_line применяется при потоковой передаче больших объемов данных, когда их нельзя или неэффективно хранить в памяти целиком.

Аналоги в других языках
Python с библиотекой psycopg2
import psycopg2
conn = psycopg2.connect("dbname=test")
cursor = conn.cursor()
cursor.copy_from(open('data.csv'), 'mytable', sep='\t')
conn.commit()
Результат: данные из файла загружены в таблицу.
Node.js с модулем pg
const { Client } = require('pg');
const client = new Client();
await client.connect();
const stream = client.query(copyFrom('COPY mytable FROM STDIN'));
stream.write('1\tЗначение 1\n');
stream.write('2\tЗначение 2\n');
stream.end();
await client.end();
Результат: строки переданы в таблицу.

Pg put line в MySQL

В MySQL аналогичная операция выполняется командой LOAD DATA INFILE:

LOAD DATA INFILE 'data.csv' INTO TABLE mytable
FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n';
Результат: данные из файла загружены в таблицу.

Основное отличие pg_put_line – возможность потоковой передачи данных напрямую из PHP без промежуточных файлов.

Типичные ошибки
Отсутствие символов завершения копирования
<?
pg_query($conn, "COPY table FROM STDIN");
pg_put_line($conn, "1\tДанные\n");
// Забыли добавить строку с \\.\n
pg_end_copy($conn);
?>
Результат: сервер ожидает продолжения данных, операция зависает.
Некорректное форматирование данных
<?
pg_query($conn, "COPY table FROM STDIN");
// Отсутствует разделитель между полями
pg_put_line($conn, "1Значение\n");
pg_put_line($conn, "\\.\n");
pg_end_copy($conn);
?>
Результат: ошибка PostgreSQL 'extra data after last expected column'.
Использование после pg_end_copy
<?
pg_query($conn, "COPY table FROM STDIN");
pg_put_line($conn, "1\tДанные\n");
pg_put_line($conn, "\\.\n");
pg_end_copy($conn);
// Попытка отправить данные после завершения
pg_put_line($conn, "2\tЕще данные\n");
?>
Результат: предупреждение 'pg_put_line(): Send of query failed'.
Изменения в версиях PHP

В PHP 8.1 функция pg_put_line стала возвращать значение типа bool вместо int. Ранее успешное выполнение возвращало 1, теперь – true.

Начиная с PHP 8.0, при передаче некорректного типа аргумента возникает исключение TypeError. В более ранних версиях выдавалось предупреждение.

<?
// PHP 8.0 и выше
pg_put_line([], "data\n");
?>
Результат: TypeError: pg_put_line(): argument #1 ($connection) must be of type PgSql\Connection, array given.
Расширенные примеры
Потоковая загрузка из CSV-файла
Пример php
<?
$conn = pg_connect("host=localhost dbname=test");
pg_query($conn, "COPY products FROM STDIN WITH (FORMAT CSV, HEADER false)");

$handle = fopen('large_products.csv', 'r');
if ($handle) {
    while (($line = fgets($handle)) !== false) {
        pg_put_line($conn, $line);
    }
    fclose($handle);
}

pg_put_line($conn, "\\.\n");
pg_end_copy($conn);
?>
Результат: содержимое файла large_products.csv загружено в таблицу products.
Передача данных с экранированием спецсимволов
Пример php
<?
pg_query($conn, "COPY test FROM STDIN");
// Данные содержат табуляцию и обратную косую черту
$data = "1\tЗначение с \\ обратной чертой\n";
pg_put_line($conn, $data);
// Экранированная обратная косая черта передается как один символ
pg_put_line($conn, "2\tЕще \\\\ данные\n");
pg_put_line($conn, "\\.\n");
pg_end_copy($conn);
?>
Результат: в таблице test будут строки: '1', 'Значение с \\ обратной чертой' и '2', 'Еще \\ данные'.
Использование с генераторами больших данных
Пример php
<?
function generate_data($rows) {
    for ($i = 0; $i < $rows; $i++) {
        yield $i . "\t" . md5($i) . "\t" . microtime(true) . "\n";
    }
}

pg_query($conn, "COPY hash_table FROM STDIN");
foreach (generate_data(100000) as $line) {
    pg_put_line($conn, $line);
}
pg_put_line($conn, "\\.\n");
pg_end_copy($conn);
?>
Результат: 100 тысяч строк сгенерированных данных загружены в таблицу hash_table без высокого потребления памяти.

PHP pg_put_line function comments

En
Pg put line Sends a null-terminated string to PostgreSQL backend