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

Функция pg_lo_write в PHP: работа с крупными объектами БД
Раздел: Базы данных (PostgreSQL)
pg_lo_write(PgSql\Lob $lob, string $data, ?int $length = null): int|false

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

Функция pg_lo_write предназначена для записи данных в крупный объект (large object) внутри базы данных PostgreSQL. Она используется в ситуациях, когда необходимо сохранить большие бинарные данные, такие как изображения, документы или аудиофайлы, напрямую в СУБД, а не в файловой системе.

Аргументы функции
  • PgSql\Lob или resource $lob — обязательный аргумент. Дескриптор крупного объекта, полученный с помощью функции pg_lo_open().
  • string $data — обязательный аргумент. Строка с данными для записи в объект.
  • ?int $length — необязательный аргумент. Максимальное количество записываемых байтов. Если аргумент опущен или равен null, записываются все данные из строки.

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

Короткие примеры использования

Пример 1: Базовая запись строки
$conn = pg_connect("dbname=test user=postgres");
$oid = pg_lo_create($conn);
$lob = pg_lo_open($conn, $oid, "w");
$data = "Пример текстовых данных.";
$bytesWritten = pg_lo_write($lob, $data);
pg_lo_close($lob);
echo "Записано байт: " . $bytesWritten;
Записано байт: 44
Пример 2: Запись с ограничением длины
$lob = pg_lo_open($conn, $oid, "w");
$result = pg_lo_write($lob, "Очень длинная строка для примера.", 10);
pg_lo_close($lob);
echo $result;
10
Пример 3: Обработка результата false
$invalidLob = null;
$result = pg_lo_write($invalidLob, "данные");
if ($result === false) {
    echo "Ошибка при записи.";
}
Ошибка при записи.

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

Функция для чтения данных из крупного объекта. Используется вместе с pg_lo_write для реализации полного цикла работы.

Создает крупный объект из файла в локальной файловой системе. Позволяет импортировать данные без явного открытия и поэтапной записи.

Выгружает крупный объект в файл. Альтернатива последовательному чтению через pg_lo_read.

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

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

Python (библиотека psycopg2)
import psycopg2
conn = psycopg2.connect("dbname=test")
lo = conn.lobject()
data = b"Binary data"
n = lo.write(data)
print(n)
11

В Python работа с крупными объектами организована через методы объекта lobject, что ближе к объектно-ориентированному стилю.

JavaScript (Node.js, библиотека 'pg' и 'pg-large-object')
const { LargeObject } = require('pg-large-object');
// ... получение client из 'pg'
const buffer = Buffer.from('Data');
client.query('BEGIN', (err) => {
  const stream = new LargeObject(client, oid, 'w');
  stream.write(buffer, (err, bytesWritten) => {
    console.log(bytesWritten);
  });
});

В Node.js часто используется потоковый API (Streams) для записи, что упрощает обработку больших объемов.

Pg lo write в MySQL

В MySQL нет прямого аналога крупных объектов PostgreSQL. Для хранения больших данных используются типы BLOB. Запись происходит стандартными SQL-операторами INSERT или UPDATE.

INSERT INTO files (blob_column) VALUES (LOAD_FILE('/tmp/file.bin'));

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

Использование неверного дескриптора объекта
$conn = pg_connect("dbname=test");
$fakeLob = "not a resource";
$result = pg_lo_write($fakeLob, "test");
Warning: pg_lo_write() expects parameter 1 to be resource, string given
Попытка записи в объект, открытый только для чтения
$lob = pg_lo_open($conn, $oid, "r"); // Открыт для чтения
$bytes = pg_lo_write($lob, "data");
Запись не выполняется, функция вернет false.
Работа вне управляющей транзакции

В PostgreSQL операции с крупными объектами требуют нахождения внутри транзакции. В противном случае может возникнуть ошибка.

pg_query($conn, "END"); // Завершаем предыдущую транзакцию
$oid = pg_lo_create($conn); // Вызовет ошибку

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

Начиная с PHP 8.1.0, первый аргумент функции ($lob) ожидается как объект PgSql\Lob. Ранее он был ресурсом (resource).

В PHP 8.0.0, при неудачном выполнении, функция теперь возвращает false. В очень старых версиях мог возвращать 0. Рекомендуется всегда использовать строгое сравнение (===) для проверки на ошибку.

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

Запись данных из файла с использованием цикла
Пример php
$filePath = "/путь/к/большому/файлу.iso";
$oid = pg_lo_create($conn);
$lob = pg_lo_open($conn, $oid, "w");
$handle = fopen($filePath, "rb");
$chunkSize = 4096;
$totalWritten = 0;
while (!feof($handle)) {
    $buffer = fread($handle, $chunkSize);
    $written = pg_lo_write($lob, $buffer);
    if ($written === false) {
        // Обработка ошибки
        break;
    }
    $totalWritten += $written;
}
fclose($handle);
pg_lo_close($lob);
echo "Всего записано: $totalWritten байт";
Использование внутри управляющей транзакции
Пример php
pg_query($conn, "BEGIN");
try {
    $oid = pg_lo_create($conn);
    $lob = pg_lo_open($conn, $oid, "w");
    pg_lo_write($lob, "Важные данные транзакции.");
    pg_lo_close($lob);
    // Связываем OID с записью в таблице
    pg_query($conn, "INSERT INTO documents (file_oid) VALUES ($oid)");
    pg_query($conn, "COMMIT");
} catch (Exception $e) {
    pg_query($conn, "ROLLBACK");
    throw $e;
}
Запись сгенерированных данных, например, изображения
Пример php
// Создаем простое изображение GD
$im = imagecreatetruecolor(100, 100);
$color = imagecolorallocate($im, 200, 100, 50);
imagefill($im, 0, 0, $color);

// Сохраняем изображение в буфер
ob_start();
imagepng($im);
$imageData = ob_get_clean();
imagedestroy($im);

// Записываем буфер в крупный объект
$oid = pg_lo_create($conn);
$lob = pg_lo_open($conn, $oid, "w");
$bytes = pg_lo_write($lob, $imageData);
pg_lo_close($lob);
echo "Изображение сохранено в БД, OID: $oid";

PHP pg_lo_write function comments

En
Pg lo write Write to a large object