支持的版本:当前 (17) / 16 / 15 / 14 / 13
开发版本:devel
不支持的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

33.3. 客户端接口 #

本节介绍 PostgreSQLlibpq 客户端接口库提供的访问大型对象的功能。PostgreSQL 大型对象接口是仿照Unix文件系统接口建模的,具有类似 openreadwritelseek 等函数。

所有使用这些函数的大型对象操作必须在 SQL 事务块中进行,因为大型对象文件描述符仅在事务期间有效。在只读事务中不允许进行写入操作,包括使用 INV_WRITE 模式的 lo_open

如果在执行这些函数中的任何一个时发生错误,该函数将返回一个不可能的值,通常是 0 或 -1。描述该错误的消息存储在连接对象中,可以使用 PQerrorMessage 获取。

使用这些函数的客户端应用程序应包含头文件 libpq/libpq-fs.h 并与 libpq 库链接。

当 libpq 连接处于流水线模式时,客户端应用程序无法使用这些函数。

33.3.1. 创建大型对象 #

函数

Oid lo_create(PGconn *conn, Oid lobjId);

创建一个新的大型对象。要分配的 OID 可以由 lobjId 指定;如果指定了,如果该 OID 已被某个大型对象使用,则会发生失败。如果 lobjIdInvalidOid (零),则 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 完全等效。但是,除非您需要使用早于 8.1 的服务器,否则几乎没有理由使用 lo_creat。要使用如此旧的服务器,您必须使用 lo_creat 而不是 lo_create,并且您必须将 mode 设置为 INV_READINV_WRITEINV_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 已被某个大型对象使用,则会发生失败。如果 lobjIdInvalidOid (零),则 lo_import_with_oid 将分配一个未使用的 OID(这与 lo_import 的行为相同)。返回值是分配给新大型对象的 OID,如果失败,则返回 InvalidOid (零)。

lo_import_with_oidPostgreSQL 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_readlo_writelo_lseeklo_lseek64lo_telllo_tell64lo_truncatelo_truncate64lo_close 中使用。该描述符仅在当前事务期间有效。如果失败,则返回 -1。

服务器当前不区分 INV_WRITEINV_READ | INV_WRITE 模式:在这两种情况下,您都可以从描述符中读取。但是,这些模式与单独的 INV_READ 之间存在显著差异:使用 INV_READ,您无法写入描述符,并且从中读取的数据将反映在执行 lo_open 时处于活动状态的事务快照时大型对象的内容,而不管此事务或其他事务的后续写入。从使用 INV_WRITE 打开的描述符读取的数据反映了其他已提交事务的写入以及当前事务的写入。这类似于普通 SQL SELECT 命令的 REPEATABLE READREAD COMMITTED 事务模式的行为。

如果大型对象不可用 SELECT 权限,或者指定了 INV_WRITE 且不可用 UPDATE 权限,则 lo_open 将失败。(在 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);

buf (大小必须为 len) 中的 len 个字节写入到大型对象描述符 fdfd 参数必须由先前的 lo_open 返回。返回实际写入的字节数(在当前实现中,除非发生错误,否则这始终等于 len)。如果发生错误,则返回值为 -1。

尽管 len 参数声明为 size_t,但此函数将拒绝大于 INT_MAX 的长度值。实际上,最好还是以最多几兆字节的块传输数据。

33.3.6. 从大型对象读取数据 #

函数

int lo_read(PGconn *conn, int fd, char *buf, size_t len);

从大型对象描述符 fd 中读取最多 len 个字节到 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。

当处理可能超过 2GB 大小的大对象时,请改用

pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence);

此函数的行为与 lo_lseek 相同,但它可以接受大于 2GB 的 offset 值,并且/或者返回大于 2GB 的结果。 请注意,如果新的位置指针大于 2GB,则 lo_lseek 将会失败。

lo_lseek64PostgreSQL 9.3 版本新增的函数。如果在较旧的服务器版本上运行此函数,则它将失败并返回 -1。

33.3.8. 获取大对象的查找位置 #

要获取大对象描述符的当前读取或写入位置,请调用

int lo_tell(PGconn *conn, int fd);

如果发生错误,则返回值为 -1。

当处理可能超过 2GB 大小的大对象时,请改用

pg_int64 lo_tell64(PGconn *conn, int fd);

此函数的行为与 lo_tell 相同,但它可以返回大于 2GB 的结果。 请注意,如果当前的读取/写入位置大于 2GB,则 lo_tell 将会失败。

lo_tell64PostgreSQL 9.3 版本新增的函数。如果在较旧的服务器版本上运行此函数,则它将失败并返回 -1。

33.3.9. 截断大对象 #

要将大对象截断为给定的长度,请调用

int lo_truncate(PGconn *conn, int fd, size_t len);

此函数将大对象描述符 fd 截断为长度 lenfd 参数必须是由先前的 lo_open 返回的。如果 len 大于大对象的当前长度,则大对象将扩展到指定的长度并填充空字节('\0')。成功时,lo_truncate 返回零。如果发生错误,则返回值为 -1。

与描述符 fd 关联的读取/写入位置不会更改。

尽管 len 参数被声明为 size_t,但 lo_truncate 将拒绝大于 INT_MAX 的长度值。

当处理可能超过 2GB 大小的大对象时,请改用

int lo_truncate64(PGconn *conn, int fd, pg_int64 len);

此函数的行为与 lo_truncate 相同,但它可以接受大于 2GB 的 len 值。

lo_truncatePostgreSQL 8.3 版本新增的函数;如果在较旧的服务器版本上运行此函数,则它将失败并返回 -1。

lo_truncate64PostgreSQL 9.3 版本新增的函数;如果在较旧的服务器版本上运行此函数,则它将失败并返回 -1。

33.3.10. 关闭大对象描述符 #

可以通过调用以下函数来关闭大对象描述符:

int lo_close(PGconn *conn, int fd);

其中 fd 是由 lo_open 返回的大对象描述符。成功时,lo_close 返回零。如果发生错误,则返回值为 -1。

在事务结束时,任何仍处于打开状态的大对象描述符都将自动关闭。

提交更正

如果您在文档中发现任何不正确、与您对特定功能的体验不符或需要进一步澄清的内容,请使用此表单报告文档问题。