]> granicus.if.org Git - postgresql/commitdiff
Modify libpq's pqexpbuffer to eliminate length restriction on how much
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 17 Jan 2000 02:59:46 +0000 (02:59 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 17 Jan 2000 02:59:46 +0000 (02:59 +0000)
data can be formatted per call.  This requires relying on vsnprintf().
On machines that haven't got vsnprintf, link in the version from
backend/port/.

src/interfaces/libpq/Makefile.in
src/interfaces/libpq/pqexpbuffer.c
src/interfaces/libpq/pqexpbuffer.h

index 1276f550a22f42dac0aaa81db8d8f8afc5304db8..99da195830b35a72e372858a0e76e3b47e3b7146 100644 (file)
@@ -6,7 +6,7 @@
 # Copyright (c) 1994, Regents of the University of California
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.51 2000/01/10 15:41:30 momjian Exp $
+#    $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.52 2000/01/17 02:59:46 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -28,7 +28,7 @@ CFLAGS+= $(MBFLAGS)
 endif
 
 OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \
-      pqexpbuffer.o dllist.o pqsignal.o
+      pqexpbuffer.o dllist.o pqsignal.o @SNPRINTF@
 
 ifdef MULTIBYTE
 OBJS+= common.o wchar.o conv.o big5.o
@@ -42,14 +42,19 @@ SHLIB_LINK+= $(findstring -lcrypt,$(LIBS))
 include $(SRCDIR)/Makefile.shlib
 
 
-# We need to compile this with special options for shared libs,
-# so we can't use the object in $(SRCDIR)/backend
+# We use several backend modules verbatim, but since we need to compile
+# with appropriate options to build a shared lib, we can't necessarily
+# use the same object files as the backend uses.  Instead, symlink the
+# source files in here and build our own object file.
+
 dllist.c:      $(SRCDIR)/backend/lib/dllist.c
        -$(LN_S) $(SRCDIR)/backend/lib/dllist.c .
 
+# this only gets done if configure finds system doesn't have snprintf()
+snprintf.c:    $(SRCDIR)/backend/port/snprintf.c
+       -$(LN_S) $(SRCDIR)/backend/port/snprintf.c .
+
 ifdef MULTIBYTE
-# We need to compile this with special options for shared libs,
-# so we can't use the object in $(SRCDIR)/backend
 common.c: $(SRCDIR)/backend/utils/mb/common.c
        -$(LN_S) $(SRCDIR)/backend/utils/mb/common.c .
 
@@ -63,6 +68,7 @@ big5.c: $(SRCDIR)/backend/utils/mb/big5.c
        -$(LN_S) $(SRCDIR)/backend/utils/mb/big5.c .
 endif
 
+
 # The following rules cause dependencies in the backend directory to 
 # get made if they don't exist, but don't cause them to get remade if they
 # are out of date.
@@ -87,7 +93,7 @@ install-headers: libpq-fe.h libpq-int.h
 
 clean: clean-shlib
        rm -f lib$(NAME).a $(OBJS)
-       rm -f dllist.c common.c wchar.c conv.c big5.c
+       rm -f dllist.c snprintf.c common.c wchar.c conv.c big5.c
 
 depend dep:
        $(CC) -MM $(CFLAGS) *.c >depend
index ddaca7e67b51f23465156f0abc9d24387550ff68..bedf456b3ceb67ed333f7ed476292485b7043eb9 100644 (file)
@@ -8,11 +8,15 @@
  *
  * This module is essentially the same as the backend's StringInfo data type,
  * but it is intended for use in frontend libpq and client applications.
- * Thus, it does not rely on palloc(), elog(), nor vsnprintf().
+ * Thus, it does not rely on palloc() nor elog().
+ *
+ * It does rely on vsnprintf(); if configure finds that libc doesn't provide
+ * a usable vsnprintf(), then a copy of our own implementation of it will
+ * be linked into libpq.
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqexpbuffer.c,v 1.1 1999/08/31 01:37:37 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqexpbuffer.c,v 1.2 2000/01/17 02:59:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -148,27 +152,47 @@ enlargePQExpBuffer(PQExpBuffer str, int needed)
  * and insert it into str.  More space is allocated to str if necessary.
  * This is a convenience routine that does the same thing as
  * resetPQExpBuffer() followed by appendPQExpBuffer().
- *
- * CAUTION: the frontend version of this routine WILL FAIL if the result of
- * the sprintf formatting operation exceeds 1KB of data (but the size of the
- * pre-existing string in the buffer doesn't matter).  We could make it
- * support larger strings, but that requires vsnprintf() which is not
- * universally available.  Currently there is no need for long strings to be
- * formatted in the frontend.  We could support it, if necessary, by
- * conditionally including a vsnprintf emulation.
  */
 void
 printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
 {
        va_list         args;
-       char            buffer[1024];
-
-       va_start(args, fmt);
-       vsprintf(buffer, fmt, args);
-       va_end(args);
+       int                     avail,
+                               nprinted;
 
        resetPQExpBuffer(str);
-       appendPQExpBufferStr(str, buffer);
+
+       for (;;)
+       {
+               /*----------
+                * Try to format the given string into the available space;
+                * but if there's hardly any space, don't bother trying,
+                * just fall through to enlarge the buffer first.
+                *----------
+                */
+               avail = str->maxlen - str->len - 1;
+               if (avail > 16)
+               {
+                       va_start(args, fmt);
+                       nprinted = vsnprintf(str->data + str->len, avail,
+                                                                fmt, args);
+                       va_end(args);
+                       /*
+                        * Note: some versions of vsnprintf return the number of chars
+                        * actually stored, but at least one returns -1 on failure.
+                        * Be conservative about believing whether the print worked.
+                        */
+                       if (nprinted >= 0 && nprinted < avail-1)
+                       {
+                               /* Success.  Note nprinted does not include trailing null. */
+                               str->len += nprinted;
+                               break;
+                       }
+               }
+               /* Double the buffer size and try again. */
+               if (! enlargePQExpBuffer(str, str->maxlen))
+                       return;                         /* oops, out of memory */
+       }
 }
 
 /*------------------------
@@ -178,26 +202,45 @@ printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
  * and append it to whatever is already in str.  More space is allocated
  * to str if necessary.  This is sort of like a combination of sprintf and
  * strcat.
- *
- * CAUTION: the frontend version of this routine WILL FAIL if the result of
- * the sprintf formatting operation exceeds 1KB of data (but the size of the
- * pre-existing string in the buffer doesn't matter).  We could make it
- * support larger strings, but that requires vsnprintf() which is not
- * universally available.  Currently there is no need for long strings to be
- * formatted in the frontend.  We could support it, if necessary, by
- * conditionally including a vsnprintf emulation.
  */
 void
 appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
 {
        va_list         args;
-       char            buffer[1024];
-
-       va_start(args, fmt);
-       vsprintf(buffer, fmt, args);
-       va_end(args);
+       int                     avail,
+                               nprinted;
 
-       appendPQExpBufferStr(str, buffer);
+       for (;;)
+       {
+               /*----------
+                * Try to format the given string into the available space;
+                * but if there's hardly any space, don't bother trying,
+                * just fall through to enlarge the buffer first.
+                *----------
+                */
+               avail = str->maxlen - str->len - 1;
+               if (avail > 16)
+               {
+                       va_start(args, fmt);
+                       nprinted = vsnprintf(str->data + str->len, avail,
+                                                                fmt, args);
+                       va_end(args);
+                       /*
+                        * Note: some versions of vsnprintf return the number of chars
+                        * actually stored, but at least one returns -1 on failure.
+                        * Be conservative about believing whether the print worked.
+                        */
+                       if (nprinted >= 0 && nprinted < avail-1)
+                       {
+                               /* Success.  Note nprinted does not include trailing null. */
+                               str->len += nprinted;
+                               break;
+                       }
+               }
+               /* Double the buffer size and try again. */
+               if (! enlargePQExpBuffer(str, str->maxlen))
+                       return;                         /* oops, out of memory */
+       }
 }
 
 /*------------------------
index 5c2d2f122ce69d6c5f83a00228582b6c0c43a627..df3566820a499fe65f47badb0c2d1e66b5742074 100644 (file)
@@ -9,11 +9,15 @@
  *
  * This module is essentially the same as the backend's StringInfo data type,
  * but it is intended for use in frontend libpq and client applications.
- * Thus, it does not rely on palloc(), elog(), nor vsnprintf().
+ * Thus, it does not rely on palloc() nor elog().
+ *
+ * It does rely on vsnprintf(); if configure finds that libc doesn't provide
+ * a usable vsnprintf(), then a copy of our own implementation of it will
+ * be linked into libpq.
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pqexpbuffer.h,v 1.1 1999/08/31 01:37:37 tgl Exp $
+ * $Id: pqexpbuffer.h,v 1.2 2000/01/17 02:59:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -116,14 +120,6 @@ extern int enlargePQExpBuffer(PQExpBuffer str, int needed);
  * and insert it into str.  More space is allocated to str if necessary.
  * This is a convenience routine that does the same thing as
  * resetPQExpBuffer() followed by appendPQExpBuffer().
- *
- * CAUTION: the frontend version of this routine WILL FAIL if the result of
- * the sprintf formatting operation exceeds 1KB of data (but the size of the
- * pre-existing string in the buffer doesn't matter).  We could make it
- * support larger strings, but that requires vsnprintf() which is not
- * universally available.  Currently there is no need for long strings to be
- * formatted in the frontend.  We could support it, if necessary, by
- * conditionally including a vsnprintf emulation.
  */
 extern void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...);
 
@@ -133,14 +129,6 @@ extern void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...);
  * and append it to whatever is already in str.  More space is allocated
  * to str if necessary.  This is sort of like a combination of sprintf and
  * strcat.
- *
- * CAUTION: the frontend version of this routine WILL FAIL if the result of
- * the sprintf formatting operation exceeds 1KB of data (but the size of the
- * pre-existing string in the buffer doesn't matter).  We could make it
- * support larger strings, but that requires vsnprintf() which is not
- * universally available.  Currently there is no need for long strings to be
- * formatted in the frontend.  We could support it, if necessary, by
- * conditionally including a vsnprintf emulation.
  */
 extern void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...);