




已閱讀5頁,還剩71頁未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
PostgreSQL數(shù)據(jù)庫學(xué)習(xí)手冊之libpq - C 庫-介紹(轉(zhuǎn))moreChapter 1. libpq - C 庫Table of Contents1.1. 介紹1.2. 數(shù)據(jù)庫聯(lián)接函數(shù)1.3. 命令執(zhí)行函數(shù)1.3.1. 主過程1.3.2. 為包含在 SQL 查詢中逃逸字串1.3.3. 逃逸包含在 SQL 查詢中的二進(jìn)制字串1.3.4. 檢索 SELECT 的結(jié)果信息1.3.5. 檢索 SELECT 結(jié)果數(shù)值1.3.6. 檢索非-SELECT 結(jié)果信息1.4. 異步查詢處理1.5. 捷徑接口1.6. 異步通知1.7. 與 COPY 命令相關(guān)的函數(shù)1.8. libpq 跟蹤函數(shù)1.9. libpq 控制函數(shù)1.10. 環(huán)境變量1.11. 文件1.12. 線程特性1.13. 制作 Libpq 程序1.14. 例子程序1.1. 介紹libpq 是 PostgreSQL的 C 應(yīng)用程序員的接口 libpq 是一套允許客戶程序向 PostgreSQL 后端服務(wù)進(jìn)程發(fā)送查詢 并且獲得查詢返回的庫過程 libpq 同時(shí)也是其他幾個(gè) PostgreSQL 應(yīng)用接口下面的引擎, 包括 libpq+ (C+), libpgtcl(Tcl),Perl,和 ecpg所以如果你使用這些軟件包, libpq某些方面的特性會(huì)對你非常重要本節(jié)末尾有三個(gè)小程序顯示如何利用 libpq書寫程序 在下面目錄里面有幾個(gè)完整的 libpq 應(yīng)用的例子:src/test/examplessrc/bin/psql使用 libpq 的前端程序必須包括頭文件 libpq-fe.h 并且必須與 libpq 庫鏈接PostgreSQL數(shù)據(jù)庫學(xué)習(xí)手冊之libpq-C庫-數(shù)據(jù)庫聯(lián)接函數(shù)(轉(zhuǎn))more1.2. 數(shù)據(jù)庫聯(lián)接函數(shù)下面的過程處理與 PostgreSQL 后端服務(wù)器聯(lián)接的事情 一個(gè)應(yīng)用程序一次可以與多個(gè)后端建立聯(lián)接 (這么做的原因之一是訪問多于一個(gè)數(shù)據(jù)庫) 每個(gè)連接都是用一個(gè)從PQconnectdb()或 PQsetdbLogin() 獲得的PGconn對象表示 注意,這些函數(shù)總是返回一個(gè)非空的對象指針, 除非存儲(chǔ)器少得連個(gè)PGconn對象都分配不出來 在把查詢發(fā)送給聯(lián)接對象之前,可以調(diào)用PQstatus 函數(shù)來檢查一下聯(lián)接是否成功*PQconnectdb 與后端數(shù)據(jù)庫服務(wù)器建立一個(gè)新的聯(lián)接PGconn *PQconnectdb(const char *conninfo)這個(gè)過程用從一個(gè)字符串 conninfo 來的參數(shù)與數(shù)據(jù)庫打開一個(gè)新的聯(lián)接 與下面的PQsetdbLogin()不同的是, 我們可以不必更換函數(shù)簽名(名字)就可以擴(kuò)展參數(shù)集, 所以我們建議應(yīng)用程序中使用這個(gè)函數(shù)或者是它的非阻塞的相似函數(shù) PQconnectStart 和 PQconnectPoll 傳入的參數(shù)可以為空,表明使用所有缺省的參數(shù), 或者可以包含一個(gè)或更多個(gè)用空白間隔的參數(shù)設(shè)置每個(gè)參數(shù)以 關(guān)鍵字 = 數(shù)值的形式設(shè)置 (要寫一個(gè)空值或者一個(gè)包含空白的值, 你可以用一對單引號包圍它們,例如, keyword = a value 數(shù)值內(nèi)部的單引號和反斜扛必須用一個(gè)反斜扛逃逸, 也就是說, 或) 等號周圍的空白是可選的目前可識別的參數(shù)鍵字是:host要聯(lián)接的主機(jī)(host ) 如果主機(jī)名以斜扛開頭, 則它聲明使用 Unix 域套接字通訊而不是 TCP/IP 通訊; 該值就是套接字文件所存儲(chǔ)的目錄 缺省時(shí)是與位于 /tmp 里面的 Unix-域套接字聯(lián)接 hostaddr與之聯(lián)接的主機(jī)的 IP 地址。這個(gè)可以是標(biāo)準(zhǔn)的數(shù)字-點(diǎn)的形式, 象在 BSD 函數(shù)inet_aton等里面用的那樣。 如果聲明了一個(gè)非零長的字符串,那么使用 TCP/IP 通訊機(jī)制。使用hostaddr取代 host 可以讓應(yīng)用避免一次主機(jī)名查找, 這一點(diǎn)對于那些有時(shí)間約束的應(yīng)用來說可能是非常重要的。 不過,Kerberos 認(rèn)證系統(tǒng)要求主機(jī)(host)名。因此,應(yīng)用下面的規(guī)則。 如果聲明了不帶hostaddr的 host 那么就強(qiáng)制進(jìn)行主機(jī)名查找。 如果聲明中沒有 host,hostaddr 的值給出遠(yuǎn)端的地址; 如果使用了 Kerberos, 將導(dǎo)致一次反向名字查詢。如果同時(shí)聲明了 host 和hostaddr, 除非使用了 Kerberos,否則將使用hostaddr的值作為遠(yuǎn)端地址; host 的值將被忽略,如果使用了 Kerberos,host 的值用于 Kerberos 認(rèn)證。 要注意如果傳遞給libpq的主機(jī)名(host) 不是地址hostaddr處的機(jī)器名,那么認(rèn)證很有可能失敗。如果主機(jī)名(host)和主機(jī)地址都沒有, 那么libpq將使用一個(gè)本地的 Unix 域套接字進(jìn)行通訊。 port主機(jī)服務(wù)器的端口號,或者在 Unix 域套接字聯(lián)接時(shí)的套接字?jǐn)U展文件名 dbname數(shù)據(jù)庫名 user要聯(lián)接的用戶名。 password如果后端要求口令認(rèn)證,所用的口令 connect_timeout給連接過程設(shè)置的時(shí)間范圍,以秒計(jì)。零或者不設(shè)置表示無窮。 options發(fā)給后端的跟蹤/調(diào)試選項(xiàng) tty文件或控制臺(tty),用于從后端的可選調(diào)試輸出 requiressl設(shè)為 1 要求與后端進(jìn)行 SSL 聯(lián)接如果服務(wù)器不支持 SSL, 那么Libpq將馬上拒絕聯(lián)接 設(shè)置為 0 (缺?。┡c服務(wù)器進(jìn)行協(xié)商 如果有任何沒有聲明的參數(shù),那么將檢查對應(yīng)的環(huán)境變量(參閱Section 1.10 小節(jié))。 如果環(huán)境變量也沒有設(shè)置,那么使用編譯時(shí)的硬代碼。 返回的值是一個(gè)指向代表與后端聯(lián)接的抽象 struct指針。*PQsetdbLogin 與后端數(shù)據(jù)庫服務(wù)器建立一個(gè)新的聯(lián)接PGconn *PQsetdbLogin(const char *pghost,const char *pgport,const char *pgoptions,const char *pgtty,const char *dbName,const char *login,const char *pwd)這個(gè)函數(shù)是 PQconnectdb 前身, 它有固定個(gè)數(shù)的參數(shù),但是有相同的功能。*PQsetdb 與后端數(shù)據(jù)庫服務(wù)器建立一個(gè)新的聯(lián)接PGconn *PQsetdb(char *pghost,char *pgport,char *pgoptions,char *pgtty,char *dbName)這是一個(gè)調(diào)用 PQsetdbLogin() 的宏,只是login和pwd參數(shù)用空(null )代替 提供這個(gè)函數(shù)主要是為了與老版本的程序兼容*PQconnectStart, PQconnectPoll 與數(shù)據(jù)庫服務(wù)器建立一次非阻塞的聯(lián)接。PGconn *PQconnectStart(const char *conninfo)PostgreSQLPollingStatusType PQconnectPoll(PGconn *conn)這兩個(gè)過程用于打開一個(gè)與數(shù)據(jù)庫服務(wù)器之間的非阻塞的聯(lián)接: 你的應(yīng)用的執(zhí)行線索在執(zhí)行它的時(shí)候不會(huì)因遠(yuǎn)端的 I/O 而阻塞。數(shù)據(jù)庫聯(lián)接是用從 conninfo字符串里取得的參數(shù)傳遞給 PQconnectStart進(jìn)行的。 這個(gè)字符串的格式與上面PQconnectdb里描述的一樣。PQconnectStart 和PQconnectPoll 都不會(huì)阻塞(進(jìn)程),不過有一些條件:o必須正確提供hostaddr和host 參數(shù)以確保不會(huì)發(fā)生正向或者反向的名字查找。 參閱上面PQconnectdb里的這些參數(shù)的文檔獲取細(xì)節(jié)。o如果你調(diào)用了PQtrace, 確保你跟蹤進(jìn)入的流對象不會(huì)阻塞。o你必須在調(diào)用PQconnectPoll之前確保 socket 處于正確的狀態(tài),象下面描述的那樣。 要開始(聯(lián)接),調(diào)用 conn=PQconnectStart(connection_info_string) 如果conn是NULL, 表明libpq無法分配一個(gè)新的 PGconn 結(jié)構(gòu)。 否則,返回一個(gè)有效的PGconn指針 (盡管還不一定代表一個(gè)與數(shù)據(jù)庫有效聯(lián)接)。 PQconnectStart 一返回,調(diào)用 status=PQstatus(conn)。 如果 status 等于CONNECTION_BAD, PQconnectStart 失敗。如果PQconnectStart成功了,下一個(gè)階段是輪詢 libpq, 這樣它就可以繼續(xù)進(jìn)行后繼的聯(lián)接動(dòng)作。 象這樣循環(huán):認(rèn)為一個(gè)聯(lián)接缺省時(shí)是不活躍的。 如果PQconnectPoll的最后一個(gè)返回是 PGRES_POLLING_ACTIVE,則認(rèn)為它是活躍的。 如果PQconnectPoll(conn)的最后一個(gè)返回是 PGRES_POLLING_READING,執(zhí)行一個(gè)對 PQsocket(conn)的讀select()。 如果最后一個(gè)返回是PGRES_POLLING_WRITING, 執(zhí)行一個(gè)對PQsocket(conn)的寫select()。 如果還要調(diào)用PQconnectPoll, 也就是調(diào)用完P(guān)QconnectStart之后, 把它當(dāng)作最后返回PGRES_POLLING_WRITING那樣對待。 如果select()顯示 socket 已經(jīng)準(zhǔn)備好, 那么認(rèn)為它是活躍的。如果認(rèn)為一個(gè)聯(lián)接是 活躍的, 再次調(diào)用PQconnectPoll(conn)。 如果這次調(diào)用返回PGRES_POLLING_FAILED, 聯(lián)接過程失敗,如果這次調(diào)用 返回PGRES_POLLING_OK,聯(lián)接成功。要注意上面用select()來確保一個(gè) socket 準(zhǔn)備好只是一個(gè)(近似)的例子; 還可以用其他方法,比如一個(gè)poll()調(diào)用,來代替 select。在聯(lián)接的任意時(shí)刻,我們都可以通過調(diào)用PQstatus 來檢查聯(lián)接的狀態(tài)。 如果這是CONNECTION_BAD, 那么聯(lián)接過程失?。蝗绻荂ONNECTION_OK, 那么聯(lián)接已經(jīng)做好。 這兩種狀態(tài)同樣也可以從上面的PQconnectPoll 的返回值里檢測到。 其他狀態(tài)可能(也只能)在一次異步聯(lián)接過程中看到。 這些標(biāo)識聯(lián)接過程 的當(dāng)前狀態(tài),因而可能對給用戶提供反饋有幫助。這些狀態(tài)可能包括:CONNECTION_STARTED等待進(jìn)行聯(lián)接。 CONNECTION_MADE聯(lián)接成功;等待發(fā)送。 CONNECTION_AWAITING_RESPONSE等待來自服務(wù)器的響應(yīng)。 CONNECTION_AUTH_OK已收到認(rèn)證;等待聯(lián)接啟動(dòng)繼續(xù)進(jìn)行。 CONNECTION_SETENV協(xié)商環(huán)境(聯(lián)接啟動(dòng)的一部分)。 注意,盡管這些常量將保持下去(為了維持兼容性), 應(yīng)用決不應(yīng)該依賴于這些常量的某種特定順序, 或者是根本不應(yīng)依賴于這些常量, 或者是不應(yīng)該依賴于這些狀態(tài)總是某個(gè)文檔聲明的值。 一個(gè)應(yīng)用可能象象下面這樣:switch(PQstatus(conn)case CONNECTION_STARTED:feedback = Connecting.;break;case CONNECTION_MADE:feedback = Connected to server.;break;.default:feedback = Connecting.;要注意如果PQconnectStart返回一個(gè)非空的指針, 你必須在使用完它(指針)之后調(diào)用PQfinish, 以處理那些結(jié)構(gòu)和所有相關(guān)的存儲(chǔ)塊。 甚至調(diào)用PQconnectStart或者 PQconnectPoll失敗時(shí)也要這樣處理。如果編譯libpq時(shí)定義了USE_SSL 那么目前的PQconnectPoll將阻塞住。 這個(gè)限制可能在將來的版本移除。這些函數(shù)把 socket 置于一個(gè)非阻塞的狀態(tài),就好象調(diào)用了 PQsetnonblocking 一樣。*PQconndefaults 返回缺省的聯(lián)接選項(xiàng)。PQconninfoOption *PQconndefaults(void)struct PQconninfoOptionchar *keyword; /* The keyword of the option */char *envvar; /* Fallback environment variable name */char *compiled; /* Fallback compiled in default value */char *val; /* Options current value, or NULL */char *label; /* Label for field in connect dialog */char *dispchar; /* Character to display for this fieldin a connect dialog. Values are: Display entered value as is* Password field - hide valueD Debug option - dont show by default */int dispsize; /* Field size in characters for dialog */返回聯(lián)接選項(xiàng)結(jié)構(gòu)的地址 可以用于獲取所有可能的PQconnectdb選項(xiàng)和它們的當(dāng)前缺省值 返回值指向一個(gè)PQconninfoOption struct 的數(shù)組, 該數(shù)組以一個(gè)有 NULL 關(guān)鍵字指針的條目結(jié)束注意缺省值(val 域)將 依賴于環(huán)境變量和其他上下文調(diào)用者必須把聯(lián)接選項(xiàng)當(dāng)作只讀對待在處理完選項(xiàng)數(shù)組后,把數(shù)組交給PQconninfoFree()釋放 如果沒有這么做,每次調(diào)用PQconndefaults() 都會(huì)有一小部分內(nèi)存泄漏在PostgreSQL7.0 以前的版本, PQconndefaults() 返回一個(gè)指向靜態(tài)數(shù)組的指針, 而不是一個(gè)動(dòng)態(tài)分配的數(shù)組這樣做是線程不安全的,因此這個(gè)特點(diǎn)被修改了*PQfinish 關(guān)閉與后端的聯(lián)接同時(shí)釋放被PGconn 對象使用的存儲(chǔ)器void PQfinish(PGconn *conn)注意,即使與后端的聯(lián)接嘗試失?。捎蒔Qstatus判斷), 應(yīng)用也要調(diào)用PQfinish釋放被PGconn 對象使用的存儲(chǔ)器不應(yīng)該在調(diào)用 PQfinish后再使用PGconn 指針*PQreset 重置與后端的通訊端口void PQreset(PGconn *conn)此函數(shù)將關(guān)閉與后端的聯(lián)接并且試圖與同一個(gè)服務(wù)器重建新的聯(lián)接, 使用所有前面使用過的參數(shù)這在 失去工作聯(lián)接后進(jìn)行故障恢復(fù)時(shí)很有用*PQresetStart PQresetPoll 以非阻塞模式重置與后端的通訊端口。int PQresetStart(PGconn *conn);PostgreSQLPollingStatusType PQresetPoll(PGconn *conn);此函數(shù)將關(guān)閉與后端的聯(lián)接并且試圖與同一個(gè)服務(wù)器重建新的聯(lián)接, 使用所有前面使用過的參數(shù)這在 失去工作聯(lián)接后進(jìn)行故障恢復(fù)時(shí)很有用 它們和上面的PQreset的區(qū)別是它們工作在非阻塞模式。 這些函數(shù)的使用有與上面PQconnectStart和 PQconnectPoll一樣的限制。調(diào)用PQresetStart。如果它返回 0,那么重置失敗。 如果返回 1,用與使用PQconnectPoll 建立聯(lián)接的同樣的 方法使用PQresetPoll重置聯(lián)接。 libpq應(yīng)用程序員應(yīng)該仔細(xì)維護(hù)PGconn結(jié)構(gòu)使用下面的訪問函數(shù)來獲取PGconn的內(nèi)容避免直接引用PGconn結(jié)構(gòu)里的字段,因?yàn)檫@些字段在今后可能被改變(從 PostgreSQL 版本 6.4 開始, struct PGconn的定義甚至沒有放在 libpq-fe.h里如果你有一些直接訪問PGconn數(shù)據(jù)域的舊代碼,你可以通過包含 libpq-int.h 來訪問它們,但我們鼓勵(lì)你趕快修改那些代碼)*PQdb 返回聯(lián)接的數(shù)據(jù)庫名char *PQdb(const PGconn *conn)PQdb 和下面幾個(gè)函數(shù)返回聯(lián)接時(shí)建立起來的幾個(gè)值這些值在PGconn對象的生存期內(nèi)是固定的*PQuser 返回聯(lián)接的用戶名char *PQuser(const PGconn *conn)*PQpass 返回聯(lián)接的口令char *PQpass(const PGconn *conn)*PQhost 返回聯(lián)接的服務(wù)器主機(jī)名char *PQhost(const PGconn *conn)*PQport 返回聯(lián)接的端口號char *PQport(const PGconn *conn)*PQtty 返回聯(lián)接的調(diào)試控制臺( tty )char *PQtty(const PGconn *conn)*PQoptions 返回聯(lián)接中使用的后端選項(xiàng)char *PQoptions(const PGconn *conn)*PQstatus 返回聯(lián)接的狀態(tài)ConnStatusType PQstatus(const PGconn *conn)這個(gè)狀態(tài)可以是一些值之一。 不過,如果不是一次異步聯(lián)接過程的話,我們只能看到其中的兩個(gè) - CONNECTION_OK 或 CONNECTION_BAD。一個(gè)與數(shù)據(jù)庫的成功的聯(lián)接返回狀態(tài) CONNECTION_OK。 一次失敗的企圖用狀態(tài) CONNECTION_BAD 標(biāo)識。 通常,一個(gè) OK 狀態(tài)保持到 PQfinish,但是一個(gè)通訊失敗可能會(huì)導(dǎo)致狀態(tài)過早地改變?yōu)?CONNECTION_BAD 。這時(shí)應(yīng)用可以試著調(diào)用 PQreset 來恢復(fù)參閱PQconnectStart和PQconnectPoll 條目看看可能出現(xiàn)的其他的狀態(tài)碼。*PQerrorMessage 返回聯(lián)接中操作產(chǎn)生的最近的錯(cuò)誤信息char *PQerrorMessage(const PGconn* conn);幾乎所有l(wèi)ibpq函數(shù)在失敗時(shí)都會(huì)設(shè)置 PQerrorMessage注意libpq的傳統(tǒng)是, 一個(gè)非空的 PQerrorMessage 將在結(jié)尾包含一個(gè)新行*PQbackendPID 返回控制此聯(lián)接的后端服務(wù)器的進(jìn)程號ID。int PQbackendPID(const PGconn *conn);這個(gè)后端PID 在調(diào)試和對比 NOTIFY 信息( 包含發(fā)出通知的后端的 PID )時(shí)很有用 注意該 PID 屬于運(yùn)行數(shù)據(jù)庫服務(wù)器的主機(jī)的進(jìn)程, 而不是本地主機(jī)!*PQgetssl 返回聯(lián)接使用的 SSL 結(jié)構(gòu),或者如果 SSL 沒有使用的話返回 NULLSSL *PQgetssl(const PGconn *conn);這個(gè)結(jié)構(gòu)可以用于核實(shí)加密級別,檢查服務(wù)器認(rèn)證等信息參考 SSL 文檔獲取關(guān)于這個(gè)結(jié)構(gòu)的更多信息為了獲取這個(gè)函數(shù)的原形,你必須定義 USE_SSL 這樣做會(huì)自動(dòng)包含來自O(shè)penSSL的 ssl.h PostgreSQL數(shù)據(jù)庫學(xué)習(xí)手冊之libpq-C庫-命令執(zhí)行函數(shù)(轉(zhuǎn))more1.3. 命令執(zhí)行函數(shù)一旦與數(shù)據(jù)庫服務(wù)器的聯(lián)接成功建立,便可用這里描述的函數(shù)執(zhí)行 SQL 查詢和命令。1.3.1. 主過程*PQexec 給服務(wù)器提交一條命令并且等待結(jié)果PGresult *PQexec(PGconn *conn,const char *query);返回一個(gè)PGresult指針或者也可能是一個(gè) NULL 指針 通常返回一個(gè)非空(non-NULL)的指針, 除非沒有內(nèi)存或發(fā)生了象不能把命令發(fā)送到后端這樣的嚴(yán)重錯(cuò)誤 如果返回的是 NULL,它應(yīng)該被當(dāng)作PGRES_FATAL_ERROR結(jié)果處理 用PQerrorMessage獲取有關(guān)錯(cuò)誤的更多信息PGresult 結(jié)構(gòu)封裝了后端返回的結(jié)果 libpq 應(yīng)用程序員應(yīng)該仔細(xì)維護(hù)PGresult抽象用下面的訪問函數(shù)來獲取PGresult的內(nèi)容避免直接引用 PGresult結(jié)構(gòu)的數(shù)據(jù)域,因?yàn)檫@個(gè)結(jié)構(gòu)可能會(huì)在未來被改變(從 PostgreSQL 版本 6.4 開始, struct PGresult的定義甚至都沒有放在 libpq-fe.h里如果你有一些直接訪問 PGresult數(shù)據(jù)域的老代碼,你可以通過包含libpq-int.h繼續(xù)使用它們,但是我們鼓勵(lì)你立刻修改代碼)*PQresultStatus 返回命令的結(jié)果狀態(tài)ExecStatusType PQresultStatus(const PGresult *res)PQresultStatus可以返回下面數(shù)值之一:oPGRES_EMPTY_QUERY - 發(fā)送給后端的字串是空的oPGRES_COMMAND_OK - 成功完成一個(gè)沒有返回?cái)?shù)據(jù)的命令oPGRES_TUPLES_OK - 成功執(zhí)行查詢oPGRES_COPY_OUT - (從服務(wù)器)Copy Out (拷貝出)數(shù)據(jù)傳輸開始o(jì)PGRES_COPY_IN - Copy In (拷貝入)(到服務(wù)器)數(shù)據(jù)傳輸開始o(jì)PGRES_BAD_RESPONSE - 服務(wù)器的響應(yīng)無法理解oPGRES_NONFATAL_ERRORoPGRES_FATAL_ERROR如果結(jié)果狀態(tài)是 PGRES_TUPLES_OK ,那么可以用下面的過程從查詢的返回中抽取元組信息注意一個(gè)碰巧檢索了零條元組的 SELECT 仍然顯示 PGRES_TUPLES_OK。 PGRES_COMMAND_OK用于不返回元組的命令(INSERT,UPDATE,等)。返回 PGRES_EMPTY_QUERY 的響應(yīng)通常意味著客戶端軟件里面的臭蟲。*PQresStatus 把PQresultStatus返回的枚舉類型轉(zhuǎn)換成一個(gè)描述狀態(tài)碼的字符串常量。char *PQresStatus(ExecStatusType status);*PQresultErrorMessage 返回與查詢關(guān)聯(lián)的錯(cuò)誤信息,或在沒有錯(cuò)誤時(shí)返回一個(gè)空字符串char *PQresultErrorMessage(const PGresult *res);緊跟在一個(gè) PQexec 或 PQgetResult 調(diào)用后面,PQerrorMessage (對聯(lián)接)將返回與 PQresultErrorMessage (對結(jié)果)一樣的字符串不過,一個(gè)PGresult將保有其錯(cuò)誤信息直到被刪除,而連結(jié)的錯(cuò)誤信息將在后續(xù)的操作完成時(shí)被改變當(dāng)你想知道與某個(gè) PGresult相關(guān)聯(lián)的狀態(tài)時(shí)用 PQresultErrorMessage ;當(dāng)你想知道與聯(lián)接的最近一個(gè)操作相關(guān)聯(lián)的狀態(tài)時(shí)用 PQerrorMessage;*PQclear 釋放于PGresult相關(guān)聯(lián)的存儲(chǔ)空間 任何不再需要的查詢結(jié)果在不需要的時(shí)候都應(yīng)該用 PQclear釋放掉void PQclear(PQresult *res);你可以保留PGresult對象任意長的時(shí)間; 當(dāng)你提交新的查詢時(shí)它并不消失, 甚至你斷開聯(lián)接后也是這樣要?jiǎng)h除它,你必須調(diào)用 PQclear不這么做將導(dǎo)致前端的存儲(chǔ)器泄漏*PQmakeEmptyPGresult 構(gòu)造一個(gè)給出狀態(tài)的為空的PGresult對象PGresult* PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status);這是libpq的內(nèi)部過程, 用于分配和初始化一個(gè)空PGresult對象 它被輸出是因?yàn)橐恍?yīng)用需要自行生成結(jié) 果對象(尤其是特定的帶有錯(cuò)誤狀態(tài)的對象) 如果conn非空(NULL)并且狀態(tài)指示一個(gè)錯(cuò)誤, 聯(lián)接當(dāng)前的錯(cuò)誤信息被拷貝到PGresult 注意最終對該對象要調(diào)用PQclear, 正如libpq本身返回的PGresult一樣1.3.2. 為包含在 SQL 查詢中逃逸字串PQescapeString 為在 SQL 查詢中使用逃逸一個(gè)字串size_t PQescapeString (char *to, const char *from, size_t length);如果你需要在查詢字串中包含一個(gè)從不可靠的源頭接收的字串 (比如,它們是隨機(jī)用戶輸入的),那么,出于安全原因,你不能把它們直接包含在 SQL 查詢里你應(yīng)該把特殊字符引起來,否則它們就會(huì)被 SQL 分析器代換PQescapeString 執(zhí)行這個(gè)操作from 指向?qū)⒁右莸淖执牡谝粋€(gè)字符,length 參數(shù)計(jì)算在這個(gè)字串里的字符數(shù)量(字串結(jié)尾的字節(jié)零不是必須的,也不計(jì)入長度) to 應(yīng)該指向一個(gè)緩沖區(qū),這個(gè)緩沖區(qū)至少能保存 length 數(shù)值的兩倍還多一個(gè)的字符,否則該函數(shù)行為將不可預(yù)測調(diào)用 PQescapeString 就會(huì)把逃逸的 from 字串轉(zhuǎn)換到 to 緩沖區(qū),把特殊字符替換掉以免發(fā)生意外,并且追加終止的字節(jié)零那些必須包圍在PostgreSQL 字串文本周圍的單引號不算結(jié)果字串的一部分PQescapeString 返回寫到 to 里面的字符數(shù)目,不包括結(jié)尾的字節(jié)零如果 to 和 from 字串相互重疊,那么其行為不可預(yù)測1.3.3. 逃逸包含在 SQL 查詢中的二進(jìn)制字串PQescapeBytea 逃逸那些在 SQL 查詢中使用二進(jìn)制字串(bytea 類型)unsigned char *PQescapeBytea(const unsigned char *from,size_t from_length,size_t *to_length);在 SQL 語句中用做 BYTEA 字串文本的 一部分的時(shí)候, 有些 ASCII 字符必需被逃逸 (但是對于所有字符而言是可以逃逸) 通常,要逃逸一個(gè)字符,它是被轉(zhuǎn)換成一個(gè)三位八進(jìn)制數(shù)字, 該數(shù)字?jǐn)?shù)值等于相應(yīng)的十進(jìn)制 ASCII 數(shù)值,然后前綴 兩個(gè)反斜扛單引號()和反斜扛字符()有自己特殊的逃逸序列參閱 用戶手冊獲取更多信息 PQescapeBytea 執(zhí)行這個(gè)操作,它只逃逸需要逃逸 的最少的字符from 參數(shù)指向需要逃逸的字串的第一個(gè)字符, from_length 參數(shù)反映在這個(gè)二進(jìn)制字串 (那種字節(jié)零既不必要也不計(jì)算在內(nèi)的字串)里字符的個(gè)數(shù) to_length 參數(shù)應(yīng)該是一個(gè)指向某個(gè)緩沖區(qū)的指針, 它的空間應(yīng)該能夠保存逃逸后的結(jié)果字串長度. 結(jié)果字串長度不包括結(jié)果結(jié)尾的字節(jié)零PQescapeBytea 返回一個(gè) from 參數(shù)的二進(jìn)制字串的逃逸后的版本,返回給調(diào)用者提供的緩沖區(qū) 返回的字串已經(jīng)把所有特殊的字符替換調(diào)了,這樣他們就可以由 PostgreSQL的字串文本分析器以及 bytea 的輸入函數(shù) 正確地處理同時(shí)還追加了一個(gè)結(jié)尾的字節(jié)零那些必需包圍在 PostgreSQL字串文本周圍的單引號不算結(jié)果字串的一部分PQunescapeBytea 把一個(gè)二進(jìn)制數(shù)據(jù)的逃逸后的字串表現(xiàn)形式轉(zhuǎn)換成二進(jìn)制數(shù)據(jù) - PQescapeBytea 的反作用unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length);from 參數(shù)指向一個(gè)逃逸后的字串, 比如 PQgetvalue 從一個(gè) BYTEA 字段返回的PQunescapeBytea 把 它的字串表現(xiàn)形式轉(zhuǎn)換成二進(jìn)制形式,填充到一個(gè)緩沖區(qū) 它返回一個(gè)指向該緩沖區(qū)的指針,若為 NULL 則出錯(cuò), 緩沖區(qū)的尺寸放在 to_length 里 該指針隨后可以用做 free(3) 的參數(shù)1.3.4. 檢索 SELECT 的結(jié)果信息*PQntuples 返回查詢結(jié)果里的元組(元組)個(gè)數(shù)int PQntuples(const PGresult *res);*PQnfields 返回查詢結(jié)果里每個(gè)元組的數(shù)據(jù)域(字段)的個(gè)數(shù)int PQnfields(const PGresult *res);*PQfname 返回與給出的數(shù)據(jù)域編號相關(guān)聯(lián)的數(shù)據(jù)域(字段)的名稱數(shù)據(jù)域編號從 0 開始char *PQfname(const PGresult *res,int field_index);*PQfnumber 返回與給出的數(shù)據(jù)域名稱相關(guān)聯(lián)的數(shù)據(jù)域(字段)的編號int PQfnumber(const PGresult *res,const char *field_name);如果給出的名字不匹配任何域,返回-1*PQftype 返回與給定數(shù)據(jù)域編號關(guān)聯(lián)的數(shù)據(jù)域類型 整數(shù)返回值是一個(gè)該類型的內(nèi)部編碼數(shù)據(jù)域編號從0 開始Oid PQftype(const PGresult *res,int field_index);你可以查詢系統(tǒng)表 pg_type 以獲取各種數(shù)據(jù)類型的名稱和屬性。內(nèi)建的數(shù)據(jù)類型的 OID 在源碼樹的 src/include/catalog/pg_type.h 文件里定義。*PQfmod 返回與給定數(shù)據(jù)域編號相關(guān)聯(lián)的類型相關(guān)的修正數(shù)據(jù)(?) 數(shù)據(jù)域編號從 0 開始int PQfmod(const PGresult *res,int field_index);*PQfsize 返回一個(gè)PGresult 里面的一條元組的單獨(dú)的一個(gè)數(shù)據(jù)域(字段)的值 元組和數(shù)據(jù)域編號從0 開始int PQfsize(const PGresult *res,int field_index);PQfsize返回在數(shù)據(jù)庫元組里面給該數(shù)據(jù)域分配的空間, 換句話說就是該數(shù)據(jù)類型在服務(wù)器里的二進(jìn)制形式的大?。ǔ叽纾?如果該數(shù)據(jù)域是可變尺寸,返回 -1*PQbinaryTuples 如果PGresult包含二進(jìn)制元組數(shù)據(jù)時(shí)返回 1, 如果包含 ASCII 數(shù)據(jù)返回 0int PQbinaryTuples(const PGresult *res);目前,二進(jìn)制元組數(shù)據(jù)只能從一個(gè)二進(jìn)制游標(biāo)里抽取數(shù)據(jù)的查詢返回1.3.5. 檢索 SELECT 結(jié)果數(shù)值*PQgetvalue 返回一個(gè)PGresult 里面一個(gè)元組單獨(dú)的一個(gè)數(shù)據(jù)域(字段)的值 元組和數(shù)據(jù)域編號從 0 開始char* PQgetvalue(const PGresult *res,int tup_num,int field_num);對大多數(shù)查詢而言, PQgetvalue 返回的值是一個(gè)表示字段值的空(NULL)結(jié)尾的字符串但是如果 PQbinaryTuples() 為 1, PQgetvalue 返回的值就是該類型在后端服務(wù)器內(nèi)部的二進(jìn)制表現(xiàn)形式(但是不包括尺寸字如果數(shù)據(jù)域是變長的)這樣,把數(shù)據(jù)轉(zhuǎn)換成對應(yīng)的 C 類型就是程序員的責(zé)任了 PQgetvalue 返回的指針指向一個(gè)本身是 PGresult結(jié)構(gòu)的一部分的存儲(chǔ)區(qū)域我們不能更改它,并且如果 我們要在PGresult結(jié)構(gòu)的生存期后還要使用它的話, 我們必須明確地把該數(shù)值拷貝到其他存儲(chǔ)器中*PQgetisnull 測試一個(gè)數(shù)據(jù)域是否為空(NULL)元組和數(shù)據(jù)域編號從 0 開始int PQgetisnull(const PGresult *res,int tup_num,int field_num);如果該域包含 NULL,函數(shù)返回 1,如果包含非空(non-null )值,返回 0 (注意,對一個(gè) NULL 數(shù)據(jù)域,PQgetvalue 將返回一個(gè)空字符串, 不是一個(gè)空指針)*PQgetlength 返回以字節(jié)計(jì)的數(shù)據(jù)域(字段)的長度元組和數(shù)據(jù)域編號從 0 開始int PQgetlength(const PGresult *res,int tup_num,int field_num);這是某一特定數(shù)據(jù)值的實(shí)際數(shù)據(jù)長度,也就是由PQgetvalue 指向的對象的尺寸注意,對于 ASCII 表示的數(shù)值,這個(gè)尺寸與PQfsize 報(bào)告的二進(jìn)制尺寸無關(guān)*PQprint 向指定的輸出流打印所有的元組和(可選的)字段名稱void PQprint(FILE* fout, /* output stream */const PGresult *res,const PQprintOpt *po);struct pqbool header; /* print output field headings and row count */pqbool align; /* fill align the fields */pqbool standard; /* old brain dead format */pqbool html3; /* output html tables */pqbool expanded; /* expand tables */pqbool pager; /* use pager for output if needed */char *fieldSep; /* field separator */char *tableOpt; /* insert to HTML table . */char *caption; /* HTML caption */char *fieldName; /* null terminated array of replacement field names */ PQprintOpt;這個(gè)函數(shù)以前被 psql 用于打印查詢結(jié)果,但是現(xiàn)在已經(jīng)不用這個(gè)函數(shù)了,并且此函數(shù)不再有活躍的支持。1.3.6. 檢索非-SELECT 結(jié)果信息*PQcmdStatus 返回產(chǎn)生PGresult的 SQL 命令的命令狀態(tài)字符串char * PQcmdStatus(PGresult *res);*PQcmdTuples 返回被 SQL 命令影響的行的數(shù)量char * PQcmdTuples(PGresult *res);如果產(chǎn)生PGresult的SQL 命令是 INSERT, UPDATE 或 DELETE, 這里返回涉及行的行數(shù)如果是其他命令返回一個(gè)空字符串*PQoidValue 返回一個(gè)插入的元組的對象標(biāo)識(OID)如果 SQL 命令是 INSERT否則,返回 InvalidOidOid PQoidValue(const PGresult *res);如果你包含了 libpq頭文件,那么 Oid 和常量 InvalidOid 的類型將被定義。他們都是某種整型類型。*PQoidStatus 返回一個(gè)被插入的元組的對象標(biāo)識的字串, 如果 SQL 命令是 INSERT。 否則. 返回一個(gè)空字串。char * PQoidStatus(const PGresult *res);因?yàn)橛辛?PQoidValue ,我們不建議使用這個(gè)函數(shù),而且它在線程里使用也是不安全的 PostgreSQL數(shù)據(jù)庫學(xué)習(xí)手冊之libpq-C庫-異步查詢處理(轉(zhuǎn))more1.4. 異步查詢處理PQexec 函數(shù)對簡單的同步應(yīng)用里提交命令已經(jīng)是足夠用的了但是它卻有幾個(gè)主要的缺陷:*PQexec 等待命令結(jié)束應(yīng)用可能有其他工作要做(例如維護(hù)用戶界面),這時(shí)它可不希望阻塞在這里等待返回*因?yàn)榭刂剖遣卦?PQexec內(nèi)部,前端很難取消掉正進(jìn)行著的命令(可以通過信號控制器進(jìn)行,但沒有別的方法)*PQexec 只能返回一個(gè)PGresult結(jié)構(gòu)如果提交的命令字符串包含多個(gè) SQL 命令,除了最后一個(gè)PGresult以外都會(huì)被 PQexec 丟棄。不想受到這些限制的應(yīng)用可以改用下面的函數(shù),這些函數(shù)也是構(gòu)造 PQexec 的函數(shù): PQsendQuery 和 PQgetResult。使用這些(異步)功能以及 PQputline 和 PQputnbytes 的老一些的程序可能在等待數(shù)據(jù)發(fā)送給后端時(shí)阻塞住,為解決這樣的問題,增加了函數(shù) PQsetnonblocking舊應(yīng)用可以忽略 PQsetnonblocking 的使用,維持原有的阻塞特征。新的程序可以利用 PQsetnonblocking 獲得與后端完全非阻塞的聯(lián)接。*PQsetnonblocking 把該聯(lián)接的狀態(tài)設(shè)置為非阻塞。int PQsetnonblocking(PGconn *conn, int arg)如果arg為 TRUE,把聯(lián)接狀態(tài)設(shè)置為非阻塞, 如果arg為 FALSE, 把聯(lián)接狀態(tài)設(shè)置為阻塞如果 OK 返回 0,如果錯(cuò)誤返回 -1 此函數(shù)將確保對在非阻塞狀態(tài),調(diào)用 PQputline,PQputnbytes, PQsendQuery 和 PQendcopy 的時(shí)候不被阻塞, 而是如果需要再次它們時(shí)將是返回一個(gè)錯(cuò)誤(而不是阻塞)。當(dāng)把一個(gè)數(shù)據(jù)庫的聯(lián)接設(shè)置為非阻塞的模式并且調(diào)用了 PQexec,它將暫時(shí)把聯(lián)接狀態(tài)設(shè)置為阻塞模式直到 PQexec 完成。在不久的將來將有更多的libpq會(huì)設(shè)計(jì)成在 PQsetnonblocking 方式下是安全的。*PQisnonblocking 返回?cái)?shù)據(jù)庫聯(lián)接的阻塞狀態(tài)。int PQisnonblocking(const PGconn *conn)如果聯(lián)接設(shè)置為非阻塞狀態(tài),返回 1,如果是阻塞狀態(tài)返回 0。*PQsendQuery 向服務(wù)器提交一個(gè)命令而不等待結(jié)果 如果查詢成功發(fā)送則返回 1,否則返回 0此時(shí),可以用PQerrorMessage 獲取關(guān)于失敗的信息)int PQsendQuery(PGconn *conn,const char *query);在成功調(diào)用 PQsendQuery后,調(diào)用 PQgetResult 一次或者多次獲取結(jié)果 可以不再調(diào)用PQsendQuery (在同一次聯(lián)接里) 直到 PQgetResult 返回 NULL,表明命令完成*PQgetResult 等待從前面 PQsendQuery 調(diào)用返回的下一個(gè)結(jié)果, 然后返回之當(dāng)查詢結(jié)束并且沒有更多結(jié)果后返回 NULLPGresult *PQgetResult(PGconn *conn);必須重復(fù)的調(diào)用 PQgetResult ,直到它返回 NULL, 表明該命令結(jié)束(如果在沒有活躍的命令時(shí)調(diào)用, PQgetResult 將只是立即返回 NULL) 每個(gè) PQgetResult 返回的非 NULL 結(jié)果都應(yīng)該用前面 描述的 PGresult 訪問函數(shù)進(jìn)行分析 不要忘了在結(jié)束分析后用 PQclear 釋放每個(gè)結(jié)果對象 注意, PQgetResult 只是在有查詢激活而且必須的返回?cái)?shù)據(jù)還沒有被 PQconsumeInput 讀取時(shí)阻塞使用 PQsendQuery 和 PQgetResult 解決了 PQexec的一個(gè)問題:如果一個(gè)命令字符串包含多個(gè) SQL 命令,這些命令的結(jié)果可以獨(dú)立的獲得(順便說一句:這樣就允許一種簡單的重疊處理模式,前端可以處理一個(gè)查詢的結(jié)果而后端可以仍然在處理同一命令字符串的后面的查詢)但是,調(diào)用 PQgetResult 將仍然導(dǎo)致前端被阻塞住直到后端完成下一個(gè) SQL 命令這一點(diǎn)可以通過合理的使用下面三個(gè)函數(shù)來避免:*PQconsumeInput 如果存在后端來的輸入可用,則使用之int PQconsumeInput(PGconn *conn);PQconsumeInput 通常返回 1 表明沒有錯(cuò)誤,而返回 0 表明有某種錯(cuò)誤發(fā)生, (同時(shí)設(shè)置 PQerrorMessage)注意這個(gè)結(jié)果并不表明實(shí)際上是否收集了數(shù)據(jù)在調(diào)用 PQconsumeInput之后,應(yīng)用可以檢查 PQisBusy 和/或 PQnotifies 看一眼它們的狀態(tài)是否改變PQconsumeInput 可以在應(yīng)用還沒有做好處理結(jié)果或通知的情況下被調(diào)用這個(gè)過程將讀取可用的數(shù)據(jù)并且在一個(gè)緩沖區(qū)里保存它,這樣導(dǎo)致一個(gè) select() 讀準(zhǔn)備好標(biāo)識的生成這樣應(yīng)用就可以使用 PQconsumeInput 立即清掉 select() 條件,然后在空閑的時(shí)候檢查結(jié)果*PQisBusy 在查詢忙的時(shí)候返回 1 ,也就是說, PQgetResult 將阻塞住等待輸入一個(gè) 0 的返回表明這時(shí)調(diào)用 PQgetResult 可以確保不阻塞int PQisBusy(PGconn *conn);PQisBusy 本身將不會(huì)試圖從后端讀取數(shù)據(jù);所以必須先調(diào)用 PQconsumeInput ,否則忙狀態(tài)將永遠(yuǎn)不會(huì)消除*PQflush 試圖把任何正在排隊(duì)的數(shù)據(jù)沖刷到后端,如果成功(或者發(fā)送隊(duì)列為空)返回 0,如果因某種原因失敗返回EOF。int PQflush(PGconn *conn);在一個(gè)非阻塞的聯(lián)接調(diào)用 select() 判斷是否有響應(yīng)到達(dá)之前需要調(diào)用一個(gè) PQflush 。如果返回 0 則保證了與后端的發(fā)送隊(duì)列里面沒有待發(fā)送的數(shù)據(jù)。只有使用了 PQsetnonblocking 的應(yīng)用需要這個(gè)。*PQsocket 獲取用于后端聯(lián)接套接字的文件描述符號 一個(gè)有效的描述符應(yīng)該是 = 0;一個(gè) -1 表明當(dāng)前沒有打開與后端的聯(lián)接int PQsocket(const PGconn *conn);PQsocket 應(yīng)該用于獲取準(zhǔn)備調(diào)用 select() 的后端套接字描述符這就允許一個(gè)應(yīng)用使用阻塞的聯(lián)接等待后端的響應(yīng)或者其他條件如果 select() 的結(jié)果表明可以從后端套接字讀取數(shù)據(jù),那么應(yīng)該調(diào)用 PQconsumeInput 讀取數(shù)據(jù);之后,P
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年農(nóng)業(yè)品牌建設(shè)與推廣策略研究報(bào)告001
- 眼科手術(shù)室相關(guān)課件
- 醫(yī)療輔助型教育機(jī)器人推動(dòng)醫(yī)療領(lǐng)域的發(fā)展與創(chuàng)新
- 教育心理學(xué)視角下的家長溝通藝術(shù)
- 南京審計(jì)大學(xué)《釀造工藝學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 創(chuàng)新教育模式下的技術(shù)培訓(xùn)與教學(xué)實(shí)踐
- 教育數(shù)據(jù)化在決策中的應(yīng)用分析
- 2024年度浙江省三支一扶之三支一扶行測自我提分評估(附答案)
- 2024年度浙江省三支一扶之公共基礎(chǔ)知識押題練習(xí)試卷A卷附答案
- 2024年度河南省護(hù)師類之社區(qū)護(hù)理主管護(hù)師考試題庫
- SOR-04-014-00 藥品受托生產(chǎn)企業(yè)審計(jì)評估報(bào)告模板
- 2024至2030年中國中試基地行業(yè)發(fā)展形勢及前景規(guī)劃分析報(bào)告
- 小孩辦身份證的委托書范本
- 《凈水絮凝劑》課件
- Linux網(wǎng)絡(luò)操作系統(tǒng)項(xiàng)目化教程 課件 項(xiàng)目1-6 安裝Linux操作系統(tǒng)- 管理進(jìn)程
- 污水處理廠安全風(fēng)險(xiǎn)分級管控體系方案1
- 珠寶行業(yè)代賣合作協(xié)議書
- (高清版)JGT 225-2020 預(yù)應(yīng)力混凝土用金屬波紋管
- 中國地理(廣州大學(xué))智慧樹知到期末考試答案章節(jié)答案2024年廣州大學(xué)
- 自然辯證法-2018版課后思考題答案
- (正式版)JBT 5300-2024 工業(yè)用閥門材料 選用指南
評論
0/150
提交評論