使用 C-API 訪問 PostgreSQL
C-API 是訪問 PostgreSQL 最強大的方式,它非常舒適。
編譯和連結
在編譯期間,你必須將包含 pg_config --includedir
的 PostgreSQL 包含目錄新增到包含路徑。
你必須連結 PostgreSQL 客戶端共享庫(UNIX 上為 libpq.so
,Windows 上為 libpq.dll
)。該庫位於 PostgreSQL 庫目錄中,可以通過 pg_config --libdir
找到。
注意: 由於歷史原因,該庫被稱為 libpq.so
而不是 libpg.so
,這是初學者的流行陷阱。
鑑於以下程式碼示例位於檔案 coltype.c
中,編譯和連結將完成
gcc -Wall -I "$(pg_config --includedir)" -L "$(pg_config --libdir)" -o coltype coltype.c -lpq
使用 GNU C 編譯器(考慮新增 -Wl,-rpath,"$(pg_config --libdir)"
來新增庫搜尋路徑)或者
cl /MT /W4 /I <include directory> coltype.c <path to libpq.lib>
在 Windows 上使用 Microsoft Visual C.
示例程式
/* necessary for all PostgreSQL client programs, should be first */
#include <libpq-fe.h>
#include <stdio.h>
#include <string.h>
#ifdef TRACE
#define TRACEFILE "trace.out"
#endif
int main(int argc, char **argv) {
#ifdef TRACE
FILE *trc;
#endif
PGconn *conn;
PGresult *res;
int rowcount, colcount, i, j, firstcol;
/* parameter type should be guessed by PostgreSQL */
const Oid paramTypes[1] = { 0 };
/* parameter value */
const char * const paramValues[1] = { "pg_database" };
/*
* Using an empty connectstring will use default values for everything.
* If set, the environment variables PGHOST, PGDATABASE, PGPORT and
* PGUSER will be used.
*/
conn = PQconnectdb("");
/*
* This can only happen if there is not enough memory
* to allocate the PGconn structure.
*/
if (conn == NULL)
{
fprintf(stderr, "Out of memory connecting to PostgreSQL.\n");
return 1;
}
/* check if the connection attempt worked */
if (PQstatus(conn) != CONNECTION_OK)
{
fprintf(stderr, "%s\n", PQerrorMessage(conn));
/*
* Even if the connection failed, the PGconn structure has been
* allocated and must be freed.
*/
PQfinish(conn);
return 1;
}
#ifdef TRACE
if (NULL == (trc = fopen(TRACEFILE, "w")))
{
fprintf(stderr, "Error opening trace file \"%s\"!\n", TRACEFILE);
PQfinish(conn);
return 1;
}
/* tracing for client-server communication */
PQtrace(conn, trc);
#endif
/* this program expects the database to return data in UTF-8 */
PQsetClientEncoding(conn, "UTF8");
/* perform a query with parameters */
res = PQexecParams(
conn,
"SELECT column_name, data_type "
"FROM information_schema.columns "
"WHERE table_name = $1",
1, /* one parameter */
paramTypes,
paramValues,
NULL, /* parameter lengths are not required for strings */
NULL, /* all parameters are in text format */
0 /* result shall be in text format */
);
/* out of memory or sever communication broken */
if (NULL == res)
{
fprintf(stderr, "%s\n", PQerrorMessage(conn));
PQfinish(conn);
#ifdef TRACE
fclose(trc);
#endif
return 1;
}
/* SQL statement should return results */
if (PGRES_TUPLES_OK != PQresultStatus(res))
{
fprintf(stderr, "%s\n", PQerrorMessage(conn));
PQfinish(conn);
#ifdef TRACE
fclose(trc);
#endif
return 1;
}
/* get count of result rows and columns */
rowcount = PQntuples(res);
colcount = PQnfields(res);
/* print column headings */
firstcol = 1;
printf("Description of the table \"pg_database\"\n");
for (j=0; j<colcount; ++j)
{
if (firstcol)
firstcol = 0;
else
printf(": ");
printf(PQfname(res, j));
}
printf("\n\n");
/* loop through rosult rows */
for (i=0; i<rowcount; ++i)
{
/* print all column data */
firstcol = 1;
for (j=0; j<colcount; ++j)
{
if (firstcol)
firstcol = 0;
else
printf(": ");
printf(PQgetvalue(res, i, j));
}
printf("\n");
}
/* this must be done after every statement to avoid memory leaks */
PQclear(res);
/* close the database connection and release memory */
PQfinish(conn);
#ifdef TRACE
fclose(trc);
#endif
return 0;
}