Chapter 27. libpq - C 庫

Table of Contents
27.1. 資料庫連線函數
27.2. 連接狀態函數
27.3. 命令執行函數
27.3.1. 主函數
27.3.2. 檢索查詢結果訊息
27.3.3. 檢索其它命令的結果訊息
27.3.4. 逃逸包含在 SQL 命令中的字串
27.3.5. 逃逸包含在 SQL 命令中的二進制字串
27.4. 異步命令處理
27.5. 取消正在處理的查詢
27.6. 捷徑接口
27.7. 異步通知
27.8. COPY命令相關的函數
27.8.1. 用於發送 COPY 資料的函數
27.8.2. 用於接收 COPY 資料的函數
27.8.3. 用於 COPY 的廢棄的函數
27.9. 控制函數
27.10. 注意訊息處理
27.11. 環境變量
27.12. 指令文件
27.13. SSL 支援
27.14. 在多線程程序裡的行為
27.15. 製作 libpq 程序
27.16. 例子程序

libpqPostgreSQLC 應用程序接口。 libpq 是一套允許客戶程序向 PostgreSQL 伺服器服務進程發送查詢並且獲得查詢返回的庫函數。

libpq 同時也是其他幾個 PostgreSQL 應用接口下面的引擎, 包括 C++,Perl,Python,Tcl 和 ECPG。 所以如果您使用這些軟件包,libpq某些方面的特性會對您非常重要。 特別是 Section 27.11Section 27.12Section 27.13 描述了任何使用 libpq 的應用的用戶可見的行為。

本章末尾有三個小程序顯示如何利用 libpq 書寫程序。 (Section 27.16)在原始碼發佈的 src/test/examples 目錄裡面有幾個完整的 libpq 應用的例子。

使用 libpq 的前端程序必須包括頭文件 libpq-fe.h 並且必須與 libpq 庫鏈接。

27.1. 資料庫連線函數

下面的函數處理與 PostgreSQL 伺服器伺服器連線的事情。 一個應用程序一次可以與多個伺服器建立連線。(這麼做的原因之一是訪問多於一個資料庫。) 每個連接都是用一個從函數PQconnectdb()PQsetdbLogin() 獲得的 PGconn 對像資料表示。 注意,這些函數總是返回一個非空的對象指針,除非儲存器少得連個PGconn對象都分配不出來。 在把查詢發送給連線對像之前,可以調用PQstatus函數來檢查一下連線是否成功。

PQconnectdb

與伺服器資料庫伺服器建立一個新的連線。

PGconn *PQconnectdb(const char *conninfo);

這個函數用從一個字元串 conninfo來的參數與資料庫打開一個新的連線。 與下面的PQsetdbLogin()不同的是, 我們可以不必更換函數簽名(名字)就可以擴展參數集, 所以我們建議應用程序中使用這個函數(或者是它的類似的非阻塞的變種 PQconnectStartPQconnectPoll)。

傳入的參數可以為空,資料表明使用所有預設的參數, 或者可以包含一個或更多個用空白間隔的參數設置。 每個參數以 關鍵字 = 數值的形式設置。 等號周圍的空白是可選的。 要寫一個空值或者一個包含空白的值,您可以用一對單引號包圍它們,例如, keyword = 'a value' 。數值內部的單引號和反斜槓必須用一個反斜槓逃逸, 比如, \'\\

目前可識別的參數鍵字是:

host

要連線的主機名。 如果主機名以斜槓開頭,則它聲明使用 Unix 域套接字通訊而不是 TCP/IP 通訊; 該值就是套接字文件所儲存的目錄。 如果沒有聲明 host,那麼預設時是與位於 /tmp 目錄(或者製作 PostgreSQL 的時候聲明的套接字目錄) 裡面的 Unix-域套接字連線。 在沒有 Unix 域套接字的機器上,預設是與 localhost 連接。

hostaddr

與之連線的主機的 IP 地址。這個應該是標準的IPv4 地址格式, 比如,172.28.40.9。如果您的機器支援 IPv6, 那麼您也可以使用 IPv6 的地址。如果聲明了一個非空的字元串,那麼使用 TCP/IP 通訊機制。

使用hostaddr取代host可以讓應用避免一次主機名查找, 這一點對於那些有時間約束的應用來說可能是非常重要的。 不過,Kerberos 認證系統要求主機(host)名。因此,應用下面的規則: 如果聲明了不帶hostaddrhost那麼就強制進行主機名查找。 如果聲明中沒有hosthostaddr 的值給出遠端的地址; 如果使用了 Kerberos,將導致一次反向名字查詢。如果同時聲明了 host 和hostaddr, 除非使用了 Kerberos,否則將使用hostaddr的值作為遠端地址; host 的值將被忽略,如果使用了 Kerberos,host 的值用於 Kerberos 認證。 (要注意如果傳遞給libpq的主機名(host) 不是地址hostaddr處的機器名,那麼認證很有可能失敗。) 同樣,在 ~/.pgpass(參閱 Section 27.12) 中是使用 host 而不是 hostaddr 來標識連接。

如果主機名(host)和主機地址都沒有, 那麼libpq將使用一個本地的 Unix 域套接字進行通訊; 或者是在沒有 Unix 域套接字的機器上,它將嘗試與 localhost 連接。

port

主機伺服器的連接埠號,或者在 Unix 域套接字連線時的套接字擴展文件名。

dbname

資料庫名。預設和用戶名相同。

user

要連線的 PostgreSQL 用戶名。 預設是與執行該應用的用戶操作系統名同名的用戶。

password

如果伺服器要求指令認證,所用的指令。

connect_timeout

連接的最大等待時間,以秒計(用十進制整數字串書寫)。 零或者不聲明資料表示無窮。我們不建議把連接超時的值設置得小於 2 秒。

options

發送給伺服器的命令行選項。

tty

忽略(以前,這個選項聲明伺服器日誌的輸出方向)。

sslmode

這個選項決定是否需要和伺服器協商一個 SSL 連接, 以及以什麼樣的優先級與伺服器進行 SSL 連接。 有四種模式可供選擇:disable 將只進行一個沒有加密的非 SSL 連接; allow 將和伺服器進行協商,首先嘗試一個非 SSL 連接, 如果失敗,嘗試一個 SSL 連接;prefer (預設) 將進行協商, 首先嘗試 SSL 連接,如果失敗,嘗試一個正常的非 SSL 連接; require 將只進行 SSL 連接。

如果 PostgreSQL 編譯時沒有打開 SSL 支援,那麼使用 require 將導致一個錯誤, 而 libpq 將接受 allowprefer,但是它實際上不會企圖進行 SSL 連接。

requiressl

這個選項因為有了 sslmode 設置之後已經廢棄了。

如果設為 1 ,則要求與伺服器進行SSL連線(等效於 sslmode require)。 如果伺服器不支援SSL,那麼libpq將馬上拒絕連線。 設置為 0 (預設)與伺服器進行協商連接類型(等效於 sslmode prefer)。 這個選項只有在編譯 PostgreSQL 時打開了 SSL 支援才有效。

service

用於額外參數的服務名。它在pg_service.conf裡面聲明一個服務名, 這個配置文件保存額外的連接參數。這樣就允許應用應用只聲明一個服務名, 而連接參數就可以在一個地方維護了。參閱安裝目錄中的 share/pg_service.conf.sample 獲取如何設置這個文件的訊息。

如果有任何沒有聲明的參數,那麼將檢查對應的環境變量(參閱Section 27.11 小節)。 如果環境變量也沒有設置,那麼使用編譯時的指明的內置預設。

PQsetdbLogin

與伺服器資料庫伺服器建立一個新的連線。

PGconn *PQsetdbLogin(const char *pghost,
		     const char *pgport,
		     const char *pgoptions,
		     const char *pgtty,
		     const char *dbName,
		     const char *login,
		     const char *pwd);

這個函數是 PQconnectdb 前身, 它有固定個數的參數。它有相同的功能,只是在調用中那些它缺少的參數總是用預設值。 如果麼給任意的固定參數設置預設值,那麼寫一個 NULL 或者一個空字串給它們。

PQsetdb

與伺服器資料庫伺服器建立一個新的連線。

PGconn *PQsetdb(char *pghost,
		char *pgport,
		char *pgoptions,
		char *pgtty,
		char *dbName);

這是一個調用 PQsetdbLogin() 的宏,只是loginpwd參數用空(null )代替。 提供這個函數是為了與非常老版本的程序兼容。

PQconnectStart
PQconnectPoll

與資料庫伺服器建立一次非阻塞的連線。

PGconn *PQconnectStart(const char *conninfo);

PostgreSQLPollingStatusType PQconnectPoll(PGconn *conn);

這兩個函數用於打開一個與資料庫伺服器之間的非阻塞的連線: 您的應用的執行線索在執行它的時候不會因遠端的 I/O 而阻塞。 這個方法的要點是等待 I/O 結束可以發生在應用的主循環裡, 而不是在 PQconnectdb 裡,這樣應用可以把這件事與其它操作並發起來一起執行。

資料庫連線是用從 conninfo 字元串裡取得的參數傳遞給 PQconnectStart 進行的。 這個字元串的格式與上面PQconnectdb裡描述的一樣。

PQconnectStartPQconnectPoll 都不會阻塞(進程),不過有一些條件:

  • 必須正確提供hostaddrhost 參數以確保不會發生正向或者反向的名字查找。 參閱上面PQconnectdb裡的這些參數的文件獲取細節。

  • 如果您調用了PQtrace, 確保您跟蹤進入的流對像不會阻塞。

  • 您必須在調用PQconnectPoll之前確保 socket 處於正確的狀態,像下面描述的那樣。

要開始一次非阻塞連接請求,調用 conn=PQconnectStart("connection_info_string")。 如果conn是空,資料表明libpq無法分配一個新的PGconn結構。 否則,返回一個有效的PGconn指針(儘管還不一定代資料表一個與資料庫有效連線)。 PQconnectStart 一返回,調用status=PQstatus(conn)。 如果status等於CONNECTION_BADPQconnectStart 失敗。

如果PQconnectStart成功了,下一個階段是輪詢 libpq, 這樣它就可以繼續連接序列動作。使用 PQsocket(conn) 獲取資料庫鏈接下層的套接字描述符。 像這樣循環:如果PQconnectPoll(conn)的最後一個返回是PGRES_POLLING_READING, 那麼就等到套接字準備好被讀取了的時候(就像系統函數 select()poll(),或者類似的系統調用聲明的那樣)。 然後再次調用 PQconnectPoll(conn)。 同樣,如果 PQconnectPoll(conn) 最後返回 PGRES_POLLING_WRITING, 那麼就等到套接字準備好可以寫了,然後再次調用 PQconnectPoll(conn)。 如果您還沒調用 PQconnectPoll,比如,剛剛調用完 PQconnectStart, 那麼按照它剛返回 PGRES_POLLING_WRITING 的原則行動。 繼續這個循環直到 PQconnectPoll(conn) 返回 PGRES_POLLING_FAILED, 資料表明連接失敗,或者 PGRES_POLLING_OK,資料表明連接成功建立。

在連線的任意時刻,我們都可以透過調用PQstatus 來檢查連線的狀態。 如果這是CONNECTION_BAD, 那麼連線過程失敗;如果是CONNECTION_OK, 那麼連線已經做好。 這兩種狀態同樣也可以從上面的PQconnectPoll 的返回值裡檢測到。 其他狀態可能(也只能)在一次異步連線過程中發生。 這些標識連線過程的目前狀態,因而可能對給用戶提供反饋有幫助。這些狀態可能包括:

CONNECTION_STARTED

等待進行連線。

CONNECTION_MADE

連線成功;等待發送。

CONNECTION_AWAITING_RESPONSE

等待來自伺服器的響應。

CONNECTION_AUTH_OK

已收到認證;等待連線啟動繼續進行。

CONNECTION_SSL_STARTUP

協商 SSL 加密。

CONNECTION_SETENV

協商環境驅動的參數設置。

注意,儘管這些常量將保持下去(為了維持相容性), 應用決不應該依賴於這些常量以某種特定順序出現, 或者是根本不應依賴於這些常量, 或者是不應該依賴於這些狀態總是某個文件聲明的值。 一個應用可能像象下面這樣:

switch(PQstatus(conn))
{
    case CONNECTION_STARTED:
	feedback = "正在連接...";
	break;

    case CONNECTION_MADE:
	feedback = "與伺服器連接已建立...";
	break;
.
.
.
    default:
	feedback = "正在連接...";
}

在使用 PQconnectPoll 的時候,連接參數 connect_timeout 將被忽略;判斷是否超時是應用的責任。否則,後面跟著一個 PQconnectPoll 循環的 PQconnectStart 等效於 PQconnectdb

要注意如果PQconnectStart返回一個非空的指針, 您必須在使用完它(指針)之後調用PQfinish, 以處理那些結構和所有相關的儲存塊。 甚至調用PQconnectStart或者 PQconnectPoll失敗時也要這樣處理。

PQconndefaults

返回預設的連線選項。

PQconninfoOption *PQconndefaults(void);

typedef struct PQconninfoOption
{
    char   *keyword;   /* 選項的鍵字 */
    char   *envvar;    /* 退守的環境變量名 */
    char   *compiled;  /* 退守的編譯時預設值 */
    char   *val;       /* 選項的目前值,或者 NULL */
    char   *label;     /* 連接對話裡字串的標識 */
    char   *dispchar;  /* 在連接對話裡為此字串顯示的字元。
			  數值有:
			  ""	原樣現實輸入的數值
			  "*"   指令字串 - 隱藏數值
			  "D"   調試選項 - 預設的時候不顯示 */
    int     dispsize;  /* 對話中字串的以字元計的大小 */
}PQconninfoOption;

返回一個連接選項數組。 可以用於獲取所有可能的PQconnectdb選項和它們的目前預設值。 返回值指向一個PQconninfoOption 結構的數組, 該數組以一個有 NULL keyword 指針的條目結束。注意預設值(val 域)將依賴於環境變量和其他環境。 調用者必須把連接選項當作只讀對待。

在處理完選項數組後,把數組交給PQconninfoFree()釋放。 如果沒有這麼做,每次調用PQconndefaults()都會有一小部分內存洩漏。

PQfinish

關閉與伺服器的連接。同時釋放被PGconn 對像使用的儲存器。

void PQfinish(PGconn *conn);

注意,即使與伺服器的連接嘗試失敗(可由PQstatus判斷), 應用也要調用PQfinish釋放被PGconn對像使用的儲存器。 不應該在調用PQfinish後再使用PGconn 指針。

PQreset

重置與伺服器的通訊連接埠。

void PQreset(PGconn *conn);

此函數將關閉與伺服器的連接並且試圖與同一個伺服器重建新的連接, 使用所有前面使用過的參數。這在失去工作連接後進行故障恢復時很有用。

PQresetStart
PQresetPoll

以非阻塞模式重置與伺服器的通訊連接埠。

int PQresetStart(PGconn *conn);

PostgreSQLPollingStatusType PQresetPoll(PGconn *conn);

此函數將關閉與伺服器的連接並且試圖與同一個伺服器重建新的連接, 使用所有前面使用過的參數。這在失去工作連接後進行故障恢復時很有用。 它們和上面的PQreset的區別是它們工作在非阻塞模式。 這些函數的使用有與上面PQconnectStartPQconnectPoll一樣的限制。

要發起一次連接重置,調用PQresetStart。如果它返回 0,那麼重置失敗。 如果返回 1,用與使用PQconnectPoll 建立連接的同樣的方法使用PQresetPoll重置連接。