Pg lo close: примеры (PHP)
pg_lo_close(PgSql\Lob $lob): boolФункция pg_lo_close в PHP предназначена для закрытия дескриптора большого объекта (Large Object) PostgreSQL. Она используется после завершения операций чтения или записи с большим объектом для освобождения ресурсов на стороне сервера и клиента.
Работа с большими объектами в PostgreSQL через модуль pgsql требует явного открытия и закрытия дескрипторов. Функция применяется в сценариях, где необходимо хранить или извлекать большие двоичные данные (BLOB), такие как изображения, документы или аудиофайлы, превышающие обычные ограничения на размер данных.
Функция принимает один обязательный аргумент:
- $lob (ресурс) - дескриптор большого объекта, полученный с помощью функций
pg_lo_openилиpg_lo_create. Этот ресурс должен быть валидным и открытым.
Возвращаемое значение: bool - true в случае успешного закрытия, false при возникновении ошибки.
Базовый пример: чтение и закрытие объекта.
<?php
$conn = pg_connect("dbname=test user=postgres");
$lob = pg_lo_open($conn, 123456, "r"); // Открытие объекта с OID 123456 для чтения
if ($lob) {
// ... операции чтения с использованием pg_lo_read ...
$result = pg_lo_close($lob); // Закрытие дескриптора
if ($result) {
echo "Дескриптор успешно закрыт";
}
}
?>Дескриптор успешно закрыт
Пример с записью в объект.
<?php
$conn = pg_connect("dbname=test user=postgres");
$lob = pg_lo_open($conn, 123457, "w"); // Открытие для записи
if ($lob) {
// ... операции записи с использованием pg_lo_write ...
var_dump(pg_lo_close($lob)); // Закрытие
}
?>bool(true)
Для работы с большими объектами в PostgreSQL через модуль pgsql существуют другие функции:
- pg_lo_unlink - удаляет большой объект из базы данных по его OID. В отличие от
pg_lo_close, которая лишь закрывает дескриптор, эта функция безвозвратно удаляет данные. - pg_lo_import - создает большой объект из файла в файловой системе и возвращает его OID. После импорта может потребоваться открыть и закрыть объект через
pg_lo_open/pg_lo_closeдля дополнительных операций. - pg_lo_export - сохраняет большой объект в файл. После экспорта дескриптор также следует закрыть.
pg_lo_close предпочтительнее использовать всегда после завершения операций с открытым дескриптором для избежания утечек ресурсов. Удаление или экспорт объекта могут выполняться независимо после закрытия.
В psycopg2 работа с большими объектами осуществляется через методы lo_open(), lo_close() объекта LargeObject.
import psycopg2
conn = psycopg2.connect("dbname=test user=postgres")
lobj = conn.lobject(123456, 'r')
# ... операции чтения ...
lobj.close() # Аналог pg_lo_closeВ Node.js обычно используются потоки (streams) для работы с большими объектами. Явного закрытия дескриптора может не требоваться, если используется потоковый интерфейс.
const { Client } = require('pg');
const client = new Client();
await client.connect();
const stream = client.query(new
QueryStream('SELECT lo_get(123456)'));
// ... обработка потока ...
// Закрытие соединения освобождает ресурсы
await client.end();Pg lo close в MySQL
В MySQL для хранения больших двоичных данных часто используют тип LONGBLOB. Операции чтения/записи выполняются стандартными запросами SELECT/UPDATE, а не через отдельные дескрипторы, поэтому аналога pg_lo_close не существует.
1. Попытка закрыть уже закрытый или невалидный дескриптор.
<?php
$conn = pg_connect("dbname=test user=postgres");
$lob = null;
$result = pg_lo_close($lob); // Неверный дескриптор
var_dump($result);
?>Warning: pg_lo_close() expects parameter 1 to be resource, null given bool(false)
2. Использование закрытого дескриптора для операций чтения/записи после вызова pg_lo_close.
<?php
$conn = pg_connect("dbname=test user=postgres");
$lob = pg_lo_open($conn, 123456, "r");
pg_lo_close($lob);
$data = pg_lo_read($lob); // Ошибка: дескриптор закрыт
?>Warning: pg_lo_read(): supplied resource is not a valid large object resource
3. Отсутствие проверки соединения с базой данных перед операциями.
В PHP 8.0 и выше значительных изменений в работе функции pg_lo_close не произошло. Однако, в PHP 8.1 были ужесточены типы аргументов для многих функций, что может приводить к более строгим ошибкам при передаче неверных значений. Сам модуль pgsql продолжает поддерживаться, но рекомендуется для новых проектов рассматривать использование расширения PDO_PGSQL или более высокоуровневых ORM.
Большие объекты в PostgreSQL часто требуют работы внутри транзакции.
<?php
$conn = pg_connect("dbname=test user=postgres");
pg_query($conn, "BEGIN");
$lob = pg_lo_open($conn, 123456, "r");
if ($lob) {
$content = pg_lo_read($lob, 4096);
// Обработка данных
pg_lo_close($lob); // Важно закрыть до commit/rollback
}
pg_query($conn, "COMMIT");
?>Для гарантированного освобождения ресурсов даже при возникновении исключений.
<?php
$conn = pg_connect("dbname=test user=postgres");
$lob = pg_lo_open($conn, 123456, "w");
try {
// ... операции записи, которые могут вызвать исключение ...
pg_lo_write($lob, "data");
} finally {
if (is_resource($lob)) {
pg_lo_close($lob); // Всегда выполнится
}
}
?><?php
$conn = pg_connect("dbname=test user=postgres");
$oids = [123456, 123457, 123458];
$handles = [];
foreach ($oids as $oid) {
$lob = pg_lo_open($conn, $oid, "r");
if ($lob) {
$handles[] = $lob;
}
}
// ... параллельная обработка ...
foreach ($handles as $handle) {
pg_lo_close($handle); // Закрытие всех открытых дескрипторов
}
?>Создание нового объекта, запись данных и немедленное закрытие.
<?php
$conn = pg_connect("dbname=test user=postgres");
pg_query($conn, "BEGIN");
$oid = pg_lo_create($conn);
$lob = pg_lo_open($conn, $oid, "w");
pg_lo_write($lob, "Новые данные большого объекта");
pg_lo_close($lob); // Дескриптор закрыт, но объект с OID сохранен
pg_query($conn, "COMMIT");
echo "Создан объект с OID: " . $oid;
?>Создан объект с OID: 123459