diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2003-04-22 00:08:07 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2003-04-22 00:08:07 +0000 |
commit | 5ed27e35f35f6c354b1a7120ec3a3ce57f93e73e (patch) | |
tree | 9ed912fbf02c36160a88881764735f8eab6103b9 /src/backend/commands | |
parent | ca944bd2d41814712cb4a4810ab4aa490f23a853 (diff) | |
download | postgresql-5ed27e35f35f6c354b1a7120ec3a3ce57f93e73e.tar.gz postgresql-5ed27e35f35f6c354b1a7120ec3a3ce57f93e73e.zip |
Another round of protocol changes. Backend-to-frontend messages now all
have length words. COPY OUT reimplemented per new protocol: it doesn't
need \. anymore, thank goodness. COPY BINARY to/from frontend works,
at least as far as the backend is concerned --- libpq's PQgetline API
is not up to snuff, and will have to be replaced with something that is
null-safe. libpq uses message length words for performance improvement
(no cycles wasted rescanning long messages), but not yet for error
recovery.
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/async.c | 10 | ||||
-rw-r--r-- | src/backend/commands/copy.c | 151 |
2 files changed, 111 insertions, 50 deletions
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 169c4ce278c..1d9fbf65809 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.92 2003/02/18 02:53:29 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.93 2003/04/22 00:08:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -847,10 +847,14 @@ NotifyMyFrontEnd(char *relname, int32 listenerPID) { StringInfoData buf; - pq_beginmessage(&buf); - pq_sendbyte(&buf, 'A'); + pq_beginmessage(&buf, 'A'); pq_sendint(&buf, listenerPID, sizeof(int32)); pq_sendstring(&buf, relname); + if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) + { + /* XXX Add parameter string here later */ + pq_sendstring(&buf, ""); + } pq_endmessage(&buf); /* diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 32e2362e99b..40948e3a3b5 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.194 2003/04/19 20:36:03 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.195 2003/04/22 00:08:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -50,13 +50,6 @@ #define ISOCTAL(c) (((c) >= '0') && ((c) <= '7')) #define OCTVALUE(c) ((c) - '0') -/* Default line termination */ -#ifndef WIN32 -#define PGEOL "\n" -#else -#define PGEOL "\r\n" -#endif - /* * Represents the different source/dest cases we need to worry about at * the bottom level @@ -92,7 +85,7 @@ typedef enum EolType /* non-export function prototypes */ static void CopyTo(Relation rel, List *attnumlist, bool binary, bool oids, - bool pipe, char *delim, char *null_print); + char *delim, char *null_print); static void CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, char *delim, char *null_print); static Oid GetInputFunction(Oid type); @@ -101,8 +94,7 @@ static char *CopyReadAttribute(const char *delim, CopyReadResult *result); static void CopyAttributeOut(char *string, char *delim); static List *CopyGetAttnums(Relation rel, List *attnamelist); -/* The trailing null is part of the signature */ -static const char BinarySignature[] = "PGBCOPY\n\377\r\n"; +static const char BinarySignature[12] = "PGBCOPY\n\377\r\n\0"; /* * Static communication variables ... pretty grotty, but COPY has @@ -135,10 +127,11 @@ static int server_encoding; */ static void SendCopyBegin(bool binary); static void ReceiveCopyBegin(bool binary); -static void SendCopyEnd(bool binary, bool pipe); +static void SendCopyEnd(bool binary); static void CopySendData(void *databuf, int datasize); static void CopySendString(const char *str); static void CopySendChar(char c); +static void CopySendEndOfRow(bool binary); static void CopyGetData(void *databuf, int datasize); static int CopyGetChar(void); #define CopyGetEof() (fe_eof) @@ -154,22 +147,32 @@ SendCopyBegin(bool binary) { if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) { - pq_putbytes("H", 1); /* new way */ - /* XXX grottiness needed for old protocol */ - pq_startcopyout(); + /* new way */ + StringInfoData buf; + + pq_beginmessage(&buf, 'H'); + pq_sendbyte(&buf, binary ? 1 : 0); + pq_endmessage(&buf); copy_dest = COPY_NEW_FE; + copy_msgbuf = makeStringInfo(); } else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2) { - pq_putbytes("H", 1); /* old way */ - /* grottiness needed for old protocol */ + /* old way */ + if (binary) + elog(ERROR, "COPY BINARY is not supported to stdout or from stdin"); + pq_putemptymessage('H'); + /* grottiness needed for old COPY OUT protocol */ pq_startcopyout(); copy_dest = COPY_OLD_FE; } else { - pq_putbytes("B", 1); /* very old way */ - /* grottiness needed for old protocol */ + /* very old way */ + if (binary) + elog(ERROR, "COPY BINARY is not supported to stdout or from stdin"); + pq_putemptymessage('B'); + /* grottiness needed for old COPY OUT protocol */ pq_startcopyout(); copy_dest = COPY_OLD_FE; } @@ -180,18 +183,29 @@ ReceiveCopyBegin(bool binary) { if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) { - pq_putbytes("G", 1); /* new way */ + /* new way */ + StringInfoData buf; + + pq_beginmessage(&buf, 'G'); + pq_sendbyte(&buf, binary ? 1 : 0); + pq_endmessage(&buf); copy_dest = COPY_NEW_FE; copy_msgbuf = makeStringInfo(); } else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2) { - pq_putbytes("G", 1); /* old way */ + /* old way */ + if (binary) + elog(ERROR, "COPY BINARY is not supported to stdout or from stdin"); + pq_putemptymessage('G'); copy_dest = COPY_OLD_FE; } else { - pq_putbytes("D", 1); /* very old way */ + /* very old way */ + if (binary) + elog(ERROR, "COPY BINARY is not supported to stdout or from stdin"); + pq_putemptymessage('D'); copy_dest = COPY_OLD_FE; } /* We *must* flush here to ensure FE knows it can send. */ @@ -199,22 +213,39 @@ ReceiveCopyBegin(bool binary) } static void -SendCopyEnd(bool binary, bool pipe) +SendCopyEnd(bool binary) { - if (!binary) + if (copy_dest == COPY_NEW_FE) { - CopySendString("\\."); - CopySendString(!pipe ? PGEOL : "\n"); + if (binary) + { + /* Need to flush out file trailer word */ + CopySendEndOfRow(true); + } + else + { + /* Shouldn't have any unsent data */ + Assert(copy_msgbuf->len == 0); + } + /* Send Copy Done message */ + pq_putemptymessage('c'); + } + else + { + /* The FE/BE protocol uses \n as newline for all platforms */ + CopySendData("\\.\n", 3); + pq_endcopyout(false); } - pq_endcopyout(false); } -/* +/*---------- * CopySendData sends output data to the destination (file or frontend) * CopySendString does the same for null-terminated strings * CopySendChar does the same for single characters + * CopySendEndOfRow does the appropriate thing at end of each data row * * NB: no data conversion is applied by these functions + *---------- */ static void CopySendData(void *databuf, int datasize) @@ -228,12 +259,13 @@ CopySendData(void *databuf, int datasize) break; case COPY_OLD_FE: if (pq_putbytes((char *) databuf, datasize)) - fe_eof = true; + { + /* no hope of recovering connection sync, so FATAL */ + elog(FATAL, "CopySendData: connection lost"); + } break; case COPY_NEW_FE: - /* XXX fix later */ - if (pq_putbytes((char *) databuf, datasize)) - fe_eof = true; + appendBinaryStringInfo(copy_msgbuf, (char *) databuf, datasize); break; } } @@ -250,6 +282,40 @@ CopySendChar(char c) CopySendData(&c, 1); } +static void +CopySendEndOfRow(bool binary) +{ + switch (copy_dest) + { + case COPY_FILE: + if (!binary) + { + /* Default line termination depends on platform */ +#ifndef WIN32 + CopySendChar('\n'); +#else + CopySendString("\r\n"); +#endif + } + break; + case COPY_OLD_FE: + /* The FE/BE protocol uses \n as newline for all platforms */ + if (!binary) + CopySendChar('\n'); + break; + case COPY_NEW_FE: + /* The FE/BE protocol uses \n as newline for all platforms */ + if (!binary) + CopySendChar('\n'); + /* Dump the accumulated row as one CopyData message */ + (void) pq_putmessage('d', copy_msgbuf->data, copy_msgbuf->len); + /* Reset copy_msgbuf to empty */ + copy_msgbuf->len = 0; + copy_msgbuf->data[0] = '\0'; + break; + } +} + /* * CopyGetData reads data from the source (file or frontend) * CopyGetChar does the same for single characters @@ -569,13 +635,6 @@ DoCopy(const CopyStmt *stmt) "from stdin. Psql's \\copy command also works for anyone."); /* - * This restriction is unfortunate, but necessary until the frontend - * COPY protocol is redesigned to be binary-safe... - */ - if (pipe && binary) - elog(ERROR, "COPY BINARY is not supported to stdout or from stdin"); - - /* * Presently, only single-character delimiter strings are supported. */ if (strlen(delim) != 1) @@ -698,13 +757,13 @@ DoCopy(const CopyStmt *stmt) elog(ERROR, "COPY: %s is a directory", filename); } } - CopyTo(rel, attnumlist, binary, oids, pipe, delim, null_print); + CopyTo(rel, attnumlist, binary, oids, delim, null_print); } if (!pipe) FreeFile(copy_file); else if (IsUnderPostmaster && !is_from) - SendCopyEnd(binary, pipe); + SendCopyEnd(binary); pfree(attribute_buf.data); /* @@ -721,7 +780,7 @@ DoCopy(const CopyStmt *stmt) * Copy from relation TO file. */ static void -CopyTo(Relation rel, List *attnumlist, bool binary, bool oids, bool pipe, +CopyTo(Relation rel, List *attnumlist, bool binary, bool oids, char *delim, char *null_print) { HeapTuple tuple; @@ -786,7 +845,7 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids, bool pipe, int32 tmp; /* Signature */ - CopySendData((char *) BinarySignature, sizeof(BinarySignature)); + CopySendData((char *) BinarySignature, 12); /* Integer layout field */ tmp = 0x01020304; CopySendData(&tmp, sizeof(int32)); @@ -918,8 +977,7 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids, bool pipe, } } - if (!binary) - CopySendString(!pipe ? PGEOL : "\n"); + CopySendEndOfRow(binary); MemoryContextSwitchTo(oldcontext); } @@ -1100,8 +1158,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, /* Signature */ CopyGetData(readSig, 12); - if (CopyGetEof() || memcmp(readSig, BinarySignature, - sizeof(BinarySignature)) != 0) + if (CopyGetEof() || memcmp(readSig, BinarySignature, 12) != 0) elog(ERROR, "COPY BINARY: file signature not recognized"); /* Integer layout field */ CopyGetData(&tmp, sizeof(int32)); |