31.3. 命令执行函数

一旦与数据库服务器的连接成功建立,便可用这里描述的函数执行SQL查询和命令。

31.3.1. 主函数

PQexec

给服务器提交一条命令并且等待结果。

PGresult *PQexec(PGconn *conn,const char *command);

返回一个PGresult指针或者也可能是一个NULL指针。通常返回一个非空的指针, 除非没有内存或发生了象不能把命令发送到服务器这样的严重错误。如果返回的是NULL, 它应该被当作PGRES_FATAL_ERROR结果处理。用PQerrorMessage获取有关错误的更多信息。

我们可以在命令行字串里包含多个SQL命令(用分号分隔)。在一次PQexec调用中发送的多个查询是在一 个事务里处理的,除非在查询字串里有明确的BEGIN/COMMIT命令用于把整个字串分隔成多个事务。 请注意这样返回的PGresult结构只描述字串里执行的最后一条命令的结果。如果有一个命令失败, 那么字串处理的过程就会停止并且返回的PGresult会描述错误条件。

PQexecParams

向服务器提交一条命令并且等待结果,还有额外的传递与SQL命令文本独立的参数的能力。

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

PQexecParams类似PQexec,但是提供了额外的功能:参数值可以独立于命令串进行声明, 并且可以要求查询结果的格式是文本或者二进制格式。PQexecParams只是在协议3.0以及以后的版本中支持; 在使用2.0的版本的时候会失败。

函数的参数是:

conn

连接对象通过发送命令。

command

要执行的SQL命令字符串。如果使用参数, 他们被称为命令字符串作为$1$2等等。

nParams

提供的参数数目;它是paramTypes[]paramValues[]paramLengths[],a和paramFormats[].数组的长度 ( 数组指针可以是NULL,当nParams为零。)

paramTypes[]

通过OID,将声明数据类型指定到参数标记。如果paramTypesNULL, 或数组中任何的特定参数是0,服务器为参数标记推断数据类型,采用的方式与一个未定义类型 的文本字符串相同。

paramValues[]

声明参数的实际值。在这个数组中的一个空指针表示相应的参数是空; 要么指针指向一个以零结尾的文本字符串或以服务器希望的方式存在的二进制数据。

paramLengths[]

为二进制格式的参数声明实际数据长度,该设置忽略空参数或文本格式的参数。 如果没有二进制参数,那么数组指针可以为空。

paramFormats[]

声明参数为一个文本(为相应参数在数组条目中放置一个0)还是一个二进制格式 (为相应参数在一个数组条目中放置一个1)。 如果数组指针是空,那么所有参数被看做是文本字符串。

以二进制格式传递的值需要能够被后台识别的内部表示。 例如,整数必须以网络字节顺序来传递; 传递numeric时需要服务器存储格式的识别,如在src/backend/utils/adt/numeric.c::numeric_send()src/backend/utils/adt/numeric.c::numeric_recv()中那样。

resultFormat

声明0用于以文本格式获得结果,或1用于以二进制格式获得结果。 (目前没有规定以不同的格式来获取不同的结果列,即使底层协议中可能实现)。

PQexecParamsPQexec主要优势是 参数值可以分开字符串命令,从而避免了繁琐和容易出错的需要 引用和逃逸。

PQexec不同的是,PQexecParams在一个给出的字串里最多允 许一个 SQL 命令。(里面可以有分号,但是不得超过一个非空的命令。)这是下层的协议的一个限制, 但是也有些额外的好处,比如可以有另外一层防止SQL攻击的层次。

Tip: 提示: 通过OID声明参数类型是非常烦琐的,尤其是你不希望在你的程序里写死特定的 OID 值的时候。 不过,你可以避免这么做,即使在服务器自己无法判断参数类型,或者是选择了一种与你预期不同的 参数类型的时候也一样。在 SQL 命令文本里,给参数负号附加一个明确的类型转换, 显示你准备发送的数据类型。比如:

SELECT * FROM mytable WHERE x = $1::bigint;

这样强制参数$1当作bigint看待,即使缺省情况下它会被赋予和x。一样的类型。 在以二进制格式发送参数值的时候,我们强烈建议通过这种方法或者是声明数字类型OID的方法强制类型判断, 因为二进制格式比文本格式少一些冗余,因此服务器就会少一些机会捕捉类型的错误匹配。

PQprepare

用给定的参数提交请求,创建一个准备好的语句,然后等待结束。

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

PQprepare创建一个为后面PQexecPrepared执行用的准备好语句。这个特性允许那 些重复使用的语句只分析和规划一次,而不是每次执行都分析规划。这个语句必须在当前 会话的前面已经准备好。只是在协议3.0和以后的连接里支持PQprepare; 在使用2.0协议的时候,它会失败。

这个函数从query字串里创建一个叫stmtName的准备好的语句,query 必须只包含 一个 SQL 命令。stmtName可以是"",这样就创建一个无名的语句,这种情况下,任何前面 存在的无名语句都会自动被代替;否则,如果语句名已经在当前会话里定义,那就是一个错误。 如果使用了参数,那么在查询里它们引用成$1$2等等。nParams是参数的个数,参数的类型在 数组paramTypes[]里事先声明好了。(如果 nParams 是零,那么这个数组指针可以是NULL。) paramTypes[]. 用 OID 的方式声明与参数符号关联的数据类型。如果paramTypesNULL,或者数组中 某个特定元素是零,那么服务器将用处理无类型文本同样的方法给这个参数符号赋予数据类型。还有, 查询可以使用比 nParams 数值更大的参数符号编号;这些参数的数据类型也是用一样的方法推导的。 (见 PQdescribePrepared作为一种手段,以找出> 什么样的数据类型推断。)

PQexec似,结果通常是一个PGresult对象,其内容表明服务器端是成功还是失败。 空的结果表示内存耗尽或者完全不能发送命令。使用PQerrorMessage获取有关这类错误的更多信息。

用于PQexecPrepared的准备好语句也可以通过执行 SQLPREPARE语句来创建。 (不过 PQprepare 更灵活,因为它不要求预先声明参数类型。)还有,尽管没有libpq函数 可以删除一个准备好语句,SQLDEALLOCATE语句却可以删除。

PQexecPrepared

发送一个请求,执行一个带有给出参数的准备好的语句,并且等待结果。

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

PQexecPreparedPQexecParams类似,但是要执行的命令是通过命名一个前面准备好的语句声明的, 而不是给出一个查询字串。这个特性允许那些要重复使用的命令只进行一次分析和规划, 而不是每次执行都来一遍。PQexecPrepared只在协议 3.0 和以后的版本里支持; 在使用 2.0 版本的协议的时候,它们会失败。

参数和PQexecParams一样,只是给出的是一个准备好语句的名字,而不是一个查询字串, 并且没有paramTypes[]参数(没必要,因为准备好语句的参数类型是在创建的时候确定的)。

PQdescribePrepared

提交请求以获取有关指定的信息 准备的声明,并等待完成。

PGresult *PQdescribePrepared(PGconn *conn,const char *stmtName);

PQdescribePrepared允许应用程序获取 有关先前准备的语句。PQdescribePrepared只在协议 3.0 和以后的版本里支持; 在使用 2.0 版本的协议的时候,它们会失败。

stmtName可以是""NULL以指向未命名声明, 要么必须与现有的预处理声明同名,成功时,会返回一个带有PGRES_COMMAND_OKPGresult。 可以在这个PGresult中使用PQnparamsPQparamtype函数以 获得预处理声明中的参数信息,同时PQnfieldsPQfnamePQftype 三个函数提供声明的结果列的信息。

PQdescribePortal

提交请求以获取有关指定的信息 门户网站,并等待完成......

PGresult *PQdescribePortal(PGconn *conn,const char *portalName);

PQdescribePortal允许应用程序获得关于之前创建的端口的信息。 (libpq不提供与端口的直接连接,但可以使用这个函数来检查 DECLARE CURSOR命令创建的游标的属性)。PQdescribePortal 只支持3.0及其之后的连接协议。

portalName可以是""NULL以指向未命名端口, 要么必须与现有的端口同名,成功时,会返回一个带有PGRES_COMMAND_OKPGresult。 可以在这个PGresult中使用PQnfieldsPQfnamePQftype函数以 获得端口的结果列的信息。

PGresult结构封装了服务器返回的结果。 libpq应该小心维护PGresult的抽象。 使用下面的访问函数获取PGresult的内容。 避免直接引用PGresult里面的字段 ,因为它们在未来版本里可能会被修改。

PQresultStatus

返回命令的结果状态。

ExecStatusType PQresultStatus(const PGresult *res);

PQresultStatus可以返回下面数值之一:

PGRES_EMPTY_QUERY

发送给服务器的字串是空的

PGRES_COMMAND_OK

成功完成一个不返回数据的命令

PGRES_TUPLES_OK

成功执行一个返回数据的查询查询(比如SELECT或者SHOW)。

PGRES_COPY_OUT

(从服务器)Copy Out (拷贝出)数据传输开始

PGRES_COPY_IN

Copy In(拷贝入)(到服务器)数据传输开始

PGRES_BAD_RESPONSE

服务器的响应无法理解

PGRES_NONFATAL_ERROR

发生了一个非致命错误(通知或者警告)

PGRES_FATAL_ERROR

发生了一个致命错误

如果结果状态是PGRES_TUPLES_OK,那么可以用下面的函数从查询的返回中抽取元组信息。 注意一个碰巧检索了零条元组的SELECT仍然显示PGRES_TUPLES_OKPGRES_COMMAND_OK 用于不返回元组的命令(INSERTUPDATE等)。返回PGRES_EMPTY_QUERY 的响应通常意味着暴露了客户端软件里面的臭虫。

状态为PGRES_NONFATAL_ERROR的结果永远不会直接由PQexec或者其它查询执行函数返回; 这类的结果会被传递给通知处理器(参阅Section 31.11)。

PQresStatus

把PPQresultStatus返回的枚举类型转换成一个描述状态码的字符串常量。 调用者不应该释放结果。

char *PQresStatus(ExecStatusType status);

PQresultErrorMessage

返回与查询关联的错误信息,或在没有错误时返回一个空字符串。

char *PQresultErrorMessage(const PGresult *res);

如果有错误,那么返回的字串将包括一个结尾的新行。调用者不应该直接释放结果。 在相关的PGresult句柄传递给PQclear之后,它会自动释放。

紧跟在一个PQexecPQgetResult调用后面,PQerrorMessage(对连接)将返回 与PQresultErrorMessage(对结果)一样的字符串。不过,一个PGresult将保有其错误信息直到被删除, 而连结的错误信息将在后续的操作完成时被改变。当你想知道与某个PGresult相关联的状态时 用PQresultErrorMessage;当你想知道与连接的最近一个操作相关联的状态时用PQerrorMessage

PQresultErrorField

返回一个独立的错误报告字段。

char *PQresultErrorField(const PGresult *res,int fieldcode);

fieldcode是一个错误字段标识符;参阅下面列出的符号。如果PGresult不是错误或者警告结 果或者不包括指定的字段,那么返回NULL。字段值通常将不包括结尾的新行。调用者不应该直接释放结果。 在相关联的PGresult句柄传递给PQclear之后,它将被自动释放。

The following field codes are available: 下列代码是可用的:

PG_DIAG_SEVERITY

严重程度,这个字段的内容是ERRORFATAL或者PANIC(在错误信息里), 或者WARNINGNOTICEDEBUGINFOLOG(在注意信息里), 或者是这些东西的一个本地化翻译。总是出现。 PG_DIAG_SQLSTATE

PG_DIAG_SQLSTATE

这个错误的 SQLSTATE 代码。SQLSTATE 代码表示所发生的错误的类型; 可以由前端应用用于对特定的数据库错误执行特定的操作(比如错误处理)。关于可能 的 SQLSTATE 代码的列表,请参阅Appendix A。这个字段是不能区域化的,并且总是出现。

PG_DIAG_MESSAGE_PRIMARY

主要的人类可读错误的信息(通常一条线)。 Always present.

PG_DIAG_MESSAGE_DETAIL

细节:一个可选的从属错误信息,里面有更多有关该问题的细节。可能有多行。

PG_DIAG_MESSAGE_HINT

提示:一个可选的有关如何处理该问题的建议。它和细节的区别是它提供了建议 (可能不太合适)而不光是事实。可能有好几行。

PG_DIAG_STATEMENT_POSITION

一个包含十进制整数的字串,当作一个错误游标使用,指出最初的语句串出错的地方的下标。 第一个字符的索引是 1,并且这个位置是用字符计,而不是用字节计。

PG_DIAG_INTERNAL_POSITION

这个和PG_DIAG_STATEMENT_POSITION字段定义是一样的,区别是它用于内部生成的命令的下标指示, 而不是客户端提交的命令。如果出现了这个字段,那么PG_DIAG_INTERNAL_QUERY字段也总是出现。

PG_DIAG_INTERNAL_QUERY

一个失败的内部生成的命令的文本。比如,这个可能是一个 PL/pgSQL 函数发出的 SQL 查询。

PG_DIAG_CONTEXT

一个指示器,表明错误发生的环境。目前这个包括活跃的过程语言函数和内部生成的查询的调用堆栈。 堆栈是每行一条,最近的在上面。

PG_DIAG_SOURCE_FILE

所报告的错误的源代码位置的所在文件。

PG_DIAG_SOURCE_LINE

报告的这个错误所在的源代码位置的行号。

PG_DIAG_SOURCE_FUNCTION

报告这个错误的源代码函数的名字。

按照自身的要求格式化显示信息是客户端的责任;特别是根据需要对长行进行折行。在错误信息字段里出现的新行字符应该当作分段符号,而不是换行。

libpq生成的错误将会有严重性和主信息,但是通常没有其它字段。3.0 协议之前返回的错误 将包含严重性和主信息,有时候还有详细信息,但是没有其它字段。

请注意这些错误字段只能从PGresult对象里获得, 而不是PGconn对象;没有PQerrorField函数。

PQclear

PQclear释放于PGresult相关联的存储空间。 任何不再需要的查询结果在不需要的时候都应该用PQclear释放掉。

void PQclear(PGresult *res);

只要你需要,你可以保留PGresult对象任意长的时间; 当你提交新的查询时它并不消失, 甚至你断开连接后也是这样。要删除它,你必须调用PQclear。 不这么做将导致你的应用中的内存泄漏。

31.3.2. Retrieving Query Result Information检索查询结果信息

这些函数用于从一个代表着成功查询结果(也就是说,状态为PGRES_TUPLES_OK的查询)的PGresult对象。 对于其它状态值的对象,他们的行为会好像他们有零行和零列一样。

PQntuples

返回查询结果里的行(元组)个数。因为在32位操作系统 它返回一个整数的结果,大型结果集可能溢出返回值。

int PQntuples(const PGresult *res);

PQnfields

返回查询结果里数据行的数据域(字段)的个数。

int PQnfields(const PGresult *res);

PQfname

返回与给出的数据域编号相关联的数据域(字段)的名称。数据域编号从 0 开始。 调用者不应该直接释放结果。在相关联的PGresult 句柄传递给PQclear之后,结果会被自动释放。

char *PQfname(const PGresult *res,
              int column_number);

如果字段编号超出范围,那么返回NULL

PQfnumber

返回与给出的数据域名称相关联的数据域(字段)的编号。

int PQfnumber(const PGresult *res,
              const char *column_name);

如果给出的名字不匹配任何字段,返回 -1。

给出的名字是当作 SQL 命令里的一个标识符看待的,也就是说,如果没有加双引号, 那么会转换为小写。比如,如果我们有一个从 SQL 命令里生成的查询结果

SELECT 1 AS FOO,2 AS "BAR";

那么我们会有下面的结果:

PQfname(res,0)          foo
PQfname(res,1)          BAR
PQfnumber(res,"FOO")    0
PQfnumber(res,"foo")    0
PQfnumber(res,"BAR")    -1
PQfnumber(res,"\"BAR\"")1

PQftable

返回我们抓取的字段所在的表的 OID。字段编号从 0 开始。

Oid PQftable(const PGresult *res,
             int column_number);

如果字段编号超出了范围,或者声明的字段不是一个指向某个表的字段的简单引用, 或者使用了 3.0 版本之前的协议,那么就会返回InvalidOid。 你可以查询系统表pg_class来判断究竟引用了哪个表。

在你包含libpq头文件的时候, 就会定义类型Oid和常量InvalidOid。 他们都是相同的整数类型。

PQftablecol

返回组成声明的查询结果字段的字段号(在它的表内部)。查询结果字段编号从 0 开始,但是表字段编号不会是 0。

int PQftablecol(const PGresult *res,
                int column_number);

如果字段编号超出范围,或者声明的字段并不是一个表字段的简单引用,或者使用的是 3.0 之前的协议,那么返回零。

PQfformat

返回说明给出字段的格式的格式代码。字段编号从 0 开始。

int PQfformat(const PGresult *res,
              int column_number);

格式码为 0 表示文本数据,而格式码是一表示二进制数据。 (其它编码保留给将来定义。)

PQftype

返回与给定数据域编号关联的数据域类型。 返回的整数是一个该类型的内部 OID 号。数据域编号从0 开始。

Oid PQftype(const PGresult *res,
            int column_number);

你可以查询系统表pg_type以获取各种数据类型的名称和属性。 内建的数据类型的 OID 在源码树的src/include/catalog/pg_type.h文件里定义。

PQfmod

返回与给定字段编号相关联的类型修饰词。 字段编号从 0 开始。

int PQfmod(const PGresult *res,
           int column_number);

类型修饰符的值是类型相关的;他们通常包括精度或者尺寸限制。数值 -1 用 于表示"没有可用信息"。大多数数据类型不用修饰词,这种情况下该值总是 -1。

PQfsize

返回与给定字段编号关联的字段以字节计的大小。 字段编号从0 开始。

int PQfsize(const PGresult *res,
            int column_number);

PQfsize返回在数据库行里面给该数据字段分配的空间,换句话说就是该数据类型在 服务器里的二进制形式的大小(尺寸)。(因此,这个对客户端没有什么用。) 如果该数据域是可变尺寸,返回 -1。

PQbinaryTuples

如果PGresult包含二进制元组数据时返回 1, 如果包含 ASCII 数据返回 0。

int PQbinaryTuples(const PGresult *res);

这个函数已经废弃了(除了还用于与COPY连接之外),因为我们可能在 一个PGresult的某些字段里包含文本数据,而另外一些字段包含二进制数据 。更好的是使用PQfformatPQbinaryTuples只有在结果中的所有字段 都是二进制(格式 1)的时候才返回 1。

PQgetvalue

返回一个PGresult里面一行的单独的一个字段的值。行和字段编号从 0 开始。 调用者不应该直接释放结果。在把PGresult句柄传递给PQclear之后, 结果会被自动释放。

char *PQgetvalue(const PGresult *res,
                 int row_number,
                 int column_number);

对于文本格式的数据,PQgetvalue返回的值是一个表示字段值的空(NULL) 结尾的字符串。对于二进制格式,返回的值就是由该数据类型的typsendtypreceive决定的二进制表现形式。(在这种情况下,数值实际上也跟着一个字节零, 但是通常这个字节没什么用处,因为数值本身很可能包含内嵌的空。)

如果字段值是空,则返回一个空字串。参阅PQgetisnull来区别空值和空字串值。

PQgetvalue返回的指针指向一个本身是PGresult结构的一部分的存储区域。我们不能更改它, 并且如果我们要在PGresult结构的生存期后还要使用它的话, 我们必须明确地把该数值拷贝到其他存储器中。

PQgetisnull

测试一个字段是否为空(NULL)。行和字段编号从 0 开始。

int PQgetisnull(const PGresult *res,
                int row_number,
                int column_number);

如果该域包含 NULL,函数返回 1,如果包含非空(non-null )值,返回 0。 (注意,对一个 NULL 数据域,PQgetvalue将返回一个空字符串,不是一个空指针。)

PQgetlength

返回以字节计的字段的长度。行和字段编号从 0 开始。

int PQgetlength(const PGresult *res,
                int row_number,
                int column_number);

这是某一特定数据值的实际数据长度。行和字段编号从 0 开始。 这是特定数值的实际数据长度,也就是说,PQgetvalue指向的对象的大小。 对于文本数据格式,它和strlen()相同。对于二进制格式,这是潜在的信息。 请注意我们不应该依靠PQfsize获取实际数据长度。

PQnparams

返回一份声明中的参数的数目。

int PQnparams(const PGresult *res);

检查的结果时,这个功能是非常有用的 PQdescribePrepared。对于其他类型的查询 将返回零。

PQparamtype

返回指示语句中的参数的数据类型。 参数编号从0开始。

Oid PQparamtype(const PGresult *res,int param_number);

检查的结果时,这个功能是非常有用的 PQdescribePrepared。对于其他类型的查询 将返回零。

PQprint

向指定的输出流打印所有的行和(可选的)字段名称。

void PQprint(FILE *fout,/* output stream */
             const PGresult *res,
             const PQprintOpt *po);
typedef struct
{
    pqbool  header;      /* 打印输出域头和行计数*/
    pqbool  align;       /*填充对齐各字段*/
    pqbool  standard;    /* 旧的傻格式  */
    pqbool  html3;       /* 输出 HTML 表 */
    pqbool  expanded;    /* 扩展表*/
    pqbool  pager;       /* 必要时在输出中使用分页器 */
    char    *fieldSep;   /* 字段分隔符*/
    char    *tableOpt;   /* 在 HTML 中插入 table ... */
    char    *caption;    /* HTML caption */
    char    **fieldName; /* 替换字段名组成的空零结尾的数组*/
} PQprintOpt;

这个函数以前被psql用于打印查询结果,但是现在已经不用这个函数了。请注意它假设所有的数据都是文本格式。

31.3.3. 检索其它命令的结果信息

这些函数用于从PGresult对象里检索那些非 SELECT 结果的信息。

PQcmdStatus

返回产生PGresult的 SQL 命令的命令状态字符串。

char *PQcmdStatus(PGresult *res);

通常这只是命令的名字,但是它可能包括额外的数据,比如处理过的行数。调用者不应该释放 结果。结果会在把PGresult句柄传递给PQclear的时候释放。

PQcmdTuples

返回被 SQL 命令影响的行的数量。

char *PQcmdTuples(PGresult *res);

这个函数返回一个生成这个PGresult的这个SQL语句影响的行数的字串。 这个函数只能用于SELECTCREATE TABLE ASINSERTUPDATEDELETEMOVEFETCH,或者COPY或者COPYEXECUTE语句执行之后的结果。 或者是一个包含INSERTUPDATEDELETE或者DELETE语句EXECUTE的一个准备好的查询。 如果生成这个PGresult的命令是其他的东西,那么 PQcmdTuples 返回一个空字串。 调用者不应该直接释放返回的数值。在相关联的PGresult被传递给PQclear之后, 它会被自动释放。

PQoidValue

返回一个插入的行的对象标识()—— 如果SQL命令是INSERT, 或者是一个包含合适INSERT语句的准备好的EXECUTE的时候。否则, 函数返回InvalidOid。如果受INSERT影响的表不包含 OID, 也返回InvalidOid

Oid PQoidValue(const PGresult *res);

PQoidStatus

如果SQL命令是INSERT,或者包含合适INSERT的准备好语句EXECUTE了。 返回一个被插入的行的 OID 的字串。(如果INSERT并非恰好插入一行, 或者目标表没有OID,那么字串将是0。) 如果命令不是INSERT,则返回一个空字串。

char *PQoidStatus(const PGresult *res);

这个函数已经废弃了,因为有了PQoidValue,而且它也不是线程安全的。

31.3.4. 逃逸包含在 SQL 命令中的字串

PQescapeLiteral

char *PQescapeLiteral(PGconn *conn,const char *str,size_t length);

PQescapeLiteral为在 SQL 命令中使用字串而对之进行逃逸处理。在我们向 SQL 命令里把数据值当作文本常量插入的时候很有用。有些字符(比如单引号和反斜杠) 必须被逃逸,以避免他们被 SQL 分析器作为特殊字符解析。 PQescapeLiteral执行这个操作。

PQescapeLiteral返回一个内存中分配有malloc()str参数 的逃逸版本。当结果不在需要时,需要通过PQfreemem()来释放这块内存。 不需要一个0字节结束,并且不应以length排序。 (如果在处理length字节之前出现0字节的结束,PQescapeLiteral在此处结束; 不同于strncpy)。返回的字符串包含所有更换的声明的字符,因此 可以很好的被PostgreSQL字符串文本解析器处理,同样,允许增加一个0字节结尾。 必须在PostgreSQL字符串文本两边的单引号包含在结果字符串中。

一旦错误,PQescapeLiteral返回NULL和在CONN对象存储合适的信息。

Tip: 处理从不可信来源收到的字符串是必须进行合适的逃逸,否则存在一定的安全风险: 容易受到"SQL injection"攻击,数据库中会被写入未知的SQL命令。

需要注意的是,当一个数据以PQexecParams或它的兄弟格式,作为一个单独的参数传递时, 做逃逸是不必要,也是不正确的。

PQescapeIdentifier

char *PQescapeIdentifier(PGconn *conn,const char *str,size_t length);

PQescapeIdentifier逃逸一个字符串作为一个SQL标识符使用,如 一个表,列,或函数名。当一个用户自定义标识符需要包含特殊的字符,否则将不能被SQL解析器解析为标识符的一部分时, 或者当标识符需要包含大写字母,且这种情况必须保留时,这样做是很有用的。

PQescapeIdentifier返回str参数逃逸为一个内存中分配有malloc()的SQL标识符 的版本。当结果不再需要时,这块内存必须使用PQfreemem()来释放。 不需要一个0字节结束,并且不应以length排序。 (如果在处理length字节之前出现0字节的结束,PQescapeLiteral在此处结束; 不同于strncpy)。返回的字符串包含所有更换的声明的字符,因此 可以很好的被PostgreSQL字符串文本解析器处理,同样,允许增加一个0字节结尾。 返回结果也是被双引号环绕。

出错时,PQescapeIdentifier返回NULL,并且在conn对象中存贮合适的信息。

Tip: 由于带有字符串常量,为阻止SQL攻击,当从一个不可信任资源获得时,SQL标识符必须逃逸。

PQescapeStringConn

size_t PQescapeStringConn(PGconn *conn,
                          char *to,const char *from,size_t length,
                          int *error);

PQescapeStringConn逃逸字符串常量,必须同于PQescapeLiteral。 不同于PQescapeLiteral,请求应该提供一个适当大小的缓冲区。 更重要的是,PQescapeStringConn不会生成一个必须在PostgreSQL字符串 常量两端的单引号;SQL命令中应该提供,这样结果中会被插入。 from参数指向字符串的第一个字符(用以逃逸), length参数指出了在这个字符串中的字节数。 不需要一个0字节结束,并且不应以length排序。 (如果在处理length字节之前出现0字节的结束,PQescapeLiteral在此处结束; 不同于strncpy)。to应该指向一个包含至少多余两倍length大小的 缓冲区,要么就不会定义该行为。如果tofrom字符串交叠,那么 也不会定义该行为。

error参数非NULL,那么在成功的时候*error会被设置为空, 失败的时候设置为非0。目前唯一可能的错误条件涉及在源字符串中无效的多字节编码。 输出字符串同样产生错误,但服务器可以视其为异常以拒绝。一旦发生错误,一条合适的信息会存储在conn对象中, 无论error是否为NULL

PQescapeStringConn返回写到to的字节数,不包含0字节终止。

PQescapeString

PQescapeString是一个老的,已经被PQescapeStringConn弃用了的版本。

size_t PQescapeString (char *to,const char *from,size_t length);

PQescapeStringConn唯一的不同是,PQescapeString不适用PGconnerror参数。 因此,不能够根据连接属性(如字符编码)来调整其行为,因此可能会给出错误的结果,同样, 不会报告错误条件。

PQescapeString可以在客户端编程(一次只有一个PostgreSQL连接)中安全的使用。 在这种情况下,它可以找到"在屏幕背后"想要知道的。 在其他情况下,这是一个安全隐患,在使用PQescapeStringConn应该避免。

PQescapeByteaConn

逃逸那些在 SQL 命令中使用的用bytea表示的二进制数据。和PQescapeStringConn一样, 这个函数只有在直接向 SQL 字串插入数据的时候使用。

unsigned char *PQescapeByteaConn(PGconn *conn,
                                 const unsigned char *from,
                                 size_t from_length,
                                 size_t *to_length);

SQL语句中用做bytea字串文本的一部分的时候,有些字节值必需逃逸(但是对于所有字节而言是可以逃逸), PQescapeByteaConn执行这个操作,它只逃逸需要逃逸的最少的字符。参阅Section 8.4获取更多信息。

from参数指向需要逃逸的字串的第一个字节,from_length参数反映在这个二进制字串( 结尾的字节零既不必要也不计算在内的字串)里字节的个数。to_length参数应该是一个指向某个缓冲区的指针, 它的空间应该能够保存逃逸后的结果字串长度。结果字串长度不包括结果结尾的字节零。

PQescapeByteaConn在内存重返回一个from参数的二进制字串的逃逸后的版本, 这片内存是用malloc()分配的(如果无法分配内存,则返回空指针)。在不再需要结果的时候, 必须用PQfreemem()释放它。返回的字串已经把所有特殊的字符替换掉了, 这样他们就可以由PostgreSQL的字串文本分析器以及bytea的输入函数正确地处理。 同时还追加了一个结尾的字节零。那些必需包围在PostgreSQL字串文本周围的单引号并非结果字串的一部分。

当出错时,返回一个空指针,一个合适的错误信息会被储存在conn对象中,事实上唯一可能的错误是结果字符串的内存不足。

PQescapeBytea

PQescapeByteaPQescapeByteaConn的一个旧的,过时的版本。

unsigned char *PQescapeBytea(const unsigned char *from,
                             size_t from_length,
                             size_t *to_length);

PQescapeByteaConn唯一的不同之处在于,PQescapeBytea不使用PGconn参数, 因此,PQescapeBytea可以在客户端编程(一次只有一个PostgreSQL连接)中安全的使用。 在这种情况下,它可以找到"在屏幕背后"想要知道的。 如果在编程中使用多个数据库连接(在这种情况下使用PQescapeByteaConn),那么可能会给出错误结果。

PQunescapeBytea

把一个二进制数据的逃逸后的字串表现形式转换成二进制数据 —PQescapeBytea的反作用。 在以文本格式抽取bytea数据的时候是必须的, 但是在以二进制格式抽取的时候是不必要的。

unsigned char *PQunescapeBytea(const unsigned char *from,size_t *to_length);

from参数指向一个逃逸后的字串,比如PQgetvalue处理过一个bytea字段后返回的。 PQunescapeBytea把它的字串表现形式转换成二进制形式, 它返回一个用malloc()分配的指向该缓冲区的指针,或者是出错时返回空, 缓冲区的尺寸放在to_length里。在不再需要这个结果之后,这片内存必须用PQfreemem释放。

这种PQescapeBytea转换实际上是不可逆的, 因为,当从PQgetvalue接收时,字符串不被希望逃逸。 尤其是,这意味着,不需要考虑字符串引用,并且不需要PGconn参数。