mirror of
https://github.com/postgres/postgres.git
synced 2025-08-19 23:22:23 +03:00
Update frontend libpq to remove limits on query lengths,
error/notice message lengths, and number of fields per tuple. Add pqexpbuffer.c/.h, a frontend version of backend's stringinfo module. This is first step in applying Mike Ansley's long-query patches, even though he didn't do any of these particular changes...
This commit is contained in:
254
src/interfaces/libpq/pqexpbuffer.c
Normal file
254
src/interfaces/libpq/pqexpbuffer.c
Normal file
@@ -0,0 +1,254 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pqexpbuffer.c
|
||||
*
|
||||
* PQExpBuffer provides an indefinitely-extensible string data type.
|
||||
* It can be used to buffer either ordinary C strings (null-terminated text)
|
||||
* or arbitrary binary data. All storage is allocated with malloc().
|
||||
*
|
||||
* 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().
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
#include "pqexpbuffer.h"
|
||||
|
||||
/*
|
||||
* createPQExpBuffer
|
||||
*
|
||||
* Create an empty 'PQExpBufferData' & return a pointer to it.
|
||||
*/
|
||||
PQExpBuffer
|
||||
createPQExpBuffer(void)
|
||||
{
|
||||
PQExpBuffer res;
|
||||
|
||||
res = (PQExpBuffer) malloc(sizeof(PQExpBufferData));
|
||||
if (res != NULL)
|
||||
initPQExpBuffer(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* initPQExpBuffer
|
||||
*
|
||||
* Initialize a PQExpBufferData struct (with previously undefined contents)
|
||||
* to describe an empty string.
|
||||
*/
|
||||
void
|
||||
initPQExpBuffer(PQExpBuffer str)
|
||||
{
|
||||
str->data = (char *) malloc(INITIAL_EXPBUFFER_SIZE);
|
||||
if (str->data == NULL)
|
||||
{
|
||||
str->maxlen = 0;
|
||||
str->len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
str->maxlen = INITIAL_EXPBUFFER_SIZE;
|
||||
str->len = 0;
|
||||
str->data[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------
|
||||
* destroyPQExpBuffer(str);
|
||||
* free()s both the data buffer and the PQExpBufferData.
|
||||
* This is the inverse of createPQExpBuffer().
|
||||
*/
|
||||
void
|
||||
destroyPQExpBuffer(PQExpBuffer str)
|
||||
{
|
||||
if (str)
|
||||
{
|
||||
termPQExpBuffer(str);
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------
|
||||
* termPQExpBuffer(str)
|
||||
* free()s the data buffer but not the PQExpBufferData itself.
|
||||
* This is the inverse of initPQExpBuffer().
|
||||
*/
|
||||
void
|
||||
termPQExpBuffer(PQExpBuffer str)
|
||||
{
|
||||
if (str->data)
|
||||
{
|
||||
free(str->data);
|
||||
str->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------
|
||||
* resetPQExpBuffer
|
||||
* Reset a PQExpBuffer to empty
|
||||
*/
|
||||
void
|
||||
resetPQExpBuffer(PQExpBuffer str)
|
||||
{
|
||||
if (str)
|
||||
{
|
||||
str->len = 0;
|
||||
if (str->data)
|
||||
str->data[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------
|
||||
* enlargePQExpBuffer
|
||||
* Make sure there is enough space for 'needed' more bytes in the buffer
|
||||
* ('needed' does not include the terminating null).
|
||||
*
|
||||
* Returns 1 if OK, 0 if failed to enlarge buffer.
|
||||
*/
|
||||
int
|
||||
enlargePQExpBuffer(PQExpBuffer str, int needed)
|
||||
{
|
||||
int newlen;
|
||||
char *newdata;
|
||||
|
||||
needed += str->len + 1; /* total space required now */
|
||||
if (needed <= str->maxlen)
|
||||
return 1; /* got enough space already */
|
||||
|
||||
/*
|
||||
* We don't want to allocate just a little more space with each
|
||||
* append; for efficiency, double the buffer size each time it
|
||||
* overflows. Actually, we might need to more than double it if
|
||||
* 'needed' is big...
|
||||
*/
|
||||
newlen = str->maxlen ? (2 * str->maxlen) : 64;
|
||||
while (needed > newlen)
|
||||
newlen = 2 * newlen;
|
||||
|
||||
newdata = (char *) realloc(str->data, newlen);
|
||||
if (newdata != NULL)
|
||||
{
|
||||
str->data = newdata;
|
||||
str->maxlen = newlen;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*------------------------
|
||||
* printfPQExpBuffer
|
||||
* Format text data under the control of fmt (an sprintf-like format string)
|
||||
* 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);
|
||||
|
||||
resetPQExpBuffer(str);
|
||||
appendPQExpBufferStr(str, buffer);
|
||||
}
|
||||
|
||||
/*------------------------
|
||||
* appendPQExpBuffer
|
||||
*
|
||||
* Format text data under the control of fmt (an sprintf-like format string)
|
||||
* 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);
|
||||
|
||||
appendPQExpBufferStr(str, buffer);
|
||||
}
|
||||
|
||||
/*------------------------
|
||||
* appendPQExpBufferStr
|
||||
* Append the given string to a PQExpBuffer, allocating more space
|
||||
* if necessary.
|
||||
*/
|
||||
void
|
||||
appendPQExpBufferStr(PQExpBuffer str, const char *data)
|
||||
{
|
||||
appendBinaryPQExpBuffer(str, data, strlen(data));
|
||||
}
|
||||
|
||||
/*------------------------
|
||||
* appendPQExpBufferChar
|
||||
* Append a single byte to str.
|
||||
* Like appendPQExpBuffer(str, "%c", ch) but much faster.
|
||||
*/
|
||||
void
|
||||
appendPQExpBufferChar(PQExpBuffer str, char ch)
|
||||
{
|
||||
/* Make more room if needed */
|
||||
if (! enlargePQExpBuffer(str, 1))
|
||||
return;
|
||||
|
||||
/* OK, append the character */
|
||||
str->data[str->len] = ch;
|
||||
str->len++;
|
||||
str->data[str->len] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* appendBinaryPQExpBuffer
|
||||
*
|
||||
* Append arbitrary binary data to a PQExpBuffer, allocating more space
|
||||
* if necessary.
|
||||
*/
|
||||
void
|
||||
appendBinaryPQExpBuffer(PQExpBuffer str, const char *data, int datalen)
|
||||
{
|
||||
/* Make more room if needed */
|
||||
if (! enlargePQExpBuffer(str, datalen))
|
||||
return;
|
||||
|
||||
/* OK, append the data */
|
||||
memcpy(str->data + str->len, data, datalen);
|
||||
str->len += datalen;
|
||||
|
||||
/*
|
||||
* Keep a trailing null in place, even though it's probably useless
|
||||
* for binary data...
|
||||
*/
|
||||
str->data[str->len] = '\0';
|
||||
}
|
Reference in New Issue
Block a user