Skip to content

35.3. 客户端接口#

35.3.1. 创建大对象
35.3.2. 导入大对象
35.3.3. 导出大对象
35.3.4. 打开现有大对象
35.3.5. 向大对象写入数据
35.3.6. 从大对象读取数据
35.3.7. 在大对象中查找
35.3.8. 获取大对象的查找位置
35.3.9. 截断大对象
35.3.10. 关闭大对象描述符
35.3.11. 删除大对象

本节介绍PostgreSQL的libpq客户端接口库为访问大对象提供的功能。PostgreSQL大对象接口模仿Unix文件系统接口,具有openreadwritelseek等类似项。

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

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

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

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

35.3.1. 创建大对象#

该函数

Oid lo_create(PGconn *conn, Oid lobjId);

创建一个新的大型对象。可通过*lobjId指定要分配的 OID;如果指定,则在该 OID 已被某些大型对象使用的情况下会发生故障。如果lobjId*为InvalidOid(零),则lo_create会分配一个未使用的 OID。返回值是分配给新大型对象或故障时的InvalidOid(零)的 OID。

一个示例

inv_oid = lo_create(conn, desired_oid);

旧函数

Oid lo_creat(PGconn *conn, int mode);

也创建一个新的大型对象,始终分配一个未使用的 OID。返回值是分配给新大型对象或故障时的InvalidOid(零)的 OID。

在PostgreSQL8.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);

35.3.2. 导入大型对象#

要将操作系统文件导入为大型对象,请调用

Oid lo_import(PGconn *conn, const char *filename);

*filename*指定要作为大型对象导入的文件的操作系统名称。返回值是分配给新大型对象或故障时的InvalidOid(零)的 OID。请注意,该文件由客户端接口库读取,而不是由服务器读取;因此,它必须存在于客户端文件系统中,并且客户端应用程序可读。

函数

Oid lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId);

还导入一个新的大型对象。可通过*lobjId指定要分配的 OID;如果指定,则在该 OID 已被某些大型对象使用的情况下会发生故障。如果lobjId*为InvalidOid(零),则lo_import_with_oid会分配一个未使用的 OID(此行为与lo_import相同)。返回值是分配给新大型对象或故障时的InvalidOid(零)的 OID。

lo_import_with_oid是PostgreSQL8.4 的新功能,内部使用lo_create,后者是 8.1 中的新功能;如果针对 8.0 或更早版本运行此函数,它将失败并返回InvalidOid

35.3.3. 导出大对象#

要将大对象导出到操作系统文件,请调用

int lo_export(PGconn *conn, Oid lobjId, const char *filename);

*lobjId参数指定要导出的对象的大对象 OID,filename*参数指定文件的操作系统名称。请注意,该文件由客户端接口库编写,而不是由服务器编写。成功返回 1,失败返回 -1。

35.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打开的描述符中读取会返回反映其他已提交事务的所有写入以及当前事务写入的数据。这类似于普通 SQLSELECT命令的REPEATABLE READREAD COMMITTED事务模式的行为。

lo_open将在以下情况下失败:如果大对象没有SELECT权限,或者如果指定了INV_WRITE而没有UPDATE权限。(在PostgreSQL11 之前,这些权限检查是在使用描述符的第一次实际读取或写入调用时执行的。)这些权限检查可以使用lo_compat_privileges运行时参数禁用。

一个示例

inv_fd = lo_open(conn, inv_oid, INV_READ|INV_WRITE);

35.3.5. 向大对象写入数据#

该函数

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

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

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

35.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的长度值。实际上,最好将数据以最多几兆字节的块传输。

35.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_lseek64是PostgreSQL9.3 中的新增功能。如果此函数针对较旧的服务器版本运行,它将失败并返回 -1。

35.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_tell64是PostgreSQL9.3 中的新增功能。如果此函数针对较旧的服务器版本运行,它将失败并返回 -1。

35.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_truncate在PostgreSQL8.3 中为新功能;如果针对较旧的服务器版本运行此函数,它将失败并返回 -1。

lo_truncate64在PostgreSQL9.3 中为新功能;如果针对较旧的服务器版本运行此函数,它将失败并返回 -1。

35.3.10. 关闭大对象描述符#

可以通过调用关闭大对象描述符

int lo_close(PGconn *conn, int fd);

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

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

35.3.11. 删除大对象#

要从数据库中删除大对象,请调用

int lo_unlink(PGconn *conn, Oid lobjId);

*lobjId*参数指定要删除的大对象的 OID。如果成功,则返回 1,如果失败,则返回 -1。