33.3. 命令执行功能

成功构建与数据库服务器的连接后,此处描述的功能将用于执行 SQL 查询和命令。

33 .3.1. 主要功能

  • PQexec
    • 向服务器提交命令,然后 await 结果。
PGresult *PQexec(PGconn *conn, const char *command);

返回PGresult指针或可能为空的指针。通常会返回非空指针,除非在内存不足的情况下或严重错误(例如无法将命令发送到服务器)。应该调用PQresultStatus函数来检查返回值是否有错误(包括空指针的值,在这种情况下它将返回PGRES_FATAL_ERROR)。使用PQerrorMessage获得有关此类错误的更多信息。

命令字符串可以包含多个 SQL 命令(以分号分隔)。除非在查询字符串中包含明确的BEGIN/COMMIT命令以将其分为多个事务,否则在单个PQexec调用中发送的多个查询将在单个事务中处理。但是请注意,返回的PGresult结构仅描述了从字符串执行的最后一个命令的结果。如果其中一个命令失败,则字符串的处理随之停止,返回的PGresult描述了错误情况。

  • PQexecParams
    • 将命令提交到服务器并 await 结果,并能够将参数与 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 和更高版本的 Connecting 受支持;使用协议 2.0 时它将失败。

函数参数为:

  • conn

    • 通过其发送命令的连接对象。

    • command

      • 要执行的 SQL 命令字符串。如果使用了参数,则它们在命令字符串中称为$1$2等。
    • nParams

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

      • 通过 OID 指定要分配给参数符号的数据类型。如果* paramTypes *为NULL,或者数组中的任何特定元素为零,则服务器将以与处理无类型 Literals 字符串相同的方式推断参数符号的数据类型。
    • paramValues[]

      • 指定参数的实际值。该数组中的空指针表示相应的参数为空;否则,指针将指向以零结尾的文本字符串(对于文本格式)或服务器期望的格式的二进制数据(对于二进制格式)。
    • paramLengths[]

      • 指定二进制格式参数的实际数据长度。对于空参数和文本格式参数,它将被忽略。没有二进制参数时,数组指针可以为 null。
    • paramFormats[]

      • 指定参数是文本(在对应参数的数组条目中 Importing 零)还是二进制(在对应参数的数组条目中 Importing 一)。如果数组指针为 null,则假定所有参数均为文本字符串。

以二进制格式传递的值需要了解后端期望的内部表示形式。例如,必须以网络字节 Sequences 传递整数。传递numeric值需要了解服务器存储格式,如src/backend/utils/adt/numeric.c::numeric_send()src/backend/utils/adt/numeric.c::numeric_recv()所实现。

  • resultFormat

    • 指定零可获取文本格式的结果,或指定一个可获取二进制格式的结果。 (尽管在底层协议中可能实现,但目前尚无以不同格式获取不同结果列的规定.)

PQexecParams优于PQexec的主要优点是可以将参数值与命令字符串分开,从而避免了乏味且容易出错的引号和转义。

PQexec不同,PQexecParams在给定的字符串中最多允许一个 SQL 命令。 (其中可以包含分号,但不能超过一个非空命令.)这是对基础协议的限制,但可以作为对 SQL 注入攻击的额外防御来使用。

Tip

通过 OID 指定参数类型很繁琐,尤其是如果您不想将特定的 OID 值硬连接到程序中时。但是,即使服务器本身无法确定参数的类型或选择与所需类型不同的类型,也可以避免这样做。在 SQL 命令文本中,将显式强制转换附加到参数符号以显示将发送的数据类型。例如:

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

这将强制将参数$1视为bigint,而默认情况下会将其分配为与x相同的类型。在以二进制格式发送参数值时,强烈建议通过这种方式或通过指定数字类型 OID 来强制执行参数类型决定,因为二进制格式的冗余度小于文本格式,因此服务器检测类型的可能性较小为您错配错误。

  • PQprepare
    • 提交请求以使用给定的参数创建准备好的语句,然后 await 完成。
PGresult *PQprepare(PGconn *conn,
                    const char *stmtName,
                    const char *query,
                    int nParams,
                    const Oid *paramTypes);

PQprepare创建一个准备好的语句,供以后使用PQexecPrepared执行。此功能允许重复执行命令,而无需每次都进行解析和计划。有关详情,请参见PREPAREPQprepare仅在协议 3.0 及更高版本的 Connecting 受支持;使用协议 2.0 时它将失败。

该函数从* query 字符串创建一个名为 stmtName *的准备好的语句,该语句必须包含一个 SQL 命令。 * stmtName 可以是""以创建未命名的语句,在这种情况下,任何现有的未命名的语句都会被自动替换;否则,如果在当前会话中已经定义了语句名称,则会出现错误。如果使用了任何参数,则它们在查询中称为$1$2等. nParams 是在数组 paramTypes[] 中预先指定类型的参数的数量。 (当 nParams 为零时,数组指针可以为NULL.) paramTypes[] 通过 OID 指定要分配给参数符号的数据类型。如果 paramTypes NULL,或者数组中的任何特定元素为零,则服务器将其数据类型分配给参数符号,方式与对无类型 Literals 字符串的处理方式相同。此外,查询可以使用数字符号大于 nParams *的参数符号;这些符号也将推断出数据类型。 (请参见PQdescribePrepared,以了解推断出哪些数据类型的方法.)

PQexec一样,结果通常是PGresult对象,其内容表示服务器端成功或失败。结果为空表示内存不足或根本无法发送命令。使用PQerrorMessage获取有关此类错误的更多信息。

也可以通过执行 SQL PREPARE语句来创建供PQexecPrepared使用的预备语句。同样,尽管没有 libpq 函数可删除准备好的语句,但 SQL DEALLOCATE语句可用于该目的。

  • PQexecPrepared
    • 发送请求以给定的参数执行准备好的语句,然后 await 结果。
PGresult *PQexecPrepared(PGconn *conn,
                         const char *stmtName,
                         int nParams,
                         const char * const *paramValues,
                         const int *paramLengths,
                         const int *paramFormats,
                         int resultFormat);

PQexecPrepared类似于PQexecParams,但是要执行的命令是通过命名先前准备的语句来指定的,而不是给出查询字符串。此功能允许将重复使用的命令解析和计划一次,而不是每次执行时都进行解析和计划。该声明必须已经在当前会话中预先准备好了。 PQexecPrepared仅在协议 3.0 和更高版本的 Connecting 受支持;使用协议 2.0 时它将失败。

参数与PQexecParams相同,除了给出的是预准备语句的名称而不是查询字符串,并且不存在* paramTypes[] *参数(由于创建时准备好的语句的参数类型是确定的,因此不需要此参数) 。

  • PQdescribePrepared
    • 提交请求以获取有关指定的准备好的语句的信息,然后 await 完成。
PGresult *PQdescribePrepared(PGconn *conn, const char *stmtName);

PQdescribePrepared允许应用程序获取有关先前准备好的语句的信息。 PQdescribePrepared仅在协议 3.0 和更高版本的 Connecting 受支持;使用协议 2.0 时它将失败。

  • stmtName *可以是""NULL来引用未命名的语句,否则它必须是现有准备好的语句的名称。成功时,将返回状态为PGRES_COMMAND_OKPGresult。可以将函数PQnparamsPQparamtype应用于此PGresult以获得有关已准备语句的参数的信息,而函数PQnfieldsPQfnamePQftype等提供有关语句的结果列(如果有)的信息。
  • PQdescribePortal
    • 提交请求以获取有关指定门户网站的信息,然后 await 完成。
PGresult *PQdescribePortal(PGconn *conn, const char *portalName);

PQdescribePortal允许应用程序获取有关先前创建的门户的信息。 (libpq 不提供对门户的任何直接访问,但是您可以使用此功能来检查使用DECLARE CURSOR SQL 命令创建的游标的属性.)PQdescribePortal仅在协议 3.0 及更高版本的 Connecting 受支持;使用协议 2.0 时它将失败。

  • portalName *可以是""NULL来引用未命名的门户,否则,它必须是现有门户的名称。成功时,将返回状态为PGRES_COMMAND_OKPGresult。可以将功能PQnfieldsPQfnamePQftype等应用于PGresult以获得有关门户的结果列(如果有)的信息。

PGresult 结构封装了服务器返回的结果。 libpq 应用程序程序员应小心维护PGresult抽象。使用下面的访问器函数获取PGresult的内容。避免直接引用PGresult结构的字段,因为它们将来可能会发生变化。

  • PQresultStatus
    • 返回命令的结果状态。
ExecStatusType PQresultStatus(const PGresult *res);

PQresultStatus可以返回以下值之一:

  • PGRES_EMPTY_QUERY
    • 发送到服务器的字符串为空。

    • PGRES_COMMAND_OK

      • 成功完成命令,不返回任何数据。
    • PGRES_TUPLES_OK

      • 成功完成返回数据的命令(例如SELECTSHOW)。
    • PGRES_COPY_OUT

      • 复制(从服务器)数据传输开始。
    • PGRES_COPY_IN

      • 复制(到服务器)数据传输开始。
    • PGRES_BAD_RESPONSE

      • 无法理解服务器的响应。
    • PGRES_NONFATAL_ERROR

      • 发生非致命错误(通知或警告)。
    • PGRES_FATAL_ERROR

      • 发生致命错误。
    • PGRES_COPY_BOTH

      • 复制进/出(与服务器之间的复制)数据传输开始。此功能当前仅用于流复制,因此在普通应用程序中不应出现此状态。
    • PGRES_SINGLE_TUPLE

      • PGresult包含来自当前命令的单个结果 Tuples。仅当为查询选择单行模式时,才会出现此状态(请参见Section 33.5)。

如果结果状态为PGRES_TUPLES_OKPGRES_SINGLE_TUPLE,则可以使用下面描述的函数来检索查询返回的行。请注意,恰巧检索零行的SELECT命令仍显示PGRES_TUPLES_OKPGRES_COMMAND_OK用于永远不会返回行的命令(没有RETURNING子句的INSERTUPDATE等)。响应PGRES_EMPTY_QUERY可能表示 Client 端软件中存在错误。

状态PGRES_NONFATAL_ERROR的结果将永远不会被PQexec或其他查询执行功能直接返回;此类结果将传递到通知处理器(请参阅Section 33.12)。

  • PQresStatus
    • PQresultStatus返回的枚举类型转换为描述状态码的字符串常量。调用方不应释放结果。
char *PQresStatus(ExecStatusType status);
  • PQresultErrorMessage
    • 返回与命令关联的错误消息,如果没有错误,则返回空字符串。
char *PQresultErrorMessage(const PGresult *res);

如果有错误,则返回的字符串将包含尾随换行符。调用方不应直接释放结果。当关联的PGresult句柄传递到PQclear时,它将被释放。

紧接PQexecPQgetResult调用之后,PQerrorMessage(在连接上)将返回与PQresultErrorMessage(在结果上)相同的字符串。但是,PGresult将保留其错误消息,直到被销毁,而连接的错误消息将在后续操作完成后更改。当您想了解与特定PGresult关联的状态时,请使用PQresultErrorMessage;当您想从连接的最新操作中了解状态时,请使用PQerrorMessage

  • PQresultVerboseErrorMessage
    • 返回与PGresult对象关联的错误消息的重新格式化版本。
char *PQresultVerboseErrorMessage(const PGresult *res,
                                  PGVerbosity verbosity,
                                  PGContextVisibility show_context);

在某些情况下,Client 可能希望获得以前报告的错误的更详细的版本。 PQresultVerboseErrorMessage通过计算在生成给定PGresult时对连接有效的指定详细设置对PQresultErrorMessage会产生的消息来满足此需求。如果PGresult不是错误结果,则会报告“ PGresult 不是错误结果”。返回的字符串包括尾随换行符。

与大多数其他用于从PGresult提取数据的函数不同,此函数的结果是一个新分配的字符串。当不再需要该字符串时,调用者必须使用PQfreemem()释放它。

如果没有足够的内存,则可能返回 NULL。

  • PQresultErrorField
    • 返回错误报告的单个字段。
char *PQresultErrorField(const PGresult *res, int fieldcode);
  • fieldcode *是错误字段标识符;请参阅下面列出的符号。如果PGresult不是错误或警告结果,或者不包含指定的字段,则返回NULL。字段值通常将不包含尾随换行符。调用方不应直接释放结果。当关联的PGresult句柄传递给PQclear时,它将释放。

可以使用以下域代码:

  • PG_DIAG_SEVERITY
    • 严重程度;字段内容是ERRORFATALPANIC(在错误消息中)或WARNINGNOTICEDEBUGINFOLOG(在通知消息中),或其中之一的本地化翻译。始终存在。

    • PG_DIAG_SEVERITY_NONLOCALIZED

      • 严重程度;字段内容是ERRORFATALPANIC(在错误消息中),或WARNINGNOTICEDEBUGINFOLOG(在通知消息中)。这与PG_DIAG_SEVERITY字段相同,除了内容从未本地化。这仅在 PostgreSQL 9.6 及更高版本生成的报告中存在。
    • PG_DIAG_SQLSTATE

      • 错误的 SQLSTATE 代码。 SQLSTATE 代码标识已发生的错误的类型。前端应用程序可以使用它来响应特定的数据库错误来执行特定的操作(例如错误处理)。有关可能的 SQLSTATE 代码的列表,请参见Appendix 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字段相同,但是当光标位置引用内部生成的命令而不是 Client 端提交的命令时使用。出现此字段时,总是会出现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

      • 报告错误的源代码功能的名称。

Note

仅为有限数量的错误类型提供模式名称,表名称,列名称,数据类型名称和约束名称的字段。参见Appendix A。不要以为任何这些字段的存在都可以保证另一个字段的存在。核心错误源遵循上面提到的相互关系,但是用户定义的函数可能以其他方式使用这些字段。同样,不要假定这些字段表示当前数据库中的当代对象。

Client 负责格式化显示的信息以满足其需求;特别是它应根据需要断开长行。错误消息字段中出现的换行符应视为段落分隔符,而不是换行符。

libpq 内部生成的错误将具有严重性和主要消息,但通常没有其他字段。 3.0 协议之前的服务器返回的错误将包括严重性和主要消息,有时还包括详细消息,但没有其他字段。

请注意,错误字段仅适用于PGresult个对象,而不适用于PGconn个对象;没有PQerrorField功能。

  • PQclear
    • 释放与PGresult关联的存储。当不再需要每个命令结果时,应通过PQclear释放它们。
void PQclear(PGresult *res);

您可以根据需要保持PGresult对象的存在时间。发出新命令或关闭连接也不会消失。要摆脱它,您必须调用PQclear。否则,将导致应用程序中的内存泄漏。

33 .3.2. 检索查询结果信息

这些函数用于从表示成功查询结果的PGresult对象(即状态为PGRES_TUPLES_OKPGRES_SINGLE_TUPLE)中提取信息。它们也可以用于从成功的 Describe 操作中提取信息:Describe 的结果具有与实际执行查询所提供的所有列信息相同的信息,但其行数为零。对于具有其他状态值的对象,这些函数的作用就好像结果具有零行零列。

  • PQntuples
    • 返回查询结果中的行数(Tuples)。 (请注意,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);

如果列号超出范围,或者指定的列不是对表列的简单引用,或者使用 3.0 之前的协议,则返回InvalidOid。您可以查询系统表pg_class以确定确切引用了哪个表。

当您包含 libpq 头文件时,将定义类型Oid和常量InvalidOid。它们都将是某种整数类型。

  • PQftablecol
    • 返回组成指定查询结果列的列的列号(在其表内)。查询结果列号从 0 开始,但是表列的数字非零。
int PQftablecol(const PGresult *res,
                int column_number);

如果列号超出范围,或者指定的列不是对表列的简单引用,或者使用 3.0 之前的协议,则返回零。

  • PQfformat
    • 返回表示给定列格式的格式代码。列号从 0 开始。
int PQfformat(const PGresult *res,
              int column_number);

格式代码零表示文本数据表示,而格式代码 1 表示二进制表示。 (其他代码保留以供将来定义.)

  • 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返回在数据库行中为此列分配的空间,换句话说,服务器内部数据类型表示的大小。 (因此,它对 Client 端并不是很有用.)负值表示数据类型为可变长度。

  • PQbinaryTuples
    • 如果PGresult包含二进制数据,则返回 1;如果包含文本数据,则返回 0.
int PQbinaryTuples(const PGresult *res);

不建议使用此功能(与COPY结合使用时除外),因为单个PGresult可能在某些列中包含文本数据,而在另一些列中包含二进制数据。 PQfformat是首选。 PQbinaryTuples仅在结果的所有列均为二进制(格式 1)时返回 1.

  • PQgetvalue
    • 返回PGresult的一行的单个字段值。行号和列号从 0 开始。调用者不应直接释放结果。当关联的PGresult句柄传递给PQclear时,它将被释放。
char *PQgetvalue(const PGresult *res,
                 int row_number,
                 int column_number);

对于文本格式的数据,由PQgetvalue返回的值是该字段值的以空值终止的字符串表示形式。对于二进制格式的数据,该值采用由数据类型的typsendtypreceive函数确定的二进制表示形式。 (在这种情况下,该值实际上也跟有一个零字节,但这通常不起作用,因为该值可能包含嵌入的 null.)

如果字段值为空,则返回一个空字符串。请参见PQgetisnull,以区分空值和空字符串值。

PQgetvalue返回的指针指向PGresult结构的一部分的存储。一个人不应该修改它指向的数据,如果要在PGresult结构本身的生存期之后使用它,则必须将其显式复制到其他存储中。

  • PQgetisnull
    • 测试字段的空值。行号和列号从 0 开始。
int PQgetisnull(const PGresult *res,
                int row_number,
                int column_number);

如果该字段为 null,则此函数返回 1;如果该字段包含非 null 值,则返回 0. (请注意,PQgetvalue将为空字段返回空字符串,而不是空指针.)

  • 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 以前曾使用此函数来打印查询结果,但现在不再如此。请注意,它假定所有数据均为文本格式。

33 .3.3. 检索其他结果信息

这些功能用于从PGresult对象中提取其他信息。

  • PQcmdStatus
    • 从生成PGresult的 SQL 命令返回命令状态标记。
char *PQcmdStatus(PGresult *res);

通常,这只是命令的名称,但是它可能包含其他数据,例如处理的行数。调用方不应直接释放结果。当关联的PGresult句柄传递到PQclear时,它将被释放。

  • PQcmdTuples
    • 返回受 SQL 命令影响的行数。
char *PQcmdTuples(PGresult *res);

此函数返回一个字符串,其中包含受生成PGresult的 SQL 语句影响的行数。仅在执行SELECTCREATE TABLE ASINSERTUPDATEDELETEMOVEFETCHCOPY语句或包含INSERTUPDATEDELETE语句的已准备查询的EXECUTE之后,才能使用此函数。如果生成PGresult的命令是其他命令,则PQcmdTuples返回空字符串。调用者不应直接释放返回值。当关联的PGresult句柄传递给PQclear时,它将被释放。

  • PQoidValue
    • 如果 SQL 命令是将_恰好插入一行到具有 OID 的表中的INSERT或包含适当INSERT语句的已准备查询的EXECUTE,则返回插入行的 OID 。否则,此函数返回InvalidOid。如果受INSERT语句影响的表不包含 OID,则此函数还将返回InvalidOid
Oid PQoidValue(const PGresult *res);
  • PQoidStatus
    • 不推荐使用此函数,而推荐使用PQoidValue,并且该函数不是线程安全的。它返回具有插入行的 OID 的字符串,而PQoidValue返回 OID 值。
char *PQoidStatus(const PGresult *res);

33 .3.4. 转义包含在 SQL 命令中的字符串

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

PQescapeLiteral转义用于 SQL 命令的字符串。在 SQL 命令中将数据值作为 Literals 常量插入时,这很有用。某些字符(例如引号和反斜杠)必须转义以防止它们由 SQL 解析器特别解释。 PQescapeLiteral执行此操作。

PQescapeLiteral在分配给malloc()的内存中返回* str 参数的转义版本。当不再需要结果时,应使用PQfreemem()释放此内存。不需要终止的零字节,也不应该在 length 中计数。 (如果在处理 length *字节之前找到了终止的零字节,则PQescapeLiteral会在零处停止;因此,行为就像strncpy一样.)返回字符串将替换所有特殊字符,以便 PostgreSQL 字符串可以对其进行正确处理。Literals 解析器。还添加了一个终止的零字节。结果字符串中包含必须包含 PostgreSQL 字符串 Literals 的单引号。

错误时,PQescapeLiteral返回NULL,并且适当的消息存储在* conn *对象中。

Tip

在处理从不可靠来源收到的字符串时,进行正确的转义尤为重要。否则存在安全风险:您容易受到“ SQL 注入”攻击的攻击,在这种攻击中,不需要的 SQL 命令会被馈送到数据库中。

请注意,当在PQexecParams或其同级例程中将数据值作为单独的参数传递时,进行转义既没有必要,也不正确。

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

PQescapeIdentifier转义一个字符串以用作 SQL 标识符,例如表,列或函数名。当用户提供的标识符可能包含特殊字符(否则 SQL 解析器不会将其解释为标识符的一部分),或者当标识符可能包含应保留大小写的大写字符时,此功能很有用。

PQescapeIdentifier返回通过malloc()分配的内存中作为 SQL 标识符转义的* str 参数的版本。当不再需要结果时,必须使用PQfreemem()释放此内存。不需要终止的零字节,也不应该在 length 中计数。 (如果在处理 length *字节之前找到终止的零字节,则PQescapeIdentifier会在零处停止;因此,行为就像strncpy一样.)返回字符串已替换了所有特殊字符,以便可以将其正确处理为 SQL 标识符。还添加了一个终止的零字节。返回字符串也将用双引号引起来。

错误时,PQescapeIdentifier返回NULL,并且适当的消息存储在* conn *对象中。

Tip

与字符串 Literals 一样,为防止 SQL 注入攻击,当从不可靠的来源收到 SQL 标识符时,必须对其进行转义。

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

PQescapeStringConn转义字符串 Literals,非常类似于PQescapeLiteral。与PQescapeLiteral不同,调用方负责提供适当大小的缓冲区。此外,PQescapeStringConn不会生成必须括在 PostgreSQL 字符串 Literals 中的单引号。应该在插入结果的 SQL 命令中提供它们。参数* from 指向要转义的字符串的第一个字符,而参数 length 给出此字符串中的字节数。不需要终止的零字节,也不应该在 length 中计数。 (如果在处理 length 字节之前找到终止的零字节,则PQescapeStringConn停止在零处;因此,行为类似于strncpy.) to 指向一个缓冲区,该缓冲区至少可以容纳一个比字节多的字节。值 length 的两倍。否则行为未定义。如果 to from *字符串重叠,则行为同样不确定。

如果* error 参数不是NULL,则成功时将*error设置为零,错误时则设置为非零。目前,唯一可能的错误条件是源字符串中的无效多字节编码。错误仍会生成输出字符串,但是可以预期服务器会拒绝该字符串,格式错误。错误时,无论 error 是否为NULL,都会在 conn *对象中存储适当的消息。

PQescapeStringConn返回写入* to *的字节数,不包括终止的零字节。

  • PQescapeString
  • PQescapeStringPQescapeStringConn的旧版本,已弃用。
size_t PQescapeString (char *to, const char *from, size_t length);

PQescapeStringConn的唯一区别是PQescapeString不使用PGconn或* error 参数。因此,它无法根据连接属性(例如字符编码)调整其行为,因此它可能会给出错误的结果*。同样,它也无法报告错误情况。

PQescapeString可以安全地用于一次只能使用一个 PostgreSQL 连接的 Client 端程序中(在这种情况下,它可以找出“幕后”需要知道的内容)。在其他情况下,这是安全隐患,应避免使用PQescapeStringConn

  • PQescapeByteaConn
    • 转义二进制数据以在类型为bytea的 SQL 命令中使用。与PQescapeStringConn一样,仅在将数据直接插入 SQL 命令字符串中时使用。
unsigned char *PQescapeByteaConn(PGconn *conn,
                                 const unsigned char *from,
                                 size_t from_length,
                                 size_t *to_length);

当某些字节值用作 SQL 语句中byteaLiterals 的一部分时,必须转义。 PQescapeByteaConn使用十六进制编码或反斜杠转义符转义字节。有关更多信息,请参见Section 8.4

  • from 参数指向要转义的字符串的第一个字节, from_length 参数给出此二进制字符串中的字节数。 (终止零字节既不是必需的,也不是计数的.) to_length *参数指向一个变量,该变量将保存所得的转义字符串长度。该结果字符串长度包括结果的终止零字节。

PQescapeByteaConn在分配给malloc()的内存中返回* from *参数二进制字符串的转义版本。当不再需要结果时,应使用PQfreemem()释放此内存。返回字符串将替换所有特殊字符,以便 PostgreSQL 字符串 Literals 解析器和byteaImporting 函数可以正确处理它们。还添加了一个终止的零字节。必须用 PostgreSQL 字符串 Literals 括起来的单引号不是结果字符串的一部分。

发生错误时,将返回空指针,并将适当的错误消息存储在* conn *对象中。当前,唯一可能的错误是结果字符串的内存不足。

  • PQescapeBytea
    • PQescapeByteaPQescapeByteaConn的旧版本,已弃用。
unsigned char *PQescapeBytea(const unsigned char *from,
                             size_t from_length,
                             size_t *to_length);

PQescapeByteaConn的唯一区别是PQescapeBytea不采用PGconn参数。因此,PQescapeBytea只能在一次使用单个 PostgreSQL 连接的 Client 端程序中安全使用(在这种情况下,它可以“了解其幕后情况”)。如果在使用多个数据库连接的程序中使用(在这种情况下,请使用PQescapeByteaConn),它“可能会给出错误的结果”。

  • PQunescapeBytea
    • 将二进制数据的字符串表示形式转换为二进制数据(与PQescapeBytea相反)。以文本格式检索bytea数据时需要此功能,但以二进制格式检索时则不需要。
unsigned char *PQunescapeBytea(const unsigned char *from, size_t *to_length);
  • from 参数指向一个字符串,例如应用于bytea列时PQgetvalue可能返回。 PQunescapeBytea将此字符串表示形式转换为其二进制表示形式。它返回指向分配给malloc()或错误时NULL的缓冲区的指针,并将缓冲区的大小放入 to_length *中。当不再需要结果时,必须使用PQfreemem释放结果。

此转换与PQescapeBytea并不完全相反,因为从PQgetvalue接收到该字符串时,预计该字符串不会“转义”。特别是,这意味着不需要考虑字符串引用,因此不需要PGconn参数。