struct PQconninfoOption { char *keyword; /* The keyword of the option */ char *envvar; /* Fallback environment variable name */ char *compiled; /* Fallback compiled in default value */ char *val; /* Option's current value, or NULL */ char *label; /* Label for field in connect dialog */ char *dispchar; /* Character to display for this field in a connect dialog. Values are: "" Display entered value as is "*" Password field - hide value "D" Debug option - don't show by default */ int dispsize; /* Field size in characters for dialog */ } 返回聯接選項結構的地址.可以用于獲取所有可能的 PQconnectdb 選項和它們的當前缺省值.返回值指向一個 PQconninfoOption 結構數組,該數組以一個有 NULL 關鍵字指針的入口結束.注意缺省值("val" 域)將依賴于環境變量和其他上下文.調用者必須把聯接選項當作只讀對待. 在處理完選項數組后,把數組交給 PQconninfoFree() 釋放.如果沒有這么做,每次調用 PQconndefaults() 都會有一小部分內存泄漏.
int PQntuples(const PGresult *res); PQnfields 返回查詢結果里每個記錄的數據域(字段)的個數. int PQnfields(const PGresult *res); PQbinaryTuples 如果 PGresult 包含二進制記錄數據時返回 1,如果包含 ASCII 數據返回 0. int PQbinaryTuples(const PGresult *res); 目前,二進制記錄數據只能從一個從 BINARY 游標里抽取數據的查詢返回. PQfname 返回與給出的數據域索引相關聯的數據域(字段)的名稱.數據域索引從 0 開始
char *PQfname(const PGresult *res, int field_index); PQfnumber Returns the field (attribute) index associated with the given field name. int PQfnumber(const PGresult *res, const char *field_name); -1 is returned if the given name does not match any field. PQftype 返回與給定數據域索引關聯的數據域類型.整數返回值是一個該類型的內部編碼.數據域索引從 0 開始.
Oid PQftype(const PGresult *res, int field_num); 你可以查詢系統表 pg_type 以獲取各種數據類型的名稱和屬性。內建的數據類型的OID 在源碼樹的 src/include/catalog/pg_type.h 文件里定義。 PQfsize 返回與給定數據域索引關聯的數據域的大小.數據域索引從 0 開始.
int PQfsize(const PGresult *res, int field_index); PQfsize 返回在數據庫記錄里面給該數據域分配的空間,換句話說就是該數據類型在服務器里的二進制形式的大小(尺寸).如果該數據域是可變尺寸,返回 -1. PQfmod 返回與給定數據域索引相關聯的類型相關的修正數據(??).數據域索引從 0 開始.
int PQfmod(const PGresult *res, int field_index); PQgetvalue 返回一個 PGresult 里面的一條記錄的單獨的一個數據域(字段)的值.記錄和數據域索引從 0 開始. char* PQgetvalue(const PGresult *res, int tup_num, int field_num); 對大多數查詢而言,PQgetvalue 返回的值是一個表示字段值的空(NULL)結尾的ASCII 字符串.但是如果 PQbinaryTuples() 為 1,PQgetvalue 返回的值就是該類型在后端服務器內部的二進制表現形式(但是不包括尺寸字--如果數據域是變長的).這樣,把數據轉換成對應的 C 類型就是程序員的責任了.PQgetvalue 返回的指針指向一個本身是 PGresult 結構的一部分的存儲區域.我們不能更改它,并且如果我們要在 PGresult 結構的生存期后還要使用它的話,我們必須顯式的把該數值拷貝到其他存儲器中. PQgetlength 返回以字節計的數據域(字段)的長度.記錄和數據域索引從 0 開始.
int PQgetlength(const PGresult *res, int tup_num, int field_num); 這是某一特定數據值的實際數據長度,也就是由 PQgetvalue 指向的對象的尺寸.注意,對于 ASCII 代表的數值,這個尺寸與 PQfsize 報告的二進制尺寸無關. PQgetisnull 測試一個數據域是否為空(NULL).記錄和數據域索引從 0 開始.
int PQgetisnull(const PGresult *res, int tup_num, int field_num); 如果該域包含 NULL,函數返回 1,如果包含非空(non-null )值,返回 0.(注意,對一個 NULL 數據域,PQgetvalue 將返回一個空字符串,不是一個空指針.) PQcmdStatus 返回產生 PGresult 的 SQL 命令的命令狀態字符串.
環境變量 下面的環境變量可以用于選擇缺省的聯接參數值,這些值將被 PQconnectdb 或 PQsetdbLogin 使用--如果調用代碼沒有直接聲明相應值的話.這些(環境變量)可以避免把麻煩的數據庫名強加入簡單的應用程序的硬代碼里面.The following environment variables can be used to select default connection parameter values, which will be used by PQconnectdb or PQsetdbLogin if no value is directly specified by the calling code. These are useful to avoid hard-coding database names into simple application programs. PGHOST 設置缺省的服務器名.如果聲明了一個非零長的字符串,將使用 TCP/IP 通訊.如果沒有主機名,libpq 將使用本地的Unix 域套接字. PGPORT 設置與 Postgres 后端通訊的缺省端口號或本地 Unix 主控套接字的文件擴展(文件標識符).
main() { char *pghost, *pgport, *pgoptions, *pgtty; char *dbName; int nFields; int i, j;
/* FILE *debug; */
PGconn *conn; PGresult *res;
/* * begin, by setting the parameters for a backend connection if the * parameters are null, then the system will try to use reasonable * defaults by looking up environment variables or, failing that, * using hardwired constants */ pghost = NULL; /* host name of the backend server */ pgport = NULL; /* port of the backend server */ pgoptions = NULL; /* special options to start up the backend * server */ pgtty = NULL; /* debugging tty for the backend server */ dbName = "template1";
/* make a connection to the database */ conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
/* * check to see that the backend connection was successfully made */ if (PQstatus(conn) == CONNECTION_BAD) { fprintf(stderr, "Connection to database '%s' failed./n", dbName); fprintf(stderr, "%s", PQerrorMessage(conn)); exit_nicely(conn); }
/* start a transaction block */ res = PQexec(conn, "BEGIN"); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "BEGIN command failed/n"); PQclear(res); exit_nicely(conn); }
/* * should PQclear PGresult whenever it is no longer needed to avoid * memory leaks */ PQclear(res);
/* * fetch instances from the pg_database, the system catalog of * databases */ res = PQexec(conn, "DECLARE mycursor CURSOR FOR select * from pg_database"); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "DECLARE CURSOR command failed/n"); PQclear(res); exit_nicely(conn); } PQclear(res); res = PQexec(conn, "FETCH ALL in mycursor"); if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "FETCH ALL command didn't return tuples properly/n"); PQclear(res); exit_nicely(conn); }
/* first, print out the attribute names */ nFields = PQnfields(res); for (i = 0; i < nFields; i++) printf("%-15s", PQfname(res, i)); printf("/n/n");
/* next, print out the instances */ for (i = 0; i < PQntuples(res); i++) { for (j = 0; j < nFields; j++) printf("%-15s", PQgetvalue(res, i, j)); printf("/n"); } PQclear(res);
/* close the cursor */ res = PQexec(conn, "CLOSE mycursor"); PQclear(res);
/* commit the transaction */ res = PQexec(conn, "COMMIT"); PQclear(res);
/* close the connection to the database and cleanup */ PQfinish(conn);
/* fclose(debug); */ return 0;
} 例子程序 2 /* * testlibpq2.c * Test of the asynchronous notification interface * * Start this program, then from psql in another window do * NOTIFY TBL2; * * Or, if you want to get fancy, try this: * Populate a database with the following: * * CREATE TABLE TBL1 (i int4); * * CREATE TABLE TBL2 (i int4); * * CREATE RULE r1 AS ON INSERT TO TBL1 DO * (INSERT INTO TBL2 values (new.i); NOTIFY TBL2); * * and do * * INSERT INTO TBL1 values (10); * */ #include #include "libpq-fe.h"
main() { char *pghost, *pgport, *pgoptions, *pgtty; char *dbName; int nFields; int i, j;
PGconn *conn; PGresult *res; PGnotify *notify;
/* * begin, by setting the parameters for a backend connection if the * parameters are null, then the system will try to use reasonable * defaults by looking up environment variables or, failing that, * using hardwired constants */ pghost = NULL; /* host name of the backend server */ pgport = NULL; /* port of the backend server */ pgoptions = NULL; /* special options to start up the backend * server */ pgtty = NULL; /* debugging tty for the backend server */ dbName = getenv("USER"); /* change this to the name of your test * database */
/* make a connection to the database */ conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
/* * check to see that the backend connection was successfully made */ if (PQstatus(conn) == CONNECTION_BAD) { fprintf(stderr, "Connection to database '%s' failed./n", dbName); fprintf(stderr, "%s", PQerrorMessage(conn)); exit_nicely(conn); }
res = PQexec(conn, "LISTEN TBL2"); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "LISTEN command failed/n"); PQclear(res); exit_nicely(conn); }
/* * should PQclear PGresult whenever it is no longer needed to avoid * memory leaks */ PQclear(res);
while (1) {
/* * wait a little bit between checks; waiting with select() * would be more efficient. */ sleep(1); /* collect any asynchronous backend messages */ PQconsumeInput(conn); /* check for asynchronous notify messages */ while ((notify = PQnotifies(conn)) != NULL) { fprintf(stderr, "ASYNC NOTIFY of '%s' from backend pid '%d' received/n", notify->relname, notify->be_pid); free(notify); } }
/* close the connection to the database and cleanup */ PQfinish(conn);
return 0; } 例子程序 3 /* * testlibpq3.c Test the C version of Libpq, the Postgres frontend * library. tests the binary cursor interface * * * * populate a database by doing the following: * * CREATE TABLE test1 (i int4, d float4, p polygon); * * INSERT INTO test1 values (1, 3.567, '(3.0, 4.0, 1.0, * 2.0)'::polygon); * * INSERT INTO test1 values (2, 89.05, '(4.0, 3.0, 2.0, * 1.0)'::polygon); * * the expected output is: * * tuple 0: got i = (4 bytes) 1, d = (4 bytes) 3.567000, p = (4 * bytes) 2 points boundbox = (hi=3.000000/4.000000, lo = * 1.000000,2.000000) tuple 1: got i = (4 bytes) 2, d = (4 bytes) * 89.050003, p = (4 bytes) 2 points boundbox = * (hi=4.000000/3.000000, lo = 2.000000,1.000000) * * */ #include #include "libpq-fe.h" #include "utils/geo-decls.h" /* for the POLYGON type */
main() { char *pghost, *pgport, *pgoptions, *pgtty; char *dbName; int nFields; int i, j; int i_fnum, d_fnum, p_fnum; PGconn *conn; PGresult *res;
/* * begin, by setting the parameters for a backend connection if the * parameters are null, then the system will try to use reasonable * defaults by looking up environment variables or, failing that, * using hardwired constants */ pghost = NULL; /* host name of the backend server */ pgport = NULL; /* port of the backend server */ pgoptions = NULL; /* special options to start up the backend * server */ pgtty = NULL; /* debugging tty for the backend server */
dbName = getenv("USER"); /* change this to the name of your test * database */
/* make a connection to the database */ conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
/* * check to see that the backend connection was successfully made */ if (PQstatus(conn) == CONNECTION_BAD) { fprintf(stderr, "Connection to database '%s' failed./n", dbName); fprintf(stderr, "%s", PQerrorMessage(conn)); exit_nicely(conn); }
/* start a transaction block */ res = PQexec(conn, "BEGIN"); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "BEGIN command failed/n"); PQclear(res); exit_nicely(conn); }
/* * should PQclear PGresult whenever it is no longer needed to avoid * memory leaks */ PQclear(res);
/* * fetch instances from the pg_database, the system catalog of * databases */ res = PQexec(conn, "DECLARE mycursor BINARY CURSOR FOR select * from test1"); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "DECLARE CURSOR command failed/n"); PQclear(res); exit_nicely(conn); } PQclear(res);
res = PQexec(conn, "FETCH ALL in mycursor"); if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "FETCH ALL command didn't return tuples properly/n"); PQclear(res); exit_nicely(conn); }
for (i = 0; i < 3; i++) { printf("type[%d] = %d, size[%d] = %d/n", i, PQftype(res, i), i, PQfsize(res, i)); } for (i = 0; i < PQntuples(res); i++) { int *ival; float *dval; int plen; POLYGON *pval;
/* we hard-wire this to the 3 fields we know about */ ival = (int *) PQgetvalue(res, i, i_fnum); dval = (float *) PQgetvalue(res, i, d_fnum); plen = PQgetlength(res, i, p_fnum);
/* * plen doesn't include the length field so need to * increment by VARHDSZ */ pval = (POLYGON *) malloc(plen + VARHDRSZ); pval->size = plen; memmove((char *) &pval->npts, PQgetvalue(res, i, p_fnum), plen); printf("tuple %d: got/n", i); printf(" i = (%d bytes) %d,/n", PQgetlength(res, i, i_fnum), *ival); printf(" d = (%d bytes) %f,/n", PQgetlength(res, i, d_fnum), *dval); printf(" p = (%d bytes) %d points /tboundbox = (hi=%f/%f, lo = %f,%f)/n", PQgetlength(res, i, d_fnum), pval->npts, pval->boundbox.xh, pval->boundbox.yh, pval->boundbox.xl, pval->boundbox.yl); } PQclear(res);
/* close the cursor */ res = PQexec(conn, "CLOSE mycursor"); PQclear(res);
/* commit the transaction */ res = PQexec(conn, "COMMIT"); PQclear(res);
/* close the connection to the database and cleanup */ PQfinish(conn);