COPY
命令相關的函式 #PostgreSQL 中的 COPY
命令具有從 libpq 使用的網路連線讀取或寫入資料的選項。本節介紹的函式允許應用程式透過提供或消耗複製的資料來利用此功能。
整個過程是,應用程式首先透過 PQexec
或其中一個等效函式發出 SQL COPY
命令。對此的響應(如果命令沒有錯誤)將是一個 PGresult
物件,其狀態碼為 PGRES_COPY_OUT
或 PGRES_COPY_IN
(取決於指定的複製方向)。然後,應用程式應使用本節中的函式來接收或傳輸資料行。資料傳輸完成後,將返回另一個 PGresult
物件來指示傳輸的成功或失敗。其狀態將為 PGRES_COMMAND_OK
表示成功,或 PGRES_FATAL_ERROR
表示遇到問題。此時可以透過 PQexec
發出更多 SQL 命令。(在 COPY
操作進行期間,無法使用同一連線執行其他 SQL 命令。)
如果在可能包含其他命令的字串中透過 PQexec
發出 COPY
命令,則在完成 COPY
序列後,應用程式必須繼續透過 PQgetResult
獲取結果。只有當 PQgetResult
返回 NULL
時,才能確定 PQexec
命令字串已完成,並且可以安全地發出更多命令。
本節中的函式應僅在從 PQexec
或 PQgetResult
獲得 PGRES_COPY_OUT
或 PGRES_COPY_IN
的結果狀態後執行。
帶有這些狀態值之一的 PGresult
物件會攜帶有關即將開始的 COPY
操作的一些額外資料。這些額外資料可以使用與查詢結果相關的函式來訪問。
COPY
資料的函式 #這些函式用於在 COPY FROM STDIN
期間傳送資料。如果在連線不在 COPY_IN
狀態時呼叫它們,它們將失敗。
PQputCopyData
#在 COPY_IN
狀態期間將資料傳送到伺服器。
int PQputCopyData(PGconn *conn, const char *buffer, int nbytes);
將指定 buffer
中的 COPY
資料(長度為 nbytes
)傳輸到伺服器。結果是 1 表示資料已排隊,0 表示由於緩衝區已滿未排隊(這僅發生在非阻塞模式下),或 -1 表示發生錯誤。(如果返回值是 -1,請使用 PQerrorMessage
檢索詳細資訊。如果值為零,則等待資料可寫並重試。)
應用程式可以將 COPY
資料流分成任意方便大小的緩衝區載入。傳送時,緩衝區載入邊界沒有語義意義。資料流的內容必須與 COPY
命令期望的資料格式匹配;有關詳細資訊,請參閱 COPY。
PQputCopyEnd
#在 COPY_IN
狀態期間將資料結束指示傳送到伺服器。
int PQputCopyEnd(PGconn *conn, const char *errormsg);
如果 errormsg
是 NULL
,則成功結束 COPY_IN
操作。如果 errormsg
不是 NULL
,則強制 COPY
失敗,並將 errormsg
指向的字串用作錯誤訊息。(但是,不應假設伺服器會返回此精確的錯誤訊息,因為伺服器可能已因自身原因導致 COPY
失敗。)
結果是 1 表示終止訊息已傳送;或在非阻塞模式下,這可能僅表示終止訊息已成功排隊。(在非阻塞模式下,要確保資料已傳送,您應該接下來等待資料可寫並呼叫 PQflush
,重複呼叫直到其返回零。)零表示由於緩衝區已滿,該函式無法排隊終止訊息;這僅發生在非阻塞模式下。(在這種情況下,等待資料可寫並再次嘗試 PQputCopyEnd
呼叫。)如果發生硬錯誤,則返回 -1;您可以使用 PQerrorMessage
檢索詳細資訊。
成功呼叫 PQputCopyEnd
後,呼叫 PQgetResult
以獲取 COPY
命令的最終結果狀態。可以按常規方式等待此結果可用。然後返回到正常操作。
COPY
資料的函式 #這些函式用於在 COPY TO STDOUT
期間接收資料。如果在連線不在 COPY_OUT
狀態時呼叫它們,它們將失敗。
PQgetCopyData
#在 COPY_OUT
狀態期間從伺服器接收資料。
int PQgetCopyData(PGconn *conn, char **buffer, int async);
COPY
期間,嘗試從伺服器獲取下一行資料。資料始終一次返回一行;如果只有部分行可用,則不返回。成功返回資料行涉及分配記憶體塊來儲存資料。buffer
引數必須非 NULL
。*buffer
被設定為指向分配的記憶體,或在未返回緩衝區的情況下設定為 NULL
。在不再需要時,必須使用 PQfreemem
釋放非 NULL
的結果緩衝區。
當成功返回一行時,返回值是該行中資料的位元組數(始終大於零)。返回的字串始終以 null 結尾,儘管這可能僅對文字 COPY
有用。返回 0 表示 COPY
仍在進行中,但尚未準備好行(僅當 async
為 true 時才可能)。返回 -1 表示 COPY
已完成。返回 -2 表示發生錯誤(請參閱 PQerrorMessage
獲取原因)。
當 async
為 true(非零)時,PQgetCopyData
不會阻塞等待輸入;如果 COPY
仍在進行中但尚未準備好完整行,它將返回零。(在這種情況下,等待資料可讀,然後呼叫 PQconsumeInput
,然後再呼叫 PQgetCopyData
。)當 async
為 false(零)時,PQgetCopyData
將阻塞直到有資料可用或操作完成。
在 PQgetCopyData
返回 -1 後,呼叫 PQgetResult
以獲取 COPY
命令的最終結果狀態。可以按常規方式等待此結果可用。然後返回到正常操作。
COPY
函式 #這些函式代表了處理 COPY
的舊方法。儘管它們仍然有效,但由於錯誤處理不佳、檢測資料結束的方法不方便以及不支援二進位制或非阻塞傳輸,因此已棄用。
PQgetline
#將伺服器傳輸的以換行符結尾的字元行讀取到大小為 length
的緩衝區字串中。
int PQgetline(PGconn *conn, char *buffer, int length);
此函式將最多 length
-1 個字元複製到緩衝區,並將終止的換行符轉換為零位元組。 PQgetline
在輸入結束時返回 EOF
,如果已讀取整行則返回 0,如果緩衝區已滿但尚未讀取終止換行符則返回 1。
請注意,應用程式必須檢查新行是否由兩個字元 \.
組成,這表示伺服器已完成傳送 COPY
命令的結果。如果應用程式可能收到長度超過 length
-1 個字元的行,則需要小心確保它正確識別 \.
行(並且不,例如,將長資料行的末尾誤認為終止符行)。
PQgetlineAsync
#在不阻塞的情況下將 COPY
資料行(由伺服器傳輸)讀取到緩衝區中。
int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize);
此函式類似於 PQgetline
,但可供必須非同步讀取 COPY
資料的應用程式使用,即不阻塞。COPY
命令已發出並收到 PGRES_COPY_OUT
響應後,應用程式應呼叫 PQconsumeInput
和 PQgetlineAsync
,直到檢測到資料結束訊號。
與 PQgetline
不同,此函式負責檢測資料結束。
每次呼叫時,如果 libpq 的輸入緩衝區中有完整的資料行可用,PQgetlineAsync
就會返回資料。否則,直到行的其餘部分到達才會返回資料。如果識別到複製資料結束標記,則函式返回 -1;如果沒有資料可用,則返回 0;否則返回一個正數,表示返回的資料位元組數。如果返回 -1,呼叫者隨後必須呼叫 PQendcopy
,然後返回到正常處理。
返回的資料不會超出資料行的邊界。如果可能,將一次返回一整行。但是,如果呼叫者提供的緩衝區太小而無法容納伺服器傳送的一行,則將返回部分資料行。對於文字資料,可以透過測試最後一個返回的位元組是否為 \n
來檢測。(在二進位制 COPY
中,需要實際解析 COPY
資料格式才能做出等效的判斷。)返回的字串不是 null 結尾的。(如果要新增終止 null,請確保將 bufsize
設定為比實際可用空間小一。)
PQputline
#將一個 null 結尾的字串傳送到伺服器。如果成功則返回 0,如果無法傳送字串則返回 EOF
。
int PQputline(PGconn *conn, const char *string);
透過一系列 PQputline
呼叫傳送的 COPY
資料流的格式與 PQgetlineAsync
返回的格式相同,不同之處在於應用程式不必每呼叫一次 PQputline
就傳送正好一個數據行;每次呼叫傳送部分行或多行是允許的。
在 PostgreSQL 協議 3.0 之前,應用程式必須顯式傳送兩個字元 \.
作為最後一行,以向伺服器指示其已完成傳送 COPY
資料。雖然這仍然有效,但已棄用,並且 \.
的特殊含義預計將在未來版本中被移除。(它在 CSV
模式下可能已出現問題。)在傳送實際資料後呼叫 PQendcopy
就足夠了。
PQputnbytes
#將一個非 null 結尾的字串傳送到伺服器。如果成功則返回 0,如果無法傳送字串則返回 EOF
。
int PQputnbytes(PGconn *conn, const char *buffer, int nbytes);
這與 PQputline
完全相同,不同之處在於資料緩衝區不必是 null 結尾的,因為要傳送的位元組數是直接指定的。傳送二進位制資料時使用此過程。
PQendcopy
#與伺服器同步。
int PQendcopy(PGconn *conn);
此函式等待直到伺服器完成複製。當使用 PQputline
向伺服器傳送最後一條字串,或者使用 PQgetline
從伺服器接收最後一條字串時,都應發出此函式。必須發出此函式,否則伺服器將與客戶端 “失去同步”。此函式返回後,伺服器就可以接收下一個 SQL 命令了。返回值是 0 表示成功完成,非零表示失敗。(如果返回值非零,請使用 PQerrorMessage
檢索詳細資訊。)
當使用 PQgetResult
時,應用程式應響應 PGRES_COPY_OUT
結果,透過反覆執行 PQgetline
,然後在看到終止符行後執行 PQendcopy
。然後應返回到 PQgetResult
迴圈,直到 PQgetResult
返回 null 指標。類似地,PGRES_COPY_IN
結果透過一系列 PQputline
呼叫,然後執行 PQendcopy
來處理,然後返回到 PQgetResult
迴圈。這種安排將確保一系列命令中嵌入的 COPY
命令SQL能夠正確執行。
舊的應用程式很可能會透過 PQexec
提交 COPY
,並在 PQendcopy
之後假設事務已完成。只有當 COPY
是命令字串中的唯一SQL命令時,這才會正常工作。
如果您在文件中發現任何不正確、與您對特定功能的使用經驗不符或需要進一步說明的內容,請使用 此表格 報告文件問題。