The COPY command in PostgreSQL has options to read from or write to the network connection used by libpq. Therefore, functions are necessary to access this network connection directly so applications may take advantage of this capability.
These functions should be executed only after obtaining a
PGRES_COPY_OUT or PGRES_COPY_IN result object from PQexec
or PQgetResult
.
PQgetline
Reads a
newline-terminated line of characters (transmitted by the
backend server) into a buffer string of size length.
int PQgetline(PGconn *conn, char *string, int length)
Like fgets
, this routine
copies up to length-1 characters into string. It is like
gets
, however, in that it
converts the terminating newline into a zero byte.
PQgetline
returns EOF at the end of input, 0 if the entire line
has been read, and 1 if the buffer is full but the
terminating newline has not yet been read.
Notice that the application must check to see if a new line consists of the two characters \., which indicates that the backend server has finished sending the results of the copy command. If the application might receive lines that are more than length-1 characters long, care is needed to be sure one recognizes the \. line correctly (and does not, for example, mistake the end of a long data line for a terminator line). The code in src/bin/psql/copy.c contains example routines that correctly handle the copy protocol.
PQgetlineAsync
Reads a
newline-terminated line of characters (transmitted by the
backend server) into a buffer without blocking.
int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize)
This routine is similar to PQgetline
, but it can be used by
applications that must read COPY data asynchronously, that is
without blocking. Having issued the COPY command and gotten a
PGRES_COPY_OUT response, the
application should call PQconsumeInput
and PQgetlineAsync
until the end-of-data signal
is detected. Unlike PQgetline
,
this routine takes responsibility for detecting end-of-data.
On each call, PQgetlineAsync
will return data if a complete newline- terminated data line
is available in libpq's
input buffer, or if the incoming data line is too long to fit
in the buffer offered by the caller. Otherwise, no data is
returned until the rest of the line arrives.
The routine returns -1 if the end-of-copy-data marker has
been recognized, or 0 if no data is available, or a positive
number giving the number of bytes of data returned. If -1 is
returned, the caller must next call PQendcopy
, and then return to normal
processing. The data returned will not extend beyond a
newline character. If possible a whole line will be returned
at one time. But if the buffer offered by the caller is too
small to hold a line sent by the backend, then a partial data
line will be returned. This can be detected by testing
whether the last returned byte is \n
or not. The returned string is not null-terminated. (If you
want to add a terminating null, be sure to pass a
bufsize
one smaller than the
room actually available.)
PQputline
Sends a
null-terminated string to the backend server. Returns 0 if
OK, EOF if unable to send the
string.
int PQputline(PGconn *conn, const char *string);
Note the application must explicitly send the two characters \. on a final line to indicate to the backend that it has finished sending its data.
PQputnbytes
Sends a
non-null-terminated string to the backend server. Returns 0
if OK, EOF if unable to send the
string.
int PQputnbytes(PGconn *conn, const char *buffer, int nbytes);
This is exactly like PQputline
, except that the data buffer need
not be null-terminated since the number of bytes to send is
specified directly.
PQendcopy
Synchronizes with
the backend. This function waits until the backend has
finished the copy. It should either be issued when the last
string has been sent to the backend using PQputline
or when the last string has been
received from the backend using PGgetline
. It must be issued or the backend
may get "out of sync" with the
frontend. Upon return from this function, the backend is
ready to receive the next SQL command. The return value is 0
on successful completion, nonzero otherwise.
int PQendcopy(PGconn *conn);
As an example:
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);
When using PQgetResult
, the
application should respond to a PGRES_COPY_OUT result by executing PQgetline
repeatedly, followed by PQendcopy
after the terminator line is seen. It
should then return to the PQgetResult
loop until PQgetResult
returns NULL. Similarly a
PGRES_COPY_IN result is processed by a
series of PQputline
calls followed
by PQendcopy
, then return to the
PQgetResult
loop. This arrangement
will ensure that a copy in or copy out command embedded in a
series of SQL commands will be
executed correctly.
Older applications are likely to submit a copy in or copy out
via PQexec
and assume that the
transaction is done after PQendcopy
. This will work correctly only if the
copy in/out is the only SQL
command in the command string.