支援的版本: 目前 (17) / 16 / 15 / 14 / 13
開發版本: devel
不再支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0

32.7. 取消進行中的查詢 #

32.7.1. 用於傳送取消請求的函式 #

PQcancelCreate #

準備一個連接,以便可以透過該連接傳送取消請求。

PGcancelConn *PQcancelCreate(PGconn *conn);

PQcancelCreate 建立一個 PGcancelConn 物件,但它不會立即開始透過此連接傳送取消請求。可以使用 PQcancelBlocking 以封鎖方式,以及使用 PQcancelStart 以非封鎖方式,透過此連接傳送取消請求。傳回值可以傳遞給 PQcancelStatus,以檢查 PGcancelConn 物件是否成功建立。PGcancelConn 物件是一個不透明的結構,不應由應用程式直接存取。這個 PGcancelConn 物件可以用於以執行緒安全的方式取消在原始連接上執行的查詢。

在設定取消請求的連接時,將重複使用原始用戶端的許多連線參數。重要的是,如果原始連接需要連接加密和/或目標主機驗證(使用 sslmodegssencmode),則取消請求的連接將使用相同的要求進行。但是,任何僅在用戶端驗證期間或驗證後使用的連接選項都會被忽略,因為取消請求不需要驗證,並且連接在提交取消請求後立即關閉。

請注意,當 PQcancelCreate 傳回非空指標時,您必須在完成後呼叫 PQcancelFinish,以便釋放結構和任何相關的記憶體區塊。即使取消請求失敗或被放棄,也必須這樣做。

PQcancelBlocking #

請求伺服器以封鎖方式放棄處理目前指令。

int PQcancelBlocking(PGcancelConn *cancelConn);

該請求透過給定的 PGcancelConn 提出,該 PGcancelConn 需要使用 PQcancelCreate 建立。如果成功發送取消請求,則 PQcancelBlocking 的傳回值為 1,否則為 0。如果請求不成功,可以使用 PQcancelErrorMessage 檢索錯誤訊息。

但是,成功發送取消請求並不能保證該請求會產生任何效果。如果取消有效,則正在取消的指令將提早終止並傳回錯誤結果。如果取消失敗(例如,由於伺服器已完成處理指令),則根本不會有任何可見的結果。

PQcancelStart
PQcancelPoll #

請求伺服器以非封鎖方式放棄處理目前指令。

int PQcancelStart(PGcancelConn *cancelConn);

PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn);

該請求透過給定的 PGcancelConn 提出,該 PGcancelConn 需要使用 PQcancelCreate 建立。如果可以啟動取消請求,則 PQcancelStart 的傳回值為 1,否則為 0。如果請求不成功,可以使用 PQcancelErrorMessage 檢索錯誤訊息。

如果 PQcancelStart 成功,下一步是輪詢 libpq,以便它可以繼續取消連線的流程。使用 PQcancelSocket 來取得資料庫連線底層的 socket 的描述符。(注意:不要假設 socket 在 PQcancelPoll 的呼叫之間保持不變。)循環如下:如果 PQcancelPoll(cancelConn) 上次傳回 PGRES_POLLING_READING,請等到 socket 準備好讀取(由 select()poll() 或類似的系統函數指示)。然後再次呼叫 PQcancelPoll(cancelConn)。相反地,如果 PQcancelPoll(cancelConn) 上次傳回 PGRES_POLLING_WRITING,請等到 socket 準備好寫入,然後再次呼叫 PQcancelPoll(cancelConn)。在第一次迭代時,也就是說,如果您尚未呼叫 PQcancelPoll(cancelConn),請表現得好像它上次傳回了 PGRES_POLLING_WRITING。繼續這個循環,直到 PQcancelPoll(cancelConn) 傳回 PGRES_POLLING_FAILED,表示連線程序失敗,或 PGRES_POLLING_OK,表示取消請求已成功發送。

但是,成功發送取消請求並不能保證該請求會產生任何效果。如果取消有效,則正在取消的指令將提早終止並傳回錯誤結果。如果取消失敗(例如,由於伺服器已完成處理指令),則根本不會有任何可見的結果。

在連線期間的任何時間,都可以透過呼叫 PQcancelStatus 來檢查連線的狀態。如果此呼叫傳回 CONNECTION_BAD,則表示取消程序失敗;如果呼叫傳回 CONNECTION_OK,則表示取消請求已成功發送。這兩種狀態都可以從上面描述的 PQcancelPoll 的傳回值中偵測到。在非同步連線程序期間(且僅在期間)也可能發生其他狀態。這些狀態表示連線程序的目前階段,可能對向使用者提供回饋很有用。這些狀態為

CONNECTION_ALLOCATED #

等待呼叫 PQcancelStartPQcancelBlocking 來實際開啟 socket。這是呼叫 PQcancelCreatePQcancelReset 之後的連線狀態。此時尚未啟動與伺服器的任何連線。要實際開始發送取消請求,請使用 PQcancelStartPQcancelBlocking

CONNECTION_STARTED #

等待建立連線。

CONNECTION_MADE #

連線正常;等待傳送。

CONNECTION_AWAITING_RESPONSE #

等待伺服器的回應。

CONNECTION_SSL_STARTUP #

協商 SSL 加密。

CONNECTION_GSS_STARTUP #

協商 GSS 加密。

請注意,儘管這些常數將保留(為了保持相容性),但應用程式永遠不應依賴這些常數以特定順序出現,或根本不出現,或狀態始終是這些已記錄的值之一。應用程式可以這樣做

switch(PQcancelStatus(conn))
{
        case CONNECTION_STARTED:
            feedback = "Connecting...";
            break;

        case CONNECTION_MADE:
            feedback = "Connected to server...";
            break;
.
.
.
        default:
            feedback = "Connecting...";
}

使用 PQcancelPoll 時,會忽略 connect_timeout 連線參數;由應用程式負責判斷是否經過了過多的時間。否則,PQcancelStart 後面接一個 PQcancelPoll 迴圈等同於 PQcancelBlocking

PQcancelStatus #

傳回取消連線的狀態。

ConnStatusType PQcancelStatus(const PGcancelConn *cancelConn);

該狀態可以是多個值之一。但是,只有三個值在非同步取消程序之外可見:CONNECTION_ALLOCATEDCONNECTION_OKCONNECTION_BAD。使用 PQcancelCreate 成功建立的 PGcancelConn 的初始狀態為 CONNECTION_ALLOCATED。已成功發送的取消請求的狀態為 CONNECTION_OK。失敗的取消嘗試由狀態 CONNECTION_BAD 發出訊號。在呼叫 PQcancelFinishPQcancelReset 之前,OK 狀態將保持不變。

有關可能傳回的其他狀態碼,請參閱 PQcancelStart 的條目。

但是,成功發送取消請求並不能保證該請求會產生任何效果。如果取消有效,則正在取消的指令將提早終止並傳回錯誤結果。如果取消失敗(例如,由於伺服器已完成處理指令),則根本不會有任何可見的結果。

PQcancelSocket #

取得與伺服器取消連線 socket 的檔案描述符編號。

int PQcancelSocket(const PGcancelConn *cancelConn);

有效的描述符將大於或等於 0;結果為 -1 表示目前沒有開啟伺服器連線。透過對 PGcancelConn 呼叫本節中的任何函數(除了 PQcancelErrorMessagePQcancelSocket 本身),這可能會改變。

PQcancelErrorMessage #

傳回最近由取消連線上的操作產生的錯誤訊息。

char *PQcancelErrorMessage(const PGcancelConn *cancelconn);

幾乎所有採用 PGcancelConnlibpq 函數都會在失敗時設定 PQcancelErrorMessage 的訊息。請注意,按照 libpq 慣例,非空的 PQcancelErrorMessage 結果可以包含多行,並且將包含尾隨換行符。呼叫者不應直接釋放結果。當相關的 PGcancelConn 控制代碼傳遞給 PQcancelFinish 時,將釋放該結果。不應期望結果字串在 PGcancelConn 結構上的操作中保持不變。

PQcancelFinish #

關閉取消連線(如果尚未完成發送取消請求)。也會釋放 PGcancelConn 物件使用的記憶體。

void PQcancelFinish(PGcancelConn *cancelConn);

請注意,即使取消嘗試失敗(如 PQcancelStatus 所示),應用程式也應呼叫 PQcancelFinish 以釋放 PGcancelConn 物件使用的記憶體。在呼叫 PQcancelFinish 之後,不得再次使用 PGcancelConn 指標。

PQcancelReset #

重設 PGcancelConn,以便它可以重新用於新的取消連線。

void PQcancelReset(PGcancelConn *cancelConn);

如果目前使用 PGcancelConn 發送取消請求,則將關閉此連線。然後,它將準備 PGcancelConn 物件,以便它可以用於發送新的取消請求。

這可以用於為一個 PGconn 建立一個 PGcancelConn,並在原始 PGconn 的整個生命週期中多次重複使用它。

32.7.2. 傳送取消請求的已過時函式 #

這些函式代表傳送取消請求的較舊方法。雖然它們仍然有效,但由於即使原始連線指定 sslmodegssencmode 以要求加密,它們也不以加密方式傳送取消請求,因此它們已被棄用。 因此,強烈建議不要在新程式碼中使用這些較舊的方法,並建議更改現有程式碼以改用新的函式。

PQgetCancel #

建立一個資料結構,其中包含使用 PQcancel 取消命令所需的資訊。

PGcancel *PQgetCancel(PGconn *conn);

PQgetCancel 給定一個 PGconn 連線物件,建立一個 PGcancel 物件。 如果給定的 connNULL 或無效連線,它將傳回 NULLPGcancel 物件是一個不透明結構,不應由應用程式直接存取;它只能傳遞給 PQcancelPQfreeCancel

PQfreeCancel #

釋放由 PQgetCancel 建立的資料結構。

void PQfreeCancel(PGcancel *cancel);

PQfreeCancel 釋放先前由 PQgetCancel 建立的資料物件。

PQcancel #

PQcancelPQcancelBlocking 的已棄用且不安全的變體,但可以從訊號處理常式中安全地使用它。

int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize);

PQcancel 僅因向後相容性原因而存在。 應該改用 PQcancelBlockingPQcancel 唯一的優點是,如果 errbuf 是訊號處理常式中的區域變數,則可以從訊號處理常式中安全地調用它。 但是,通常認為這不足以成為此函式存在的安全問題。

PQcancel 而言,PGcancel 物件是唯讀的,因此也可以從與操縱 PGconn 物件的執行緒不同的執行緒中調用它。

如果取消請求已成功發送,則 PQcancel 的傳回值為 1,否則為 0。 如果沒有,errbuf 將填寫一個解釋性錯誤訊息。 errbuf 必須是一個大小為 errbufsize 的 char 陣列(建議的大小為 256 位元組)。

PQrequestCancel #

PQrequestCancelPQcancelBlocking 的已棄用且不安全的變體。

int PQrequestCancel(PGconn *conn);

PQrequestCancel 僅因向後相容性原因而存在。 應該改用 PQcancelBlocking。 使用 PQrequestCancel 優於 PQcancelBlocking 沒有任何好處。

請求伺服器放棄處理目前的命令。 它直接在 PGconn 物件上操作,並且在失敗的情況下,將錯誤訊息儲存在 PGconn 物件中(可以由此通過 PQerrorMessage 檢索)。 雖然功能相同,但這種方法在多執行緒程式或訊號處理常式中並不安全,因為覆寫 PGconn 的錯誤訊息可能會破壞目前在連線上進行的操作。

提交更正

如果您在文件中看到任何不正確、與您使用特定功能的經驗不符或需要進一步澄清的內容,請使用此表單報告文件問題。