libpq 是 Postgres的 C 应用程序员的接口. libpq 是一套允许客户程序向 Postgres 后端服务进程发送查询 并且获得查询返回的库过程. libpq 同时也是其他几个 Postgres 应用接口下面的引擎, 包括 libpq++ (C++), libpgtcl(Tcl),Perl,和 ecpg.所以如果你使用这些软件包, libpq 某些方面的特性会对你非常重要.
本节末尾有三个小程序显示如何利用 libpq书写程序. 在下面目录里面有几个完整的 libpq 应用的例子:
../src/test/regress ../src/test/examples ../src/bin/psql
使用 libpq 的前端程序必须包括头文件 libpq-fe.h 并且必须与 libpq 库链接.
下面的过程处理与 Postgres 后端服务器联接的事情. 一个应用程序一次可以与多个后端建立联接. (这么做的原因之一是访问多于一个数据库.) 每个连接都是用一个从PQconnectdb()或 PQsetdbLogin() 获得的PGconn对象表示. 注意,这些函数总是返回一个非空的对象指针, 除非存储器少得连个PGconn对象都分配不出来. 在把查询发送给联接对象之前,可以调用PQstatus 函数来检查一下联接是否成功.
PQconnectdb 与后端数据库服务器建立一个新的联接.
PGconn *PQconnectdb(const char *conninfo)这个过程用从一个字符串 conninfo 来的参数与数据库打开一个新的联接. 与下面的 PQsetdbLogin() 不同的是, 我们可以不必更换函数签名(名字)就可以扩展参数集, 所以我们建议应用程序中使用这个函数或者是它的非阻塞的相似函数 PQconnectStart / PQconnectPoll. 传入的参数可以为空,表明使用所有缺省的参数, 或者可以包含一个或更多个用空白间隔的参数设置.
每个参数以 关键字 = 数值的形式设置. (要写一个空值或者一个包含空白的值, 你可以用一对单引号包围它们,例如, keyword = 'a value' . 数值内部的单引号必须书写为 \'. 等号周围的空白是可选的.)目前可识别的参数值是:
要联接的主机(host ). 如果主机名以斜扛开头, 则它声明使用 Unix 域套接字通讯而不是 TCP/IP 通讯; 该值就是套接字文件所存储的目录. 缺省时是与位于 /tmp 里面的 Unix-域套接字联接.
与之联接的主机的 IP 地址。这个可以是标准的数字-点的形式, 象在 BSD 函数 inet_aton 等里面用的那样。 如果声明了一个非零长的字符串,那么使用 TCP/IP 通讯机制。
使用 hostaddr 取代 host 可以让应用避免一次主机名查找, 这一点对于那些有时间约束的应用来说可能是非常重要的。 不过,Kerberos 认证系统要求主机(host)名。因此,应用下面的规则。 如果声明了不带 hostaddr 的 host 那么就强制进行主机名查找。 如果声明中没有 host,hostaddr 的值给出远端的地址; 如果使用了 Kerberos, 将导致一次反向名字查询。如果同时声明了 host 和 hostaddr, 除非使用了 Kerberos,否则将使用 hostaddr 的值作为远端地址; host 的值将被忽略,如果使用了 Kerberos,host 的值用于 Kerberos 认证。 要注意如果传递给 libpq 的主机名(host)不是地址 hostaddr 处的机器名, 那么认证很有可能失败。
如果主机名(host)和主机地址都没有, 那么 libpq 将使用一个本地的 Unix 域套接字进行通讯。
主机服务器的端口号,或者在 Unix 域套接字联接时的套接字扩展文件名.
数据库名.
要联接的用户名。
如果后端要求口令认证,所用的口令.
发给后端的跟踪/调试选项.
文件或控制台,用于从后端的可选调试输出.
设为 '1' 要求与后端进行 SSL 联接.如果服务器不支持 SSL, 那么 Libpq 将马上拒绝联接.设置为 '0' (缺省)与服务器进行协商.
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 前身, 它有固定个数的参数,但是有相同的功能。
PQsetdb 与后端数据库服务器建立一个新的联接.
PGconn *PQsetdb(char *pghost, char *pgport, char *pgoptions, char *pgtty, char *dbName)这是一个调用 PQsetdbLogin() 的宏,只是 login 和 pwd 参数用空(null )代替. 提供这个函数主要是为了与老版本的程序兼容.
PQconnectStart, PQconnectPoll 与数据库服务器建立一次非阻塞的联接。
PGconn *PQconnectStart(const char *conninfo)
PostgresPollingStatusType PQconnectPoll(PGconn *conn)这两个过程用于打开一个与数据库服务器之间的非阻塞的联接: 你的应用的执行线索在执行它的时候不会因远端的 I/O 而阻塞。
数据库联接是用从 conninfo字符串里取得的参数传递给 PQconnectStart 进行的。 这个字符串的格式与上面 PQconnectdb 里描述的一样。
PQconnectStart 和 PQconnectPoll 都不会阻塞(进程),不过有一些条件:
必须正确提供 hostaddr 和 host 参数以确保不会发生正向或者反向的名字查找。 参阅上面 PQconnectdb里的这些参数的文档获取细节。
如果你调用了 PQtrace,确保你跟踪进入的流对象不会阻塞。
你必须在调用 PQconnectPoll 之前确保 socket 处于正确的状态, 象下面描述的那样。
要开始(联接),调用 conn=PQconnectStart("<connection_info_string>") . 如果 conn 是NULL,表明 libpq 无法分配一个新的 PGconn 结构。 否则,返回一个有效的 PGconn 指针 (尽管还不一定代表一个与数据库有效联接)。 PQconnectStart 一返回,调用 status=PQstatus(conn)。 如果 status 等于CONNECTION_BAD,PQconnectStart 失败。
如果 PQconnectStart 成功了,下一个阶段是轮询 libpq, 这样它就可以继续进行后继的联接动作。 象这样循环:认为一个联接缺省时是'不活跃'的。 如果 PQconnectPoll 的最后一个返回是 PGRES_POLLING_ACTIVE,则认为它是'活跃的'。 如果 PQconnectPoll(conn) 的最后一个返回是 PGRES_POLLING_READING,执行一个对 PQsocket(conn) 的读 select。 如果最后一个返回是PGRES_POLLING_WRITING, 执行一个对 PQsocket(conn) 的写 select。 如果还要调用PQconnectPoll,也就是调用完 PQconnectStart 之后, 把它当作最后返回PGRES_POLLING_WRITING那样对待。 如果 select 显示 socket 已经准备好, 那么认为它是'活跃的'。如果认为一个联接是'活跃的', 再次调用 PQconnectPoll(conn)。 如果这次调用返回 PGRES_POLLING_FAILED,联接过程失败,如果这次调用 返回 PGRES_POLLING_OK,联接成功。
要注意上面用 select() 来确保一个 socket 准备好只是一个(近似)的例子; 还可以用其他方法,比如一个poll() 调用,来代替 select。
在联接的任意时刻,我们都可以通过调用 PQstatus 来检查联接的状态。 如果这是 CONNECTION_BAD,那么联接过程失败;如果是 CONNECTION_OK, 那么联接已经做好。 这两种状态同样也可以从上面的PQconnectPoll 的返回值里检测到。 其他状态可能(也只能)在一次异步联接过程中看到。 这些标识联接过程 的当前状态,因而可能对给用户提供反馈有帮助。这些状态可能包括:
CONNECTION_STARTED:等待进行联接。
CONNECTION_MADE:联接成功;等待发送。
CONNECTION_AWAITING_RESPONSE:等待来自 postmaster 的响应。
CONNECTION_AUTH_OK:已收到认证;等待后端启动。
CONNECTION_SETENV:协商环境。
switch(PQstatus(conn)) { case CONNECTION_STARTED: feedback = "Connecting..."; break; case CONNECTION_MADE: feedback = "Connected to server..."; break; . . . default: feedback = "Connecting..."; }
要注意如果 PQconnectStart 返回一个非空的指针, 你必须在使用完它(指针)之后调用 PQfinish, 以处理那些结构和所有相关的存储块。 甚至调用 PQconnectStart 或者 PQconnectPoll 失败时也要这样处理。
如果编译 libpq 时定义了 USE_SSL 那么目前的 PQconnectPoll 将阻塞住。 这个限制可能在将来的版本移除。
除非编译 libpq 时定义了 WIN32_NON_BLOCKING_CONNECTIONS, 否则目前的 PQconnectPoll 将在Windows 里阻塞住。 这些代码还没有在 Windows 里测试过,因此目前缺省时是不带这些代码的。 这一点以后可能修改。
这些函数把 socket 置于一个非阻塞的状态,就好象调用了 PQsetnonblocking 一样。
PQconndefaults 返回缺省的联接选项。
PQconninfoOption *PQconndefaults(void) 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() 都会有一小部分内存泄漏.
在 Postgres 7.0 以前的版本, PQconndefaults() 返回一个指向静态数组的指针, 而不是一个动态分配的数组.这样做是线程不安全的,因此这个特点被修改了.
PQfinish PQfinish 关闭与后端的联接.同时释放被 PGconn 对象使用的存储器.
void PQfinish(PGconn *conn)注意,即使与后端的联接尝试失败(可由 PQstatus 判断), 应用也要调用 PQfinish 释放被 PGconn 对象使用 的存储器.PGconn 指针不应该在调用 PQfinish 后再使用.
PQreset PQreset 重置与后端的通讯端口.
void PQreset(PGconn *conn)此函数将关闭与后端的联接并且试图与同一个 postmaster 重建新的联接, 使用所有前面使用过的参数.这在 失去工作联接后进行故障恢复时很有用.
PQresetStart PQresetPoll 以非阻塞模式重置与后端的通讯端口。
int PQresetStart(PGconn *conn);
PostgresPollingStatusType PQresetPoll(PGconn *conn);此函数将关闭与后端的联接并且试图与同一个 postmaster 重建新的联接, 使用所有前面使用过的参数.这在 失去工作联接后进行故障恢复时很有用. 它们和上面的 PQreset 的区别是它们工作在非阻塞模式。 这些函数的使用有与上面 PQconnectStart 和 PQconnectPoll 一样的限制。
调用 PQresetStart。如果它返回 0,那么重置失败。 如果返回 1,用与使用 PQconnectPoll 建立联接的同样的 方法使用 PQresetPoll 重置联接。
libpq 应用程序员应该仔细维护 PGconn 结构. 使用下面的访问函数来获取 PGconn 的内容. 避免直接引用 PGconn 结构里的字段,因为这些字段在今后可能被改变. (从 Postgres 版本 6.4 开始, 结构 PGconn 的定义甚至 没有放在 libpq-fe.h里. 如果你有一些直接访问 PGconn 数据域的旧代码, 你可以通过包含 libpq-int.h 来访问它们,但我们鼓励你赶快修改那些代码.)
PQdb 返回联接的数据库名.
char *PQdb(const PGconn *conn)和下面几个函数返回联接时建立起来的几个值. 这些值在 PGconn 对象的生存期内是固定的.
PQuser 返回联接的用户名.
char *PQuser(const PGconn *conn)
PQpass 返回联接的口令.
char *PQpass(const PGconn *conn)
PQhost 返回联接的服务器主机名.
char *PQhost(const PGconn *conn)
PQport 返回联接的端口号.
char *PQport(const PGconn *conn)
PQtty 返回联接的调试控制台( tty ).
char *PQtty(const PGconn *conn)
PQoptions 返回联接中使用的后端选项.
char *PQoptions(const PGconn *conn)
PQstatus 返回联接的状态.
ConnStatusType PQstatus(const PGconn *conn)
这个状态可以是一些值之一。 不过,如果不是一次异步联接过程的话,我们只能看到其中的两个 - CONNECTION_OK 或 CONNECTION_BAD。一个与数据库的成功的联接返回状态 CONNECTION_OK。 一次失败的企图用状态 CONNECTION_BAD 标识。 通常,一个 OK 状态保持到 PQfinish,但是一个通讯失败可能会导致状态过早地改变为 CONNECTION_BAD 。这时应用可以试着调用 PQreset 来恢复.
参阅 PQconnectStart 和 PQconnectPoll 条目看看可能出现的其他的状态码。
PQerrorMessage 返回联接中操作产生的最近的错误信息.
char *PQerrorMessage(const PGconn* conn);
几乎所有 libpq 函数在失败时都会设置 PQerrorMessage.注意 libpq 的传统是, 一个非空的 PQerrorMessage 将在结尾包含一个新行.
PQbackendPID 返回控制此联接的后端服务器的进程号ID。
int PQbackendPID(const PGconn *conn);这个后端PID 在调试和对比 NOTIFY 信息( 包含发出通知的后端的 PID )时很有用. 注意该 PID 属于运行数据库服务器的主机的进程, 而不是本地主机!
PQgetssl 返回联接使用的 SSL 结构,或者如果 SSL 没有使用的话返回 NULL.
SSL *PQgetssl(const PGconn *conn);这个结构可以用于核实加密级别,检查服务器认证等信息.参考 OpenSSL 文档获取关于这个结构的更多信息.
为了获取这个函数的原形,你必须定义 USE_SSL. 这样做会自动包含来自 OpenSSL ssl.h.