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

Использование pg_lo_seek для позиционирования в больших объектах
Раздел: Базы данных (PostgreSQL)
pg_lo_seek(PgSql\Lob $lob, int $offset, int $whence = SEEK_CUR): bool
Описание функции pg_lo_seek

Функция pg_lo_seek применяется для перемещения внутреннего указателя позиции в большом объекте PostgreSQL. Она используется при работе с данными типа Large Object, которые хранятся в базе данных, а не в файловой системе.

Аргументы функции
  • $lob – ресурс большого объекта, полученный через pg_lo_open.
  • $offset – количество байт для перемещения указателя. Может быть положительным (вперед) или отрицательным (назад).
  • $whence (опциональный, по умолчанию SEEK_CUR) – определяет точку отсчета:
    • SEEK_SET – отсчет от начала объекта.
    • SEEK_CUR – отсчет от текущей позиции.
    • SEEK_END – отсчет от конца объекта.
Краткие примеры использования
Перемещение от начала объекта
<?
$conn = pg_connect('dbname=test');
$lob = pg_lo_open($conn, $oid, 'r');
pg_lo_seek($lob, 100, SEEK_SET); // Указатель на 100-й байт от начала
echo 'Позиция: ' . pg_lo_tell($lob);
?>
Позиция: 100
Обратное перемещение от текущей позиции
<?
pg_lo_seek($lob, -20, SEEK_CUR); // На 20 байтов назад от текущей позиции
echo 'Позиция: ' . pg_lo_tell($lob);
?>
Позиция: 80
Альтернативные функции в PHP

pg_lo_read – чтение части большого объекта без явного перемещения указателя. Подходит для последовательного чтения.

pg_lo_tell – получение текущей позиции указателя. Используется вместе с pg_lo_seek для контроля.

Работа с файловой системой – если объекты сохраняются как файлы, можно применять fseek. Это быстрее, но требует синхронизации данных.

Аналоги в других языках
Python (psycopg2)
import psycopg2
conn = psycopg2.connect('dbname=test')
lobj = conn.lobject(oid, 'r')
lobj.seek(100, 0)  # SEEK_SET
print(lobj.tell())
100
JavaScript (node-postgres)
const { Client } = require('pg');
const client = new Client();
await client.connect();
const stream = client.query(new Cursor('SELECT lo_open($1, 0)', [oid]));
// В node-postgres нет прямой seek-функции, используется потоковое чтение.
Типичные ошибки
Некорректный ресурс объекта
<?
pg_lo_seek(false, 0); // Неверный ресурс
?>
Warning: pg_lo_seek() expects parameter 1 to be resource, boolean given
Выход за границы объекта
<?
pg_lo_seek($lob, -10, SEEK_SET); // Отрицательное смещение от начала
?>
Позиция указателя остается неизменной, ошибки не возникает.
Изменения в версиях PHP

В PHP 8.0 аргумент $whence стал опциональным и по умолчанию равен SEEK_CUR. Ранее требовалось явное указание.

Начиная с PHP 7.4, устаревшие функции работы с большими объектами (например, pg_loopen) не рекомендуются, но pg_lo_seek остается актуальной.

Расширенные примеры
Редактирование середины объекта
Пример php
<?
$conn = pg_connect('dbname=test');
$oid = pg_lo_create($conn);
$lob = pg_lo_open($conn, $oid, 'w');
pg_lo_write($lob, str_repeat('0', 500)); // Запись 500 байт
pg_lo_seek($lob, 250, SEEK_SET);
pg_lo_write($lob, 'XYZ'); // Замена данных с позиции 250
pg_lo_close($lob);
?>
Объект изменен, 3 байта заменены на 'XYZ'.
Построчное чтение текстового объекта
Пример php
<?
function readLine($lob) {
    $line = '';
    while (($char = pg_lo_read($lob, 1)) !== false && $char !== "\n") {
        $line .= $char;
    }
    return $line;
}
$lob = pg_lo_open($conn, $oid, 'r');
pg_lo_seek($lob, 0, SEEK_SET);
echo readLine($lob); // Первая строка
pg_lo_seek($lob, 10, SEEK_CUR); // Пропуск 10 байт
echo readLine($lob); // Следующая строка после пропуска
?>

PHP pg_lo_seek function comments

En
Pg lo seek Seeks position within a large object