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.
Все дескрипторы больших объектов, которые остаются открытыми в конце транзакции, будут автоматически закрыты.