Pg lo export: примеры (PHP)

Сохраняем данные из PostgreSQL: практическое руководство по pg_lo_export
Раздел: Базы данных (PostgreSQL)
pg_lo_export(PgSql\Connection $connection, int $oid, string $filename): bool
Описание функции pg_lo_export

Функция pg_lo_export в PHP экспортирует большой объект (Large Object) из базы данных PostgreSQL и сохраняет его содержимое в файл в локальной файловой системе. Ее применяют для извлечения бинарных данных, например изображений, документов или медиафайлов, которые хранятся в виде объектов в базе данных.

Аргументы функции
  • $connection (ресурс соединения) - идентификатор подключения к базе данных PostgreSQL.
  • $oid (int) - OID (Object Identifier) большого объекта, который необходимо экспортировать.
  • $pathname (string) - полный путь к файлу в локальной файловой системе, куда будет сохранен объект. Если файл уже существует, он будет перезаписан.

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

Примеры использования pg_lo_export
Базовый пример экспорта объекта

Код подключается к базе данных и экспортирует объект с известным OID в указанный файл.

$conn = pg_connect('host=localhost dbname=test user=postgres');
$oid = 12345; // OID большого объекта
$result = pg_lo_export($conn, $oid, '/tmp/exported_file.pdf');
if ($result) {
    echo 'Объект успешно экспортирован.';
} else {
    echo 'Произошла ошибка при экспорте.';
}
Объект успешно экспортирован.
Пример с обработкой ошибок
$conn = pg_connect('host=localhost dbname=test user=postgres');
if (!$conn) {
    die('Ошибка подключения');
}
$oid = 99999; // Несуществующий OID
if (pg_lo_export($conn, $oid, '/tmp/file.txt')) {
    echo 'Успех';
} else {
    echo 'Экспорт не удался. Проверьте OID и права на запись в директорию.';
}
Экспорт не удался. Проверьте OID и права на запись в директорию.
Альтернативные функции в PHP

Для работы с большими объектами (Large Objects) в PostgreSQL через PHP существуют другие функции модуля pgsql:

  • pg_lo_open - открывает большой объект для чтения или записи, возвращая ресурс объекта (дескриптор). Позволяет работать с данными по частям.
  • pg_lo_read - читает часть данных из открытого большого объекта.
  • pg_lo_write - записывает данные в открытый большой объект.
  • pg_lo_import - функция, обратная pg_lo_export. Она импортирует файл из файловой системы в базу данных как большой объект и возвращает его OID.

pg_lo_export используют, когда нужно быстро сохранить весь объект в файл. Функции pg_lo_open, pg_lo_read и pg_lo_write предпочтительнее, если требуется потоковая обработка данных или работа с фрагментами большого файла.

Аналоги функции в других языках
Python (библиотека psycopg2)

В psycopg2 для экспорта большого объекта используют метод lo_export объекта Large Object.

import psycopg2
conn = psycopg2.connect('host=localhost dbname=test user=postgres')
conn.autocommit = True
lobj = conn.lobject(12345) # Открытие объекта по OID
lobj.export('/tmp/exported_file.pdf') # Экспорт в файл
print('Экспорт завершен')
Экспорт завершен
JavaScript (Node.js, библиотека pg)

В Node.js работа с большими объектами требует использования потоков (streams). Прямого аналога pg_lo_export нет.

const { Client } = require('pg');
const fs = require('fs');
const client = new Client();
(async () => {
    await client.connect();
    const lo = client.largeObject(12345); // OID объекта
    const stream = lo.read(); // Создание потока для чтения
    const fileStream = fs.createWriteStream('/tmp/file.pdf');
    stream.pipe(fileStream); // Запись потока в файл
    console.log('Объект экспортируется через поток.');
})();

Pg lo export в MySQL

В MySQL нет прямого аналога больших объектов PostgreSQL. Для хранения файлов часто используют тип данных BLOB (Binary Large Object) и стандартные запросы SELECT для извлечения данных, которые затем сохраняют через файловые операции языка программирования.

SELECT file_data FROM documents WHERE id = 1 INTO DUMPFILE '/tmp/file.bin'; -- Требует особых привилегий
Типичные ошибки
Неверный OID объекта

Попытка экспорта несуществующего большого объекта приводит к ошибке и возврату false.

$result = pg_lo_export($conn, 0, '/tmp/file.txt'); // OID 0 обычно не существует
var_dump($result);
bool(false)
Отсутствие прав на запись в директорию
// Попытка сохранить файл в системную директорию без прав
$result = @pg_lo_export($conn, 12345, '/root/exported_file.bin');
if (!$result) {
    $error = error_get_last();
    echo 'Ошибка: ' . $error['message'];
}
Ошибка: pg_lo_export(): Unable to open /root/exported_file.bin for writing
Работа в транзакции без autocommit

Для операций с большими объектами вне транзакции необходимо либо установить autocommit, либо явно открывать транзакцию.

pg_query($conn, 'BEGIN');
$result = pg_lo_export($conn, 12345, '/tmp/file.txt'); // Может не сработать ожидаемо
pg_query($conn, 'COMMIT');
Изменения в функции

В последних версиях PHP 8 существенных изменений в работе функции pg_lo_export не произошло. Поведение и сигнатура функции остались стабильными. Основные изменения в модуле pgsql касались внутренних улучшений и соответствия современным стандартам.

Расширенные примеры
Экспорт с предварительным получением OID из таблицы
Пример php
$conn = pg_connect('host=localhost dbname=test user=postgres');
// Предположим, что в таблице 'documents' есть столбец 'lo_oid'
$res = pg_query($conn, 'SELECT lo_oid FROM documents WHERE id = 101');
$row = pg_fetch_assoc($res);
if ($row) {
    $oid = $row['lo_oid'];
    $filename = '/var/www/uploads/doc_' . $oid . '.bin';
    if (pg_lo_export($conn, $oid, $filename)) {
        echo 'Документ сохранен как: ' . htmlspecialchars($filename);
    }
}
Документ сохранен как: /var/www/uploads/doc_12346.bin
Пакетный экспорт нескольких объектов
Пример php
$oids = [12345, 12346, 12347];
$exported = [];
foreach ($oids as $oid) {
    $path = sprintf('/backup/object_%d.bin', $oid);
    if (pg_lo_export($conn, $oid, $path)) {
        $exported[] = $oid;
    }
}
echo 'Успешно экспортировано объектов: ' . count($exported);
Успешно экспортировано объектов: 3
Комбинация с pg_lo_open для проверки перед экспортом
Пример php
$oid = 12345;
$lo = pg_lo_open($conn, $oid, 'r'); // 'r' - режим чтения
if ($lo) {
    // Объект существует и доступен для чтения
    pg_lo_close($lo);
    $success = pg_lo_export($conn, $oid, '/tmp/checked_export.bin');
} else {
    echo 'Не удалось открыть объект с OID: ' . $oid;
}

PHP pg_lo_export function comments

En
Pg lo export Export a large object to a file