В данном разделе описываются механизмы, которые
Digital Q.DataBaseбиблиотека libpq
интерфейса клиента предоставляет для доступа к большим объектам.
Интерфейс Digital Q.DataBase для работы с большими объектами построен по модели Unix интерфейса файловой системы с
аналогами функций open, read,
write,
lseekи т. д.
Любые операции с большими объектами с использованием данных функций
должны выполняться внутри блока транзакции SQL,
так как дескрипторы файлов больших объектов остаются действительными только до завершения
транзакции. Операции записи, включая lo_open
с использованием режима INV_WRITE , не допускаются в транзакциях, предназначенных только для чтения.
Если при выполнении любой из этих функций возникает ошибка, функция возвращает специальное значение, обычно 0 или -1. Сообщение с описанием ошибки сохраняется в объекте соединения и может быть получено с помощью
PQerrorMessage
.
Клиентские приложения, использующие эти функции, должны включать заголовочный файл
libpq/libpq-fs.h и выполнять компоновку с
libpq библиотекой.
Клиентские приложения не могут использовать эти функции, пока соединение libpq находится в режиме конвейерной обработки.
Oid lo_create(PGconn *conn, Oid lobjId);
создаёт новый большой объект. Идентификатор OID для назначения может быть указан через lobjId; в этом случае, если данный OID уже используется для какого-либо большого объекта, возникнет ошибка. Если lobjId
равен InvalidOid (ноль), то функция lo_create
назначает неиспользуемый OID. Возвращаемое значение представляет собой OID, присвоенный новому большому объекту, или InvalidOid (ноль) в случае ошибки.
Пример:
inv_oid = lo_create(conn, desired_oid);
Oid lo_creat(PGconn *conn, int mode);
также создает новый большой объект, всегда присваивая ему неиспользуемый OID.
Возвращаемым значением является OID, присвоенный новому большому объекту,
или InvalidOid (ноль) в случае ошибки.
В Digital Q.DataBase версиях 8.1 и более поздних
параметр mode игнорируется,
вследствие чего функция lo_creat полностью эквивалентна функции
lo_create с нулевым значением второго аргумента.
Тем не менее, оснований использовать lo_creat
недостаточно, за исключением случаев, когда необходимо работать с серверами версий ниже 8.1.
Для работы с такими устаревшими серверами необходимо
использовать lo_creat вместо lo_create,
при этом необходимо установить параметр mode в
одно из следующих значений: INV_READ, INV_WRITE,
или INV_READ | INV_WRITE.
(Данные символические константы определены
в заголовочном файле libpq/libpq-fs.h.)
Пример:
inv_oid = lo_creat(conn, INV_READ|INV_WRITE);
Для импорта файла операционной системы в качестве большого объекта вызовите функцию
Oid lo_import(PGconn *conn, const char *filename);
filename
задаёт имя файла в операционной системе, который необходимо импортировать в качестве большого объекта. Возвращаемое значение представляет собой OID, присвоенный новому большому объекту, или InvalidOid (ноль) в случае ошибки. Обратите внимание, что файл считывается клиентской библиотекой интерфейса, а не сервером; поэтому он должен существовать в файловой системе клиента и быть доступен для чтения клиентскому приложению.
Oid lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId);
также импортирует новый большой объект. Идентификатор OID для назначения может быть указан через lobjId; в этом случае, если данный OID уже используется для какого-либо большого объекта, возникнет ошибка. Если lobjId
равен InvalidOid (ноль), то функция lo_import_with_oid назначает неиспользуемый
OID (данное поведение аналогично lo_import).
Возвращаемое значение — это OID, присвоенный новому большому объекту,
или InvalidOid (ноль) в случае ошибки.
lo_import_with_oid появился в версии Digital Q.DataBase
8.4 и использует lo_create внутренний механизм, реализованный в версии 8.1; если эта функция будет вызвана в версии 8.0 или ниже, она завершится с ошибкой и вернёт InvalidOid.
Чтобы экспортировать большой объект в файл операционной системы, вызовите функцию
int lo_export(PGconn *conn, Oid lobjId, const char *filename);
Параметр lobjId определяет OID большого объекта для экспорта, а параметр filename определяет
имя файла в операционной системе. Обратите внимание, что файл
записывается клиентской библиотекой интерфейса, а не сервером. Возвращает 1
при успешном завершении и -1 в случае ошибки.
Для открытия существующего большого объекта на чтение или запись вызовите функцию
int lo_open(PGconn *conn, Oid lobjId, int mode);
Параметр lobjId определяет OID большого объекта для открытия. Параметр mode биты управляют тем, открывается ли большой объект для чтения (INV_READ), записи
(INV_WRITE) или обоих действий.
(Данные символические константы определены
в заголовочном файле libpq/libpq-fs.h.)
lo_open возвращает (неотрицательный) дескриптор большого объекта для последующего использования в lo_read,
lo_write, lo_lseek,
lo_lseek64, lo_tell,
lo_tell64, lo_truncate,
lo_truncate64и lo_close.
Дескриптор действителен только в течение
текущей транзакции.
В случае ошибки возвращается -1.
В настоящее время сервер не различает режимы
INV_WRITE и INV_READ |
INV_WRITE: чтение из дескриптора разрешено в обоих случаях. Однако существует значительное различие между
этими режимами и режимом INV_READ в отдельности: при использовании INV_READ
запись в дескриптор невозможна, а считываемые из него данные будут отражать состояние большого объекта на момент создания снимка транзакции, активного при вызове функции lo_open ,
вне зависимости от последующих операций записи в этой или других транзакциях. Чтение
из дескриптора, открытого с флагом INV_WRITE возвращает
данные, отражающие все изменения, внесенные другими зафиксированными транзакциями, а также
изменения в рамках текущей транзакции. Данное поведение аналогично поведению функции REPEATABLE READ в сравнении с READ COMMITTED режимами транзакций для обычных SQL- SELECT команд.
lo_open завершится ошибкой, если SELECT
права доступа к большому объекту отсутствуют, или
если INV_WRITE указано и UPDATE
соответствующие права отсутствуют.
(До версии Digital Q.DataBase 11 эти проверки прав выполнялись при первом фактическом вызове чтения или записи через дескриптор.) Данные проверки прав можно отключить с помощью параметра
lo_compat_privileges времени выполнения.
Пример:
inv_fd = lo_open(conn, inv_oid, INV_READ|INV_WRITE);
int lo_write(PGconn *conn, int fd, const char *buf, size_t len);
записывает len байтов из buf
(который должен иметь размер len) к дескриптору большого объекта fd. Аргумент fd аргумент должен быть предварительно возвращен вызовом функции lo_open. Возвращается количество фактически записанных байтов (в текущей реализации это значение всегда будет равно len (за исключением случаев возникновения ошибки). При возникновении ошибки возвращается значение -1.
Хотя параметр len объявлен как
size_t, данная функция отклоняет значения длины, превышающие
INT_MAX. На практике в любом случае рекомендуется передавать данные фрагментами размером не более нескольких мегабайт.
int lo_read(PGconn *conn, int fd, char *buf, size_t len);
считывает до len байтов из дескриптора большого объекта
fd в buf (который должен иметь
размер len). Данный fd
аргумент должен быть ранее возвращен функцией
lo_open. Возвращается количество фактически прочитанных байтов; это значение будет меньше, чем len , если конец большого объекта будет достигнут раньше. В случае ошибки возвращается значение -1.
Хотя параметр len объявлен как
size_t, данная функция отклоняет значения длины, превышающие
INT_MAX. На практике в любом случае рекомендуется передавать данные фрагментами размером не более нескольких мегабайт.
Для изменения текущей позиции чтения или записи, связанной с дескриптором большого объекта, вызовите функцию
int lo_lseek(PGconn *conn, int fd, int offset, int whence);
Данная функция перемещает указатель текущей позиции для дескриптора большого объекта, идентифицируемого параметром
fd , в новое положение, указанное параметром
offset. Допустимыми значениями для whence
являются: SEEK_SET (поиск от начала объекта),
SEEK_CUR (поиск от текущей позиции) и
SEEK_END (поиск от конца объекта). Возвращаемое значение представляет собой новый указатель позиции или -1 в случае ошибки.
При работе с большими объектами, размер которых может превышать 2 ГБ, используйте функцию
pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence);
Данная функция работает так же,
как и lo_lseek, но она может принимать аргумент
offset более 2 ГБ и/или возвращать результат, превышающий 2 ГБ. Обратите внимание, что функция lo_lseek завершится ошибкой, если новое значение указателя позиции превысит 2 ГБ.
lo_lseek64 появился в версии Digital Q.DataBase
9.3. Если данная функция будет вызвана на сервере более старой версии, она завершится с ошибкой и вернет -1.
Для получения текущей позиции чтения или записи дескриптора большого объекта вызовите функцию
int lo_tell(PGconn *conn, int fd);
В случае возникновения ошибки возвращаемое значение равно -1.
При работе с большими объектами, размер которых может превышать 2 ГБ, используйте функцию
pg_int64 lo_tell64(PGconn *conn, int fd);
Данная функция работает так же,
как и lo_tell, однако она может возвращать результат размером более 2 ГБ. Обратите внимание, что lo_tell завершится ошибкой, если текущая
позиция чтения/записи превышает 2 ГБ.
lo_tell64 появился в версии Digital Q.DataBase
9.3. Если данная функция будет вызвана на сервере более старой версии, она завершится с ошибкой и вернет -1.
Чтобы усечь большой объект до заданной длины, вызовите функцию
int lo_truncate(PGconn *conn, int fd, size_t len);
Данная функция усекает большой объект с дескриптором fd до длины len. Параметр
fd должен быть возвращен
предыдущим вызовом функции lo_open. Если параметр len превышает
текущую длину большого объекта, то большой объект
расширяется до указанной длины с заполнением нулевыми байтами ('\0').
В случае успеха функция lo_truncate возвращает
ноль. В случае ошибки возвращается значение -1.
Позиция чтения/записи, связанная с дескриптором
fd не изменяется.
Хотя параметр len объявлен как
size_t, lo_truncate отклонит значения длины, превышающие INT_MAX.
При работе с большими объектами, размер которых может превышать 2 ГБ, используйте функцию
int lo_truncate64(PGconn *conn, int fd, pg_int64 len);
Данная функция работает так же,
как и lo_truncate, но может принимать
len значение, превышающее 2 ГБ.
lo_truncate появился в версии Digital Q.DataBase
8.3; если эта функция будет вызвана на сервере более ранней версии, она завершится ошибкой и вернет -1.
lo_truncate64 появился в версии Digital Q.DataBase
9.3; если эта функция будет вызвана на сервере более ранней версии, она завершится ошибкой и вернет -1.
Дескриптор большого объекта можно закрыть с помощью вызова функции
int lo_close(PGconn *conn, int fd);
где fd — это дескриптор большого объекта, возвращаемый функцией lo_open.
При успешном выполнении lo_close возвращает нуль. В случае
ошибки возвращается значение -1.
Все дескрипторы больших объектов, остающиеся открытыми в конце транзакции, закрываются автоматически.
Для удаления большого объекта из базы данных используется функция
int lo_unlink(PGconn *conn, Oid lobjId);
Параметр lobjId аргумент определяет OID большого объекта, который требуется удалить. Возвращает 1 в случае успеха и -1 в случае ошибки.