数据库编程接口Libpq 2

来源:互联网 发布:聚类算法的作用 编辑:程序博客网 时间:2024/05/01 20:32

1.4 异步函数

    使用函数PQexec执行SQL命令很方便,但也有下面的缺点:

·         PQexec 必须等到发出的命令执行结束才会返回,如果命令执行的时间比较长,应用程序将长时间处于等待状态,不能响应用户的其它请求,降低了程序的交互性。    

·         PQexec如果一次执行多条命令,只有最后一条命令的PGresult才会被返回,前面的命令的PGresult会被丢弃

    Libpq同时提供了异步函数来执行SQL命令,这些函数不用等到命令执行完就可以返回。但这些异步函数使用起来比PQexec这样的同步函数要复杂得多。下面列出了这些函数:

 

PQsendQuery

发送一条命令给服务器,然后立即返回。返回值是1表示命令成功地传给服务器。返回值是0表示命令没有成功地传给服务器(调用函数PQerrorMessage得到详细的错误信息)。

        int PQsendQuery(PGconn *conn, const char *command);
       

PQsendQuery执行成功以后,调用PQgetResult一次或多次来得到查询返回的结果。直到PQgetResult返回一个空指针,才能在同一个连接上再次调用PQsendQuery

 

PQsendQueryParams

发送一个命令给数据库执行,然后立即返回。这个函数可以执行带参数的SQL命令。

Submits a command and separate parameters to the server without waiting for the result(s).

        int PQsendQueryParams(PGconn *conn,
                              const char *command,
                              int nParams,
                              const Oid *paramTypes,
                              const char * const *paramValues,
                              const int *paramLengths,
                              const int *paramFormats,
                              int resultFormat);
       

函数的参数与PQexecParams一样。一次只能执行一条SQL命令。

 

PQsendPrepare

发一个请求给数据库,要求创建一个准备好的SQL语句,然后立即返回。

 

 

        int PQsendPrepare(PGconn *conn,
                          const char *stmtName,
                          const char *query,
                          int nParams,
                          const Oid *paramTypes);
       

它是PQprepare的异步版本,它的参数与PQprepare也是一样的。返回1表示请求成功地传给服务器。返回0表示请求没有成功地传给服务器。函数执行成功以后,调用PQgetResult确定准备好的语句是否被成功地创建。

 

PQsendQueryPrepared

 

给服务发送一个执行一条准备好的语句的请求,然后立即返回。

 

        int PQsendQueryPrepared(PGconn *conn,
                                const char *stmtName,
                                int nParams,
                                const char * const *paramValues,
                                const int *paramLengths,
                                const int *paramFormats,
                                int resultFormat);
       

它的参数与PQexecPrepared是一样的。

 

PQsendDescribePrepared

给服务发送一个得到一条准备好的语句的信息的请求,然后立即返回。

 

        int PQsendDescribePrepared(PGconn *conn, const char *stmtName);
       

 

这个函数的参数与PQdescribePrepared是一样的。返回1表示请求成功地传给服务器。返回0表示请求没有成功地传给服务器。函数执行成功以后,调用PQgetResult得到命令执行的结果。

 

 

PQgetResult

取前面被调用的PQsendQueryPQendQueryParamsPQsendPreparePQendQueryPrepared函数发出的命令的下一个执行结果。如果返回一个空指针表示命令已经执行结束,所有的结果已被取回。

 
        PGresult *PQgetResult(PGconn *conn);
       

应当多次重复调用这个函数直到它返回一个空指针,表示前面发出的命令已经执行结束。如果没有命令在执行,PQgetResult会立即返回一个空指针。注意调用PQgetResult时,它可能会处在等待状态,因为命令仍然在执行,结果还没有产生。

 

 

    如果一条命令包含多条SQL查询,使用PQgetResult就能得到每一个SQL查询返回的查询结果。因为调用PQgetResult时,仍然可能进入等待状态, Libpq提供了PQconsumeInputPQisBusy 这两个函数来解决这个问题:

 

PQconsumeInput

如果服务器有数据要发送给客户端,直接读这些数据到客户端。

        int PQconsumeInput(PGconn *conn);

 

函数返回1表示执行成功,函数返回0表示执行失败(调用PQrrorMessage得到详细的错误信息)。

 

PQisBusy

返回1表示发送给服务器的命令正在执行,如果调用PQgetResult,会处于等待的状态。返回0表示服务器已经准备好数据,调用PQgetResult可以立即得到命令执行的结果。

        int PQisBusy(PGconn *conn);
       

PQisBusy不会尝试从服务器读数据,必须先调用PQconsumeInput,再调用PQisBusy

 

    使用PQsendQuery/PQgetResult进行异步命令处理的客户端也可以调用PQcancel终止一个正在被服务器执行的命令,详细信息参考本章第1.5小节。但即使一个命令被终止执行以后,客户端也必须调用PQgetResult得到命令已经返回的结果,PQcancel只是让一个命令提前结束执行,但这个命令结束以前产生的结果仍然是有效的。

 

    如果客户端发送很长的命令给服务器或者使用COPY IN传送大量数据给服务器,此时客户端可能在传送数据的过程中处于等待的状态。Libpq提供了下面的函数可以让数据库连接在非阻塞的状态下运行。

 

PQsetnonblocking

设置数据库连接的阻塞模式。

 

        int PQsetnonblocking(PGconn *conn, int arg);
       

如果参数arg的值是1,连接将处于非阻塞模式。如果参数arg的值是0,连接将处于阻塞模式。函数返回0表示执行成功,函数返回-1表示执行失败。

 

如果连接处于阻塞模式,函数PQsendQueryPQendcopy如果不能立即将数据传递给服务器,将立即返回一个错误,而不是进入等待状态。

 

函数PQexec不受连接的阻塞模式的影响,无论连接是否处于阻塞模式,它都会等到命令执行完以后才返回。

 

PQisnonblocking

返回数据库连接的阻塞模式。

        int PQisnonblocking(const PGconn *conn);
       

返回1表示连接处于非阻塞模式,返回0表示连接处于阻塞模式。

 

PQflush

将客户端所有的还没有发送给服务器的数据发送给服务器。如果成功,返回0。如果遇到错误,返回-1。返回1表示只成功地发送了一部分数据(只有在连接处于非阻塞的模式下才可能返回1)。

 

        int PQflush(PGconn *conn);
       

      在非阻塞的连接上发送了任何命令给数据库以后,都应该调用PQflush。如果它返回1,应该等待一段时间后再调用PQflush,直到它返回0

1.5 终止正在执行的查询
客户端可以发送请求给服务器,要求终止正在被服务器执行的命令。本节介绍的函数就实现了这样的功能。

PQgetCancel

创建一个数据结构,这个数据结构包含终止正在被服务器执行的命令需要的所有信息。

PGcancel *PQgetCancel(PGconn *conn);
函数返回一个指向PQcancel对象的指针。如果参数conn的值是NULL或者指向一个非法的连接,函数将返回NULL。可以将函数返回的指针作为参数传给PQcancel PQfreeCancel

PQfreeCancel

释放PQgetCancel创建的PQcancel对象占用的内存。

void PQfreeCancel(PGcancel *cancel);


PQcancel
要求服务器终止正在执行的命令。

int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize);

返回值是1表示请求成功地传递给服务器。返回值是0表示请求没有被成功地传递给服务器。如果函数返回0,参数errbuf指向的缓冲区中将存有具体的错误信息。参数errbufsize指明errbuf指向的缓冲区的大小,单位是字节,推荐值是256。

即使请求被成功地发送给服务器,也不代表请求会生效。如果请求被成功地执行,正在执行的命令会被终止,并给客户端返回一个错误结果。如果请求没有被成功地执行(因为被终止的命令已经执行结束),服务器不会返回任何结果给客户端。

可以在信号处理程序(signal handler)内部调用PQcancelerrbuf必须是信号处理程序的局部变量。
1.5 终止正在执行的查询
客户端可以发送请求给服务器,要求终止正在被服务器执行的命令。本节介绍的函数就实现了这样的功能。

PQgetCancel

创建一个数据结构,这个数据结构包含终止正在被服务器执行的命令需要的所有信息。

PGcancel *PQgetCancel(PGconn *conn);
函数返回一个指向PQcancel对象的指针。如果参数conn的值是NULL或者指向一个非法的连接,函数将返回NULL。可以将函数返回的指针作为参数传给PQcancel PQfreeCancel

PQfreeCancel

释放PQgetCancel创建的PQcancel对象占用的内存。

void PQfreeCancel(PGcancel *cancel);


PQcancel
要求服务器终止正在执行的命令。

int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize);

返回值是1表示请求成功地传递给服务器。返回值是0表示请求没有被成功地传递给服务器。如果函数返回0,参数errbuf指向的缓冲区中将存有具体的错误信息。参数errbufsize指明errbuf指向的缓冲区的大小,单位是字节,推荐值是256。

即使请求被成功地发送给服务器,也不代表请求会生效。如果请求被成功地执行,正在执行的命令会被终止,并给客户端返回一个错误结果。如果请求没有被成功地执行(因为被终止的命令已经执行结束),服务器不会返回任何结果给客户端。

可以在信号处理程序(signal handler)内部调用PQcancelerrbuf必须是信号处理程序的局部变量。
1.6 注意(Notice)消息处理
服务器产生的注意(Notice)和警告(Warning) 消息不会被执行查询的函数(如PQexec)返回。这些消息被传递给客户端的注意消息处理函数,注意消息处理函数执行完以后,客户端会继续执行其它的操作。Libpq提供的默认的注意消息处理函数只是将注意和警告消息输出到stderr,应用程序也可以使用自己定义的消息处理函数。


实际上,客户端收到服务器产生的注意和警告消息以后,会首先调用一个注意消息接收函数,然后再调用一个注意消息处理函数。默认的注意消息接收函数格式化收到的注意消息,然后把格式化以后的消息发给注意消息处理函数。默认的消息处理函数将输出收到的格式化以后的消息。应用程序可以只提供自己的注意消息接收函数,在这个函数里完成所有的工作。


应用程序可以使用函数PQnoticeReceiver来注册和查询注意消息接受函数,使用函数PQsetNoticeProcessor来注册和查询注意消息处理函数。

typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res);
PQnoticeReceiver

PQsetNoticeReceiver(PGconn *conn,

PQnoticeReceiver proc,

void *arg);

typedef void (*PQnoticeProcessor) (void *arg, const char *message);

PQnoticeProcessor

PQsetNoticeProcessor(PGconn *conn,

PQnoticeProcessor proc,

void *arg);

这两个函数都返回指向以前使用的注意消息接收函数或注意消息处理函数的指针,并且设置新的注意消息接收函数或注意消息处理函数。如果参数PQnoticeReceiver或PQnoticeProcessor的值为NULL,这两个函数什么都不会做,只是返回指向当前使用的注意消息接收函数或注意消息处理函数的指针。


只要客户端收到服务器发送过来的注意或警告消息,或者libpq自身产生的注意或警告消息,注意消息接收函数就会被调用。注意消息接收函数使用PQresultErrorFieldPQresultErrorMessage来得到消息的细节。


默认的注意消息接收函数调用PQresultErrorMessage得到具体的消息的内容,然后把它传给注意消息处理函数。


默认的注意消息处理函数的定义如下:
static voiddefaultNoticeProcessor(void *arg, const char *message){
fprintf(stderr, "%s", message);
}

注意消息接收函数和注意消息处理函数与PGconn对象相关,不同的数据库连接可以设置不同的注意消息接收函数和注意消息处理函数
原创粉丝点击