COPY
命令相关的函数 #在 PostgreSQL 中,COPY
命令具有从 libpq 使用的网络连接读取或写入的选项。本节中描述的函数允许应用程序通过提供或使用复制数据来利用此功能。
总体过程是,应用程序首先通过 PQexec
或等效函数之一发出 SQL COPY
命令。对该命令的响应(如果命令中没有错误)将是一个 PGresult
对象,该对象具有 PGRES_COPY_OUT
或 PGRES_COPY_IN
的状态代码(取决于指定的复制方向)。然后,应用程序应使用本节中的函数来接收或传输数据行。数据传输完成后,将返回另一个 PGresult
对象以指示传输成功或失败。其状态将为 PGRES_COMMAND_OK
表示成功,或 PGRES_FATAL_ERROR
表示遇到了一些问题。此时,可以通过 PQexec
发出进一步的 SQL 命令。(在 COPY
操作正在进行时,无法使用相同的连接执行其他 SQL 命令。)
如果通过 PQexec
在可能包含其他命令的字符串中发出 COPY
命令,则应用程序必须在完成 COPY
序列后继续通过 PQgetResult
获取结果。只有当 PQgetResult
返回 NULL
时,才能确定 PQexec
命令字符串已完成,并且可以安全地发出更多命令。
本节中的函数应仅在从 PQexec
或 PQgetResult
获得 PGRES_COPY_OUT
或 PGRES_COPY_IN
的结果状态后执行。
具有这些状态值之一的 PGresult
对象承载了一些关于正在开始的 COPY
操作的附加数据。可以使用也用于连接查询结果的函数来获取这些附加数据
COPY
数据的函数 #这些函数用于在 COPY FROM STDIN
期间发送数据。如果在连接未处于 COPY_IN
状态时调用它们,它们将失败。
PQputCopyData
#在 COPY_IN
状态期间将数据发送到服务器。
int PQputCopyData(PGconn *conn, const char *buffer, int nbytes);
将指定 buffer
中长度为 nbytes
的 COPY
数据传输到服务器。如果数据已排队,则结果为 1;如果由于缓冲区已满而未排队(这仅在非阻塞模式下才会发生),则结果为 0;如果发生错误,则结果为 -1。(如果返回值为 -1,请使用 PQerrorMessage
来检索详细信息。如果值为零,请等待写入就绪并重试。)
应用程序可以将 COPY
数据流划分为任何方便大小的缓冲区负载。在发送时,缓冲区负载边界没有语义意义。数据流的内容必须与 COPY
命令预期的格式匹配;有关详细信息,请参见 COPY。
PQputCopyEnd
#在 COPY_IN
状态期间将数据结束指示发送到服务器。
int PQputCopyEnd(PGconn *conn, const char *errormsg);
如果 errormsg
为 NULL
,则成功结束 COPY_IN
操作。如果 errormsg
不为 NULL
,则强制 COPY
失败,并将 errormsg
指向的字符串用作错误消息。(但是,不应假设此确切的错误消息将从服务器返回,因为服务器可能已出于自身原因使 COPY
失败。)
如果已发送终止消息,则结果为 1;或者在非阻塞模式下,这可能仅表示已成功将终止消息排队。(在非阻塞模式下,要确保数据已发送,您应该接下来等待写入就绪并调用 PQflush
,重复此操作直到它返回零。)零表示该函数由于缓冲区已满而无法将终止消息排队;这仅在非阻塞模式下才会发生。(在这种情况下,请等待写入就绪并再次尝试调用 PQputCopyEnd
。)如果发生严重错误,则返回 -1;您可以使用 PQerrorMessage
来检索详细信息。
成功调用 PQputCopyEnd
后,调用 PQgetResult
以获取 COPY
命令的最终结果状态。您可以以通常的方式等待此结果可用。然后返回正常操作。
COPY
数据的函数 #这些函数用于在 COPY TO STDOUT
期间接收数据。如果在连接未处于 COPY_OUT
状态时调用它们,它们将失败。
PQgetCopyData
#在 COPY_OUT
状态期间从服务器接收数据。
int PQgetCopyData(PGconn *conn, char **buffer, int async);
尝试在 COPY
期间从服务器获取另一行数据。数据始终一次返回一行数据;如果仅部分行可用,则不返回该行。成功返回数据行涉及分配一块内存来保存数据。 buffer
参数必须是非 NULL
。 *buffer
设置为指向分配的内存,或者在没有返回缓冲区的情况下设置为 NULL
。在不再需要时,应使用 PQfreemem
释放非 NULL
结果缓冲区。
当成功返回一行时,返回值是该行中的数据字节数(这将始终大于零)。返回的字符串始终以 null 结尾,尽管这可能仅对文本类型的 COPY
有用。结果为零表示 COPY
仍在进行中,但尚未有行可用(只有当 async
为真时才有可能)。结果为 -1 表示 COPY
已完成。结果为 -2 表示发生了错误(请参阅 PQerrorMessage
获取原因)。
当 async
为真(非零)时,PQgetCopyData
不会阻塞等待输入;如果 COPY
仍在进行中但没有完整的行可用,它将返回零。(在这种情况下,请等待读就绪,然后调用 PQconsumeInput
,然后再再次调用 PQgetCopyData
。)当 async
为假(零)时,PQgetCopyData
将阻塞,直到数据可用或操作完成。
在 PQgetCopyData
返回 -1 后,请调用 PQgetResult
以获取 COPY
命令的最终结果状态。您可以通过通常的方式等待该结果可用。然后恢复正常操作。
COPY
的过时函数 #这些函数代表处理 COPY
的旧方法。虽然它们仍然有效,但由于错误处理不佳、检测数据结尾的方法不方便以及不支持二进制或非阻塞传输,因此已弃用。
PQgetline
#将服务器传输的以换行符结尾的行字符读入大小为 length
的缓冲区字符串中。
int PQgetline(PGconn *conn, char *buffer, int length);
此函数将最多 length
-1 个字符复制到缓冲区中,并将终止换行符转换为零字节。PQgetline
在输入结束时返回 EOF
,如果整行已读取则返回 0,如果缓冲区已满但终止换行符尚未读取则返回 1。
请注意,应用程序必须检查以查看新行是否包含两个字符 \.
,这表示服务器已完成发送 COPY
命令的结果。如果应用程序可能接收长度超过 length
-1 个字符的行,则需要小心以确保它正确识别 \.
行(例如,不要将长数据行的结尾误认为终止符行)。
PQgetlineAsync
#非阻塞地将一行 COPY
数据(由服务器传输)读入缓冲区。
int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize);
此函数类似于 PQgetline
,但它可以被必须异步读取 COPY
数据的应用程序使用,也就是说,不阻塞。在发出 COPY
命令并获得 PGRES_COPY_OUT
响应后,应用程序应调用 PQconsumeInput
和 PQgetlineAsync
,直到检测到数据结尾信号。
与 PQgetline
不同,此函数负责检测数据结尾。
在每次调用中,PQgetlineAsync
将在 libpq 的输入缓冲区中存在完整的DataRow 时返回数据。否则,在DataRow 的其余部分到达之前不会返回任何数据。如果识别出数据结尾标记,则该函数返回 -1;如果无数据可用,则返回 0;如果返回正数,则表示返回的数据字节数。如果返回 -1,则调用者必须接下来调用 PQendcopy
,然后恢复正常处理。
返回的数据不会超出DataRow 边界。如果可能,将一次返回整个DataRow。但是,如果调用者提供的缓冲区太小而无法容纳服务器发送的DataRow,则将返回部分DataRow。对于文本数据,可以通过测试最后一个返回的字节是否为 \n
来检测这一点。(在二进制 COPY
中,需要对 COPY
数据格式进行实际解析才能做出等效的确定。)返回的字符串不是以 null 结尾的。(如果要添加终止 null,请确保传递的 bufsize
比实际可用的空间小一个。)
PQputline
#将以 null 结尾的字符串发送到服务器。如果成功则返回 0,如果无法发送字符串则返回 EOF
。
int PQputline(PGconn *conn, const char *string);
通过一系列对 PQputline
的调用发送的 COPY
数据流与 PQgetlineAsync
返回的格式相同,只是应用程序不必在每次 PQputline
调用中发送正好一个DataRow;可以每次调用发送部分行或多行。
在 PostgreSQL 协议 3.0 之前,应用程序必须显式发送两个字符 \.
作为最后一行,以指示服务器已完成发送 COPY
数据。虽然这仍然有效,但它已被弃用,并且预计将在将来的版本中删除 \.
的特殊含义。在发送完实际数据后,调用 PQendcopy
就足够了。
PQputnbytes
#将非以 null 结尾的字符串发送到服务器。如果成功则返回 0,如果无法发送字符串则返回 EOF
。
int PQputnbytes(PGconn *conn, const char *buffer, int nbytes);
这与 PQputline
完全相同,只是数据缓冲区不必以 null 结尾,因为要发送的字节数是直接指定的。在发送二进制数据时使用此过程。
PQendcopy
#与服务器同步。
int PQendcopy(PGconn *conn);
此函数将等待,直到服务器完成复制。它应该在使用 PQputline
将最后一个字符串发送到服务器时或使用 PQgetline
从服务器接收最后一个字符串时发出。它必须发出,否则服务器将与客户端“不同步”。从此函数返回后,服务器已准备好接收下一个 SQL 命令。如果成功完成,则返回值为 0,否则为非零。(如果返回值为非零,请使用 PQerrorMessage
获取详细信息。)
当使用 PQgetResult
时,应用程序应通过重复执行 PQgetline
来响应 PGRES_COPY_OUT
结果,并在看到终止符行后执行 PQendcopy
。然后它应该返回到 PQgetResult
循环,直到 PQgetResult
返回一个空指针。类似地,通过一系列 PQputline
调用,后跟 PQendcopy
处理 PGRES_COPY_IN
结果,然后返回到 PQgetResult
循环。这种安排将确保嵌入在 SQL 命令系列中的 COPY
命令被正确执行。SQL命令将被正确执行。
旧的应用程序可能会通过 PQexec
提交 COPY
,并假设在 PQendcopy
之后事务已完成。这只有在 COPY
是命令字符串中的唯一命令时才能正常工作。SQL命令。
如果您在文档中看到任何不正确的内容,与您对特定功能的体验不符或需要进一步澄清,请使用 此表格 报告文档问题。