</listitem>
</varlistentry>
+ <varlistentry id="libpq-pqresultmemorysize">
+ <term>
+ <function>PQresultMemorySize</function>
+ <indexterm>
+ <primary>PQresultMemorySize</primary>
+ </indexterm>
+ </term>
+
+ <listitem>
+ <para>
+ Retrieves the number of bytes allocated for
+ a <structname>PGresult</structname> object.
+<synopsis>
+size_t PQresultMemorySize(const PGresult *res);
+</synopsis>
+ </para>
+
+ <para>
+ This value is the sum of all <function>malloc</function> requests
+ associated with the <structname>PGresult</structname> object, that is,
+ all the space that will be freed by <function>PQclear</function>.
+ This information can be useful for managing memory consumption.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="libpq-pqlibversion">
<term>
<function>PQlibVersion</function>
int PQresultSetInstanceData(PGresult *res, PGEventProc proc, void *data);
</synopsis>
</para>
+
+ <para>
+ Beware that any storage represented by <parameter>data</parameter>
+ will not be accounted for by <function>PQresultMemorySize</function>,
+ unless it is allocated using <function>PQresultAlloc</function>.
+ (Doing so is recommendable because it eliminates the need to free
+ such storage explicitly when the result is destroyed.)
+ </para>
</listitem>
</varlistentry>
static bool static_std_strings = false;
-static PGEvent *dupEvents(PGEvent *events, int count);
+static PGEvent *dupEvents(PGEvent *events, int count, size_t *memSize);
static bool pqAddTuple(PGresult *res, PGresAttValue *tup,
const char **errmsgp);
static bool PQsendQueryStart(PGconn *conn);
result->curBlock = NULL;
result->curOffset = 0;
result->spaceLeft = 0;
+ result->memorySize = sizeof(PGresult);
if (conn)
{
/* copy events last; result must be valid if we need to PQclear */
if (conn->nEvents > 0)
{
- result->events = dupEvents(conn->events, conn->nEvents);
+ result->events = dupEvents(conn->events, conn->nEvents,
+ &result->memorySize);
if (!result->events)
{
PQclear(result);
/* Wants to copy PGEvents? */
if ((flags & PG_COPYRES_EVENTS) && src->nEvents > 0)
{
- dest->events = dupEvents(src->events, src->nEvents);
+ dest->events = dupEvents(src->events, src->nEvents,
+ &dest->memorySize);
if (!dest->events)
{
PQclear(dest);
* Copy an array of PGEvents (with no extra space for more).
* Does not duplicate the event instance data, sets this to NULL.
* Also, the resultInitialized flags are all cleared.
+ * The total space allocated is added to *memSize.
*/
static PGEvent *
-dupEvents(PGEvent *events, int count)
+dupEvents(PGEvent *events, int count, size_t *memSize)
{
PGEvent *newEvents;
+ size_t msize;
int i;
if (!events || count <= 0)
return NULL;
- newEvents = (PGEvent *) malloc(count * sizeof(PGEvent));
+ msize = count * sizeof(PGEvent);
+ newEvents = (PGEvent *) malloc(msize);
if (!newEvents)
return NULL;
free(newEvents);
return NULL;
}
+ msize += strlen(events[i].name) + 1;
}
+ *memSize += msize;
return newEvents;
}
*/
if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
{
- block = (PGresult_data *) malloc(nBytes + PGRESULT_BLOCK_OVERHEAD);
+ size_t alloc_size = nBytes + PGRESULT_BLOCK_OVERHEAD;
+
+ block = (PGresult_data *) malloc(alloc_size);
if (!block)
return NULL;
+ res->memorySize += alloc_size;
space = block->space + PGRESULT_BLOCK_OVERHEAD;
if (res->curBlock)
{
block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE);
if (!block)
return NULL;
+ res->memorySize += PGRESULT_DATA_BLOCKSIZE;
block->next = res->curBlock;
res->curBlock = block;
if (isBinary)
return space;
}
+/*
+ * PQresultMemorySize -
+ * Returns total space allocated for the PGresult.
+ */
+size_t
+PQresultMemorySize(const PGresult *res)
+{
+ if (!res)
+ return 0;
+ return res->memorySize;
+}
+
/*
* pqResultStrdup -
* Like strdup, but the space is subsidiary PGresult space.
realloc(res->tuples, newSize * sizeof(PGresAttValue *));
if (!newTuples)
return false; /* malloc or realloc failed */
+ res->memorySize +=
+ (newSize - res->tupArrSize) * sizeof(PGresAttValue *);
res->tupArrSize = newSize;
res->tuples = newTuples;
}
extern PGresult *PQcopyResult(const PGresult *src, int flags);
extern int PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs);
extern void *PQresultAlloc(PGresult *res, size_t nBytes);
+extern size_t PQresultMemorySize(const PGresult *res);
extern int PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len);
/* Quoting strings before inclusion in queries. */