aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc G. Fournier <scrappy@hub.org>1997-03-18 20:15:39 +0000
committerMarc G. Fournier <scrappy@hub.org>1997-03-18 20:15:39 +0000
commit812a6c2b546850e9f9721b580698d5a161e5d76e (patch)
tree043e497eb6ccd99bb7b7d8052dbdb0fd9429d8c3
parentd1463050658950afd25ef2457182a498b6b3a6b4 (diff)
downloadpostgresql-812a6c2b546850e9f9721b580698d5a161e5d76e.tar.gz
postgresql-812a6c2b546850e9f9721b580698d5a161e5d76e.zip
- Move most of the I/O in both libpq and the backend to a set
of common routines in pqcomprim.c (pq communication primitives). Not all adapted to it yet, but it's a start. - Rewritten some of those routines, to write/read bigger chunks of data, precomputing stuff in buffers instead of sending out byte by byte. - As a consequence, I need to know the endianness of the machine. Currently I rely on getting it from machine/endian.h, but this may not be available everywhere? (Who the hell thought it was a good idea to pass integers to the backend the other way around than the normal network byte order? *argl*) - Libpq looks in the environment for magic variables, and upon establishing a connection to the backend, sends it queries of the form "SET var_name TO 'var_value'". This needs a change in the backend parser (Mr. Parser, are you there? :) - Currently it looks for two Env-Vars, namely PG_DATEFORMAT and PG_FLOATFORMAT. What else makes sense? PG_TIMEFORMAT? PG_TIMEZONE? From: "Martin J. Laubach" <mjl@wwx.vip.at>
-rw-r--r--src/backend/libpq/Makefile4
-rw-r--r--src/backend/libpq/pqcomm.c141
-rw-r--r--src/backend/libpq/pqcomprim.c158
-rw-r--r--src/backend/utils/init/globals.c5
-rw-r--r--src/include/miscadmin.h5
-rw-r--r--src/interfaces/libpq/fe-connect.c30
6 files changed, 275 insertions, 68 deletions
diff --git a/src/backend/libpq/Makefile b/src/backend/libpq/Makefile
index a7c7f13704e..84b2b9a3a38 100644
--- a/src/backend/libpq/Makefile
+++ b/src/backend/libpq/Makefile
@@ -4,7 +4,7 @@
# Makefile for libpq subsystem (backend half of libpq interface)
#
# IDENTIFICATION
-# $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.5 1997/03/12 21:17:45 scrappy Exp $
+# $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.6 1997/03/18 20:14:32 scrappy Exp $
#
#-------------------------------------------------------------------------
@@ -23,7 +23,7 @@ CFLAGS+= $(KRBFLAGS)
LDADD+= $(KRBLIBS)
endif
-OBJS = be-dumpdata.o be-fsstubs.o be-pqexec.o \
+OBJS = be-dumpdata.o be-fsstubs.o be-pqexec.o pqcomprim.o\
auth.o hba.o pqcomm.o portal.o util.o portalbuf.o pqpacket.o pqsignal.o \
password.o
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 6b8ecdac28b..10fa738c0fd 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -1,4 +1,4 @@
-/*-------------------------------------------------------------------------
+ /*-------------------------------------------------------------------------
*
* pqcomm.c--
* Communication functions between the Frontend and the Backend
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.12 1997/03/12 21:17:58 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.13 1997/03/18 20:14:33 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -206,26 +206,29 @@ pq_getstr(char *s, int maxlen)
* the line ended within maxlen bytes.)
* 1 in other cases
*/
-int
-PQgetline(char *s, int maxlen)
-{
- int c = '\0';
-
+int PQgetline(char *s, int maxlen)
+ {
if (!Pfin || !s || maxlen <= 1)
return(EOF);
- for (; maxlen > 1 && (c = pq_getc(Pfin)) != '\n' && c != EOF; --maxlen) {
- *s++ = c;
- }
+ if(fgets(s, maxlen - 1, Pfin) == NULL)
+ {
+ return feof(Pfin) ? EOF : 1;
+ }
+ else
+ {
+ for( ; *s; *s++)
+ {
+ if(*s == '\n')
+ {
*s = '\0';
+ break;
+ }
+ }
+ }
- if (c == EOF) {
- return(EOF); /* error -- reached EOF before \n */
- } else if (c == '\n') {
- return(0); /* done with this line */
+ return 0;
}
- return(1); /* returning a full buffer */
-}
/*
* USER FUNCTION - sends a string to the backend.
@@ -252,6 +255,9 @@ PQputline(char *s)
int
pq_getnchar(char *s, int off, int maxlen)
{
+ return pqGetNBytes(s + off, maxlen, Pfin);
+
+#if 0
int c = '\0';
if (Pfin == (FILE *) NULL) {
@@ -270,6 +276,7 @@ pq_getnchar(char *s, int off, int maxlen)
if (c == EOF)
return(EOF);
return(!EOF);
+#endif
}
/* --------------------------------
@@ -282,20 +289,38 @@ pq_getnchar(char *s, int off, int maxlen)
int
pq_getint(int b)
{
- int n, c, p;
-
- if (Pfin == (FILE *) NULL) {
-/* elog(DEBUG, "pq_getint: Input descriptor is null"); */
- return(EOF);
+ int n, status = 1;
+
+ if(!Pfin)
+ return EOF;
+ /* mjl: Seems inconsisten w/ return value of pq_putint (void). Also,
+ EOF is a valid return value for an int! XXX */
+
+ switch(b)
+ {
+ case 1:
+ status = ((n = fgetc(Pfin)) == EOF);
+ break;
+ case 2:
+ pqGetShort(&n, Pfin);
+ break;
+ case 4:
+ pqGetLong(&n, Pfin);
+ break;
+ default:
+ fprintf(stderr, "** Unsupported size %d\n", b);
}
- n = p = 0;
- while (b-- && (c = pq_getc(Pfin)) != EOF && p < 32) {
- n |= (c & 0xff) << p;
- p += 8;
+ if(status)
+ {
+ (void) sprintf(PQerrormsg,
+ "FATAL: pq_getint failed: errno=%d\n", errno);
+ fputs(PQerrormsg, stderr);
+ pqdebug("%s", PQerrormsg);
+ n = 0;
}
- return(n);
+ return n;
}
/* --------------------------------
@@ -305,26 +330,13 @@ pq_getint(int b)
void
pq_putstr(char *s)
{
- int status;
-
- if (Pfout) {
- status = fputs(s, Pfout);
- if (status == EOF) {
- (void) sprintf(PQerrormsg,
- "FATAL: pq_putstr: fputs() failed: errno=%d\n",
- errno);
- fputs(PQerrormsg, stderr);
- pqdebug("%s", PQerrormsg);
- }
- status = fputc('\0', Pfout);
- if (status == EOF) {
+ if(pqPutString(s, Pfout))
+ {
(void) sprintf(PQerrormsg,
- "FATAL: pq_putstr: fputc() failed: errno=%d\n",
- errno);
+ "FATAL: pq_putstr: fputs() failed: errno=%d\n", errno);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
}
- }
}
/* --------------------------------
@@ -333,13 +345,9 @@ pq_putstr(char *s)
*/
void
pq_putnchar(char *s, int n)
-{
- int status;
-
- if (Pfout) {
- while (n--) {
- status = fputc(*s++, Pfout);
- if (status == EOF) {
+ {
+ if(pqPutNBytes(s, n, Pfout))
+ {
(void) sprintf(PQerrormsg,
"FATAL: pq_putnchar: fputc() failed: errno=%d\n",
errno);
@@ -347,8 +355,6 @@ pq_putnchar(char *s, int n)
pqdebug("%s", PQerrormsg);
}
}
- }
-}
/* --------------------------------
* pq_putint - send an integer to connection
@@ -362,22 +368,31 @@ pq_putint(int i, int b)
{
int status;
- if (b > 4)
- b = 4;
-
- if (Pfout) {
- while (b--) {
- status = fputc(i & 0xff, Pfout);
- i >>= 8;
- if (status == EOF) {
+ if(!Pfout) return;
+
+ status = 1;
+ switch(b)
+ {
+ case 1:
+ status = (fputc(i, Pfout) == EOF);
+ break;
+ case 2:
+ status = pqPutShort(i, Pfout);
+ break;
+ case 4:
+ status = pqPutLong(i, Pfout);
+ break;
+ default:
+ fprintf(stderr, "** Unsupported size %d\n", b);
+ }
+
+ if(status)
+ {
(void) sprintf(PQerrormsg,
- "FATAL: pq_putint: fputc() failed: errno=%d\n",
- errno);
+ "FATAL: pq_putint failed: errno=%d\n", errno);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
}
- }
- }
}
/* ---
diff --git a/src/backend/libpq/pqcomprim.c b/src/backend/libpq/pqcomprim.c
index fa1fc866b88..abb634b536f 100644
--- a/src/backend/libpq/pqcomprim.c
+++ b/src/backend/libpq/pqcomprim.c
@@ -35,6 +35,164 @@ int pqPutShort(const int integer, FILE *f)
n = hton_s(integer);
if(fwrite(&n, sizeof(u_short), 1, f) != 1)
+ retval = EOF;
+
+ return retval;
+ }
+
+/* --------------------------------------------------------------------- */
+int pqPutLong(const int integer, FILE *f)
+ {
+ int retval = 0;
+ u_long n;
+
+ n = hton_l(integer);
+ if(fwrite(&n, sizeof(u_long), 1, f) != 1)
+ retval = EOF;
+
+ return retval;
+ }
+
+/* --------------------------------------------------------------------- */
+int pqGetShort(int *result, FILE *f)
+ {
+ int retval = 0;
+ u_short n;
+
+ if(fread(&n, sizeof(u_short), 1, f) != 1)
+ retval = EOF;
+
+ *result = ntoh_s(n);
+ return retval;
+ }
+
+/* --------------------------------------------------------------------- */
+int pqGetLong(int *result, FILE *f)
+ {
+ int retval = 0;
+ u_long n;
+
+ if(fread(&n, sizeof(u_long), 1, f) != 1)
+ retval = EOF;
+
+ *result = ntoh_l(n);
+ return retval;
+ }
+
+/* --------------------------------------------------------------------- */
+/* pqGetNBytes: Read a chunk of exactly len bytes in buffer s.
+ Return 0 if ok.
+*/
+int pqGetNBytes(char* s, const int len, FILE *f)
+ {
+ int cnt;
+
+ if (f == NULL)
+ return EOF;
+
+ cnt = fread(s, 1, len, f);
+ s[cnt] = '\0';
+ /* mjl: actually needs up to len+1 bytes, is this okay? XXX */
+
+ return (cnt == len) ? 0 : EOF;
+ }
+
+/* --------------------------------------------------------------------- */
+int pqPutNBytes(const char *s, const int len, FILE *f)
+ {
+ if (f == NULL)
+ return 0;
+
+ if(fwrite(s, 1, len, f) != len)
+ return EOF;
+
+ return 0;
+ }
+
+/* --------------------------------------------------------------------- */
+int pqGetString(char *s, int len, FILE *f)
+ {
+ int c;
+
+ if (f == NULL)
+ return EOF;
+
+ while (len-- && (c = getc(f)) != EOF && c)
+ *s++ = c;
+ *s = '\0';
+ /* mjl: actually needs up to len+1 bytes, is this okay? XXX */
+
+ return 0;
+ }
+
+/* --------------------------------------------------------------------- */
+int pqPutString(const char *s, FILE *f)
+ {
+ if (f == NULL)
+ return 0;
+
+ if (fputs(s, f) == EOF)
+ return EOF;
+
+ fputc('\0', f); /* important to send an ending \0 since backend expects it */
+ fflush(f);
+
+ return 0;
+ }
+
+/* --------------------------------------------------------------------- */
+int pqGetByte(FILE *f)
+ {
+ return getc(f);
+ }
+
+/* --------------------------------------------------------------------- */
+int pqPutByte(const int c, FILE *f)
+ {
+ if(!f) return 0;
+
+ return (putc(c, f) == c) ? 0 : EOF;
+ }
+
+/* --------------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "postgres.h"
+#include "libpq/pqcomm.h"
+
+/* --------------------------------------------------------------------- */
+/* Is the other way around than system ntoh/hton, so we roll our own
+ here */
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define ntoh_s(n) n
+#define ntoh_l(n) n
+#define hton_s(n) n
+#define hton_l(n) n
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+#define ntoh_s(n) (u_short)(((u_char *) &n)[0] << 8 | ((u_char *) &n)[1]);
+#define ntoh_l(n) (u_long)(((u_char *)&n)[0] << 24 | ((u_char *)&n)[1] << 16 |\
+ ((u_char *)&n)[2] << 8 | ((u_char *)&n)[3]);
+#define hton_s(n) (ntoh_s(n))
+#define hton_l(n) (ntoh_l(n))
+#endif
+#if BYTE_ORDER == PDP_ENDIAN
+#endif
+#ifndef ntoh_s
+#error Please write byte order macros
+#endif
+
+/* --------------------------------------------------------------------- */
+int pqPutShort(const int integer, FILE *f)
+ {
+ int retval = 0;
+ u_short n;
+
+ n = hton_s(integer);
+ if(fwrite(&n, sizeof(u_short), 1, f) != 1)
retval = 1;
return retval;
diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c
index 65ea4b10dd4..d5fa06071f3 100644
--- a/src/backend/utils/init/globals.c
+++ b/src/backend/utils/init/globals.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.6 1997/03/18 16:35:46 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.7 1997/03/18 20:14:46 scrappy Exp $
*
* NOTES
* Globals used all over the place should be declared here and not
@@ -71,6 +71,9 @@ bool CDayLight = false;
int CTimeZone = 0;
char CTZName[8] = "";
+char DateFormat[20] = "%d-%m-%Y"; /* mjl: sizes! or better malloc? XXX */
+char FloatFormat[20] = "%f";
+
char *IndexedCatalogNames[] = {
AttributeRelationName,
ProcedureRelationName,
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 81fcece3463..a7648feb99a 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -11,7 +11,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: miscadmin.h,v 1.6 1997/03/18 16:36:23 scrappy Exp $
+ * $Id: miscadmin.h,v 1.7 1997/03/18 20:15:19 scrappy Exp $
*
* NOTES
* some of the information in this file will be moved to
@@ -70,6 +70,9 @@ extern bool CDayLight;
extern int CTimeZone;
extern char CTZName[];
+extern char FloatFormat[];
+extern char DateFormat[];
+
extern Oid LastOidProcessed; /* for query rewrite */
#define MAX_PARSE_BUFFER 8192
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 60f55ae5993..4b3a8630a51 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.24 1997/03/12 21:23:09 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.25 1997/03/18 20:15:39 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -100,6 +100,16 @@ static PQconninfoOption PQconninfoOptions[] = {
NULL, NULL, 0 }
};
+struct EnvironmentOptions
+ {
+ const char *envName, *pgName;
+ } EnvironmentOptions[] =
+ {
+ { "PG_DATEFORMAT", "pg_dateformat" },
+ { "PG_FLOATFORMAT", "pg_floatformat" },
+ { NULL }
+ };
+
/* ----------------
* PQconnectdb
*
@@ -514,6 +524,24 @@ connectDB(PGconn *conn)
conn->port = port;
+ {
+ struct EnvironmentOptions *eo;
+ char setQuery[80]; /* mjl: size okay? XXX */
+
+ for(eo = EnvironmentOptions; eo->envName; eo++)
+ {
+ const char *val;
+
+ if(val = getenv(eo->envName))
+ {
+ PGresult *res;
+
+ sprintf(setQuery, "SET %s TO \".60%s\"", eo->pgName, val);
+ res = PQexec(conn, setQuery);
+ PQclear(res); /* Don't care? */
+ }
+ }
+ }
return CONNECTION_OK;
connect_errReturn: