31.1. 数据库联接函数

下面的函数处理与PostgreSQL服务器服务器联接的事情。 一个应用程序一次可以与多个服务器建立联接。(这么做的原因之一是访问多于一个数据库。 ) 每个连接都是用一个从函数PQconnectdbPQconnectdbParamsPQsetdbLogin获得的PGconn对象表示。 注意,这些函数总是返回一个非空的对象指针,除非存储器少得连个PGconn对象都分配不出来。 在把查询发送给联接对象之前,可以调用PQstatus函数来检查一下联接是否成功。

在Unix上,分叉与开放的libpq连接进程可能会导致 不可预知的结果,因为父和子进程共享 相同的插座和操作系统资源。出于这个原因, 这种用法是不推荐,虽然做的exec 子进程加载一个新的可执行文件是安全的。

Note: 在Windows上,有一个方式可以提高性能,如果一个单一的数据库连接重复的开启和关闭。 内部,libpq为连接启动和关闭分别调用WSAStartup()WSACleanup()WSAStartup()引用WSACleanup()递减的技术来增量内置Windows库。 当引用的技术只有一时,调用WSACleanup()来释放所有的资源并写在所有的DLL。 这个操作的开销很大,为了避免,一个应用程序可以经常调用WSAStartup(), 这样当最后一个数据库连接关闭时,不会释放所有资源。

PQconnectdbParams

与服务器数据库服务器建立一个新的联接。

PGconn *PQconnectdbParams(const char **keywords,const char **values,int expand_dbname);

这个函数使用取自两个NULL终止数组的参数来开启一个新的数据库连接。 首先,被定义为一个字符串数组的keywords中的每个元素都是一个关键字。 其次,values为每个关键字赋值。不同于下面的PQsetdbLogin, 这个参数设置可以无需修改参数签名来扩展,因此,使用这个函数(或其非阻塞的变形PQconnectStartParamsPQconnectPoll) 更适合一个新的应用程序编程。

expand_dbname非0时,dbname关键字值允许被确认为 一个conninfo字符串。

所有传递的数组可以被清空以用于所有的缺省参数,或用于包含一个或多个参数设置。 它们必须是等长的。进程会随着keywords数组中最后一个非NULL元素而终止。

目前可识别的参数键字是:

host

要联接的主机名。如果主机名以斜杠开头,则它声明使用 Unix 域套接字通讯而 不是 TCP/IP 通讯;该值就是套接字文件所存储的目录。如果没有声明host, 那么缺省时是与位于/tmp目录(或者制作PostgreSQL的时候声明的套接字目录) 里面的 Unix-域套接字联接。在没有域套接字的机器上, 缺省是与localhost连接。

hostaddr

与之联接的主机的IP地址。这个应该是标准的IPv4地址格式, 比如,172.28.40.9。如果你的机器支持IPv6,那么你也可以使用IPv6的地址。 如果声明了一个非空的字符串,那么使用TCP/IP通讯机制。

使用hostaddr取代host可以让应用避免一次主机名查找, 这一点对于那些有时间约束的应用来说可能是非常重要的。不过,Kerberos认证 系统要求主机(host)名。因此,应用下面的规则:如果声明了 不带hostaddrhost那么就强制进行主机名查找。如果声明中没有host,hostaddr的值 给出远端的地址; 如果使用了 Kerberos,将导致一次反向名字查询。 如果同时声明了hosthostaddr,除非使用了Kerberos, 否则将使用hostaddr的值作为远端地址;host的值将被忽略, 如果使用了Kerberos,host的值用于 Kerberos 认证。 (要注意如果传递给libpq的主机名(host)不是地址hostaddr处的机器名, 那么认证很有可能失败。) 同样,在~/.pgpass(参阅Section 31.14)中是 使用host而不是hostaddr来标识连接。

如果主机名(host)和主机地址都没有,那么libpq将使用一个本地 的 Unix 域套接字进行通讯; 或者是在没有 Unix 域套接字的机器上, 它将尝试与localhost连接。

port

主机服务器的端口号,或者在Unix域套接字联接时的套接字扩展文件名。

dbname

数据库名。缺省和用户名相同。

user

要联接的PostgreSQL用户名。 缺省是与运行该应用的用户操作系统名同名的用户。

password

如果服务器要求口令认证,所用的口令。

connect_timeout

连接的最大等待时间,以秒计(用十进制整数字串书写)。零或者不声明表示无穷。 我们不建议把连接超时的值设置得小于2秒。

options

发送给服务器的命令行选项。 例如,设置这-c geqo=off设置 会话的价值geqo参数为 off。为详细讨论了可用 选项,参阅Chapter 18

application_name

application_name配置参数指定值

fallback_application_name

application_name配置参数声明一个备用值。 如果连接参数或PGAPPNAME环境变量没有为application_name赋值,那么就会使用该值。 在通用的应用程序(最好设置一个缺省应用程序名)中,声明一个备用名字时很有用的,这样用户自己可以重写该名字。

keepalives

控制是否保持客户端的TCP连接使用。缺省值是1,表示开启,但可以改为0,表示不开启。 通过一个Unix域套接字,可以为连接模式忽略该参数。

keepalives_idle

控制空闲秒数,在这个秒数之后,TCP应该向服务器发送一个保持活动的信息。 系统缺省是0。通过一个Unix域套接字,或者如果禁用保持活动,可以为连接模式忽略该参数。 只有在Windows,或TCP_KEEPIDLETCP_KEEPALIVE套接字选项可用的操作系统 上才可以使用这个参数,在其他操作系统上,该参数无效。

keepalives_interval

控制空闲秒数,在这个秒数之后,一个服务器无法识别的TCP保持活动的信息应该被重新翻译。 系统缺省是0。通过一个Unix域套接字,或者如果禁用保持活动,可以为连接模式忽略该参数。 只有在Windows,或TCP_KEEPINTVL套接字选项可用的操作系统 上才可以使用这个参数,在其他操作系统上,该参数无效。

keepalives_count

控制那些在客户端到服务器端连接被认为dead之前会丢失的TCP保持连接的数目。 系统缺省是0。通过一个Unix域套接字,或者如果禁用保持活动,可以为连接模式忽略该参数。 只有在Windows,或TCP_KEEPINTVL套接字选项可用的操作系统 上才可以使用这个参数,在其他操作系统上,该参数无效。

tty

忽略(以前,这个选项声明服务器日志的输出方向)。

sslmode

这个选项决定是否需要和服务器协商一个SSL连接, 以及以什么样的优先级与服务器进行SSL连接。有六种模式可供 选择:

Table 31-1. sslmode选项

OptionDescription
disable只有尝试非SSL连接
allow 首次尝试非SSL 连接,如果失败,尝试SSL 连接
prefer(缺省) 首次尝试SSL 连接,如果失败,尝试非SSL 连接。
require仅尝试一个SSL连接
verify-ca 只尝试SSL连接,并通过可信任的CA验证 服务器证书。
verify-full 只尝试SSL连接,通过可信任的CA验证 服务器证书是和证书中 该服务器的主机名是否匹配。

了解这些选项的详细信息请查阅Section 31.17

sslmode被Unix域套接字沟通忽略 如果不支持SSL编译PostgreSQL的, 使用选项requireverify-ca,或 verify-full将导致一个错误,而 选项??allowprefer会 接受,但的libpq实际上不会尝试 SSL连接。

requiressl

这个选项因为有了sslmode设置之后已经废弃了。

如果设为1,则要求与服务器进行SSL联接 (等效于sslmode。 如果服务器不支持SSL,那么libpq 将马上拒绝联接。设置为0(缺省)与服务器进行协商连接类型(等效于 sslmode)。这个选项只有 在编译PostgreSQL时打开了SSL支持才有效。

sslcert

此参数指定的客户端SSL 证书文件名,替换默认 ~/.postgresql/postgresql.crt。 如果没有一个SSL连接,则忽略此参数。

sslkey

这个参数声明用于客户端认证的密钥的位置。要么声明一个文件名用于代替缺省的~/.postgresql/postgresql.key, 要么从外部"engine"获得并声明的一个关键字("engine"OpenSSL可加载模块)。 一个外部引擎声明得是由一个冒号分隔的引擎名称和一个特定引擎的密钥标识符组成。 如果不是SLL连接模式,那么忽略该参数。

sslrootcert

此参数指定的文件包含SSL的名称 证书颁发机构(CA)证书(S)。 如果该文件存在,服务器的证书 由这些机构签署确认。 默认是~/.postgresql/root.crt

sslcrl

这个参数声明的是CRL的文件名。如果存在,那么在这个文件中的声明列表在尝试认证服务器端认证时会使用。 缺省是~/.postgresql/root.crl

krbsrvname

当认证带有Kerberos 5或GSSAPI是使用的Kerberos服务名。 它必须匹配在Kerberos认证成功的服务器配置参数中声明的服务名。 (参阅Section 19.3.5Section 19.3.3)。

gsslib

用于GSSAPI认证的GSS库。只用于Windows操作系统。 设置gssapi强制libpq使用GSSAPI库以代替缺省的SSPI来认证。

service

用于额外参数的服务名。它在pg_service.conf里面声明一个服务名, 这个配置文件保 存额外的连接参数。这样就允许应用应用只声明一个服务名,而连接参数就可以在一 个地方维护了。参阅安装目录中的Section 31.15获取如何设置这个文 件的信息。

如果有任何没有声明的参数,那么将检查对应的环境变量 (参阅Section 31.13小节)。 如果环境变量也没有设置,那么使用编译时的指明的内置缺省。

如果expand_dbname非0,同时dbname中包含 一个=标记,它会看做是一个conninfo字符串, 以相同的方式传递到PQconnectdb中。之前的关键字会被conninfo 中的关键字代替。

通常情况下,关键字会从索引序列中的数组的开始进程处理。这样的话,如果关键字重复了,那么在这之前的最后一个 处理结果会被保留。因此,通过仔细防放置dbname关键字, 可以决定哪些方式可以通过conninfo字符串来覆盖,哪些不可以。

PQconnectdb

与服务器数据库服务器建立一个新的联接。

PGconn *PQconnectdb(const char *conninfo);

此函数打开一个新的数据库连接, 从字符串conninfo使用所采取的参数。

可以清空传递的字符串以使用所有的缺省参数,或包含一个或多个通过空格分开的参数设置。 每个参数设置是以keyword = value出现的。 等号两边的空格可以有,也可以没有。在写一个空值,或value中包含空格,可以在其两边使用单引号,如keyword = 'a value'。 在value中的单引号和反斜杠必须使用一个反斜杠来逃逸,如\'\\

目前公认的参数关键词是与上述相同。

PQsetdbLogin

Makes a new connection to the database server.

PGconn *PQsetdbLogin(const char *pghost,
                     const char *pgport,
                     const char *pgoptions,
                     const char *pgtty,
                     const char *dbName,
                     const char *login,
                     const char *pwd);

这个函数是PQconnectdb前身, 它有固定个数的参数。它有相同的功能, 只是在调用中那些它缺少的参数总是用缺省值。如果么给任意的固定参数设置缺省值, 那么写一个NULL或者一个空字串给它们。

如果的dbName包含=符号,它 作为的conninfo字符串完全相同的方式 如果它已通过PQconnectdb,其余 上述参数然后被应用。

PQsetdb

与服务器数据库服务器建立一个新的联接。

PGconn *PQsetdb(char *pghost,
                char *pgport,
                char *pgoptions,
                char *pgtty,
                char *dbName);

这是一个调用PQsetdbLogin的宏, 只是loginpwd参数null代替。 提供这个函数是为了与非常老版本的程序兼容

PQconnectStartParams
PQconnectStart
PQconnectPoll

与数据库服务器建立一次非阻塞的联接。

PGconn *PQconnectStartParams(const char **keywords,const char **values,int expand_dbname);


PGconn *PQconnectStart(const char *conninfo);


PostgresPollingStatusType PQconnectPoll(PGconn *conn);

这3个函数用于打开一个与数据库服务器之间的非阻塞的联接: 你的应用的执行线索在执行它的时候不会因远端的I/O而阻塞。 这个方法的要点是等待I/O结束可以发生在应用的主循环里, 而不是在PQconnectdbParamsPQconnectdb里, 这样应用可以把这件事与其它操作并发起来一起执行。

通过PQconnectStartParams,数据库连接使用来自keywordsvalues数组的参数,并且通过expand_dbname控制,如在PQconnectdbParams 中的描述。

数据库联接是用从conninfo字符串里取得的参数传递给 PQconnectStart进行的。 这个字符串的格式与上面PQconnectdb里描述的一样

PQconnectStartParamsPQconnectStartPQconnectPoll 都不会阻塞,只要有一些限制。

  • 必须正确提供hostaddrhost参数以确保不会发生正向或者反向的名字查找。 参阅上面PQconnectdbParams里的这些参数的文档获取细节。

  • 如果你调用了PQtrace,确保你跟踪进入的流对象不会阻塞。

  • 你必须在调用PQconnectPoll之前确保socket处于正确的状态, 象下面描述的那样。

注意:PQconnectStartParams是类似于PQconnectStart如下所示。

要开始一次非阻塞连接请求,调用 conn = PQconnectStart("connection_info_string")。 如果conn是空,表明libpq无法分配一个新的PGconn结构。 否则,返回一个有效的PGconn指针 (尽管还不一定代表一个与数据库有效联接)。PQconnectStart一返回,调用 status = PQstatus(conn)。 如果status等于CONNECTION_BADPQconnectStart失败。

如果PQconnectStart成功了,下一个阶段是轮询libpq,这样它就可以继续连接序列动作。 使用PQsocket(conn)获取数据库链接下层的套接字描述符。象这样循环: 如果PQconnectPoll(conn)的最后一个返回是PGRES_POLLING_READING,那么就等到套接 字准备好被读取了的时候(就像系统函数select()poll(),或者类似的系统调用声明的那样)。 然后再次调用PQconnectPoll(conn)。同样,如果PQconnectPoll(conn)最后返 回PGRES_POLLING_WRITING,那么就等到套接字准备好可以写了,然后再次调用PQconnectPoll(conn)。 如果你还没调用PQconnectPoll,比如,刚刚调用完PQconnectStart,那么按照它刚 返回PGRES_POLLING_WRITING的原则行动。继续这个循环直到PQconnectPoll(conn)返 回PGRES_POLLING_FAILED,表明连接失败,或者PGRES_POLLING_OK,表明连接成功建立。

在联接的任意时刻,我们都可以通过调用PQstatus来检查联接的状态。 如果这是CONNECTION_BAD,那么联接过程失败;如果是CONNECTION_OK,那么联接已经做好。 这两种状态同样也可以从上面的PQconnectPoll的返回值里检测到。其他状态可能(也只能) 在一次异步联接过程中发生。这些标识联接过程的当前状态,因而可能对给用户提供反馈有帮助。 这些状态可能包括:

CONNECTION_STARTED

等待进行联接。

CONNECTION_MADE

联接成功;等待发送

CONNECTION_AWAITING_RESPONSE

等待来自服务器的响应。

CONNECTION_AUTH_OK

已收到认证;等待联接启动继续进行。

CONNECTION_SSL_STARTUP

协商SSL加密。

CONNECTION_SETENV

协商环境驱动的参数设置。

注意,尽管这些常量将保持下去(为了维持兼容性),应用决不应该依赖于这些常 量以某种特定顺序出现,或者是根本不应依赖于这些常量,或者是不应该依赖于这些 状态总是某个文档声明的值。一个应用可能象象下面这样:

switch(PQstatus(conn))
{
        case CONNECTION_STARTED:
            feedback = "Connecting...";
            break;

        case CONNECTION_MADE:
            feedback = "Connected to server...";
            break;
.
.
.
        default:
            feedback = "Connecting...";
}

在使用PQconnectPoll的时候,连接参数connect_timeout将被忽略; 判断是否超时是应用的责任。否则,后面跟着一个PQconnectPoll循环的 PQconnectStart等效于PQconnectdb

要注意如果PQconnectStart返回一个非空的指针,你必须在使用完它(指针)之后调用 PQfinish, 以处理那些结构和所有相关的存储块,甚至连接失败时也要这样处理。

PQconndefaults

返回缺省的联接选项。

PQconninfoOption *PQconndefaults(void);

typedef struct
{
    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;  /* Indicates how to display 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 */
} PQconninfoOption;

返回一个连接选项数组。可以用于获取所有可能的PQconnectdb选项和它们的当前缺省值。 返回值指向一个PQconninfoOption结构的数组,该数组以一个有NULLkeyword指针的条目结束。 如果无法分配内存,则返回空指针。注意缺省值(val域)将依赖于环境变量和其他环境。 调用者必须把连接选项当作只读对待。

在处理完选项数组后,把数组交给PPQconninfoFree释放。如果没有这么做, 每次调用PQconndefaults都会有一小部分内存泄漏。

PQconninfoParse

返回解析提供的连接字符串的连接选项。

PQconninfoOption *PQconninfoParse(const char *conninfo,char **errmsg);

解析一个连接字符串,并返回结果选项为一个数组,或这,如果连接字符串有问题,那么返回一个NULL。 这个可以用于决定在提供的连接字符串中的PQconnectdb选项。 返回值指向一个PQconninfoOption结构的数组,这个结构一个带有空keyword指针 的条目结束。

需要注意的是,只有明确在字符串中声明的选项可以在结果数组中的设置中有参数值;没有缺省的话是插入。

如果errmsgNULL,那么成功的时候,*errmsg被设置为NULL, 否则设置为malloc的错误字符串以说明错误。 (也可以将*errmsg设置为NULL,即使返回一个NULL;这表示内存溢出)。

在处理完选项数组之后,通过将其传递给PQconninfoFree来进行释放。 如果没有这么做,那么每个PQconninfoParse的请求时会有一些内存溢出。 反过来,如果发生错误并且errmsgNULL,通过PQfreemem 来释放错误字符串。

PQfinish

关闭与服务器的连接。同时释放被PGconn对象使用的存储器。

void PQfinish(PGconn *conn);

注意,即使与服务器的连接尝试失败(可由PQstatus判断),应用也要 调用PQfinish释放被PGconn对象使用的存储器。 不应该在调用PQfinish后再使用PGconn 指针。

PQreset

重置与服务器的通讯端口。

void PQreset(PGconn *conn);

此函数将关闭与服务器的连接并且试图与同一个服务器重建新的连接, 使用所有前面使用过的参数。这在失去工作连接后进行故障恢复时很有用。

PQresetStart
PQresetPoll

以非阻塞模式重置与服务器的通讯端口。

int PQresetStart(PGconn *conn);

PostgresPollingStatusType PQresetPoll(PGconn *conn);

此函数将关闭与服务器的连接并且试图与同一个服务器重建新的连接,使用所有前面使用过的参数。 这在失去工作连接后进行故障恢复时很有用。它们和上面的PQreset的区别是它们工作在非阻塞模式。 这些函数的使用有与上面PQconnectStartParamsPQconnectStartPQconnectPoll一样的限制。

要发起一次连接重置,调用PQresetStart。如果它返回0,那么重置失败。 如果返回1,用与使用PQresetPoll建立连接的同样的方法使用PQconnectPoll重置连接。