W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
COPY
數(shù)據(jù)的函數(shù)COPY
數(shù)據(jù)的函數(shù)COPY
的廢棄函數(shù) PostgreSQL中的COPY
命令有用于libpq的對網(wǎng)絡(luò)連接讀出或者寫入的選項。這一節(jié)描述的函數(shù)允許應(yīng)用通過提供或者消耗已拷貝的數(shù)據(jù)來充分利用這個功能。
整個處理是應(yīng)用首先通過PQexec
或者一個等效的函數(shù)發(fā)出 SQL COPY
命令。 對這個命令的響應(yīng)(如果命令無誤)將是一個狀態(tài)代碼是PGRES_COPY_OUT
或 者PGRES_COPY_IN
(取決于指定的拷貝方向)的
PGresult
對象。 應(yīng)用然后就應(yīng)該使用這一節(jié)的函數(shù)接收或者傳送數(shù)據(jù)行。在數(shù)據(jù)傳輸結(jié)束之后,另外一個PGresult
對象會被返回以表明傳輸?shù)某晒蛘呤 ?它的狀態(tài)將是:PGRES_COMMAND_OK
表示成功,PGRES_FATAL_ERROR
表示發(fā)生了一些問題。 此時我們可以通過PQexec
發(fā)出進一步的 SQL 命令(在COPY
操作的處理過程中,不能用同一個連接執(zhí)行其它 SQL 命令)。
如果一個COPY
命令是通過PQexec
在一個可能包含額外命令的字符串中發(fā)出的,那么應(yīng)用在完成COPY
序列之后必須繼續(xù)用
PQgetResult
取得結(jié)果。 只有在PQgetResult
返回NULL
時,我們才能確信PQexec
的命令字符串已經(jīng)處理完畢,
并且可以安全地發(fā)出更多命令。
這一節(jié)的函數(shù)應(yīng)該只在從PQexec
或 PQgetResult
獲得了PGRES_COPY_OUT
或
PGRES_COPY_IN
結(jié)果狀態(tài)的后執(zhí)行。
一個承載了這些狀態(tài)值之一的PGresult
對象攜帶了正在開始的COPY
操作的一些額外數(shù)據(jù)。這些額外的數(shù)據(jù)可以用于那些與帶查詢結(jié)果的連接一起使用的函數(shù):
PQnfields
返回要拷貝的列(域)的個數(shù)。
PQbinaryTuples
0 表示整體拷貝格式都是文本(行用新行分隔,列用分隔字符分隔等等)。1 表示整體拷貝格式都是二進制。詳見COPY。
PQfformat
返回與拷貝操的每列相關(guān)的格式代碼(0 是文本,1 是二進制)。當整體拷貝格式是文本時,那么每列的格式代碼將總是零,但是二進制格式可以同時支持文本和二進制列(不過,就目前的COPY
實現(xiàn)而言,二進制拷貝中只會出現(xiàn)二進制列;所以目前每列的格式總是匹配總體格式)。
這些額外的數(shù)據(jù)值只在使用協(xié)議 3.0 時可用。在使用協(xié)議 2.0 時,所有這些函數(shù)都返回 0。
COPY
數(shù)據(jù)的函數(shù)這些函數(shù)用于在COPY FROM STDIN
期間發(fā)送數(shù)據(jù)。如果在連接不是COPY_IN
狀態(tài),調(diào)用它們會失敗。
PQputCopyData
在COPY_IN
狀態(tài)中向服務(wù)器發(fā)送數(shù)據(jù)。
int PQputCopyData(PGconn *conn,
const char *buffer,
int nbytes);
傳輸指定buffer
中長度為nbytes
的COPY
數(shù)據(jù)到服務(wù)器。 如果數(shù)據(jù)被放在隊列中,結(jié)果是 1;如果因為緩沖區(qū)滿而無法被放在隊列中(只可能發(fā)生在連接是非阻塞模式時),那么結(jié)果是零;如果發(fā)生錯誤,結(jié)果為 -1(如果返回值為 -1,那么使用
PQerrorMessage
檢索細節(jié)。如果值是零,那么等待寫準備好然后重試)。
應(yīng)用可以把COPY
數(shù)據(jù)流劃分成任意方便的大小放到緩沖區(qū)中。在發(fā)送時,緩沖區(qū)載荷的邊界沒有什么語意。數(shù)據(jù)流的內(nèi)容必須匹配COPY
命令預(yù)期的數(shù)據(jù)格式;詳見COPY。
PQputCopyEnd
在COPY_IN
狀態(tài)中向服務(wù)器發(fā)送數(shù)據(jù)結(jié)束的指示。
int PQputCopyEnd(PGconn *conn,
const char *errormsg);
如果errormsg
是NULL
,則成功結(jié)束COPY_IN
操作。如果errormsg
不是NULL
則COPY
被強制失敗,
errormsg
指向的字符串是錯誤消息(不過,我們不應(yīng)假定這個準確的錯誤信息將會從服務(wù)器傳回,因為服務(wù)器可能已經(jīng)因為其自身原因?qū)е?code class="command">COPY失敗。還要注意的是在使用 3.0 協(xié)議之前的連接時,強制失敗的選項是不能用的)。
如果終止消息被發(fā)送,則結(jié)果為 1;在非阻塞模式中,結(jié)果為 1 也可能只表示終止消息被成功地放在了發(fā)送隊列中 (在非阻塞模式中,要確認數(shù)據(jù)確實被發(fā)送出去,你應(yīng)該接著等待寫準備好并且調(diào)用PQflush
,重復(fù)這些直到返回零)。 零表示該函數(shù)由于緩沖區(qū)滿而無法將該終止消息放在隊列中,這只會發(fā)生在非阻塞模式中(在這種情況下,等待寫準備好并且再次嘗試
PQputCopyEnd
調(diào)用)。 如果發(fā)生系統(tǒng)錯誤,則返回 -1,可以使用PQerrorMessage
檢索詳情。
在成功調(diào)用PQputCopyEnd
之后,調(diào)用PQgetResult
獲取COPY
命令的最終結(jié)果狀態(tài)。
我們可以用平常的方法來等待這個結(jié)果可用。然后返回到正常的操作。
COPY
數(shù)據(jù)的函數(shù)這些函數(shù)用于在COPY TO STDOUT
的過程中接收數(shù)據(jù)。如果連接不在COPY_OUT
狀態(tài),那么調(diào)用它們將會失敗。
PQgetCopyData
在COPY_OUT
狀態(tài)下從服務(wù)器接收數(shù)據(jù)。
int PQgetCopyData(PGconn *conn,
char **buffer,
int async);
在一個COPY
期間嘗試從服務(wù)器獲取另外一行數(shù)據(jù)。數(shù)據(jù)總是以每次一個數(shù)據(jù)行的方式被返回;如果只有一個部分行可用,那么它不會被返回。 成功返回一個數(shù)據(jù)行涉及到分配一塊內(nèi)存來保存該數(shù)據(jù)。buffer
參數(shù)必須為非NULL
。 *buffer
被設(shè)置為指向分配到的內(nèi)存的指針,或者是在沒有返回緩沖區(qū)的情況下指向
NULL
。 一個非NULL
的結(jié)果緩沖區(qū)在不需要時必須用PQfreemem
釋放。
在成功返回一行之后,返回的值就是該數(shù)據(jù)行里數(shù)據(jù)的字節(jié)數(shù)(將是大于零)。 被返回的字符串總是空終止的,雖然這可能只是對文本COPY
有用。 一個零結(jié)果表示該COPY
仍然在處理中,但是還沒有可用的行(只在async
為真時才可能)。 一個 -1 結(jié)果表示COPY
已經(jīng)完成。-2
結(jié)果表示發(fā)生了錯誤(參考PQerrorMessage
獲取原因)。
當async
為真時(非零),PQgetCopyData
將不會阻塞等待輸入; 如果COPY
仍在處理過程中并且沒有可用的完整行,那么它將返回零 (在這種情況下等待讀準備好,然后在再次調(diào)用
PQgetCopyData
之前,調(diào)用PQconsumeInput
)。 當async
為假(零)時,PQgetCopyData
將阻塞,直到數(shù)據(jù)可用或者操作完成。
在PQgetCopyData
返回 -1 之后,調(diào)用PQgetResult
獲取COPY
命令的最后結(jié)果狀態(tài)。
我們可以用平常的方法來等待這個結(jié)果可用。然后返回到正常的操作。
COPY
的廢棄函數(shù)這些函數(shù)代表了以前的處理COPY
的方法。盡管它們還能用,但是現(xiàn)在已經(jīng)被廢棄,因為它們的錯誤處理很糟糕、檢測結(jié)束數(shù)據(jù)的方法也不方便,并且缺少對二進制或非阻塞傳輸?shù)闹С帧?/p>
PQgetline
讀取一個以新行終止的字符行到(由服務(wù)器傳輸) 到一個長度為length
的字符串緩沖區(qū)。
int PQgetline(PGconn *conn,
char *buffer,
int length);
這個函數(shù)拷貝最多length
-1 個字符到該緩沖區(qū)中,并且把終止的新行轉(zhuǎn)換成一個零字節(jié)。 PQgetline
在輸入結(jié)束時返回EOF
,如果整行都被讀取則返回 0,如果緩沖區(qū)填滿了而還沒有遇到結(jié)束的新行則返回
1。
注意,應(yīng)用必須檢查是否一個新行包含兩個字符\.
,這表明服務(wù)器 已經(jīng)完成了COPY
命令的結(jié)果發(fā)送。如果應(yīng)用可能收到超過length
-1 字符長的行, 我們就應(yīng)該確保正確識別\.
行(例如,不要把一個長數(shù)據(jù)行的結(jié)束當作一個終止行)。
PQgetlineAsync
不阻塞地讀取一行COPY
數(shù)據(jù)(由服務(wù)器傳輸)到一個緩沖區(qū)中。
int PQgetlineAsync(PGconn *conn,
char *buffer,
int bufsize);
這個函數(shù)類似于PQgetline
,但是可以被用于那些必須異步讀取COPY
數(shù)據(jù)的應(yīng)用, 也就是不阻塞的應(yīng)用。 在發(fā)出了COPY
命令并得到了PGRES_COPY_OUT
響應(yīng)之后,
應(yīng)用應(yīng)該調(diào)用PQconsumeInput
和 PQgetlineAsync
直到檢測到結(jié)束數(shù)據(jù)的信號。
不像PQgetline
,這個函數(shù)負責檢測結(jié)束數(shù)據(jù)。
在每次調(diào)用時,如果libpq的輸入緩沖區(qū)中有一個完整的數(shù)據(jù)行可用,PQgetlineAsync
都將返回數(shù)據(jù)。 否則,在剩余行到達之前不會返回數(shù)據(jù)。如果識別到拷貝數(shù)據(jù)結(jié)束的標志,此函數(shù)返回 -1;如果沒有可用數(shù)據(jù)則返回 0; 或者是給出一個正數(shù)給出被返回的字節(jié)數(shù)。如果返回
-1,調(diào)用者下一步必須調(diào)用PQendcopy
,然后回到正常處理。
返回的數(shù)據(jù)將不超過一個數(shù)據(jù)行的范圍。如果可能,每次將返回一個完整行。但如果調(diào)用者提供的緩沖區(qū)太小不足以容下服務(wù)器發(fā)送的行,那么將返回部分行。對于文本數(shù)據(jù),這可以通過測試返回的最后一個字節(jié)是否\n
來檢測(在二進制COPY
中, 需要對COPY
數(shù)據(jù)格式進行實際的分析,以便做相同的判斷)。被返回的字符串不是空結(jié)尾的(如果你想增加一個終止空,確保傳遞一個比實際可用空間少一字節(jié)的
bufsize
)。
PQputline
向服務(wù)器發(fā)送一個空終止的字符串。如果 OK 則返回 0;如果不能發(fā)送字符串則返回EOF
。
int PQputline(PGconn *conn,
const char *string);
一系列PQputline
調(diào)用發(fā)送的COPY
數(shù)據(jù)流和PQgetlineAsync
返回的數(shù)據(jù)具有相同的格式,
只是應(yīng)用不需要每次PQputline
調(diào)用中發(fā)送剛好一個數(shù)據(jù)行;在每次調(diào)用中發(fā)送多行或者部分行都是可以的。
在PostgreSQL協(xié)議 3.0 之前,應(yīng)用必須顯式地發(fā)送兩個字符\.
作為最后一行來指示服務(wù)器已經(jīng)完成發(fā)送COPY
數(shù)據(jù)。 雖然這么做仍然有效,但是它已經(jīng)被廢棄并且\.
的特殊含義可能在將來的版本中刪除。 在發(fā)送完實際數(shù)據(jù)之后, 調(diào)用PQendcopy
就足夠了。
PQputnbytes
向服務(wù)器發(fā)送一個非空終止的字符串。如果 OK 則返回 0,如果不能發(fā)送字符串則返回EOF
。
int PQputnbytes(PGconn *conn,
const char *buffer,
int nbytes);
這個函數(shù)類似PQputline
,除了數(shù)據(jù)緩沖區(qū)不需要是空終止,因為要發(fā)送的字節(jié)數(shù)是直接指定的。在發(fā)送二進制數(shù)據(jù)時使用這個過程。
PQendcopy
與服務(wù)器同步。
int PQendcopy(PGconn *conn);
這個函數(shù)等待服務(wù)器完成拷貝。當最后一個字符串已經(jīng)用PQputline
發(fā)送給服務(wù)器時或者當最后一個字符串已經(jīng)用PQgetline
從服務(wù)器接收到時,就會發(fā)出這個函數(shù)。 這個函數(shù)必須被發(fā)出,否則服務(wù)器將會和客戶端“不同步”。從這個函數(shù)返回后,服務(wù)器就已經(jīng)準備好接收下一個
SQL 命令了。函數(shù)成功完成時返回值為 0,否則返回非零值(如果返回值為非零值,用PQerrorMessage
檢索詳情)。
在使用PQgetResult
時,應(yīng)用應(yīng)該通過反復(fù)調(diào)用PQgetline
并且在看到終止行后調(diào)用
PQendcopy
來響應(yīng)PGRES_COPY_OUT
結(jié)果。 然后它應(yīng)該返回到PQgetResult
循環(huán)直到PQgetResult
返回一個空指針。
類似地,PGRES_COPY_IN
結(jié)果會用一系列PQputline
加上之后的PQendcopy
來處理,然后返
回到PQgetResult
循環(huán)。 這樣的安排將保證嵌入到一系列SQL命令中的COPY
命令將被正確執(zhí)行。
舊的應(yīng)用很可能會通過PQexec
提交一個COPY
命令并且假定事務(wù)在PQendcopy
之后完成。
只有在COPY
是命令字符串中唯一的SQL命令時才能正確工作。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: