本节末尾有三个小程序显示如何利用 libpq 书写程序.在下面目录里面有几个完整的
libpq
应用的例子:
../src/test/regress ../src/test/examples ../src/bin/psql使用 libpq 的前端程序必须包括头文件 libpq-fe.h 并且必须与 libpq 库链接.
PGconn *PQconnectdb(const char *conninfo)这个过程用从一个字符串 conninfo 来的参数与数据库打开一个新的联接.与下面的 PQsetdbLogin() 不同的是,我们可以不必更换函数签名(名字)就可以扩展参数集,所以我们建议应用程序中使用这个函数或者是它的非阻塞的相似函数 PQconnectStart / PQconnectPoll.传入的参数可以为空,表明使用所有缺省的参数,或者可以包含一个或更多个用空白间隔的参数设置.
每个参数设置以 关键字=数值 keyword = value 的形式设置.(要写一个空值或者一个包含空白的值,你可以用一对单引号包围它们,例如,keyword = 'a value' .数值内部的单引号必须书写为 \'.等号周围的空白是可选的.)目前可识别的参数值是:
使用 hostaddr 取代 host 允许应用避免一次主机名查找,这一点对于那些有时间约束的应用来说可能是非常重要的。不过,Kerberos 认证系统要求主机(host)名。因此,应用下面的规则。如果声明了不带 hostaddr 的 host 那么就强制进行主机名查找。如果声明中没有 host,hostaddr 的值给出远端的地址;如果使用了 Kerberos,将导致一次反向名字查询。如果同时声明了 host 和 hostaddr,除非使用了 Kerberos,否则将使用 hostaddr 的值作为远端地址;host 的值将被忽略,如果使用了 Kerberos,host 的值用于 Kerberos 认证。要注意如果传递给 libpq 的主机名(host)不是地址 hostaddr 处的机器名,那么认证很有可能失败。
如果主机名(host)和主机地址都没有,那么 libpq 将使用一个本地的 Unix 域套接字进行通讯。
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(PQconn *conn)着两个过程用于打开一个与数据库服务器之间的非阻塞的联接:你的应用的执行线索在运行的时候不会阻塞远端的 I/O。
数据库联接是用从 conninfo 字符串里取得的参数传递给 PQconnectStart 进行的。这个字符串的格式与上面 PQconnectdb 里描述的一样。
PQconnectStart 和 PQconnectPoll 都不会阻塞(进程),不过有一些限制:
如果你调用了 PQtrace,确保你跟踪进入的流对象不会阻塞。
你必须在调用 PQconnectPoll 之前确保 socket 处于正确的状态,象下面描述的那样。
如果 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_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 关闭与后端的联接.同时释放被 PGconn 对象使用的存储器.
void PQfinish(PGconn *conn)注意,即使与后端的联接尝试失败(可由 PQstatus 判断),应用也要调用 PQfinish 释放被 PGconn 对象使用的存储器.PGconn 指针不应该在调用 PQfinish 后再使用.
PQreset 重置与后端的通讯端口.
void PQreset(PGconn *conn)此函数将关闭与后端的联接并且试图与同一个 postmaster 重建新的联接,使用所有前面使用过的参数.这在失去工作联接后进行故障恢复时很有用.
PQresetStart PQresetPoll 重置与后端的非阻塞模式的通讯端口。
int PQresetStart(PGconn *conn);
PostgresPollingStatusType PQresetPoll(PGconn *conn);此函数将关闭与后端的联接并且试图与同一个 postmaster 重建新的联接,使用所有前面使用过的参数.这在失去工作联接后进行故障恢复时很有用.它们和上面的 PQreset (above) 的区别是它们工作在非阻塞模式。这些函数的使用有与上面 PQconnectStart 和 PQconnectPoll 一样的限制。
调用 PQresetStart。如果它返回 0,那么重置失败。如果返回 1,用与使用 PQconnectPoll 建立联接的同样的方法使用 PQresetPoll 重置联接。 libpq 应用程序员应该仔细维护 PGconn 结构.使用下面的访问函数来获取 PGconn 的内容.避免直接引用 PGconn 结构里的字段,因为这些字段在今后可能被改变.(从PostgreSQL 版本 6.4 开始, 结构 PGconn 的定义甚至没有放在 libpq-fe.h 里.如果你有一些直接访问 PGconn 数据域的旧代码,你可以通过包含 libpq-int.h 来访问它们,但我们鼓励你赶快修改那些代码.)
char *PQdb(const PGconn *conn)PQdb 和下面几个函数返回联接后建立起来的几个值.这些值在 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 属于运行数据库服务器的主机的进程,而不是本地主机!