lo

Модуль lo предоставляет поддержку управления большими объектами (также называемыми БО или LO (Large Objects) либо BLOB (Binary Large OBjects)). Это включает в себя тип данных lo и триггер lo_manage.

Этот модуль считается «доверенным», то есть его могут устанавливать обычные пользователи с правом CREATE в текущей базе данных.


Обоснование

Одна из проблем с драйвером JDBC (которая распространяется и на драйвер ODBC), в том, что спецификация предполагает, что ссылки на BLOB хранятся в таблице, и если эта запись меняется, связанный BLOB удаляется из базы данных.

Однако с QHB этого не происходит. Большие объекты обрабатываются как самостоятельные объекты; запись в таблице может ссылаться на большой объект по OID, но при этом на один и тот же OID большого объекта могут ссылаться несколько записей таблицы, так что система не удаляет большой объект только потому, что вы меняете или удаляете одну такую запись.

Это не проблема для приложений, специфичных для QHB, но стандартный код, использующий JDBC или ODBC, не будет удалять эти объекты, в результате чего они окажутся потерянными — объектами, на которые ничто не ссылается и которые просто занимают место на диске.

Модуль lo позволяет это исправить, добавляя триггер к таблицам, которые содержат столбцы, ссылающиеся на БО. Этот триггер по сути просто вызывает lo_unlink, когда вы удаляете или изменяете значение, ссылающееся на большой объект. При использовании этого триггера предполагается, что на любой большой объект, на который ссылается управляемый триггером столбец, указывает только одна ссылка базы данных!

Этот модуль также предоставляет тип данных lo, который на самом деле является просто доменом на базе типа oid. Это полезно для дифференциации столбцов базы данных, хранящих ссылки на большие объекты, от столбцов, содержащих OID или какие-то другие данные. Для использования триггера применять тип lo необязательно, но он может быть полезен для отслеживания того, какие столбцы в вашей базе данных предоставляют большие объекты, которыми управляет триггер. Также есть мнение, что драйвер ODBC не работает корректно, если не использовать для столбцов BLOB тип lo.


Как его использовать

Простой пример его использования:

CREATE TABLE image (title text, raster lo);

CREATE TRIGGER t_raster BEFORE UPDATE OR DELETE ON image
    FOR EACH ROW EXECUTE FUNCTION lo_manage(raster);

Для каждого столбца, который будет содержать уникальные ссылки на большие объекты, создайте триггер BEFORE UPDATE OR DELETE и передайте имя столбца в качестве единственного аргумента триггера. Также можно ограничить этот триггер, чтобы он срабатывал только при изменениях в столбце, указав BEFORE UPDATE OF имя_столбца. Если вам нужно иметь в одной таблице несколько столбцов lo, создайте отдельный триггер для каждого, не забывая давать всем этим триггерам разные имена.


Ограничения

  • При удалении таблицы относящиеся к ней объекты все равно будут потеряны, так как триггер не выполнится. Этого можно избежать, выполнив перед командой DROP TABLE команду DELETE FROM таблица.

    То же касается и команды TRUNCATE.

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

  • Некоторые клиентские части приложений могут создавать собственные таблицы, но не будут создавать для них соответствующие триггеры. Кроме того, пользователи могут забыть и не создать такие триггеры (или не знать, как это делается).


Автор

Питер Маунт (Peter Mount), peter@retep.org.uk