32.3. 客户端接口

本节描述PostgreSQL 客户端接口库提供来访问大对象的设施。 所有使用这些函数进行的大对象操作都必须 在一个SQL事务里实现。(这个要求是自PostgreSQL 6.5 以来的一个严格的要求,虽然在以前的版本里就隐含这样的要求, 如果忽略这一点会导致错误的表现。)PostgreSQL 大对象接口是对Unix文件系统的模仿, 有仿真的open, read, write,lseek等。

使用libpq里面大对象 接口的的客户端应用应该包含头文件 libpq/libpq-fs.h并且和 libpq库链接。

32.3.1. 创建大对象

函数

Oid lo_creat(PGconn *conn, int mode);

创建一个新的大对象。返回值是赋予新大对象的OID, 或者是失败的时候是InvalidOid(零)。 在PostgreSQL8.1里, 没有再使用mode, 并且它被忽略;不过,为了和早期的版本向下兼容, 我们最好将其设置为INV_READ, INV_WRITE, 或者INV_READ | INV_WRITE。 (这些符号常量在头文件libpq/libpq-fs.h里定义。)

例如:

inv_oid = lo_creat(conn, INV_READ|INV_WRITE);

函数

Oid lo_create(PGconn *conn, Oid lobjId);

也创建一个大对象。要赋予数值的OID可以用 lobjId声明; 如果这么做,那么在该OID已经被其他大对象使用的情况下就会生成错误。 如果lobjIdInvalidOid(零), 那么lo_create赋予一个未用的 OID 这个和lo_creat的行为一致。) 返回值是赋予新的大对象的OID,或者是失败 情况下的InvalidOid(零)。

lo_create函数是PostgreSQL8.1 里面新增加的;如果在老的服务器上运行这个函数, 它会失败并返回InvalidOid

一个例子:

inv_oid = lo_create(conn, desired_oid);

32.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_oidPostgreSQL 8.4 里面新增加的,并且内壁调用lo_create(8.1新增的),如果此功能在8.0或之前运行这个函数, 它会失败并返回InvalidOid

32.3.3. 输出大对象

要把一个大对象输出为操作系统文件,调用

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

lobjId 参数指明要输出的大对象OID, filename参数指明操作系统文件的路径名。 请注意这个文件是由客户端接口库写入的, 而不是服务器端。 成功时返回1,失败时返回-1。

32.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_telllo_close。 这个描述符只是在当前事务中有效。 失败的时候,返回-1。

服务器目前并不区分INV_WRITEINV_READ | INV_WRITE模式:可以从这些任一模式中读取描述符。但与INV_READ有明显的不同: 对于INV_READ,你不能写入描述符, 并且从其中读取的数据将反映执行lo_open的时候事务快照对应的 大对象的数据,而不会考虑本次事务后面写入的或者其他事务写入的数据。 从一个用INV_WRITE打开的描述符里面读取的数据反 映所有其他已经提交的事务和当前事务的写操作写入的大对象的数据。 这个行为类似普通SQL语句SELECT在事务模式 SERIALIZABLEREAD COMMITTED中的行为。

一个例子:

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

32.3.5. 向大对象中写数据

函数

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

从大对象描述符buf中读取len字节 数据到从大对象描述符fd中。 fd参数必须是前面的一个 lo_open调用的返回。 返回实际读取的字节数。出错时,返回一个负数。

32.3.6. 从大对象中读取数据

函数

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

从大对象描述符fd中读取 len字节数据到buf中。 fd参数必须是前面的一个lo_open调用的返回。 返回实际读取的字节数。出错时,返回一个负数。

32.3.7. 大对象中数据的查找

要改变与一个大对象描述符相关的读写位置,调用

int lo_lseek(PGconn *conn, int fd, int offset, int whence);

这个过程把当前fd代表的大对象描述符 位置指针移动到offset指明的新的位置。 参数whence的合法的取值是SEEK_SET (从对象开头开始找),SEEK_CUR(从当前位置开始找), 和SEEK_END(从对象结尾开始找)。 返回值是新位置指针,如果出错为-1。

32.3.8. 获取一个大对象的当前索引位置

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

int lo_tell(PGconn *conn, int fd);

如果有错误,返回值是负数。

32.3.9. 截断一个大对象

截断一个给定长度的大对象,调用

int lo_truncate(PGcon *conn, int fd, size_t len);

截断描述fd到长度len的大对象, fd参数必须通过lo_open返回。 如果len大于当前大对象的长度,大对象延长空字节('\0')。

文件偏移量没有改变。

成功时,lo_truncate返回零。错误时,返回值是负数。

lo_truncatePostgreSQL8.3里面新增的, 如果在老的服务器上运行这个函数,它会失败并返回负值。

32.3.10. 关闭一个大对象描述符

一个大对象的关闭可以通过调用

int lo_close(PGconn *conn, int fd);

是返回的大对象的描述符。 成功时,lo_close返回零。错误时,返回值是负数。

任何在事务结尾时仍然打开的大对象描述符将在事务结束时自动关闭。

32.3.11. 删除一个大对象

从数据库中删除一个大对象,调用

int lo_unlink(PGconn *conn, Oid lobjId);

lobjId参数声明要删除的大对象的OID。 成功时返回1,失败时返回-1。