PostgreSQL 客戶端接口

2021-09-02 13:56 更新
34.3.1. 創(chuàng)建一個大對象
34.3.2. 導入一個大對象
34.3.3. 導出一個大對象
34.3.4. 打開一個現(xiàn)有的大對象
34.3.5. 向一個大對象寫入數(shù)據(jù)
34.3.6. 從一個大對象讀取數(shù)據(jù)
34.3.7. 在一個大對象中查找
34.3.8. 獲取一個大對象的查找位置
34.3.9. 截斷一個大對象
34.3.10. 關閉一個大對象描述符
34.3.11. 移除一個大對象

本節(jié)描述PostgreSQLlibpq客戶端接口為訪問大對象所提供的功能。PostgreSQL的大對象接口按照Unix文件系統(tǒng)的接口建模,也有相似的openreadwrite、lseek等。

所有使用這些函數(shù)對大對象的操作都必須發(fā)生在一個SQL事務塊中,因為大對象文件描述符只在事務期間有效。

在執(zhí)行任何一個這種函數(shù)期間如果發(fā)生一個錯誤,該函數(shù)將會返回一個其他的不可能值,典型的是0或-1。 一個關于該錯誤的消息亦會被保存在連接對象中,可以通過PQerrorMessage檢索到。

使用這些函數(shù)的客戶端應用應該包括頭文件libpq/libpq-fs.h并鏈接libpq庫。

34.3.1. 創(chuàng)建一個大對象

函數(shù)

Oid lo_creat(PGconn *conn, int mode);

創(chuàng)建一個新的大對象。其返回值是分配給這個新大對象的OID或者InvalidOid(0)表示失敗。 modePostgreSQL 8.1就不再使用且會被忽略。但是,為了和以前的發(fā)行兼容,它最好被設置為INV_READ、INV_WRITEINV_READ | INV_WRITE(這些符號常量定義在頭文件libpq/libpq-fs.h中)。

一個例子:

inv_oid = lo_creat(conn, INV_READ|INV_WRITE);

函數(shù)

Oid lo_create(PGconn *conn, Oid lobjId);

也創(chuàng)建一個新的大對象。分配給該大對象的OID可以通過lobjId指定,如果這樣做,該OID已經被某個大對象使用時會產生錯誤。如果lobjIdInvalidOid(0),則lo_create會分配一個未使用的OID(這時和 lo_creat的行為相同)。返回值是分配給新大對象的OID或InvalidOid(0)表示發(fā)生錯誤。

lo_create在從PostgreSQL 8.1開始的版本中是新的,如果該函數(shù)在舊服務器版本上運行,它將失敗并返回InvalidOid

一個例子:

inv_oid = lo_create(conn, desired_oid);

34.3.2. 導入一個大對象

要將一個操作系統(tǒng)文件導入成一個大對象,調用:

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

filename指定了要導入為大對象的操作系統(tǒng)文件名。返回值是分配給新大對象的OID或InvalidOid(0)表示發(fā)生錯誤。注意該文件是被客戶端接口庫而不是服務器所讀取,因此它必須存在于客戶端文件系統(tǒng)中并且對于客戶端應用是可讀的。

函數(shù)

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

也可以導入一個新大對象。分配給新大對象的OID可以用lobjId指定,如果這樣做,該OID已經被某個大對象使用時會產生錯誤。如果lobjIdInvalidOid(0),則lo_import_with_oid會分配一個未使用的OID(這和 lo_import的行為相同)。返回值是分配給新大對象的OID或InvalidOid(0)表示發(fā)生錯誤。

lo_import_with_oid在從PostgreSQL 8.1開始的版本中是新的并且在內部使用了lo_create(在8.1中也是新的),如果該函數(shù)在舊服務器版本上運行,它將失敗并返回InvalidOid。

34.3.3. 導出一個大對象

要把一個大對象導出到一個操作系統(tǒng)文件,調用:

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

lobjId參數(shù)指定要導出的大對象的OID,filename參數(shù)指定操作系統(tǒng)文件名。注意該文件是被客戶端接口庫而不是服務器寫入。成功返回1,錯誤返回-1。

34.3.4. 打開一個現(xiàn)有的大對象

要打開一個現(xiàn)有的大對象進行讀寫,調用:

int lo_open(PGconn *conn, Oid lobjId, int mode);

lobjId參數(shù)指定要打開的大對象的OID。mode位控制著打開對象是為了只讀(INV_READ)、只寫(INV_WRITE)或者讀寫(這些符號常量定義在頭文件libpq/libpq-fs.h中)。 lo_open返回一個(非負)大對象描述符以便后面用于lo_read、lo_write、lo_lseek、lo_lseek64lo_tell、lo_tell64、 lo_truncate、lo_truncate64以及lo_close。該描述符只在當前事務期間有效。如果打開錯誤將會返回-1。

服務器目前并不區(qū)分模式INV_WRITEINV_READ |INV_WRITE:在兩種情況中都允許從描述符讀取。但是在這些模式和單獨的INV_READ之間有明顯的區(qū)別:使用INV_READ我們不能向描述符寫入,從中讀取的數(shù)據(jù)則反映了該大對象在活動事務快照時刻的內容(該快照在 lo_open被執(zhí)行時創(chuàng)建),而不管之后被該事務或其他事務寫入的內容。從一個以INV_WRITE模式打開的描述符讀取的數(shù)據(jù)所有其他已提交事務以及當前事務所作的寫入。這與普通SQL命令 SELECTREPEATABLE READREAD COMMITTED事務模式之間的區(qū)別相似。

如果大對象的SELECT特權不可用,或者如果在指定了INV_WRITEUPDATE特權不可用,則lo_open將會失?。ㄔ?span id="ah5sygv" class="productname">PostgreSQL 11之前,這些特權的檢查是在使用該描述符的第一次實際讀取或寫入時進行)。這些特權檢查可以用 lo_compat_privileges運行時參數(shù)禁用。

一個例子:

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

34.3.5. 向一個大對象寫入數(shù)據(jù)

函數(shù)

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

buf(大小必須是 len)中寫出len字節(jié)到大對象描述符fd。參數(shù)fd必須是已經由前面的 lo_open返回的大對象描述符。函數(shù)將返回實際寫入的字節(jié)數(shù)(在當前的實現(xiàn)中,除非出錯,返回的字節(jié)數(shù)總是等于len)。在出錯時,返回值為-1。

盡管參數(shù)len被聲明為類型size_t,該函數(shù)會拒絕超過INT_MAX的長度值。在實際中,被傳送的數(shù)據(jù)最好是每塊最多數(shù)兆字節(jié)。

34.3.6. 從一個大對象讀取數(shù)據(jù)

函數(shù)

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

從大對象描述符fd中讀取最多len字節(jié)到buf (大小必須是len)中。參數(shù)fd必須是已經由前面的 lo_open返回的大對象描述符。實際讀出的字節(jié)數(shù)將被返回,如果先到達了大對象的末尾返回值可能會小于len。出錯時返回值為-1。

盡管參數(shù)len被聲明為類型size_t,該函數(shù)會拒絕超過INT_MAX的長度值。在實際中,被傳送的數(shù)據(jù)最好是每塊最多數(shù)兆字節(jié)。

34.3.7. 在一個大對象中查找

要改變一個大對象描述符的當前讀或寫位置,調用:

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

該函數(shù)將大對象文件描述符fd的當前位置指針移動到由offset指定的新位置。whence的可用值是SEEK_SET(從對象開頭定位)、SEEK_CUR (從當前位置定位)以及 SEEK_END(從對象末尾定位)。返回值是新位置的指針,或者是-1表示出錯。

在處理可能超過2GB大小的大對象時,換用

pg_int64 lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence);

該函數(shù)的行為和lo_lseek相同,但是它能接受一個超過2GB的offset并/或傳送一個超過2GB的結果。注意如果新位置的指針超過2GB,lo_lseek會失敗。

lo_lseek64是從 PostgreSQL 9.3開始增加的新函數(shù)。如果該函數(shù)在一個舊服務器版本上執(zhí)行,將會失敗并返回-1。

34.3.8. 獲取一個大對象的查找位置

要得到一個大對象描述符的當前讀或寫位置,調用:

int lo_tell(PGconn *conn, int fd);

如果出現(xiàn)錯誤,返回值是-1。

在處理可能超過2GB大小的大對象時,換用:

pg_int64 lo_tell64(PGconn *conn, int fd);

該函數(shù)和lo_tell的行為相同,但是它能傳遞超過2GB的結果。注意如果當前讀/寫位置超過2GB,lo_tell將會失敗。

lo_tell64是從PostgreSQL 9.3開始新增的函數(shù)。如果該函數(shù)在舊服務器版本上運行,將會失敗并返回-1。

34.3.9. 截斷一個大對象

要將一個大對象截斷成一個給定長度,調用:

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

該函數(shù)將大對象描述符fd截斷為長度len。參數(shù)fd必須是已經由前面的lo_open返回的大對象描述符。如果len超過了大對象的當前長度,大對象將會被使用空字節(jié)('\0')擴展到指定長度。成功時 lo_truncate返回0,失敗時返回值為-1。

描述fd的讀/寫位置不變。

盡管參數(shù)len被聲明為類型size_tlo_truncate會拒絕超過INT_MAX的長度值。

在處理可能超過2GB大小的大對象時,換用:

int lo_truncate64(PGcon *conn, int fd, pg_int64 len);

該函數(shù)和lo_truncate的行為相同,但它能夠接受超過2GB的len值。

lo_truncate是從PostgreSQL 8.3開始新的函數(shù),如果該函數(shù)運行在一個舊服務器版本上,它將失敗并返回-1。

lo_truncate64是從PostgreSQL 9.3開始新的函數(shù),如果該函數(shù)運行在一個舊服務器版本上,它將失敗并返回-1。

34.3.10. 關閉一個大對象描述符

要關閉一個大對象描述符,調用:

int lo_close(PGconn *conn, int fd);

其中fd是由lo_open返回的大對象描述符。成功時,lo_close返回0,失敗時返回-1。

在事務末尾仍然保持打開的任何大對象描述符都會自動被關閉。

34.3.11. 移除一個大對象

要從數(shù)據(jù)庫中移除一個大對象,調用:

int lo_unlink(PGconn *conn, Oid lobjId);

lobjId參數(shù)指定要移除的大對象的OID。成功時返回1,失敗時返回-1。


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號