↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 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
开发快照。 PostgreSQL 20devel 尚未正式发布,内容仍可能变化。

33.3. 客户端接口 #

本节描述 PostgreSQL 的 libpq 客户端接口库为访问大对象所提供的功能。PostgreSQL 的大对象接口是仿照 Unix 文件系统接口设计的,提供了与 open、read、write、lseek 等相对应的操作。

使用这些函数对大对象进行的所有操作都必须发生在一个 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 已经被某个大对象使用,则会失败。如果 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 完全等价。不过,除非需要与早于 8.1 的服务器配合使用,否则几乎没有理由使用 lo_creat。若要与这种旧服务器协作,必须使用 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 是 PostgreSQL 8.4 新增的,它在内部使用了 8.1 新增的 lo_create;如果将该函数用于 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 打开的描述符,读取返回的数据会反映其他已提交事务的所有写入以及当前事务的写入。这类似于普通 SQL SELECT 命令在 REPEATABLE READ 与 READ 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)写入大对象描述符 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);

从大对象描述符 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。

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

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

该函数的行为与 lo_lseek 相同,但它既可以接受大于 2 GB 的 offset,也可以返回大于 2 GB 的结果。请注意,如果新位置指针会大于 2 GB,lo_lseek 将失败。

lo_lseek64 是 PostgreSQL 9.3 新增的。如果将该函数用于更早版本的服务器,它会失败并返回 -1。

33.3.8. 获取大对象的当前位置 #

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

int lo_tell(PGconn *conn, int fd);

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

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

int64_t lo_tell64(PGconn *conn, int fd);

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

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 GB 的大对象时,改用

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

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

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。

任何在事务结束时仍保持打开的大对象描述符都会被自动关闭。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.