本节介绍 PostgreSQL 的 libpq 客户端接口库为访问大对象提供的功能。 PostgreSQL 大对象接口模仿了Unix文件系统接口,类似于 open
、read
、write
、lseek
等。
使用这些函数的所有大对象操作必须在 SQL 事务块中执行,因为大对象文件描述符仅在事务期间有效。写操作,包括带有 INV_WRITE
模式的 lo_open
,不允许在只读事务中使用。
如果在执行这些函数中的任何一个时发生错误,则该函数将返回一个通常是 0 或 -1 的不实际的值。描述错误的消息存储在连接对象中,可以用 PQerrorMessage
检索。
使用这些函数的客户端应用程序应包括头文件 libpq/libpq-fs.h
,并与 libpq 库链接。
当 libpq 连接处于管道模式时,客户端应用程序无法使用这些函数。
Oid lo_create(PGconn *conn, Oid lobjId);
创建一个新的对象。可由 lobjId
指定要分配的 OID;如果已将该 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);
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
自 PostgreSQL 8.4 起是新的,并且在内部使用 lo_create
,该函数在 8.1 中是新的;如果针对 8.0 或更早版本运行此函数,则它将发生故障并返回 InvalidOid
。
int lo_export(PGconn *conn, Oid lobjId, const char *filename);
lobjId
参数指定要导出的对象 OID,filename
参数指定文件的操作系统名称。请注意,该文件是由客户端接口库而不是服务器编写的。成功时返回 1,失败时返回 -1。
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);
int lo_write(PGconn *conn, int fd, const char *buf, size_t len);
将 len
字节从 buf
(其大小必须为 len
)写入大对象描述符 fd
。 fd
参数必须由以前的 lo_open
返回。返回实际写入的字节数(在当前实现中,除非出错,否则这始终等于 len
)。如果出现错误,则返回值为 -1。
尽管将len
参数声明为size_t
,但该函数仍会拒绝大于INT_MAX
的长度值。实际上,最好按每次最多几兆字节的数据块传输数据
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
的长度值。实际上,最好按每次最多几兆字节的数据块传输数据
int lo_lseek(PGconn *conn, int fd, int offset, int whence);
此函数将由fd
标识的大对象描述符的当前位置指针移动到由offset
指定的新位置。对于whence
有效的数值为SEEK_SET
(从对象开始查找)、SEEK_CUR
(从当前位置开始查找)和SEEK_END
(从对象结束位置开始查找)。返回值为新的位置指针,如果发生错误,则返回 -1。
pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence);
此函数的行为与lo_lseek
相同,但是它能够接受大于 2GB 的offset
和/或返回一个大于 2GB 的结果。请注意,如果新的位置指针将大于 2GB,则lo_lseek
将会失败。
lo_lseek64
是PostgreSQL 9.3 的一项新功能。如果对较旧的服务器版本运行此函数,则它将会失败并返回 -1。
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
是 PostgreSQL 9.3 中的新功能。如果该函数针对较旧的服务器版本运行,它将失败并返回 -1。
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
的长度值。
int lo_truncate64(PGconn *conn, int fd, pg_int64 len);
此函数的行为与 lo_truncate
相同,但是可以接受一个大于 2GB 的 len
值。
lo_truncate
是 PostgreSQL 8.3 中的新功能;如果该函数针对较旧的服务器版本运行,它将失败并返回 -1。
lo_truncate64
是 PostgreSQL 9.3 中的新功能;如果该函数针对较旧的服务器版本运行,它将失败并返回 -1。
int lo_close(PGconn *conn, int fd);
其中 fd
是由 lo_open
返回的大型对象描述符。如果成功,lo_close
将返回零。否则,返回值为 -1。
在事务结束时仍保持打开状态的任何大型对象描述符都将自动关闭。
int lo_unlink(PGconn *conn, Oid lobjId);
lobjId
参数指定要删除的大对象 OID。如果成功返回 1,如果失败返回 -1。