Commit 2fd4e776 authored by Tom Lane's avatar Tom Lane

Modify libpq's pqexpbuffer to eliminate length restriction on how much

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/.
parent 6759f438
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# Copyright (c) 1994, Regents of the University of California # Copyright (c) 1994, Regents of the University of California
# #
# IDENTIFICATION # 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) ...@@ -28,7 +28,7 @@ CFLAGS+= $(MBFLAGS)
endif endif
OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \ 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 ifdef MULTIBYTE
OBJS+= common.o wchar.o conv.o big5.o OBJS+= common.o wchar.o conv.o big5.o
...@@ -42,14 +42,19 @@ SHLIB_LINK+= $(findstring -lcrypt,$(LIBS)) ...@@ -42,14 +42,19 @@ SHLIB_LINK+= $(findstring -lcrypt,$(LIBS))
include $(SRCDIR)/Makefile.shlib include $(SRCDIR)/Makefile.shlib
# We need to compile this with special options for shared libs, # We use several backend modules verbatim, but since we need to compile
# so we can't use the object in $(SRCDIR)/backend # 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 dllist.c: $(SRCDIR)/backend/lib/dllist.c
-$(LN_S) $(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 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 common.c: $(SRCDIR)/backend/utils/mb/common.c
-$(LN_S) $(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 ...@@ -63,6 +68,7 @@ big5.c: $(SRCDIR)/backend/utils/mb/big5.c
-$(LN_S) $(SRCDIR)/backend/utils/mb/big5.c . -$(LN_S) $(SRCDIR)/backend/utils/mb/big5.c .
endif endif
# The following rules cause dependencies in the backend directory to # 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 # get made if they don't exist, but don't cause them to get remade if they
# are out of date. # are out of date.
...@@ -87,7 +93,7 @@ install-headers: libpq-fe.h libpq-int.h ...@@ -87,7 +93,7 @@ install-headers: libpq-fe.h libpq-int.h
clean: clean-shlib clean: clean-shlib
rm -f lib$(NAME).a $(OBJS) 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: depend dep:
$(CC) -MM $(CFLAGS) *.c >depend $(CC) -MM $(CFLAGS) *.c >depend
......
...@@ -8,11 +8,15 @@ ...@@ -8,11 +8,15 @@
* *
* This module is essentially the same as the backend's StringInfo data type, * 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. * 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 * 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) ...@@ -148,27 +152,47 @@ enlargePQExpBuffer(PQExpBuffer str, int needed)
* and insert it into str. More space is allocated to str if necessary. * and insert it into str. More space is allocated to str if necessary.
* This is a convenience routine that does the same thing as * This is a convenience routine that does the same thing as
* resetPQExpBuffer() followed by appendPQExpBuffer(). * 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 void
printfPQExpBuffer(PQExpBuffer str, const char *fmt,...) printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
{ {
va_list args; va_list args;
char buffer[1024]; int avail,
nprinted;
resetPQExpBuffer(str);
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); va_start(args, fmt);
vsprintf(buffer, fmt, args); nprinted = vsnprintf(str->data + str->len, avail,
fmt, args);
va_end(args); va_end(args);
/*
resetPQExpBuffer(str); * Note: some versions of vsnprintf return the number of chars
appendPQExpBufferStr(str, buffer); * 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,...) ...@@ -178,26 +202,45 @@ printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
* and append it to whatever is already in str. More space is allocated * 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 * to str if necessary. This is sort of like a combination of sprintf and
* strcat. * 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 void
appendPQExpBuffer(PQExpBuffer str, const char *fmt,...) appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
{ {
va_list args; va_list args;
char buffer[1024]; int avail,
nprinted;
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); va_start(args, fmt);
vsprintf(buffer, fmt, args); nprinted = vsnprintf(str->data + str->len, avail,
fmt, args);
va_end(args); va_end(args);
/*
appendPQExpBufferStr(str, buffer); * 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 */
}
} }
/*------------------------ /*------------------------
......
...@@ -9,11 +9,15 @@ ...@@ -9,11 +9,15 @@
* *
* This module is essentially the same as the backend's StringInfo data type, * 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. * 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 * 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); ...@@ -116,14 +120,6 @@ extern int enlargePQExpBuffer(PQExpBuffer str, int needed);
* and insert it into str. More space is allocated to str if necessary. * and insert it into str. More space is allocated to str if necessary.
* This is a convenience routine that does the same thing as * This is a convenience routine that does the same thing as
* resetPQExpBuffer() followed by appendPQExpBuffer(). * 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,...); extern void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...);
...@@ -133,14 +129,6 @@ 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 * 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 * to str if necessary. This is sort of like a combination of sprintf and
* strcat. * 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,...); extern void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment