From e25e6a6dc389f7a795d7aeba07ba8de5de083c73 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 31 Aug 1999 04:26:40 +0000 Subject: [PATCH] Commit the bulk of Mike Ansley's long-query changes in the backend. Still much left to do. --- src/backend/libpq/pqcomm.c | 26 ++++----- src/backend/libpq/pqformat.c | 29 ++++------ src/backend/tcop/postgres.c | 105 +++++++++++++---------------------- src/include/libpq/libpq.h | 5 +- src/include/libpq/pqcomm.h | 7 +-- src/include/libpq/pqformat.h | 4 +- 6 files changed, 67 insertions(+), 109 deletions(-) diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 5e129bc56f..1d57415860 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -28,7 +28,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: pqcomm.c,v 1.81 1999/07/23 03:00:10 tgl Exp $ + * $Id: pqcomm.c,v 1.82 1999/08/31 04:26:37 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -526,38 +526,32 @@ pq_getbytes(char *s, size_t len) /* -------------------------------- * pq_getstring - get a null terminated string from connection * + * The return value is placed in an expansible StringInfo. + * Note that space allocation comes from the current memory context! + * * NOTE: this routine does not do any MULTIBYTE conversion, * even though it is presumably useful only for text, because * no code in this module should depend on MULTIBYTE mode. * See pq_getstr in pqformat.c for that. * - * FIXME: we ought to use an expansible StringInfo buffer, - * rather than dropping data if the message is too long. - * * returns 0 if OK, EOF if trouble * -------------------------------- */ int -pq_getstring(char *s, size_t len) +pq_getstring(StringInfo s) { int c; - /* - * Keep on reading until we get the terminating '\0', discarding any - * bytes we don't have room for. - */ + /* Reset string to empty */ + s->len = 0; + s->data[0] = '\0'; + /* Read until we get the terminating '\0' */ while ((c = pq_getbyte()) != EOF && c != '\0') { - if (len > 1) - { - *s++ = c; - len--; - } + appendStringInfoChar(s, c); } - *s = '\0'; - if (c == EOF) return EOF; diff --git a/src/backend/libpq/pqformat.c b/src/backend/libpq/pqformat.c index e5da571886..1cc715b92a 100644 --- a/src/backend/libpq/pqformat.c +++ b/src/backend/libpq/pqformat.c @@ -15,7 +15,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: pqformat.c,v 1.7 1999/07/17 20:17:03 momjian Exp $ + * $Id: pqformat.c,v 1.8 1999/08/31 04:26:37 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -290,37 +290,30 @@ pq_getint(int *result, int b) /* -------------------------------- * pq_getstr - get a null terminated string from connection * - * FIXME: we ought to use an expansible StringInfo buffer, - * rather than dropping data if the message is too long. + * The return value is placed in an expansible StringInfo. + * Note that space allocation comes from the current memory context! * * returns 0 if OK, EOF if trouble * -------------------------------- */ int -pq_getstr(char *s, int maxlen) +pq_getstr(StringInfo s) { int c; - #ifdef MULTIBYTE char *p; - #endif - c = pq_getstring(s, maxlen); + c = pq_getstring(s); #ifdef MULTIBYTE - p = (char *) pg_client_to_server((unsigned char *) s, strlen(s)); - if (p != s) /* actual conversion has been done? */ + p = (char *) pg_client_to_server((unsigned char *) s->data, s->len); + if (p != s->data) /* actual conversion has been done? */ { - int newlen = strlen(p); - - if (newlen < maxlen) - strcpy(s, p); - else - { - strncpy(s, p, maxlen); - s[maxlen - 1] = '\0'; - } + /* reset s to empty, and append the new string p */ + s->len = 0; + s->data[0] = '\0'; + appendBinaryStringInfo(s, p, strlen(p)); } #endif diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index a667fa70c4..3986bee47b 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.127 1999/07/22 02:40:07 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.128 1999/08/31 04:26:40 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -158,9 +158,9 @@ int _exec_repeat_ = 1; * decls for routines only used in this file * ---------------------------------------------------------------- */ -static int InteractiveBackend(char *inBuf); -static int SocketBackend(char *inBuf); -static int ReadCommand(char *inBuf); +static int InteractiveBackend(StringInfo inBuf); +static int SocketBackend(StringInfo inBuf); +static int ReadCommand(StringInfo inBuf); static void pg_exec_query(char *query_string); @@ -178,9 +178,8 @@ static void pg_exec_query(char *query_string); */ static int -InteractiveBackend(char *inBuf) +InteractiveBackend(StringInfo inBuf) { - char *stuff = inBuf; /* current place in input buffer */ int c; /* character read from getc() */ bool end = false; /* end-of-input flag */ bool backslashSeen = false; /* have we seen a \ ? */ @@ -192,6 +191,10 @@ InteractiveBackend(char *inBuf) printf("backend> "); fflush(stdout); + /* Reset inBuf to empty */ + inBuf->len = 0; + inBuf->data[0] = '\0'; + for (;;) { if (UseNewLine) @@ -207,14 +210,15 @@ InteractiveBackend(char *inBuf) { if (backslashSeen) { - stuff--; + /* discard backslash from inBuf */ + inBuf->data[--inBuf->len] = '\0'; + backslashSeen = false; continue; } else { /* keep the newline character */ - *stuff++ = '\n'; - *stuff++ = '\0'; + appendStringInfoChar(inBuf, '\n'); break; } } @@ -223,7 +227,7 @@ InteractiveBackend(char *inBuf) else backslashSeen = false; - *stuff++ = (char) c; + appendStringInfoChar(inBuf, (char) c); } if (c == EOF) @@ -236,9 +240,9 @@ InteractiveBackend(char *inBuf) * ---------------- */ while ((c = getc(stdin)) != EOF) - *stuff++ = (char) c; + appendStringInfoChar(inBuf, (char) c); - if (stuff == inBuf) + if (inBuf->len == 0) end = true; } @@ -261,7 +265,7 @@ InteractiveBackend(char *inBuf) * ---------------- */ if (EchoQuery) - printf("query: %s\n", inBuf); + printf("query: %s\n", inBuf->data); fflush(stdout); return 'Q'; @@ -274,7 +278,7 @@ InteractiveBackend(char *inBuf) * the user is placed in its parameter inBuf. * * If the input is a fastpath function call (case 'F') then - * the function call is processed in HandleFunctionRequest(). + * the function call is processed in HandleFunctionRequest() * (now called from PostgresMain()). * * EOF is returned if the connection is lost. @@ -282,7 +286,7 @@ InteractiveBackend(char *inBuf) */ static int -SocketBackend(char *inBuf) +SocketBackend(StringInfo inBuf) { char qtype; char result = '\0'; @@ -302,7 +306,7 @@ SocketBackend(char *inBuf) * ---------------- */ case 'Q': - if (pq_getstr(inBuf, MAX_PARSE_BUFFER)) + if (pq_getstr(inBuf)) return EOF; result = 'Q'; break; @@ -312,7 +316,7 @@ SocketBackend(char *inBuf) * ---------------- */ case 'F': - if (pq_getstr(inBuf, MAX_PARSE_BUFFER)) + if (pq_getstr(inBuf)) return EOF; /* ignore "string" at start of F message */ result = 'F'; break; @@ -347,12 +351,21 @@ SocketBackend(char *inBuf) * ---------------- */ static int -ReadCommand(char *inBuf) +ReadCommand(StringInfo inBuf) { + MemoryContext oldcontext; + int result; + + /* Make sure any expansion of inBuf happens in permanent memory context, + * so that we can keep using it for future command cycles. + */ + oldcontext = MemoryContextSwitchTo(TopMemoryContext); if (IsUnderPostmaster) - return SocketBackend(inBuf); + result = SocketBackend(inBuf); else - return InteractiveBackend(inBuf); + result = InteractiveBackend(inBuf); + MemoryContextSwitchTo(oldcontext); + return result; } List * @@ -374,45 +387,7 @@ pg_parse_and_plan(char *query_string, /* string to execute */ if (DebugPrintQuery) { - if (DebugPrintQuery > 3) - { - /* Print the query string as is if query debug level > 3 */ - TPRINTF(TRACE_QUERY, "query: %s", query_string); - } - else - { - /* Print condensed query string to fit in one log line */ - char buff[MAX_QUERY_SIZE + 1]; - char c, - *s, - *d; - int n, - is_space = 1; - - for (s = query_string, d = buff, n = 0; (c = *s) && (n < MAX_QUERY_SIZE); s++) - { - switch (c) - { - case '\r': - case '\n': - case '\t': - c = ' '; - /* fall through */ - case ' ': - if (is_space) - continue; - is_space = 1; - break; - default: - is_space = 0; - break; - } - *d++ = c; - n++; - } - *d = '\0'; - TPRINTF(TRACE_QUERY, "query: %s", buff); - } + TPRINTF(TRACE_QUERY, "query: %s", query_string); } /* ---------------- @@ -889,7 +864,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) int errs = 0; int firstchar; - char parser_input[MAX_PARSE_BUFFER]; + StringInfo parser_input; char *userName; /* Used if verbose is set, must be initialized */ @@ -1452,6 +1427,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) on_shmem_exit(remove_all_temp_relations, NULL); + parser_input = makeStringInfo(); /* initialize input buffer */ + /* ---------------- * Set up handler for cancel-request signal, and * send this backend's cancellation info to the frontend. @@ -1492,7 +1469,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.127 $ $Date: 1999/07/22 02:40:07 $\n"); + puts("$Revision: 1.128 $ $Date: 1999/08/31 04:26:40 $\n"); } /* ---------------- @@ -1548,8 +1525,6 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) * (3) read a command. * ---------------- */ - MemSet(parser_input, 0, MAX_PARSE_BUFFER); - firstchar = ReadCommand(parser_input); QueryCancel = false; /* forget any earlier CANCEL signal */ @@ -1592,7 +1567,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) * ---------------- */ case 'Q': - if (strspn(parser_input, " \t\n") == strlen(parser_input)) + if (strspn(parser_input->data, " \t\n") == parser_input->len) { /* ---------------- * if there is nothing in the input buffer, don't bother @@ -1616,7 +1591,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) TPRINTF(TRACE_VERBOSE, "StartTransactionCommand"); StartTransactionCommand(); - pg_exec_query(parser_input); + pg_exec_query(parser_input->data); if (ShowStats) ShowUsage(); diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h index f4086c1137..463c5564b4 100644 --- a/src/include/libpq/libpq.h +++ b/src/include/libpq/libpq.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: libpq.h,v 1.32 1999/07/15 15:21:15 momjian Exp $ + * $Id: libpq.h,v 1.33 1999/08/31 04:26:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,6 +17,7 @@ #include +#include "lib/stringinfo.h" #include "libpq/libpq-be.h" #include "tcop/dest.h" #include "utils/exc.h" @@ -241,7 +242,7 @@ extern void pq_init(void); extern int pq_getport(void); extern void pq_close(void); extern int pq_getbytes(char *s, size_t len); -extern int pq_getstring(char *s, size_t len); +extern int pq_getstring(StringInfo s); extern int pq_peekbyte(void); extern int pq_putbytes(const char *s, size_t len); extern int pq_flush(void); diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h index d948197037..181428265a 100644 --- a/src/include/libpq/pqcomm.h +++ b/src/include/libpq/pqcomm.h @@ -8,7 +8,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: pqcomm.h,v 1.38 1999/07/17 20:18:29 momjian Exp $ + * $Id: pqcomm.h,v 1.39 1999/08/31 04:26:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -26,11 +26,6 @@ #include #endif -/* - * Internal send/receive buffers in libpq. - */ -#define PQ_BUFFER_SIZE 8192 - /* Define a generic socket address type. */ typedef union SockAddr diff --git a/src/include/libpq/pqformat.h b/src/include/libpq/pqformat.h index c7289e2390..0871ee9673 100644 --- a/src/include/libpq/pqformat.h +++ b/src/include/libpq/pqformat.h @@ -5,7 +5,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: pqformat.h,v 1.5 1999/07/15 15:21:16 momjian Exp $ + * $Id: pqformat.h,v 1.6 1999/08/31 04:26:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -26,6 +26,6 @@ extern void pq_endmessage(StringInfo buf); extern int pq_puttextmessage(char msgtype, const char *str); extern int pq_getint(int *result, int b); -extern int pq_getstr(char *s, int maxlen); +extern int pq_getstr(StringInfo s); #endif /* PQFORMAT_H */