PostgreSQL
里的 COPY 命令里有用于
libpq
里从网络联接读出或者写入的选项.
因此,这些函数有必要直接访问网络联接,以便应用可以充分利用这个功能.
这些函数应该只在从
PQexec
或
PQgetResult
获得了
PGRES_COPY_OUT
或
PGRES_COPY_IN
结果对象的情况下执行.
-
PQgetline
读取一个以回车符(换行符)结尾的字符行中指定字节数的字符
(由后端服务器传输)到一个字符串缓冲区.
int PQgetline(PGconn *conn,
char *string,
int length)
类似
fgets
,这个过程拷贝最多 length-1 个字符到字符串里.
但是它会象
gets
那样把结尾的换行符转换成一个字节零.
PQgetline
在输入结束时返回
EOF
,如果整行都被读取了返回 0,如果缓冲区填满了而还没有遇到结束的换行符则返回 1.
注意,应用程序必须检查新行是否包含两个字符 "\.",
这表明后端服务器已经完成了 copy 命令的结果集的发送.
如果应用可能收到超过 length-1 字符长的字符,我们就应该确保正确识别"\."行
(例如,不要把一个长的行的结束当作一个终止行).
src/bin/psql/copy.c
里的代码包含正确控制 copy 协议的过程.
-
PQgetlineAsync
不做阻塞地读取一行以换行符结尾的字符(由后端服务器传输)到一个缓冲区中.
int PQgetlineAsync(PGconn *conn,
char *buffer,
int bufsize)
这个过程类似于
PQgetline
,但是可以用于那些必须异步地读取
COPY 数据的应用,因而是不阻塞的.在使用了 COPY 命令和获取了
PGRES_COPY_OUT
响应之后,应用应该调用
PQconsumeInput
和
PQgetlineAsync
直到收到数据结束的信号.
不象
PQgetline
,这个过程负责检测数据结束.
在每次调用时,如果
libpq
的输入缓冲区内有可用的一个完整的换行符结尾的数据行
或者调用者声明的缓冲区小于到来的数据行的长度,
PQgetlineAsync
都将返回数据.
否则,在其他数据到达之前不会返回数据.
如果见到了拷贝数据结束的信号,此过程返回 -1,如果没有可用数据返回 0,
或者是给出一个正数表明返回的数据的字节数.如果返回 -1,调用者下一步必须调用
PQendcopy
,然后回到正常处理.返回的数据将不
会超出换行符的范围.
如果可能,每次将返回一个完整行.但如果调用者提供的缓冲区太小,
无法容下后端发出的整行,那么将返回部分行.这个可以通过测试返回的最后一个字节是否 "
\n
" 来确认.
返回的字符串不是空结尾的.
(如果你想得到一个空结尾的字串,确保你传递了一个
bufsize
比实际大小少一字节的缓冲区.)
-
PQputline
向后端服务器发送一个空结尾的字符串.成功时返回 0,如果不能发送字符串返回
EOF
.
int PQputline(PGconn *conn,
const char *string);
注意,应用在最后一行时必须明确的发送两个字符
"
\.
" ,通知后端它已经完成数据发送.
-
PQputnbytes
向后端服务器发送一个非空结尾的字符串.成功时返回 0,如果不能发送字符串返回
EOF
.
int PQputnbytes(PGconn *conn,
const char *buffer,
int nbytes);
此函数类似
PQputline
,除了数据缓冲区不需要是空结尾的之外,因为要发送的字节数是直接声明的.
-
PQendcopy
与后端同步.这个函数等到后端完成拷贝(才返回?).
你可以在用
PQputline
向后端发送完最后一个字符串后或者用
PGgetline
从后端获取最后一行字符串后调用它.
我们必须调用这个函数,否则后端可能会和前端
"同步丢失"
。在这个函数返回后,
后端就已经准备好接收下一个 SQL 命令了.成功时返回0,否则返回非零值.
int PQendcopy(PGconn *conn);
一个例子:
PQexec(conn, "CREATE TABLE foo (a int4, b char(16), d double precision)");
PQexec(conn, "COPY foo FROM STDIN");
PQputline(conn, "3\thello world\t4.5\n");
PQputline(conn,"4\tgoodbye world\t7.11\n");
...
PQputline(conn,"\\.\n");
PQendcopy(conn);
在使用
PQgetResult
时,应用应该对
PGRES_COPY_OUT
的结果做出反应:重复调用
PQgetline
,并且在收到结束行时调用
PQendcopy
.
然后应该返回到
PQgetResult
循环直到
PQgetResult
返回 NULL.
类似地,
PGRES_COPY_IN
结果是用一系列
PQputline
调用最后跟着
PQendcopy
,然后返回到
PQgetResult
循环.
这样的排列将保证嵌入到一系列
SQL
命令里的 copy in 或 copy out 命令将被正确执行.
旧的应用大多通过
PQexec
提交一个 copy in 或 copy out 命令并且假设在
PQendcopy
后事务完成.
这样只有在copy in/out 是命令字串里的唯一的
SQL
命令时才能正确工作.
|