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

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

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

Назначение и сфера применения

Использование pg_lo_truncate актуально при работе с бинарными данными, хранимыми в виде больших объектов PostgreSQL, когда требуется уменьшить их размер без полной перезаписи. Типичные сценарии включают редактирование файлов изображений, документов или медиаконтента непосредственно в базе данных.

Аргументы функции

Первый аргумент (resource $large_object) - идентификатор большого объекта, полученный с помощью pg_lo_open. Этот ресурс должен быть открыт в режиме записи.

Второй аргумент (int $size) - новый размер объекта в байтах. Если указанное значение меньше текущего размера объекта, данные обрезаются с конца. При значении больше текущего размера объект расширяется нулевыми байтами.

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

Сокращение большого объекта до 500 байт:

<?
$connection = pg_connect("dbname=test user=postgres");
$oid = 12345; // Идентификатор существующего большого объекта
$largeObject = pg_lo_open($connection, $oid, "w");

if (pg_lo_truncate($largeObject, 500)) {
    echo "Объект успешно обрезан";
} else {
    echo "Ошибка при обрезке объекта";
}

pg_lo_close($largeObject);
pg_close($connection);
?>
Объект успешно обрезан
Расширение размера объекта

Увеличение размера большого объекта до 2000 байт:

<?
$connection = pg_connect("dbname=test user=postgres");
$oid = 12346;
$largeObject = pg_lo_open($connection, $oid, "w");

$result = pg_lo_truncate($largeObject, 2000);
var_dump($result);

pg_lo_close($largeObject);
pg_close($connection);
?>
bool(true)
Похожие функции в PHP

Функция pg_lo_write позволяет записывать данные в большой объект с текущей позиции. В отличие от pg_lo_truncate, которая изменяет размер объекта, pg_lo_write добавляет или перезаписывает содержимое.

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

Полное удаление большого объекта из базы данных. Применяется когда данные больше не нужны, вместо частичной обрезки.

Критерии выбора

pg_lo_truncate предпочтительнее при необходимости изменить размер объекта без полной перезаписи содержимого. pg_lo_write используется для добавления или модификации данных, а pg_lo_unlink - для полного удаления.

Аналоги в других языках программирования
Python с библиотекой psycopg2

В Python используется метод truncate() объекта LargeObject:

import psycopg2

conn = psycopg2.connect("dbname=test user=postgres")
conn.autocommit = True

# Открытие большого объекта
lobj = conn.lobject(12345, 'w')
# Обрезка до 500 байт
lobj.truncate(500)
lobj.close()
conn.close()
# Метод не возвращает значение, вызывает исключение при ошибке
JavaScript (Node.js с pg)

В Node.js для работы с большими объектами требуется использование потоков:

// Прямого аналога pg_lo_truncate в популярных библиотеках Node.js нет
// Обычно используют запросы SQL напрямую:
const { Client } = require('pg');
const client = new Client();

async function truncateLo() {
    await client.connect();
    await client.query('BEGIN');
    await client.query('SELECT lo_truncate($1, $2)', [12345, 500]);
    await client.query('COMMIT');
    await client.end();
}
SQL команда PostgreSQL

Непосредственный вызов функции базы данных:

-- Обрезка большого объекта с OID 12345 до 500 байт
SELECT lo_truncate(12345, 500);
 lo_truncate 
-------------
           1
(1 row)
Типичные ошибки при использовании
Открытие объекта в режиме только для чтения

Попытка обрезки объекта, открытого в режиме 'r':

<?
$connection = pg_connect("dbname=test user=postgres");
$oid = 12345;
$largeObject = pg_lo_open($connection, $oid, "r"); // Ошибка: режим чтения

$result = pg_lo_truncate($largeObject, 500);
var_dump($result);
?>
bool(false)
Передача некорректного идентификатора объекта

Использование несуществующего OID:

<?
$connection = pg_connect("dbname=test user=postgres");
$largeObject = pg_lo_open($connection, 999999, "w"); // Несуществующий OID

if ($largeObject === false) {
    echo "Не удалось открыть объект";
} else {
    $result = pg_lo_truncate($largeObject, 500);
    var_dump($result);
}
?>
Не удалось открыть объект
Отрицательный размер объекта

Указание отрицательного значения размера:

<?
$connection = pg_connect("dbname=test user=postgres");
$oid = 12345;
$largeObject = pg_lo_open($connection, $oid, "w");

$result = pg_lo_truncate($largeObject, -100); // Отрицательное значение
var_dump($result);
?>
bool(false)
Изменения в последних версиях PHP

Функция pg lo truncate была добавлена в PHP 5.6.0. В PHP 7.0.0 функция начала возвращать boolean значение вместо ресурса. В PHP 8.0.0 существенных изменений в работе функции не произошло, но усилилась строгость типизации аргументов.

Эволюция обработки ошибок

В ранних версиях PHP ошибки работы с большими объектами часто оставались незамеченными. Начиная с PHP 7.0, улучшена диагностика проблем при выполнении операций с большими объектами.

Расширенные примеры использования
Пакетная обработка больших объектов

Обрезка нескольких объектов до определенного размера:

Пример php
<?
function truncateMultipleObjects($connection, $oids, $newSize) {
    $results = [];
    foreach ($oids as $oid) {
        $lo = pg_lo_open($connection, $oid, "w");
        if ($lo) {
            $results[$oid] = pg_lo_truncate($lo, $newSize);
            pg_lo_close($lo);
        } else {
            $results[$oid] = false;
        }
    }
    return $results;
}

$connection = pg_connect("dbname=test user=postgres");
$oids = [12345, 12346, 12347];
$truncationResults = truncateMultipleObjects($connection, $oids, 1024);

print_r($truncationResults);
pg_close($connection);
?>
Array
(
    [12345] => 1
    [12346] => 1
    [12347] => 1
)
Безопасная обрезка с проверкой размера

Проверка текущего размера перед обрезкой:

Пример php
<?
function safeTruncate($connection, $oid, $maxSize) {
    $lo = pg_lo_open($connection, $oid, "w");
    if (!$lo) return false;
    
    // Определяем текущий размер
    $currentSize = pg_lo_lseek($lo, 0, SEEK_END);
    
    if ($currentSize > $maxSize) {
        $result = pg_lo_truncate($lo, $maxSize);
    } else {
        $result = true; // Обрезка не требуется
    }
    
    pg_lo_close($lo);
    return $result;
}

$connection = pg_connect("dbname=test user=postgres");
$result = safeTruncate($connection, 12345, 5000);
var_dump($result);
?>
bool(true)
Использование в транзакции

Обрезка объекта с откатом изменений при ошибке:

Пример php
<?
$connection = pg_connect("dbname=test user=postgres");
pg_query($connection, "BEGIN");

try {
    $oid = 12345;
    $largeObject = pg_lo_open($connection, $oid, "w");
    
    if (!pg_lo_truncate($largeObject, 1000)) {
        throw new Exception("Ошибка обрезки объекта");
    }
    
    // Другие операции с базой данных
    pg_query($connection, "UPDATE documents SET modified = NOW() WHERE oid = $oid");
    
    pg_lo_close($largeObject);
    pg_query($connection, "COMMIT");
    echo "Транзакция успешно завершена";
} catch (Exception $e) {
    pg_query($connection, "ROLLBACK");
    echo "Ошибка: " . $e->getMessage();
}

pg_close($connection);
?>
Транзакция успешно завершена

PHP pg_lo_truncate function comments

En
Pg lo truncate Truncates a large object