2024 年 9 月 26 日:PostgreSQL 17 发布!
支持的版本:当前 (17) / 16 / 15 / 14 / 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

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_oid 是从 PostgreSQL 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 事务模式的行为。

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);

将来自 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。

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

提交更正

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