34.2. 连接状态函数
这些函数可以被用来询问一个已有数据库连接对象的状态。
提示
libpq应用程序员应该小心地维护PGconn抽象。使用下面描述的访问函数来理解PGconn的内容。我们不推荐使用libpq-int.h引用内部的PGconn域,因为它们可能在未来改变。
下列函数返回一个连接所建立的参数值。这些值在连接的生命期中是固定的。如果使用的是多主机连接字符串,如果使用同一个PGconn对象建立新连接,PQhost、PQport以及PQpass可能会改变。其他值在PGconn对象的一生中都是固定的。
PQdb : 返回该连接的数据库名。
```synopsis
char *PQdb(const PGconn *conn);
```
PQuser : 返回该连接的用户名。
```synopsis
char *PQuser(const PGconn *conn);
```
PQpass : 返回该连接的口令。
```synopsis
char *PQpass(const PGconn *conn);
```
`PQpass`将返回连接参数中指定的口令,如果连接参数中没有口令并且能从[口令文件](libpq-pgpass.md "34.15. 口令文件")中得到口令,则它将返回得到的口令。在后一种情况中,如果连接参数中指定了多个主机,在连接被建立之前都不能依赖`PQpass`的结果。连接的状态可以用函数`PQstatus`检查。
PQhost : 返回活跃连接的服务器主机名。可能是主机名、IP 地址或者一个目录路径(如果通过 Unix 套接字连接,路径的情况很容易区分,因为路径总是一个绝对路径,以/开始)。
```synopsis
char *PQhost(const PGconn *conn);
```
如果连接参数同时指定了`host`和`hostaddr`,则`PQhost`将返回`host`信息。如果仅指定了`hostaddr`,则返回它。如果在连接参数中指定了多个主机,`PQhost`返回实际连接到的主机。
如果**`conn`**参数是`NULL`,则`PQhost`返回`NULL`。否则,如果有一个错误产生主机信息(或许是连接没有被完全建立或者有什么错误),它会返回一个空字符串。
如果在连接参数中指定了多个主机,则在连接建立之前都不能依赖于`PQhost`的结果。连接的状态可以用函数`PQstatus`检查。
PQport : 返回活跃连接的端口。
```synopsis
char *PQport(const PGconn *conn);
```
如果在连接参数中指定了多个端口,`PQport`返回实际连接到的端口。
如果**`conn`**参数是`NULL`,则`PQport`返回`NULL`。否则,如果有一个错误产生端口信息(或许是连接没有被完全建立或者有什么错误),它会返回一个空字符串。
如果在连接参数中指定了多个端口,则在连接建立之前都不能依赖于`PQport`的结果。连接的状态可以用函数`PQstatus`检查。
PQtty : 返回该连接的调试TTY(这已被废弃,因为服务器不再关心TTY设置,但这个函数保持了向后兼容)。
```synopsis
char *PQtty(const PGconn *conn);
```
PQoptions : 返回被传递给连接请求的命令行选项。
```synopsis
char *PQoptions(const PGconn *conn);
```
下列函数返回会随着在PGconn对象上执行的操作改变的状态数据。
PQstatus : 返回该连接的状态。
```synopsis
ConnStatusType PQstatus(const PGconn *conn);
```
该状态可以是一系列值之一。不过,其中只有两个在一个异步连接过程之外可见:`CONNECTION_OK`和`CONNECTION_BAD`。一个到数据库的完好连接的状态为`CONNECTION_OK`。一个失败的连接尝试则由状态`CONNECTION_BAD`表示。通常,一个 OK 状态将一直保持到`PQfinish`,但是一次通信失败可能导致该状态过早地改变为`CONNECTION_BAD`。在那种情况下,该应用可以通过调用`PQreset`尝试恢复。
关于其他可能会被返回的状态代码,请见`PQconnectStartParams`、`PQconnectStart`和`PQconnectPoll`的条目。
PQtransactionStatus : 返回服务器的当前事务内状态。
```synopsis
PGTransactionStatusType PQtransactionStatus(const PGconn *conn);
```
该状态可能是`PQTRANS_IDLE`(当前空闲)、`PQTRANS_ACTIVE`(一个命令运行中)、`PQTRANS_INTRANS`(空闲,处于一个合法的事务块中)或者`PQTRANS_INERROR`(空闲,处于一个失败的事务块中)。如果该连接损坏,将会报告`PQTRANS_UNKNOWN`。只有当一个查询已经被发送给服务器并且还没有完成时,才会报告`PQTRANS_ACTIVE`。
PQparameterStatus : 查找服务器的一个当前参数设置。
```synopsis
const char *PQparameterStatus(const PGconn *conn, const char *paramName);
```
某一参数值会被服务器在连接开始或值改变时自动报告。`PQparameterStatus`可以被用来询问这些设置。它为已知的参数返回当前值,为未知的参数返回`NULL`。
自当前发布开始会被报告的参数包括
`server_version`、
`server_encoding`、
`client_encoding`、
`application_name`、
`is_superuser`、
`session_authorization`、
`DateStyle`、
`IntervalStyle`、
`TimeZone`、
`integer_datetimes`以及
`standard_conforming_strings`(
`server_encoding`、`TimeZone`以及`integer_datetimes`在 8.0 以前的发布中不被报告;`standard_conforming_strings`在 8.1 以前的发布中不被报告;`IntervalStyle`在 8.4 以前的发布中不被报告;`application_name`在 9.0 以前的发布中不被报告)。注意
`server_version`、
`server_encoding`以及
`integer_datetimes`在启动之后无法改变。
3.0 之前协议的服务器不报告参数设置,但是libpq包括获得`server_version`以及`client_encoding`值的逻辑。我们鼓励应用使用`PQparameterStatus`而不是**ad hoc**代码来确定这些值(不过注意在一个 3.0 之前的连接上,连接开始后通过`SET`改变`client_encoding`不会被`PQparameterStatus`反映)。对于`server_version`(另见`PQserverVersion`),它以一种数字形式返回信息,这样更容易进行比较。
如果没有为`standard_conforming_strings`报告值,应用能假设它是`off`,也就是说反斜线会被视为字符串中的转义。还有,这个参数的存在可以被作为转义字符串语法(`E'...'`)被接受的指示。
尽管被返回的指针被声明成`const`,它事实上指向与`PGconn`结构相关的可变存储。假定该指针在存储之间保持有效是不明智的。
PQprotocolVersion : 询问所使用的 前端/后端协议。
```synopsis
int PQprotocolVersion(const PGconn *conn);
```
应用可能希望用这个函数来确定某些特性是否被支持。当前,可能值是 2(2.0 协议)、3(3.0 协议)或零(连接损坏)。协议版本在连接启动完成后将不会改变,但是理论上在连接重置期间是可以改变的。当与PostgreSQL 7.4 或以后的服务器通信时通常使用 3.0 协议,7.4 之前的服务器只支持协议 2.0(协议 1.0 已被废弃并且不再被libpq支持)。
PQserverVersion : 返回一个表示服务器版本的整数。
```synopsis
int PQserverVersion(const PGconn *conn);
```
应用可能会使用这个函数来判断它们连接到的数据库服务器的版本。结果通过将服务器的主版本号乘以10000再加上次版本号形成。例如,版本10.1将被返回为100001,而版本11.0将被返回为110000。如果连接无效则返回零。
在主版本10之前,PostgreSQL采用一种由三个部分组成的版本号,其中前两部分共同表示主版本。对于那些版本,`PQserverVersion`为每个部分使用两个数字,例如版本9.1.5将被返回为90105,而版本9.2.0将被返回为90200。
因此,出于判断特性兼容性的目的,应用应该将`PQserverVersion`的结果除以100而不是10000来判断逻辑的主版本号。在所有的发行序列中,只有最后两个数字在次发行(问题修正发行)之间不同。
PQerrorMessage : 返回连接上的一个操作最近产生的错误消息。
```synopsis
char *PQerrorMessage(const PGconn *conn);
```
几乎所有的libpq在失败时都会为`PQerrorMessage`设置一个消息。注意按照libpq习惯,一个非空`PQerrorMessage`结果由多行构成,并且将包括一个尾部新行。调用者不应该直接释放结果。当相关的`PGconn`句柄被传递给`PQfinish`时,它将被释放。在`PGconn`结构上的多个操作之间,不能指望结果字符串会保持不变。
PQsocket : 获得到服务器连接套接字的文件描述符号。一个合法的描述符将会大于等于零。结果为 -1 表示当前没有打开服务器连接(在普通操作期间这将不会改变,但是在连接设置或重置期间可能改变)。
```synopsis
int PQsocket(const PGconn *conn);
```
PQbackendPID : 返回处理这个连接的后端进程的进程ID(PID)。
```synopsis
int PQbackendPID(const PGconn *conn);
```
后端PID有助于调试目的并且可用于与`NOTIFY`消息(它包括发出提示的后端进程的PID)进行比较。注意PID属于一个在数据库服务器主机上执行的进程,而不是本地主机进程!
PQconnectionNeedsPassword : 如果连接认证方法要求一个口令但没有可用的口令,返回真(1)。否则返回假(0)。
```synopsis
int PQconnectionNeedsPassword(const PGconn *conn);
```
这个函数可以在连接尝试失败后被应用于决定是否向用户提示要求一个口令。
PQconnectionUsedPassword : 如果连接认证方法使用一个口令,返回真(1)。否则返回假(0)。
```synopsis
int PQconnectionUsedPassword(const PGconn *conn);
```
这个函数能在一次连接尝试失败或成功后用于检测该服务器是否要求一个口令。
下面的函数返回与 SSL 有关的信息。这些信息在连接建立后通常不会改变。
PQsslInUse : 如果该连接使用了 SSL 则返回真(1),否则返回假(0)。
```synopsis
int PQsslInUse(const PGconn *conn);
```
PQsslAttribute : 返回关于该连接的有关 SSL 的信息。
```synopsis
const char *PQsslAttribute(const PGconn *conn, const char *attribute_name);
```
可用的属性列表取决于使用的 SSL 库以及连接类型。如果一个属性不可用,
会返回 NULL。
下列属性通常是可用的:
`library`
: 正在使用的 SSL 实现的名称(当前只实现了
`"OpenSSL"`)
`protocol`
: 正在使用的 SSL/TLS 版本。常见的值有`"TLSv1"`、
`"TLSv1.1"`以及`"TLSv1.2"`,但是如果
一种实现使用了其他协议,可能返回其他字符串。
`key_bits`
: 加密算法所使用的密钥位数。
`cipher`
: 所使用的加密套件的简短名称,例如
`"DHE-RSA-DES-CBC3-SHA"`。这些名称与每一种
SSL 实现相关。
`compression`
: 如果正在使用 SSL 压缩,则返回压缩算法的名称。如果使用了压缩
但是算法未知则返回 "on" 。如果没有使用压缩,则返回 "off"。
PQsslAttributeNames : 返回一个可用的 SSL 名称的数组。该数组以一个 NULL 指针终结。
```synopsis
const char * const * PQsslAttributeNames(const PGconn *conn);
```
PQsslStruct : 返回一个描述该连接的 SSL 实现相关的对象指针。
```synopsis
void *PQsslStruct(const PGconn *conn, const char *struct_name);
```
可用的结构,这些结构取决于使用的 SSL 实现。对于 OpenSSL,有一个结构可用,
其名称为 "OpenSSL"。它返回一个指向该 OpenSSL `SSL` 结构
的指针。要使用这个函数,可以用下面的代码:
```programlisting
#include <libpq-fe.h>
#include <openssl/ssl.h>
...
SSL *ssl;
dbconn = PQconnectdb(...);
...
ssl = PQsslStruct(dbconn, "OpenSSL");
if (ssl)
{
/* 使用 OpenSSL 函数来访问 ssl */
}
```
这个结构可以被用来验证加密级别、检查服务器证书等等。有关这个结构
的信息请参考OpenSSL的文档。
PQgetssl : 返回连接中使用的 SSL 结构,如果没有使用 SSL 则返回空。
```synopsis
void *PQgetssl(const PGconn *conn);
```
这个函数等效于`PQsslStruct(conn, "OpenSSL")`。在新的应用中不应该使用它,因为被返回的结构是 OpenSSL 专用的,如果使用了另一种 SSL 实现就不再可用。要检查一个连接是否使用 SSL,应该调用`PQsslInUse`,而要得到有关连接的更多细节应该使用`PQsslAttribute`。
