PostgreSQL libpq 客户端接口(一)
前言
Libpq 是为 C 语言开发这提供的关于 PostgreSQL 的接口。Libpq 由相关库函数组成,可以允许客户端程序通过将查询传递给 PostgreSQL 后台服务器并接收这些查询返回的结果。同时,libpq 也是其它几个 PostgreSQL 应用程序接口的基础引擎,包括 C++,Perl,Python,Tcl和ECPGC编程的嵌入式 SQL。
连接字符串
以下函数处理 PostgreSQL 后台服务器的连接。一个应用程序同时可以有多个打开的连接,这也是 PostgreSQL 服务器能够同时访问多个库的原因。每一个连接都通过 PGconn 对象表示,该对象可以从函数 PQconnectdb,PQconnectdbParams 中或者 PQsetdbLogin 获取信息。需要注意的是,这些对象通常返回一个非空的对象指针。除非由于内存太小导致无法分配 PGconn 对象。PQstatus 函数用来检查在执行查询前连接是否成功的状态。
函数介绍如下:
PQconnectdbParams
该参数用来创建连接到数据库服务器的新的连接。如下:
PGconn *PQconnectdbParams(const char * const *keywords, const char * const *values, int expand_dbname);
当 expand_dbname 是非零时,该 dbname 关键字的值可以允许作为一个连接字符串。
而关于 PGconn 的定义,PGconn 属于封装到后端的连接,应用程序不需要关心该结构的定义,此处给出该结构的定义:
typedef struct pg_conn PGconn;
该函数和 PQconnectdbParams 类似,只不过该函数使用的并非一个 key-value 的值,而是一个字符串数组常量。如下:
PGconn * PQconnectdb(const char * conninfo);
该函数用来使用指定的数据库信息进行连接,其实 PQconnectdb 执行时省略了这一步而已。该函数与 PQconnectdb 具有相同的功能,都时用来创建一个新的服务器连接,只不过 PQsetdbLogin 指定了相关的数据库信息,而 PQconnectdb 使用 URI 来连接。如果该参数缺少参数,也将采用默认值,即 UNIX 套接字。
PGconn *PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd);
该函数使用指定的数据库信息进行连接。主要用来和以前版本的服务器进行兼容,忽略。
连接状态函数
- PQstatus
ConnStatusType PQstatus(const PGconn *conn);
- PQerrorMessage
该函数返回最近连接时出现的错误信息。
char *PQerrorMessage(const PGconn *conn);
- PQconnectionNeedsPassword
该函数返回采用密码加密方式认证时需要请求的密码。如果需要密码但密码错误返回1,如果没有则返回 0。
int PQconnectionNeedsPassword(const PGconn *conn);
- PQparameterStatus
返回当前已连接服务器的参数信息
const char *PQparameterStatus(const PGconn *conn, const char *paramName);
- PQtransactionStatus
返回当前处于事务当中服务器状态。
PGTransactionStatusType PQtransactionStatus(const PGconn *conn);
- PQerrorMessage
该函数返回在一个已连接到服务器上生成的最近操作错误的信息。
char *PQerrorMessage(const PGconn *conn);
- PQbackendPID
该函数返回一个已连接到服务器的后台进程 ID。
int PQbackendPID(const PGconn *conn);
- PQconnectionNeedsPassword
如果连接认证方式请求一个密码,那么该函数返回 1,如果没有密码请求,则返回 0。
int PQconnectionNeedsPassword(const PGconn *conn);
- PQconnectionUsedPassword
如果一个连接认证方式使用密码则返回 1,否则返回 0。
int PQconnectionUsedPassword(const PGconn *conn);
示例
#创建源码文件存放目录 mkdir /home/postgres/libpqtest #编写源码文件 test.c #include <stdio.h> #include <stdlib.h> #include "libpq-fe.h" int main(int argc,char **argv) { const char *conninfo; //定义传入连接参数常量 PGconn *conn; //定义连接字符串 if (argc > 1) { conninfo = argv[1]; }else { conninfo = "dbname = postgres"; } //创建一个新的连接 conn = PQconnectdb(conninfo); //检查连接状态 if (PQstatus(conn) != CONNECTION_OK) { //打印连接字符串信息 fprintf(stderr,"错误的连接字符串信息: %s",PQerrorMessage(conn)); }else { //打印连接的字符串信息 printf("OK\n"); } } #编写Makefile 文件 [postgres@sungsasong libpqtest]$ cat Makefile # # Makefile for example programs # subdir = ~/libpqtest top_builddir = /home/postgres/pack/postgresql-12.3 include $(top_builddir)/src/Makefile.global ifeq ($(PORTNAME), win32) LDFLAGS += -lws2_32 endif override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) LDFLAGS_INTERNAL += $(libpq_pgport) PROGS = test all: $(PROGS) clean distclean maintainer-clean: rm -f $(PROGS) *.o #执行 make 编译 [postgres@sungsasong libpqtest]$ make make -C /home/postgres/pack/postgresql-12.3/src/backend generated-headers make[1]: Entering directory `/home/postgres/pack/postgresql-12.3/src/backend' make -C catalog distprep generated-header-symlinks make[2]: Entering directory `/home/postgres/pack/postgresql-12.3/src/backend/catalog' make[2]: Nothing to be done for `distprep'. make[2]: Nothing to be done for `generated-header-symlinks'. make[2]: Leaving directory `/home/postgres/pack/postgresql-12.3/src/backend/catalog' make -C utils distprep generated-header-symlinks make[2]: Entering directory `/home/postgres/pack/postgresql-12.3/src/backend/utils' make[2]: Nothing to be done for `distprep'. make[2]: Nothing to be done for `generated-header-symlinks'. make[2]: Leaving directory `/home/postgres/pack/postgresql-12.3/src/backend/utils' make[1]: Leaving directory `/home/postgres/pack/postgresql-12.3/src/backend' gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -I/home/postgres/pack/postgresql-12.3/src/interfaces/libpq -I/home/postgres/pack/postgresql-12.3/src/include -D_GNU_SOURCE -I/usr/include/libxml2 -c -o test.o test.c gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 test.o -L/home/postgres/pack/postgresql-12.3/src/port -L/home/postgres/pack/postgresql-12.3/src/common -L/home/postgres/pack/postgresql-12.3/src/common -lpgcommon -L/home/postgres/pack/postgresql-12.3/src/port -lpgport -L/home/postgres/pack/postgresql-12.3/src/interfaces/libpq -lpq -Wl,--as-needed -Wl,-rpath,'/data/pg12/lib',--enable-new-dtags -lpgcommon -lpgport -lpthread -lxslt -lxml2 -lpam -lssl -lcrypto -lz -lreadline -lrt -lcrypt -ldl -lm -o test #执行程序 [postgres@sungsasong libpqtest]$ ./test OK [postgres@sungsasong libpqtest]$ ./test "postgresql://localhost" OK [postgres@sungsasong libpqtest]$ ./test "postgresql://10.10.20.50:5404" 错误的连接字符串信息: could not connect to server: Connection refused Is the server running on host "10.10.20.50" and accepting TCP/IP connections on port 5404? [postgres@sungsasong libpqtest]$ vi $PGDATA/postgresql.conf [postgres@sungsasong libpqtest]$ vi $PGDATA/pg_hba.conf [postgres@sungsasong libpqtest]$ pg_ctl restart -D $PGDATA -l /tmp/logfile waiting for server to shut down.... done server stopped waiting for server to start.... done server started [postgres@sungsasong libpqtest]$ ./test "postgresql://10.10.20.50:5404" OK
作者:宋少华
PostgreSQL分会培训认证委员会委员、晟数科技首席技术专家、晟数学苑金牌讲师、oracle 11g OCM、PostgreSQL首批PGCE。
曾服务于国家电网冀北电力有限公司建设大数据平台,为人社局和北京市卫计委构建IT基础服务,为多家银行和证券公司构建web服务器,系统及数据库维护;具有对税务局、国家电网、银行等政府行业和民营企业的IT培训经验;为相关安全行业设计DW数据仓库模型,使用PostgreSQL,Greenplum,HUAWEIGaussDB,Vertica和Clickhouse做数据基础服务,开发TB级数据落地程序及百TB级别数据迁移程序。