]> granicus.if.org Git - postgresql/commitdiff
- Move most of the I/O in both libpq and the backend to a set
authorMarc G. Fournier <scrappy@hub.org>
Tue, 18 Mar 1997 20:15:39 +0000 (20:15 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Tue, 18 Mar 1997 20:15:39 +0000 (20:15 +0000)
    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>

src/backend/libpq/Makefile
src/backend/libpq/pqcomm.c
src/backend/libpq/pqcomprim.c
src/backend/utils/init/globals.c
src/include/miscadmin.h
src/interfaces/libpq/fe-connect.c

index a7c7f13704eba5591703c81bfe04718371ecfcc6..84b2b9a3a38c083c4a722321835dc44c97781691 100644 (file)
@@ -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
 
index 6b8ecdac28bc0d5673acd6f84ba6ae303324e8d3..10fa738c0fde5a6d5ba00263ae9347770fbb9edf 100644 (file)
@@ -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);
            }
-       }
-    }
 }
 
 /* ---
index fa1fc866b88d698d236c7f52b29bb8a27b2b02c5..abb634b536f5eddc084e95f248c67b5ad92f4a63 100644 (file)
 #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 = 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)
     {
index 65ea4b10dd40633a4c5ced778d93b2f772794adc..d5fa06071f3ff1a479c6ae2c32bd22bd99f514b2 100644 (file)
@@ -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,
index 81fcece3463a38bcd33ee93e74894b8c6fecc624..a7648feb99a93daa3dc2f1b69bbbf9a669facfe4 100644 (file)
@@ -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
index 60f55ae599357a18fefd4be263a3c78ef785d450..4b3a8630a516f4a6acb1048d2430131c9d0c8750 100644 (file)
@@ -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: