34.3. 命令执行函数#
成功建立与数据库服务器的连接后,此处描述的函数用于执行 SQL 查询和命令。
34.3.1. 主要函数#
PQexec#向服务器提交命令并等待结果。
PGresult *PQexec(PGconn *conn, const char *command);
返回一个
PGresult指针或一个空指针。通常会返回一个非空指针,除非在内存不足或无法将命令发送到服务器等严重错误的情况下。应调用PQresultStatus函数来检查返回值是否有任何错误(包括空指针的值,在这种情况下它将返回PGRES_FATAL_ERROR)。使用PQerrorMessage来获取有关此类错误的更多信息。
命令字符串可以包含多个 SQL 命令(用分号分隔)。在单个PQexec调用中发送的多个查询在单个事务中处理,除非查询字符串中包含显式的BEGIN/COMMIT命令将其分成多个事务。(有关服务器如何处理多查询字符串的更多详细信息,请参见第 55.2.2.1 节。)但请注意,返回的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,但提供了附加功能:可以将参数值与命令字符串本身分开指定,并且可以以文本或二进制格式请求查询结果。函数参数为
conn用于发送命令的连接对象。
command要执行的 SQL 命令字符串。如果使用参数,则在命令字符串中将它们称为
$1、$2等。nParams提供的参数数量;它是数组
paramTypes[]、paramValues[]、paramLengths[]和paramFormats[]的长度。(当nParams为零时,数组指针可以为NULL。)paramTypes[]通过 OID 指定要分配给参数符号的数据类型。如果
paramTypes为NULL,或数组中的任何特定元素为零,则服务器将推断参数符号的数据类型,就像它对未输入类型的字符串文本所做的那样。paramValues[]指定参数的实际值。此数组中的空指针表示相应参数为 null;否则,指针指向零终止文本字符串(对于文本格式)或服务器期望格式的二进制数据(对于二进制格式)。
paramLengths[]指定二进制格式参数的实际数据长度。它忽略 null 参数和文本格式参数。当没有二进制参数时,数组指针可以为 null。
paramFormats[]指定参数是文本(在相应参数的数组条目中放入零)还是二进制(在相应参数的数组条目中放入一)。如果数组指针为 null,则假定所有参数都是文本字符串。
以二进制格式传递的值需要了解后端期望的内部表示形式。例如,整数必须以网络字节序传递。传递
numeric值需要了解服务器存储格式,如在src/backend/utils/adt/numeric.c::numeric_send()和src/backend/utils/adt/numeric.c::numeric_recv()中实现的那样。resultFormat指定零以文本格式获取结果,或指定一以二进制格式获取结果。(目前没有规定以不同格式获取不同的结果列,尽管这在底层协议中是可能的。)
与PQexec相比,PQexecParams的主要优点是参数值可以与命令字符串分开,从而避免了繁琐且容易出错的引用和转义。
与PQexec不同,PQexecParams允许给定字符串中最多有一个 SQL 命令。(其中可以有分号,但不能有多个非空命令。)这是底层协议的限制,但作为抵御 SQL 注入攻击的额外防御措施,它有一定的用处。
提示
通过 OID 指定参数类型很繁琐,特别是如果你不想将特定 OID 值硬编码到程序中时。但是,即使在服务器本身无法确定参数类型或选择与你想要的类型不同的类型的情况下,你也可以避免这样做。在 SQL 命令文本中,将显式转换附加到参数符号以显示你将发送的数据类型。例如这会强制将参数$1视为bigint,而默认情况下,它将被分配与x相同的类型。强烈建议通过这种方式或通过指定数字类型 OID 来强制参数类型决策,尤其是在以二进制格式发送参数值时,因为二进制格式的冗余性低于文本格式,因此服务器检测到类型不匹配错误的可能性较小。
PQprepare#提交一个请求以创建具有给定参数的已准备语句,并等待完成。
PGresult *PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes);PQprepare为以后使用PQexecPrepared执行创建已准备语句。此功能允许重复执行命令,而无需每次都进行解析和规划;有关详细信息,请参见 PREPARE。该函数从
query字符串(其中必须包含一个 SQL 命令)创建一个名为stmtName的已准备语句。stmtName可以是""以创建一个未命名语句,在这种情况下,任何预先存在的未命名语句都会自动替换;否则,如果在当前会话中已定义语句名称,则会出错。如果使用任何参数,则在查询中将它们称为$1、$2等。nParams是在数组paramTypes[]中预先指定类型的参数的数量。(当nParams为零时,数组指针可以是NULL。)paramTypes[]通过 OID 指定要分配给参数符号的数据类型。如果paramTypes是NULL,或者数组中的任何特定元素为零,则服务器将以与对非类型化字符串文本执行相同的方式将数据类型分配给参数符号。此外,查询可以使用高于nParams的参数符号;也将为这些符号推断数据类型。(请参见PQdescribePrepared,了解找出推断出哪些数据类型的办法。)与
PQexec一样,结果通常是一个PGresult对象,其内容指示服务器端的成功或失败。空结果表示内存不足或根本无法发送命令。使用PQerrorMessage获取有关此类错误的更多信息。
也可以通过执行 SQLPREPARE语句来创建用于PQexecPrepared的预处理语句。此外,虽然libpq没有用于删除预处理语句的函数,但 SQLDEALLOCATE语句可用于此目的。
PQexecPrepared#发送请求以使用给定参数执行预处理语句,并等待结果。
PGresult *PQexecPrepared(PGconn *conn, const char *stmtName, int nParams, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);PQexecPrepared类似于PQexecParams,但要执行的命令是通过命名先前准备好的语句来指定的,而不是给出一个查询字符串。此功能允许将重复使用的命令仅解析和计划一次,而不是每次执行时都解析和计划。该语句必须在当前会话中预先准备。这些参数与
PQexecParams相同,不同之处在于给出了预处理语句的名称而不是查询字符串,并且没有paramTypes[]参数(不需要它,因为预处理语句的参数类型已在创建时确定)。PQdescribePrepared#提交请求以获取有关指定预处理语句的信息,并等待完成。
PGresult *PQdescribePrepared(PGconn *conn, const char *stmtName);
PQdescribePrepared允许应用程序获取有关先前准备好的语句的信息。stmtName可以是""或NULL以引用未命名的语句,否则它必须是现有预处理语句的名称。成功时,将返回状态为PGRES_COMMAND_OK的PGresult。可以将函数PQnparams和PQparamtype应用于此PGresult以获取有关预处理语句参数的信息,而函数PQnfields、PQfname、PQftype等提供有关语句(如果有)的结果列的信息。PQdescribePortal#提交请求以获取有关指定门户的信息,并等待完成。
PGresult *PQdescribePortal(PGconn *conn, const char *portalName);
PQdescribePortal允许应用程序获取有关先前创建的门户的信息。(libpq 不提供对门户的任何直接访问,但你可以使用此函数检查使用DECLARE CURSORSQL 命令创建的游标的属性。)portalName可以是""或NULL以引用未命名的门户,否则它必须是现有门户的名称。成功时,将返回状态为PGRES_COMMAND_OK的PGresult。可以将函数PQnfields、PQfname、PQftype等应用于PGresult以获取有关门户(如果有)的结果列的信息。
结构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#已启动复制输出(从服务器)数据传输。
PGRES_COPY_IN#已启动复制输入(到服务器)数据传输。
PGRES_BAD_RESPONSE#未理解服务器的响应。
PGRES_NONFATAL_ERROR#发生非致命错误(通知或警告)。
PGRES_FATAL_ERROR#发生致命错误。
PGRES_COPY_BOTH#已启动复制输入/输出(到服务器和从服务器)数据传输。此功能目前仅用于流复制,因此普通应用程序中不应出现此状态。
PGRES_SINGLE_TUPLE#PGresult包含当前命令的单个结果元组。仅当为查询选择了单行模式时才会出现此状态(请参阅 第 34.6 节)。PGRES_PIPELINE_SYNC#当
PQpipelineSync请求时,PGresult表示管道模式中的同步点。仅在已选择管道模式时才会出现此状态。PGRES_PIPELINE_ABORTED#PGresult表示已从服务器收到错误的管道。必须重复调用PQgetResult,每次调用都会返回此状态代码,直到当前管道结束,此时它将返回PGRES_PIPELINE_SYNC,并且可以恢复正常处理。
如果结果状态为
PGRES_TUPLES_OK或PGRES_SINGLE_TUPLE,则可以使用下面描述的函数来检索查询返回的行。请注意,碰巧检索到零行的SELECT命令仍显示PGRES_TUPLES_OK。PGRES_COMMAND_OK适用于永远无法返回行的命令(INSERT或不带RETURNING子句的UPDATE等)。PGRES_EMPTY_QUERY响应可能表明客户端软件存在错误。状态为
PGRES_NONFATAL_ERROR的结果永远不会由PQexec或其他查询执行函数直接返回;此类结果将传递给通知处理器(请参见第 34.13 节)。PQresStatus#将
PQresultStatus返回的枚举类型转换为描述状态代码的字符串常量。调用者不应释放结果。char *PQresStatus(ExecStatusType status);
PQresultErrorMessage#返回与命令关联的错误消息,如果没有错误,则返回空字符串。
char *PQresultErrorMessage(const PGresult *res);
如果出现错误,则返回的字符串将包含一个尾随换行符。调用者不应直接释放结果。当关联的
PGresult句柄传递给PQclear时,它将被释放。紧跟
PQexec或PQgetResult调用后,PQerrorMessage(在连接上)将返回与PQresultErrorMessage(在结果上)相同的字符串。但是,PGresult将保留其错误消息,直至被销毁,而连接的错误消息将在后续操作完成后发生更改。当您想了解与特定PGresult关联的状态时,请使用PQresultErrorMessage;当您想了解连接上最新操作的状态时,请使用PQerrorMessage。PQresultVerboseErrorMessage#返回与
PGresult对象关联的错误消息的重新格式化版本。char *PQresultVerboseErrorMessage(const PGresult *res, PGVerbosity verbosity, PGContextVisibility show_context);在某些情况下,客户端可能希望获取先前报告的错误的更详细版本。
PQresultVerboseErrorMessage通过计算当给定的PGresult被生成时,如果指定的详细设置对连接有效,PQresultErrorMessage将生成的消息来满足此需求。如果PGresult不是错误结果,则会报告 “PGresult is not an error result”。返回的字符串包含一个尾随换行符。与从
PGresult提取数据的其他大多数函数不同,此函数的结果是一个新分配的字符串。当不再需要该字符串时,调用者必须使用PQfreemem()释放它。如果内存不足,可能会返回 NULL。
PQresultErrorField#返回错误报告的单个字段。
char *PQresultErrorField(const PGresult *res, int fieldcode);
fieldcode是错误字段标识符;请参阅下面列出的符号。如果PGresult不是错误或警告结果,或者不包含指定字段,则返回NULL。字段值通常不包含尾随换行符。调用者不应直接释放结果。当关联的PGresult句柄传递给PQclear时,它将被释放。提供以下字段代码
PG_DIAG_SEVERITY#严重性;字段内容为
ERROR、FATAL或PANIC(在错误消息中),或WARNING、NOTICE、DEBUG、INFO或LOG(在通知消息中),或其中一个的本地化翻译。始终存在。PG_DIAG_SEVERITY_NONLOCALIZED#严重性;字段内容为
ERROR、FATAL或PANIC(在错误消息中),或WARNING、NOTICE、DEBUG、INFO或LOG(在通知消息中)。这与PG_DIAG_SEVERITY字段相同,只是内容永远不会本地化。这仅存在于 PostgreSQL 9.6 及更高版本生成的报告中。PG_DIAG_SQLSTATE#错误的 SQLSTATE 代码。SQLSTATE 代码标识发生的错误类型;前端应用程序可以使用它来针对特定的数据库错误执行特定操作(例如错误处理)。有关可能的 SQLSTATE 代码的列表,请参阅 附录 A。此字段不可本地化,并且始终存在。
PG_DIAG_MESSAGE_PRIMARY#主要的人类可读错误消息(通常为一行)。始终存在。
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_SCHEMA_NAME#如果错误与特定数据库对象相关,则包含该对象的架构(如果有)的名称。
PG_DIAG_TABLE_NAME#如果错误与特定表相关,则包含表的名称。(有关表架构的名称,请参阅架构名称字段。)
PG_DIAG_COLUMN_NAME#如果错误与特定表列相关,则包含列的名称。(有关表的名称,请参阅架构和表名称字段。)
PG_DIAG_DATATYPE_NAME#如果错误与特定数据类型相关,则包含数据类型的名称。(有关数据类型架构的名称,请参阅架构名称字段。)
PG_DIAG_CONSTRAINT_NAME#如果错误与特定约束相关,则包含约束的名称。有关关联的表或域,请参阅上面列出的字段。(出于此目的,索引被视为约束,即使它们不是使用约束语法创建的。)
PG_DIAG_SOURCE_FILE#报告错误的源代码位置的文件名。
PG_DIAG_SOURCE_LINE#报告错误的源代码位置的行号。
PG_DIAG_SOURCE_FUNCTION#报告错误的源代码函数的名称。
注意
架构名称、表名称、列名称、数据类型名称和约束名称的字段仅针对有限数量的错误类型提供;请参阅附录 A。不要假设其中任何字段的存在保证了另一个字段的存在。核心错误源遵守上面指出的相互关系,但用户定义的函数可能会以其他方式使用这些字段。同样,不要假设这些字段表示当前数据库中的当代对象。
客户端负责根据需要格式化显示的信息;特别是,它应该根据需要拆分长行。错误消息字段中出现的换行符应视为段落分隔符,而不是换行符。
libpq 内部生成的错误将具有严重性和主要消息,但通常没有其他字段。
请注意,错误字段仅可从
PGresult对象获得,而不能从PGconn对象获得;没有PQerrorField函数。PQclear#释放与
PGresult关联的存储空间。当不再需要每个命令结果时,都应通过PQclear释放该结果。void PQclear(PGresult *res);
如果参数是
NULL指针,则不执行任何操作。你可以保留
PGresult对象,只要你需要它;当你发出新命令时,它不会消失,即使你关闭连接也不会消失。要摆脱它,你必须调用PQclear。如果不这样做,你的应用程序中会出现内存泄漏。
34.3.2. 检索查询结果信息#
这些函数用于从表示成功查询结果(即状态为PGRES_TUPLES_OK或PGRES_SINGLE_TUPLE的查询结果)的PGresult对象中提取信息。它们还可用于从成功的 Describe 操作中提取信息:Describe 的结果具有与实际执行查询所提供的相同列信息,但它没有行。对于具有其他状态值的这些对象,这些函数将表现得好像结果没有行和列。
PQntuples#返回查询结果中的行(元组)数。(请注意,
PGresult对象最多限制为INT_MAX行,因此int结果就足够了。)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);如果列号超出范围,或者如果指定的列不是对表列的简单引用,则返回
InvalidOid。您可以查询系统表pg_class以准确确定引用的表。当您包含 libpq 头文件时,将定义类型
Oid和常量InvalidOid。它们都将是某种整数类型。PQftablecol#返回构成指定查询结果列的列(在其表中)的列号。查询结果列号从 0 开始,但表列具有非零编号。
int PQftablecol(const PGresult *res, int column_number);如果列号超出范围,或者如果指定的列不是对表列的简单引用,则返回零。
PQfformat#返回指示给定列格式的格式代码。列号从 0 开始。
int PQfformat(const PGresult *res, int column_number);格式代码零表示文本数据表示,而格式代码一表示二进制表示。(其他代码保留以供将来定义。)
PQftype#返回与给定列号关联的数据类型。返回的整数是类型的内部 OID 号码。列号从 0 开始。
Oid PQftype(const PGresult *res, int column_number);您可以查询系统表
pg_type以获取各种数据类型的名称和属性。内置数据类型的 在 PostgreSQL 安装的include目录中的文件catalog/pg_type_d.h中定义。PQfmod#返回与给定列号关联的列的类型修饰符。列号从 0 开始。
int PQfmod(const PGresult *res, int column_number);修饰符值的解释是特定于类型的;它们通常表示精度或大小限制。值 -1 用于表示 “无可用信息”。大多数数据类型不使用修饰符,在这种情况下,值始终为 -1。
PQfsize#返回与给定列号关联的列的字节大小。列号从 0 开始。
int PQfsize(const PGresult *res, int column_number);PQfsize返回为数据库行中的此列分配的空间,换句话说,即服务器内部数据类型表示的大小。(因此,它对客户端来说并不是非常有用。)负值表示数据类型是可变长度的。PQbinaryTuples#如果
PGresult包含二进制数据,则返回 1,如果包含文本数据,则返回 0。int PQbinaryTuples(const PGresult *res);
此函数已弃用(除了与
COPY一起使用),因为单个PGresult可能会在某些列中包含文本数据,而在其他列中包含二进制数据。PQfformat优先。仅当结果的所有列都是二进制(格式 1)时,PQbinaryTuples才返回 1。PQgetvalue#返回
PGresult一行中的单个字段值。行号和列号从 0 开始。调用者不应直接释放结果。当关联的PGresult句柄传递给PQclear时,它将被释放。char *PQgetvalue(const PGresult *res, int row_number, int column_number);对于文本格式的数据,
PQgetvalue返回的值是字段值的以 null 结尾的字符串表示。对于二进制格式的数据,该值采用由数据类型的typsend和typreceive函数确定的二进制表示。(在这种情况下,该值实际上后面还跟着一个零字节,但这通常没有用,因为该值可能包含嵌入的 null。)如果字段值为空,则返回一个空字符串。请参阅
PQgetisnull以区分空值和空字符串值。PQgetvalue返回的指针指向PGresult结构的一部分的存储。不应修改它指向的数据,并且如果要在PGresult结构本身的生命周期后使用数据,则必须将数据显式复制到其他存储中。PQgetisnull#测试字段的空值。行号和列号从 0 开始。
int PQgetisnull(const PGresult *res, int row_number, int column_number);如果字段为空,此函数返回 1,如果字段包含非空值,则返回 0。(请注意,
PQgetvalue将为 null 字段返回一个空字符串,而不是一个 null 指针。)PQgetlength#返回字段值的实际长度(以字节为单位)。行号和列号从 0 开始。
int PQgetlength(const PGresult *res, int row_number, int column_number);这是特定数据值的实际数据长度,即
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; /* 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; /* attributes for HTML table element */ char *caption; /* HTML table caption */ char **fieldName; /* null-terminated array of replacement field names */ } PQprintOpt;此函数以前由 psql 用于打印查询结果,但现在不再使用。请注意,它假定所有数据都为文本格式。
34.3.3. 检索其他结果信息#
这些函数用于从PGresult对象中提取其他信息。
PQcmdStatus#从生成
PGresult的 SQL 命令中返回命令状态标记。char *PQcmdStatus(PGresult *res);
通常,这只是命令的名称,但它可能包括其他数据,例如已处理的行数。调用方不应直接释放结果。当关联的
PGresult句柄传递给PQclear时,它将被释放。PQcmdTuples#返回受 SQL 命令影响的行数。
char *PQcmdTuples(PGresult *res);
此函数返回一个字符串,其中包含受生成
PGresult的 语句影响的行数。此函数只能在执行SELECT、CREATE TABLE AS、INSERT、UPDATE、DELETE、MERGE、MOVE、FETCH或COPY语句后使用,或执行包含INSERT、UPDATE、DELETE或MERGE语句的已准备查询的EXECUTE。如果生成PGresult的命令是其他任何命令,PQcmdTuples将返回一个空字符串。调用方不应直接释放返回值。当关联的PGresult句柄传递给PQclear时,它将被释放。PQoidValue#如果 命令是
INSERT,将插入一行到具有 OID 的表中,或者执行包含合适的INSERT语句的已准备查询的EXECUTE,则返回插入行的 OID。否则,此函数返回InvalidOid。如果受INSERT语句影响的表不包含 OID,此函数也将返回InvalidOid。Oid PQoidValue(const PGresult *res);
PQoidStatus#此函数已弃用,建议使用
PQoidValue,并且不是线程安全的。它返回一个包含插入行的 OID 的字符串,而PQoidValue返回 OID 值。char *PQoidStatus(const PGresult *res);
34.3.4. 转义字符串以包含在 SQL 命令中#
PQescapeLiteral#char *PQescapeLiteral(PGconn *conn, const char *str, size_t length);
PQescapeLiteral转义字符串以在 SQL 命令中使用。这在将数据值作为 SQL 命令中的文字常量插入时很有用。某些字符(例如引号和反斜杠)必须转义,以防止 SQL 解析器对它们进行特殊解释。PQescapeLiteral执行此操作。PQescapeLiteral在使用malloc()分配的内存中,返回str参数的转义版本。当不再需要结果时,应使用PQfreemem()释放此内存。不需要终止零字节,也不应将其计入length。(如果在处理length字节之前找到终止零字节,PQescapeLiteral将在零处停止;因此,该行为类似于strncpy。)返回字符串中的所有特殊字符都已替换,以便 PostgreSQL 字符串字面量解析器可以正确处理它们。还添加了终止零字节。必须将 PostgreSQL 字符串字面量引起来的单引号包含在结果字符串中。如果出错,
PQescapeLiteral将返回NULL,并且会将一条适当的消息存储在conn对象中。提示
在处理从不可信来源接收的字符串时,执行适当的转义尤其重要。否则存在安全风险:您容易受到“SQL 注入”攻击,其中会将不需要的 SQL 命令馈送到您的数据库。
请注意,当在
PQexecParams或其同级例程中将数据值作为单独的参数传递时,执行转义既不必要也不正确。PQescapeIdentifier#char *PQescapeIdentifier(PGconn *conn, const char *str, size_t length);
PQescapeIdentifier转义字符串以用作 SQL 标识符,例如表、列或函数名称。当用户提供的标识符可能包含特殊字符(否则 SQL 解析器不会将这些字符解释为标识符的一部分)时,或者当标识符可能包含应保留其大小写的上字符时,这很有用。PQescapeIdentifier返回str参数的版本,该版本已转义为使用malloc()分配的内存中的 SQL 标识符。当不再需要结果时,必须使用PQfreemem()释放此内存。不需要终止零字节,也不应将其计入length。(如果在处理length字节之前找到终止零字节,PQescapeIdentifier将在零处停止;因此,该行为类似于strncpy。)返回字符串中的所有特殊字符都已替换,以便将其正确处理为 SQL 标识符。还添加了终止零字节。返回字符串还将用双引号引起来。出错时,
PQescapeIdentifier返回NULL,并且在conn对象中存储一条合适的错误消息。提示
与字符串字面值一样,为了防止 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参数给出了此字符串中的字节数。不需要终止零字节,也不应将其计入length中。(如果在处理length字节之前找到终止零字节,PQescapeStringConn将在零处停止;因此,行为类似于strncpy。)to应指向一个缓冲区,该缓冲区能够容纳至少比length的值多一个字节,否则行为未定义。如果to和from字符串重叠,行为同样未定义。如果
error参数不为NULL,则在成功时*error设置为零,在出错时设置为非零。目前,唯一可能出现的错误条件涉及源字符串中的无效多字节编码。输出字符串仍会在出错时生成,但可以预期服务器会将其拒绝为格式错误。出错时,无论error是否为NULL,都会在conn对象中存储一条合适的错误消息。PQescapeStringConn返回写入to的字节数,不包括终止零字节。PQescapeString#PQescapeString是PQescapeStringConn的较旧版本,已弃用。size_t PQescapeString (char *to, const char *from, size_t length);
与
PQescapeStringConn唯一的区别在于PQescapeString不采用PGconn或error参数。因此,它无法根据连接属性(例如字符编码)调整其行为,因此 可能会给出错误的结果。此外,它也没有办法报告错误情况。PQescapeString可以安全地用于一次只处理一个 PostgreSQL 连接的客户端程序(在这种情况下,它可以找出它需要了解的内容 “幕后”)。在其他情况下,它是一个安全隐患,应该避免使用,而应该使用PQescapeStringConn。PQescapeByteaConn#转义二进制数据,以便在类型为
bytea的 SQL 命令中使用。与PQescapeStringConn一样,这仅在将数据直接插入 SQL 命令字符串时使用。unsigned char *PQescapeByteaConn(PGconn *conn, const unsigned char *from, size_t from_length, size_t *to_length);在 语句中用作
bytea文字的一部分时,必须转义某些字节值。PQescapeByteaConn使用十六进制编码或反斜杠转义来转义字节。有关详细信息,请参见 第 8.4 节。from参数指向要转义的字符串的第一个字节,from_length参数给出此二进制字符串中的字节数。(终止零字节既不必要也不计算在内。)to_length参数指向一个变量,该变量将保存结果转义字符串长度。此结果字符串长度包括结果的终止零字节。PQescapeByteaConn返回from参数二进制字符串的转义版本,该版本存储在使用malloc()分配的内存中。当不再需要结果时,应使用PQfreemem()释放此内存。返回字符串已替换所有特殊字符,以便 PostgreSQL 字符串文字解析器和bytea输入函数可以正确处理它们。还添加了一个终止零字节。必须包围 PostgreSQL 字符串文字的单引号不是结果字符串的一部分。如果出错,则返回一个空指针,并且一个合适的错误消息存储在
conn对象中。目前,唯一可能发生的错误是结果字符串的内存不足。PQescapeBytea#PQescapeBytea是PQescapeByteaConn的较旧版本,已弃用。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()分配的缓冲区的指针,或在出错时返回NULL,并将缓冲区的大小放入to_length中。当不再需要结果时,必须使用PQfreemem释放结果。此转换并非
PQescapeBytea的完全逆操作,因为在从PQgetvalue接收字符串时,不期望字符串“转义”。特别是,这意味着不需要考虑字符串引用,因此不需要PGconn参数。
