Pg lo seek: примеры (PHP)
pg_lo_seek(PgSql\Lob $lob, int $offset, int $whence = SEEK_CUR): boolФункция 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
pg_lo_read – чтение части большого объекта без явного перемещения указателя. Подходит для последовательного чтения.
pg_lo_tell – получение текущей позиции указателя. Используется вместе с pg_lo_seek для контроля.
Работа с файловой системой – если объекты сохраняются как файлы, можно применять fseek. Это быстрее, но требует синхронизации данных.
import psycopg2
conn = psycopg2.connect('dbname=test')
lobj = conn.lobject(oid, 'r')
lobj.seek(100, 0) # SEEK_SET
print(lobj.tell())100
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 8.0 аргумент $whence стал опциональным и по умолчанию равен SEEK_CUR. Ранее требовалось явное указание.
Начиная с PHP 7.4, устаревшие функции работы с большими объектами (например, pg_loopen) не рекомендуются, но pg_lo_seek остается актуальной.
<?
$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'.
<?
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); // Следующая строка после пропуска
?>