1.3. 命令执行函数 #
与数据库服务器的连接成功建立后,此处描述的函数用于执行 SQL 查询和命令。
1.3.1. 主要例程 #
PQexec向服务器提交一个命令并等待结果。PGresult *PQexec(PGconn *conn, const char *query);返回一个
PGresult指针,也可能返回 NULL 指针。除内存耗尽或无法将命令发送到后端等严重错误外,一般会返回非 NULL 指针。如果返回了 NULL,应将其视同PGRES_FATAL_ERROR结果。使用PQerrorMessage获取该错误的更多信息。
PGresult 结构封装了后端返回的结果。libpq 应用程序员应注意维护 PGresult
的抽象。请使用下面的访问函数获取
PGresult
的内容。避免直接引用
PGresult
结构的字段,因为它们将来可能改变。(从
PostgreSQL 6.4 开始,libpq-fe.h
中甚至不再提供 struct
PGresult
的定义。如果你有直接访问
PGresult 字段的旧代码,可以通过同时包含
libpq-int.h
继续使用它,但我们建议你尽快修改这些代码。)
PQresultStatus返回命令的结果状态。ExecStatusType PQresultStatus(const PGresult *res)
PQresultStatus可以返回下列值之一:PGRES_EMPTY_QUERY—— 发送给后端的字符串为空。PGRES_COMMAND_OK—— 不返回数据的命令成功完成PGRES_TUPLES_OK—— 查询成功执行PGRES_COPY_OUT—— Copy Out(从服务器传出)数据传输已开始PGRES_COPY_IN—— Copy In(向服务器传入)数据传输已开始PGRES_BAD_RESPONSE—— 无法理解服务器的响应PGRES_NONFATAL_ERRORPGRES_FATAL_ERROR
如果结果状态为
PGRES_TUPLES_OK,就可以使用下面描述的例程检索查询返回的行。注意,碰巧检索到零行的 SELECT 命令仍然显示PGRES_TUPLES_OK。PGRES_COMMAND_OK用于永远不会返回行的命令(INSERT、UPDATE 等)。PGRES_EMPTY_QUERY响应往往暴露客户端软件中的 bug。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 且 status 指示一个错误,连接的当前 errorMessage 会被复制到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
对二进制串(bytea 类型)进行转义,使其可用于 SQL 查询。
unsigned char *PQescapeBytea(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
字符串字面量所必需的单引号不是结果字符串的一部分。
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返回与给定字段下标相关联的字段的大小,以字节计。字段下标从 0 开始。int PQfsize(const PGresult *res, int field_index);PQfsize返回数据库元组中为该字段分配的空间,换句话说,即服务器对该数据类型的二进制表示的大小。如果字段是变长的则返回 -1。PQbinaryTuples如果 PGresult 包含二进制元组数据则返回 1,包含 ASCII 数据则返回 0。int PQbinaryTuples(const PGresult *res);
目前,只有从二进制游标提取数据的查询才能返回二进制元组数据。
1.3.5. 检索 SELECT 结果值 #
PQgetvalue返回PGresult中某个元组(行)的单个字段(列)值。元组和字段下标都从 0 开始。char* PQgetvalue(const PGresult *res, int tup_num, int field_num);对大多数查询而言,
PQgetvalue返回的是属性值的以空字符结尾的字符串表示。但如果PQbinaryTuples()为 1,PQgetvalue返回的就是该类型以后端服务器内部格式表示的二进制表示(若字段为变长则不含大小字)。此时由程序员负责把数据转换成正确的 C 类型。PQgetvalue返回的指针指向属于PGresult结构的存储空间。不应修改它;如果需要在PGresult结构的生命周期结束后继续使用该值,就必须显式地将它复制到其他存储空间。PQgetisnull测试一个字段是否为 NULL 条目。元组和字段下标从 0 开始。int PQgetisnull(const PGresult *res, int tup_num, int field_num);如果字段包含 NULL,此函数返回 1;包含非 NULL 值则返回 0。(注意,对于 NULL 字段,
PQgetvalue返回的是空字符串而不是空指针。)PQgetlength返回字段(属性)值的长度,以字节计。元组和字段下标从 0 开始。int PQgetlength(const PGresult *res, int tup_num, int field_num);这是该特定数据值的实际数据长度,即
PQgetvalue所指对象的大小。注意,对于以字符表示的值,此大小与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 HTMLtable ...*/ char *caption; /* HTMLcaption*/ char **fieldName; /* null terminated array of replacement field names */ } PQprintOpt;此函数以前被 psql 用于打印查询结果,但现在已不再如此,此函数也不再被积极维护。
1.3.6. 检索非 SELECT 结果信息 #
PQcmdStatus返回生成该PGresult的 SQL 命令的命令状态字符串。char * PQcmdStatus(const PGresult *res);
PQcmdTuples返回受 SQL 命令影响的行数。char * PQcmdTuples(const PGresult *res);
如果生成该
PGresult的 SQL 命令是 INSERT、UPDATE 或 DELETE,此函数返回一个包含受影响行数的字符串。如果是其他命令,返回空字符串。PQoidValue如果 SQL 命令是一个向带 OID 的表中恰好插入一行的 INSERT,返回所插入行的对象 ID。否则返回InvalidOid。Oid PQoidValue(const PGresult *res);
包含 libpq 头文件后,将定义类型
Oid和常量InvalidOid。它们都属于某种整数类型。PQoidStatus如果 SQL 命令是一个 INSERT,返回一个含有所插入行对象 ID 的字符串。(如果该 INSERT 并非恰好插入一行,或目标表不带 OID,字符串为0。)如果命令不是 INSERT,返回空字符串。char * PQoidStatus(const PGresult *res);
此函数已被弃用,由
PQoidValue取代,且不是线程安全的。