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;如果由于缓冲区已满而未排队(这仅在非阻塞模式下发生),则结果为零;如果发生错误,则结果为 -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
为 true 时才可能发生)。返回 -1 表示 COPY
已完成。返回 -2 表示发生错误(请查阅 PQerrorMessage
以了解原因)。
当 async
为 true(非零)时,PQgetCopyData
不会阻塞等待输入;如果 COPY
仍在进行中但没有完整的行可用,它将返回零。(在这种情况下,请等待读取就绪,然后在再次调用 PQgetCopyData
之前调用 PQconsumeInput
。)当 async
为 false(零)时,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
不同,此函数负责检测数据结束。
在每次调用时,如果 libpq 的输入缓冲区中有一个完整的数据行可用,PQgetlineAsync
将返回数据。否则,直到行的其余部分到达才会返回数据。如果已识别出复制数据结束标记,则该函数返回 -1;如果没有数据可用,则返回 0;或返回一个正数,表示返回的数据字节数。如果返回 -1,则调用者必须接下来调用 PQendcopy
,然后返回正常处理。
返回的数据不会超出数据行边界。如果可能,将一次返回整行。但是,如果调用者提供的缓冲区太小而无法容纳服务器发送的行,则将返回部分数据行。对于文本数据,可以通过测试最后返回的字节是否为 \n
来检测到这一点。(在二进制 COPY
中,需要实际解析 COPY
数据格式才能做出等效的判断。)返回的字符串不是以 null 结尾的。(如果要添加结尾 null,请确保传递的 bufsize
比实际可用的空间小 1。)
PQputline
#将以 null 结尾的字符串发送到服务器。如果正常则返回 0,如果无法发送字符串则返回 EOF
。
int PQputline(PGconn *conn, const char *string);
通过一系列调用 PQputline
发送的 COPY
数据流的格式与 PQgetlineAsync
返回的格式相同,但应用程序不必每次调用 PQputline
都发送完全一个数据行;每次调用发送部分行或多行都可以。
在 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
调用处理 PGRES_COPY_IN
结果,然后是 PQendcopy
,然后返回到 PQgetResult
循环。此安排将确保正确执行嵌入在一系列SQL命令中的 COPY
命令。
较旧的应用程序可能会通过 PQexec
提交 COPY
,并假设在 PQendcopy
之后事务已完成。只有当 COPY
是命令字符串中的唯一SQL命令时,此操作才能正确运行。
如果您在文档中发现任何不正确、与您使用特定功能的体验不符或需要进一步澄清的内容,请使用 此表格 报告文档问题。