PostgreSQL数据库学习手册之libpq.docx_第1页
PostgreSQL数据库学习手册之libpq.docx_第2页
PostgreSQL数据库学习手册之libpq.docx_第3页
PostgreSQL数据库学习手册之libpq.docx_第4页
PostgreSQL数据库学习手册之libpq.docx_第5页
已阅读5页,还剩71页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

PostgreSQL数据库学习手册之libpq - C 库-介绍(转)moreChapter 1. libpq - C 库Table of Contents1.1. 介绍1.2. 数据库联接函数1.3. 命令执行函数1.3.1. 主过程1.3.2. 为包含在 SQL 查询中逃逸字串1.3.3. 逃逸包含在 SQL 查询中的二进制字串1.3.4. 检索 SELECT 的结果信息1.3.5. 检索 SELECT 结果数值1.3.6. 检索非-SELECT 结果信息1.4. 异步查询处理1.5. 捷径接口1.6. 异步通知1.7. 与 COPY 命令相关的函数1.8. libpq 跟踪函数1.9. libpq 控制函数1.10. 环境变量1.11. 文件1.12. 线程特性1.13. 制作 Libpq 程序1.14. 例子程序1.1. 介绍libpq 是 PostgreSQL的 C 应用程序员的接口 libpq 是一套允许客户程序向 PostgreSQL 后端服务进程发送查询 并且获得查询返回的库过程 libpq 同时也是其他几个 PostgreSQL 应用接口下面的引擎, 包括 libpq+ (C+), libpgtcl(Tcl),Perl,和 ecpg所以如果你使用这些软件包, libpq某些方面的特性会对你非常重要本节末尾有三个小程序显示如何利用 libpq书写程序 在下面目录里面有几个完整的 libpq 应用的例子:src/test/examplessrc/bin/psql使用 libpq 的前端程序必须包括头文件 libpq-fe.h 并且必须与 libpq 库链接PostgreSQL数据库学习手册之libpq-C库-数据库联接函数(转)more1.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 PQconninfoOptionchar *keyword; /* The keyword of the option */char *envvar; /* Fallback environment variable name */char *compiled; /* Fallback compiled in default value */char *val; /* Options current value, or NULL */char *label; /* Label for field in connect dialog */char *dispchar; /* Character to display for this fieldin a connect dialog. Values are: Display entered value as is* Password field - hide valueD Debug option - dont 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 没有使用的话返回 NULLSSL *PQgetssl(const PGconn *conn);这个结构可以用于核实加密级别,检查服务器认证等信息参考 SSL 文档获取关于这个结构的更多信息为了获取这个函数的原形,你必须定义 USE_SSL 这样做会自动包含来自OpenSSL的 ssl.h PostgreSQL数据库学习手册之libpq-C库-命令执行函数(转)more1.3. 命令执行函数一旦与数据库服务器的联接成功建立,便可用这里描述的函数执行 SQL 查询和命令。1.3.1. 主过程*PQexec 给服务器提交一条命令并且等待结果PGresult *PQexec(PGconn *conn,const char *query);返回一个PGresult指针或者也可能是一个 NULL 指针 通常返回一个非空(non-NULL)的指针, 除非没有内存或发生了象不能把命令发送到后端这样的严重错误 如果返回的是 NULL,它应该被当作PGRES_FATAL_ERROR结果处理 用PQerrorMessage获取有关错误的更多信息PGresult 结构封装了后端返回的结果 libpq 应用程序员应该仔细维护PGresult抽象用下面的访问函数来获取PGresult的内容避免直接引用 PGresult结构的数据域,因为这个结构可能会在未来被改变(从 PostgreSQL 版本 6.4 开始, struct PGresult的定义甚至都没有放在 libpq-fe.h里如果你有一些直接访问 PGresult数据域的老代码,你可以通过包含libpq-int.h继续使用它们,但是我们鼓励你立刻修改代码)*PQresultStatus 返回命令的结果状态ExecStatusType PQresultStatus(const PGresult *res)PQresultStatus可以返回下面数值之一:oPGRES_EMPTY_QUERY - 发送给后端的字串是空的oPGRES_COMMAND_OK - 成功完成一个没有返回数据的命令oPGRES_TUPLES_OK - 成功执行查询oPGRES_COPY_OUT - (从服务器)Copy Out (拷贝出)数据传输开始oPGRES_COPY_IN - Copy In (拷贝入)(到服务器)数据传输开始oPGRES_BAD_RESPONSE - 服务器的响应无法理解oPGRES_NONFATAL_ERRORoPGRES_FATAL_ERROR如果结果状态是 PGRES_TUPLES_OK ,那么可以用下面的过程从查询的返回中抽取元组信息注意一个碰巧检索了零条元组的 SELECT 仍然显示 PGRES_TUPLES_OK。 PGRES_COMMAND_OK用于不返回元组的命令(INSERT,UPDATE,等)。返回 PGRES_EMPTY_QUERY 的响应通常意味着客户端软件里面的臭虫。*PQresStatus 把PQresultStatus返回的枚举类型转换成一个描述状态码的字符串常量。char *PQresStatus(ExecStatusType status);*PQresultErrorMessage 返回与查询关联的错误信息,或在没有错误时返回一个空字符串char *PQresultErrorMessage(const PGresult *res);紧跟在一个 PQexec 或 PQgetResult 调用后面,PQerrorMessage (对联接)将返回与 PQresultErrorMessage (对结果)一样的字符串不过,一个PGresult将保有其错误信息直到被删除,而连结的错误信息将在后续的操作完成时被改变当你想知道与某个 PGresult相关联的状态时用 PQresultErrorMessage ;当你想知道与联接的最近一个操作相关联的状态时用 PQerrorMessage;*PQclear 释放于PGresult相关联的存储空间 任何不再需要的查询结果在不需要的时候都应该用 PQclear释放掉void PQclear(PQresult *res);你可以保留PGresult对象任意长的时间; 当你提交新的查询时它并不消失, 甚至你断开联接后也是这样要删除它,你必须调用 PQclear不这么做将导致前端的存储器泄漏*PQmakeEmptyPGresult 构造一个给出状态的为空的PGresult对象PGresult* PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status);这是libpq的内部过程, 用于分配和初始化一个空PGresult对象 它被输出是因为一些应用需要自行生成结 果对象(尤其是特定的带有错误状态的对象) 如果conn非空(NULL)并且状态指示一个错误, 联接当前的错误信息被拷贝到PGresult 注意最终对该对象要调用PQclear, 正如libpq本身返回的PGresult一样1.3.2. 为包含在 SQL 查询中逃逸字串PQescapeString 为在 SQL 查询中使用逃逸一个字串size_t PQescapeString (char *to, const char *from, size_t length);如果你需要在查询字串中包含一个从不可靠的源头接收的字串 (比如,它们是随机用户输入的),那么,出于安全原因,你不能把它们直接包含在 SQL 查询里你应该把特殊字符引起来,否则它们就会被 SQL 分析器代换PQescapeString 执行这个操作from 指向将要逃逸的字串的第一个字符,length 参数计算在这个字串里的字符数量(字串结尾的字节零不是必须的,也不计入长度) to 应该指向一个缓冲区,这个缓冲区至少能保存 length 数值的两倍还多一个的字符,否则该函数行为将不可预测调用 PQescapeString 就会把逃逸的 from 字串转换到 to 缓冲区,把特殊字符替换掉以免发生意外,并且追加终止的字节零那些必须包围在PostgreSQL 字串文本周围的单引号不算结果字串的一部分PQescapeString 返回写到 to 里面的字符数目,不包括结尾的字节零如果 to 和 from 字串相互重叠,那么其行为不可预测1.3.3. 逃逸包含在 SQL 查询中的二进制字串PQescapeBytea 逃逸那些在 SQL 查询中使用二进制字串(bytea 类型)unsigned char *PQescapeBytea(const unsigned char *from,size_t from_length,size_t *to_length);在 SQL 语句中用做 BYTEA 字串文本的 一部分的时候, 有些 ASCII 字符必需被逃逸 (但是对于所有字符而言是可以逃逸) 通常,要逃逸一个字符,它是被转换成一个三位八进制数字, 该数字数值等于相应的十进制 ASCII 数值,然后前缀 两个反斜扛单引号()和反斜扛字符()有自己特殊的逃逸序列参阅 用户手册获取更多信息 PQescapeBytea 执行这个操作,它只逃逸需要逃逸 的最少的字符from 参数指向需要逃逸的字串的第一个字符, from_length 参数反映在这个二进制字串 (那种字节零既不必要也不计算在内的字串)里字符的个数 to_length 参数应该是一个指向某个缓冲区的指针, 它的空间应该能够保存逃逸后的结果字串长度. 结果字串长度不包括结果结尾的字节零PQescapeBytea 返回一个 from 参数的二进制字串的逃逸后的版本,返回给调用者提供的缓冲区 返回的字串已经把所有特殊的字符替换调了,这样他们就可以由 PostgreSQL的字串文本分析器以及 bytea 的输入函数 正确地处理同时还追加了一个结尾的字节零那些必需包围在 PostgreSQL字串文本周围的单引号不算结果字串的一部分PQunescapeBytea 把一个二进制数据的逃逸后的字串表现形式转换成二进制数据 - PQescapeBytea 的反作用unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length);from 参数指向一个逃逸后的字串, 比如 PQgetvalue 从一个 BYTEA 字段返回的PQunescapeBytea 把 它的字串表现形式转换成二进制形式,填充到一个缓冲区 它返回一个指向该缓冲区的指针,若为 NULL 则出错, 缓冲区的尺寸放在 to_length 里 该指针随后可以用做 free(3) 的参数1.3.4. 检索 SELECT 的结果信息*PQntuples 返回查询结果里的元组(元组)个数int PQntuples(const PGresult *res);*PQnfields 返回查询结果里每个元组的数据域(字段)的个数int PQnfields(const PGresult *res);*PQfname 返回与给出的数据域编号相关联的数据域(字段)的名称数据域编号从 0 开始char *PQfname(const PGresult *res,int field_index);*PQfnumber 返回与给出的数据域名称相关联的数据域(字段)的编号int PQfnumber(const PGresult *res,const char *field_name);如果给出的名字不匹配任何域,返回-1*PQftype 返回与给定数据域编号关联的数据域类型 整数返回值是一个该类型的内部编码数据域编号从0 开始Oid PQftype(const PGresult *res,int field_index);你可以查询系统表 pg_type 以获取各种数据类型的名称和属性。内建的数据类型的 OID 在源码树的 src/include/catalog/pg_type.h 文件里定义。*PQfmod 返回与给定数据域编号相关联的类型相关的修正数据(?) 数据域编号从 0 开始int PQfmod(const PGresult *res,int field_index);*PQfsize 返回一个PGresult 里面的一条元组的单独的一个数据域(字段)的值 元组和数据域编号从0 开始int PQfsize(const PGresult *res,int field_index);PQfsize返回在数据库元组里面给该数据域分配的空间, 换句话说就是该数据类型在服务器里的二进制形式的大小(尺寸) 如果该数据域是可变尺寸,返回 -1*PQbinaryTuples 如果PGresult包含二进制元组数据时返回 1, 如果包含 ASCII 数据返回 0int PQbinaryTuples(const PGresult *res);目前,二进制元组数据只能从一个二进制游标里抽取数据的查询返回1.3.5. 检索 SELECT 结果数值*PQgetvalue 返回一个PGresult 里面一个元组单独的一个数据域(字段)的值 元组和数据域编号从 0 开始char* PQgetvalue(const PGresult *res,int tup_num,int field_num);对大多数查询而言, PQgetvalue 返回的值是一个表示字段值的空(NULL)结尾的字符串但是如果 PQbinaryTuples() 为 1, PQgetvalue 返回的值就是该类型在后端服务器内部的二进制表现形式(但是不包括尺寸字如果数据域是变长的)这样,把数据转换成对应的 C 类型就是程序员的责任了 PQgetvalue 返回的指针指向一个本身是 PGresult结构的一部分的存储区域我们不能更改它,并且如果 我们要在PGresult结构的生存期后还要使用它的话, 我们必须明确地把该数值拷贝到其他存储器中*PQgetisnull 测试一个数据域是否为空(NULL)元组和数据域编号从 0 开始int PQgetisnull(const PGresult *res,int tup_num,int field_num);如果该域包含 NULL,函数返回 1,如果包含非空(non-null )值,返回 0 (注意,对一个 NULL 数据域,PQgetvalue 将返回一个空字符串, 不是一个空指针)*PQgetlength 返回以字节计的数据域(字段)的长度元组和数据域编号从 0 开始int PQgetlength(const PGresult *res,int tup_num,int field_num);这是某一特定数据值的实际数据长度,也就是由PQgetvalue 指向的对象的尺寸注意,对于 ASCII 表示的数值,这个尺寸与PQfsize 报告的二进制尺寸无关*PQprint 向指定的输出流打印所有的元组和(可选的)字段名称void PQprint(FILE* fout, /* output stream */const PGresult *res,const PQprintOpt *po);struct pqbool header; /* print output field headings and row count */pqbool align; /* fill align the fields */pqbool standard; /* old brain dead format */pqbool html3; /* output html tables */pqbool expanded; /* expand tables */pqbool pager; /* use pager for output if needed */char *fieldSep; /* field separator */char *tableOpt; /* insert to HTML table . */char *caption; /* HTML caption */char *fieldName; /* null terminated array of replacement field names */ PQprintOpt;这个函数以前被 psql 用于打印查询结果,但是现在已经不用这个函数了,并且此函数不再有活跃的支持。1.3.6. 检索非-SELECT 结果信息*PQcmdStatus 返回产生PGresult的 SQL 命令的命令状态字符串char * PQcmdStatus(PGresult *res);*PQcmdTuples 返回被 SQL 命令影响的行的数量char * PQcmdTuples(PGresult *res);如果产生PGresult的SQL 命令是 INSERT, UPDATE 或 DELETE, 这里返回涉及行的行数如果是其他命令返回一个空字符串*PQoidValue 返回一个插入的元组的对象标识(OID)如果 SQL 命令是 INSERT否则,返回 InvalidOidOid PQoidValue(const PGresult *res);如果你包含了 libpq头文件,那么 Oid 和常量 InvalidOid 的类型将被定义。他们都是某种整型类型。*PQoidStatus 返回一个被插入的元组的对象标识的字串, 如果 SQL 命令是 INSERT。 否则. 返回一个空字串。char * PQoidStatus(const PGresult *res);因为有了 PQoidValue ,我们不建议使用这个函数,而且它在线程里使用也是不安全的 PostgreSQL数据库学习手册之libpq-C库-异步查询处理(转)more1.4. 异步查询处理PQexec 函数对简单的同步应用里提交命令已经是足够用的了但是它却有几个主要的缺陷:*PQexec 等待命令结束应用可能有其他工作要做(例如维护用户界面),这时它可不希望阻塞在这里等待返回*因为控制是藏在 PQexec内部,前端很难取消掉正进行着的命令(可以通过信号控制器进行,但没有别的方法)*PQexec 只能返回一个PGresult结构如果提交的命令字符串包含多个 SQL 命令,除了最后一个PGresult以外都会被 PQexec 丢弃。不想受到这些限制的应用可以改用下面的函数,这些函数也是构造 PQexec 的函数: PQsendQuery 和 PQgetResult。使用这些(异步)功能以及 PQputline 和 PQputnbytes 的老一些的程序可能在等待数据发送给后端时阻塞住,为解决这样的问题,增加了函数 PQsetnonblocking旧应用可以忽略 PQsetnonblocking 的使用,维持原有的阻塞特征。新的程序可以利用 PQsetnonblocking 获得与后端完全非阻塞的联接。*PQsetnonblocking 把该联接的状态设置为非阻塞。int PQsetnonblocking(PGconn *conn, int arg)如果arg为 TRUE,把联接状态设置为非阻塞, 如果arg为 FALSE, 把联接状态设置为阻塞如果 OK 返回 0,如果错误返回 -1 此函数将确保对在非阻塞状态,调用 PQputline,PQputnbytes, PQsendQuery 和 PQendcopy 的时候不被阻塞, 而是如果需要再次它们时将是返回一个错误(而不是阻塞)。当把一个数据库的联接设置为非阻塞的模式并且调用了 PQexec,它将暂时把联接状态设置为阻塞模式直到 PQexec 完成。在不久的将来将有更多的libpq会设计成在 PQsetnonblocking 方式下是安全的。*PQisnonblocking 返回数据库联接的阻塞状态。int PQisnonblocking(const PGconn *conn)如果联接设置为非阻塞状态,返回 1,如果是阻塞状态返回 0。*PQsendQuery 向服务器提交一个命令而不等待结果 如果查询成功发送则返回 1,否则返回 0此时,可以用PQerrorMessage 获取关于失败的信息)int PQsendQuery(PGconn *conn,const char *query);在成功调用 PQsendQuery后,调用 PQgetResult 一次或者多次获取结果 可以不再调用PQsendQuery (在同一次联接里) 直到 PQgetResult 返回 NULL,表明命令完成*PQgetResult 等待从前面 PQsendQuery 调用返回的下一个结果, 然后返回之当查询结束并且没有更多结果后返回 NULLPGresult *PQgetResult(PGconn *conn);必须重复的调用 PQgetResult ,直到它返回 NULL, 表明该命令结束(如果在没有活跃的命令时调用, PQgetResult 将只是立即返回 NULL) 每个 PQgetResult 返回的非 NULL 结果都应该用前面 描述的 PGresult 访问函数进行分析 不要忘了在结束分析后用 PQclear 释放每个结果对象 注意, PQgetResult 只是在有查询激活而且必须的返回数据还没有被 PQconsumeInput 读取时阻塞使用 PQsendQuery 和 PQgetResult 解决了 PQexec的一个问题:如果一个命令字符串包含多个 SQL 命令,这些命令的结果可以独立的获得(顺便说一句:这样就允许一种简单的重叠处理模式,前端可以处理一个查询的结果而后端可以仍然在处理同一命令字符串的后面的查询)但是,调用 PQgetResult 将仍然导致前端被阻塞住直到后端完成下一个 SQL 命令这一点可以通过合理的使用下面三个函数来避免:*PQconsumeInput 如果存在后端来的输入可用,则使用之int PQconsumeInput(PGconn *conn);PQconsumeInput 通常返回 1 表明没有错误,而返回 0 表明有某种错误发生, (同时设置 PQerrorMessage)注意这个结果并不表明实际上是否收集了数据在调用 PQconsumeInput之后,应用可以检查 PQisBusy 和/或 PQnotifies 看一眼它们的状态是否改变PQconsumeInput 可以在应用还没有做好处理结果或通知的情况下被调用这个过程将读取可用的数据并且在一个缓冲区里保存它,这样导致一个 select() 读准备好标识的生成这样应用就可以使用 PQconsumeInput 立即清掉 select() 条件,然后在空闲的时候检查结果*PQisBusy 在查询忙的时候返回 1 ,也就是说, PQgetResult 将阻塞住等待输入一个 0 的返回表明这时调用 PQgetResult 可以确保不阻塞int PQisBusy(PGconn *conn);PQisBusy 本身将不会试图从后端读取数据;所以必须先调用 PQconsumeInput ,否则忙状态将永远不会消除*PQflush 试图把任何正在排队的数据冲刷到后端,如果成功(或者发送队列为空)返回 0,如果因某种原因失败返回EOF。int PQflush(PGconn *conn);在一个非阻塞的联接调用 select() 判断是否有响应到达之前需要调用一个 PQflush 。如果返回 0 则保证了与后端的发送队列里面没有待发送的数据。只有使用了 PQsetnonblocking 的应用需要这个。*PQsocket 获取用于后端联接套接字的文件描述符号 一个有效的描述符应该是 = 0;一个 -1 表明当前没有打开与后端的联接int PQsocket(const PGconn *conn);PQsocket 应该用于获取准备调用 select() 的后端套接字描述符这就允许一个应用使用阻塞的联接等待后端的响应或者其他条件如果 select() 的结果表明可以从后端套接字读取数据,那么应该调用 PQconsumeInput 读取数据;之后,P

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论