Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

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. 删除大对象

本节介绍 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);

创建一个新的对象。可由 lobjId 指定要分配的 OID;如果已将该 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 指定要作为大对象导入的文件的操作系统名称。返回值为分配给新大对象或 InvalidOid (零) 的 OID(如果发生故障)。请注意,该文件是由客户端接口库而不是服务器读取的;所以,该文件必须存在于客户端文件系统中,并且客户端应用程序可以读取该文件。

该函数

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

还导入一个新大对象。可 توسط lobjId指定要分配的 OID;如果是这样,则如果该 OID 已用于某个大对象,则会发生故障。如果 lobjIdInvalidOid(零),则 lo_import_with_oid 将分配一个未使用的 OID(这与 lo_import)的行为相同。返回值为分配给新大对象或 InvalidOid (零) 的 OID(如果发生故障)。

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

len 字节从 buf(其大小必须为 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 截断为长度 len。该 fd 参数必须是由 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。

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