1.2. 数据库联接函数
下面的过程处理与 PostgreSQL 后端服务器联接的事情. 一个应用程序一次可以与多个后端建立联接. (这么做的原因之一是访问多于一个数据库.) 每个连接都是用一个从PQconnectdb()或 PQsetdbLogin() 获得的PGconn对象表示. 注意,这些函数总是返回一个非空的对象指针, 除非存储器少得连个PGconn对象都分配不出来. 在把查询发送给联接对象之前,可以调用PQstatus 函数来检查一下联接是否成功.
*
PQconnectdb 与后端数据库服务器建立一个新的联接.
PGconn *PQconnectdb(const char *conninfo)
这个过程用从一个字符串 conninfo 来的参数与数据库打开一个新的联接. 与下面的PQsetdbLogin()不同的是, 我们可以不必更换函数签名(名字)就可以扩展参数集, 所以我们建议应用程序中使用这个函数或者是它的非阻塞的相似函数 PQconnectStart 和 PQconnectPoll. 传入的参数可以为空,表明使用所有缺省的参数, 或者可以包含一个或更多个用空白间隔的参数设置.
每个参数以 关键字 = 数值的形式设置. (要写一个空值或者一个包含空白的值, 你可以用一对单引号包围它们,例如, keyword = 'a value' . 数值内部的单引号和反斜扛必须用一个反斜扛逃逸, 也就是说, '或\\.) 等号周围的空白是可选的.目前可识别的参数键字是:
host
要联接的主机(host ). 如果主机名以斜扛开头, 则它声明使用 Unix 域套接字通讯而不是 TCP/IP 通讯; 该值就是套接字文件所存储的目录. 缺省时是与位于 /tmp 里面的 Unix-域套接字联接.
hostaddr
与之联接的主机的 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 域套接字进行通讯。
port
主机服务器的端口号,或者在 Unix 域套接字联接时的套接字扩展文件名.
dbname
数据库名.
user
要联接的用户名。
password
如果后端要求口令认证,所用的口令.
connect_timeout
给连接过程设置的时间范围,以秒计。零或者不设置表示无穷。
options
发给后端的跟踪/调试选项.
tty
文件或控制台(tty),用于从后端的可选调试输出.
requiressl
设为 '1' 要求与后端进行 SSL 联接.如果服务器不支持 SSL, 那么Libpq将马上拒绝联接. 设置为 '0' (缺省)与服务器进行协商.
如果有任何没有声明的参数,那么将检查对应的环境变量(参阅Section 1.10 小节)。 如果环境变量也没有设置,那么使用编译时的硬代码。 返回的值是一个指向代表与后端联接的抽象 struct指针。
*
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)
PostgreSQLPollingStatusType PQconnectPoll(PGconn *conn)
这两个过程用于打开一个与数据库服务器之间的非阻塞的联接: 你的应用的执行线索在执行它的时候不会因远端的 I/O 而阻塞。
数据库联接是用从 conninfo字符串里取得的参数传递给 PQconnectStart进行的。 这个字符串的格式与上面PQconnectdb里描述的一样。
PQconnectStart 和PQconnectPoll 都不会阻塞(进程),不过有一些条件:
o
必须正确提供hostaddr和host 参数以确保不会发生正向或者反向的名字查找。 参阅上面PQconnectdb里的这些参数的文档获取细节。
o
如果你调用了PQtrace, 确保你跟踪进入的流对象不会阻塞。
o
你必须在调用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
等待来自服务器的响应。
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将阻塞住。 这个限制可能在将来的版本移除。
这些函数把 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 struct 的数组, 该数组以一个有 NULL 关键字指针的条目结束.注意缺省值(val 域)将 依赖于环境变量和其他上下文.调用者必须把联接选项当作只读对待.
在处理完选项数组后,把数组交给PQconninfoFree()释放. 如果没有这么做,每次调用PQconndefaults() 都会有一小部分内存泄漏.
在PostgreSQL7.0 以前的版本, PQconndefaults() 返回一个指向静态数组的指针, 而不是一个动态分配的数组.这样做是线程不安全的,因此这个特点被修改了.
*
PQfinish 关闭与后端的联接.同时释放被PGconn 对象使用的存储器.
void PQfinish(PGconn *conn)
注意,即使与后端的联接尝试失败(可由PQstatus判断), 应用也要调用PQfinish释放被PGconn 对象使用的存储器.不应该在调用 PQfinish后再使用PGconn 指针.
*
PQreset 重置与后端的通讯端口.
void PQreset(PGconn *conn)
此函数将关闭与后端的联接并且试图与同一个服务器重建新的联接, 使用所有前面使用过的参数.这在 失去工作联接后进行故障恢复时很有用.
*
PQresetStart PQresetPoll 以非阻塞模式重置与后端的通讯端口。
int PQresetStart(PGconn *conn);
PostgreSQLPollingStatusType PQresetPoll(PGconn *conn);
此函数将关闭与后端的联接并且试图与同一个服务器重建新的联接, 使用所有前面使用过的参数.这在 失去工作联接后进行故障恢复时很有用. 它们和上面的PQreset的区别是它们工作在非阻塞模式。 这些函数的使用有与上面PQconnectStart和 PQconnectPoll一样的限制。
调用PQresetStart。如果它返回 0,那么重置失败。 如果返回 1,用与使用PQconnectPoll 建立联接的同样的 方法使用PQresetPoll重置联接。
libpq应用程序员应该仔细维护PGconn结构.使用下面的访问函数来获取PGconn的内容.避免直接引用PGconn结构里的字段,因为这些字段在今后可能被改变.(从 PostgreSQL 版本 6.4 开始, struct PGconn的定义甚至没有放在 libpq-fe.h里.如果你有一些直接访问PGconn数据域的旧代码,你可以通过包含 libpq-int.h 来访问它们,但我们鼓励你赶快修改那些代码.)
*
PQdb 返回联接的数据库名.
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 属于运行数据库服务器的主机的进程, 而不是本地主机!
*
PQgetssl 返回联接使用的 SSL 结构,或者如果 SSL 没有使用的话返回 NULL.
SSL *PQgetssl(const PGconn *conn);
这个结构可以用于核实加密级别,检查服务器认证等信息.参考 SSL 文档获取关于这个结构的更多信息.
为了获取这个函数的原形,你必须定义 USE_SSL. 这样做会自动包含来自OpenSSL的 ssl.h.