* PQgetCopyData - read a row of data from the backend during COPY OUT * or COPY BOTH * * If successful, sets *buffer to point to a malloc'd row of data, and * returns row length (always > 0) as result. * Returns 0 if no row available yet (only possible if async is true), * -1 if end of copy (consult PQgetResult), or -2 if error (consult * PQerrorMessage). */
| 1890 | * PQerrorMessage). |
| 1891 | */ |
| 1892 | int |
| 1893 | pqGetCopyData3(PGconn *conn, char **buffer, int async) |
| 1894 | { |
| 1895 | int msgLength; |
| 1896 | |
| 1897 | for (;;) |
| 1898 | { |
| 1899 | /* |
| 1900 | * Collect the next input message. To make life simpler for async |
| 1901 | * callers, we keep returning 0 until the next message is fully |
| 1902 | * available, even if it is not Copy Data. |
| 1903 | */ |
| 1904 | msgLength = getCopyDataMessage(conn); |
| 1905 | if (msgLength < 0) |
| 1906 | return msgLength; /* end-of-copy or error */ |
| 1907 | if (msgLength == 0) |
| 1908 | { |
| 1909 | /* Don't block if async read requested */ |
| 1910 | if (async) |
| 1911 | return 0; |
| 1912 | /* Need to load more data */ |
| 1913 | if (pqWait(true, false, conn) || |
| 1914 | pqReadData(conn) < 0) |
| 1915 | return -2; |
| 1916 | continue; |
| 1917 | } |
| 1918 | |
| 1919 | /* |
| 1920 | * Drop zero-length messages (shouldn't happen anyway). Otherwise |
| 1921 | * pass the data back to the caller. |
| 1922 | */ |
| 1923 | msgLength -= 4; |
| 1924 | if (msgLength > 0) |
| 1925 | { |
| 1926 | *buffer = (char *) malloc(msgLength + 1); |
| 1927 | if (*buffer == NULL) |
| 1928 | { |
| 1929 | appendPQExpBufferStr(&conn->errorMessage, |
| 1930 | libpq_gettext("out of memory\n")); |
| 1931 | return -2; |
| 1932 | } |
| 1933 | memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength); |
| 1934 | (*buffer)[msgLength] = '\0'; /* Add terminating null */ |
| 1935 | |
| 1936 | /* Mark message consumed */ |
| 1937 | conn->inStart = conn->inCursor + msgLength; |
| 1938 | |
| 1939 | return msgLength; |
| 1940 | } |
| 1941 | |
| 1942 | /* Empty, so drop it and loop around for another */ |
| 1943 | conn->inStart = conn->inCursor; |
| 1944 | } |
| 1945 | } |
| 1946 | |
| 1947 | /* |
| 1948 | * PQgetline - gets a newline-terminated string from the backend. |
no test coverage detected