33.3. Клиентские интерфейсы#
33.3. Клиентские интерфейсы
- 33.3.1. Создание большого объекта
- 33.3.2. Импорт большого объекта
- 33.3.3. Экспорт большого объекта
- 33.3.4. Открытие существующего большого объекта
- 33.3.5. Запись данных в большой объект
- 33.3.6. Чтение данных из большого объекта
- 33.3.7. Поиск в большом объекте
- 33.3.8. Получение позиции поиска большого объекта
- 33.3.9. Обрезка большого объекта
- 33.3.10. Закрытие дескриптора большого объекта
- 33.3.11. Удаление большого объекта
Этот раздел описывает возможности, которые предоставляет библиотека интерфейса клиента libpq Tantor SE для доступа к большим объектам. Интерфейс больших объектов Tantor SE моделируется по аналогии с интерфейсом файловой системы Unix, с аналогами функций open
, read
, write
, lseek
и т. д.
Все операции с большими объектами, использующие эти функции, должны выполняться внутри блока SQL-транзакции, поскольку дескрипторы файлов больших объектов действительны только в течение транзакции.
Если происходит ошибка при выполнении любой из этих функций, функция вернет значение, которое в обычных условиях невозможно, обычно 0 или -1. Сообщение, описывающее ошибку, сохраняется в объекте соединения и может быть получено с помощью PQerrorMessage
.
Клиентские приложения, использующие эти функции, должны включать заголовочный файл
libpq/libpq-fs.h
и связываться с
библиотекой libpq.
Клиентские приложения не могут использовать эти функции, пока соединение libpq находится в режиме конвейера.
33.3.1. Создание большого объекта
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
(ноль) в случае ошибки.
В релизах PostgreSQL 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);
33.3.2. Импорт большого объекта
Чтобы импортировать файл операционной системы в виде большого объекта, вызовите
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
является новым с версии Tantor SE
8.4 и использует внутренне функцию lo_create
, которая появилась в версии 8.1; если эта функция вызывается в версии 8.0 или ранее, она завершится с ошибкой и вернет значение InvalidOid
.
33.3.3. Экспорт большого объекта
Для экспорта большого объекта в файл операционной системы вызовите
int lo_export(PGconn *conn, Oid lobjId, const char *filename);
Аргумент lobjId
указывает OID большого объекта для экспорта, а аргумент filename
указывает операционную систему имя файла. Обратите внимание, что файл записывается библиотекой клиентского интерфейса, а не сервером. Возвращает 1 в случае успеха, -1 в случае ошибки.
33.3.4. Открытие существующего большого объекта
Чтобы открыть существующий большой объект для чтения или записи, вызовите
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
. (До версии PostgreSQL 11 эти проверки прав выполнялись при первом фактическом вызове чтения или записи с использованием дескриптора). Эти проверки прав могут быть отключены с помощью параметра времени выполнения lo_compat_privileges.
Пример:
inv_fd = lo_open(conn, inv_oid, INV_READ|INV_WRITE);
33.3.5. Запись данных в большой объект
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
. На практике лучше передавать данные порциями размером не более нескольких мегабайт.
33.3.6. Чтение данных из большого объекта
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
. На практике лучше передавать данные порциями размером не более нескольких мегабайт.
33.3.7. Поиск в большом объекте
Для изменения текущего местоположения чтения или записи, связанного с дескриптором большого объекта, вызовите
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
является новым с версии PostgreSQL 9.3. Если эта функция выполняется на более старой версии сервера, она завершится с ошибкой и вернет -1.
33.3.8. Получение позиции поиска большого объекта
Чтобы получить текущее местоположение чтения или записи дескриптора большого объекта, вызовите
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
является новым начиная с PostgreSQL 9.3. Если эта функция выполняется на более старой версии сервера, она завершится с ошибкой и вернет -1.
33.3.9. Обрезка большого объекта
Чтобы обрезать большой объект до заданной длины, вызовите
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
является новым с версии PostgreSQL 8.3; если эта функция выполняется на более старой версии сервера, она завершится с ошибкой и вернет -1.
lo_truncate64
является новым с версии PostgreSQL 9.3; если эта функция запускается на более старой версии сервера, она завершится с ошибкой и вернет -1.
33.3.10. Закрытие дескриптора большого объекта
Дескриптор большого объекта может быть закрыт путем вызова
int lo_close(PGconn *conn, int fd);
где fd
- это дескриптор большого объекта, возвращаемый функцией lo_open
.
При успешном выполнении lo_close
возвращает ноль. При ошибке возвращается значение -1.
Все дескрипторы больших объектов, которые остаются открытыми в конце транзакции, будут автоматически закрыты.