libpq_replasable_alloc_r1.patch
text/x-patch
Filename: libpq_replasable_alloc_r1.patch
Type: text/x-patch
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/interfaces/libpq/exports.txt | 3 | 0 |
| src/interfaces/libpq/fe-exec.c | 19 | 8 |
| src/interfaces/libpq/libpq-fe.h | 8 | 0 |
diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index 1af8df6..3b26c7c 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -160,3 +160,6 @@ PQconnectStartParams 157
PQping 158
PQpingParams 159
PQlibVersion 160
+PQpgresult_malloc 161
+PQpgresult_realloc 162
+PQpgresult_free 163
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 8e32b18..a574848 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -67,6 +67,15 @@ static int PQsendDescribe(PGconn *conn, char desc_type,
const char *desc_target);
static int check_field_number(const PGresult *res, int field_num);
+/* ---
+ * malloc/realloc/free for PGResult is replasable for in-backend use
+ * Note that the events having the event id PGEVT_RESULTDESTROY won't
+ * fire when you free the memory blocks for PGresult without
+ * PQclear().
+ */
+void *(*PQpgresult_malloc)(size_t size) = malloc;
+void *(*PQpgresult_realloc)(void *ptr, size_t size) = realloc;
+void (*PQpgresult_free)(void *ptr) = free;
/* ----------------
* Space management for PGresult.
@@ -138,7 +147,7 @@ PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
{
PGresult *result;
- result = (PGresult *) malloc(sizeof(PGresult));
+ result = (PGresult *) PQpgresult_malloc(sizeof(PGresult));
if (!result)
return NULL;
@@ -536,7 +545,8 @@ pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
*/
if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD)
{
- block = (PGresult_data *) malloc(nBytes + PGRESULT_BLOCK_OVERHEAD);
+ block =
+ (PGresult_data *) PQpgresult_malloc(nBytes + PGRESULT_BLOCK_OVERHEAD);
if (!block)
return NULL;
space = block->space + PGRESULT_BLOCK_OVERHEAD;
@@ -560,7 +570,7 @@ pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary)
}
/* Otherwise, start a new block. */
- block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE);
+ block = (PGresult_data *) PQpgresult_malloc(PGRESULT_DATA_BLOCKSIZE);
if (!block)
return NULL;
block->next = res->curBlock;
@@ -662,12 +672,12 @@ PQclear(PGresult *res)
while ((block = res->curBlock) != NULL)
{
res->curBlock = block->next;
- free(block);
+ PQpgresult_free(block);
}
/* Free the top-level tuple pointer array */
if (res->tuples)
- free(res->tuples);
+ PQpgresult_free(res->tuples);
/* zero out the pointer fields to catch programming errors */
res->attDescs = NULL;
@@ -679,7 +689,7 @@ PQclear(PGresult *res)
/* res->curBlock was zeroed out earlier */
/* Free the PGresult structure itself */
- free(res);
+ PQpgresult_free(res);
}
/*
@@ -844,10 +854,11 @@ pqAddTuple(PGresult *res, PGresAttValue *tup)
if (res->tuples == NULL)
newTuples = (PGresAttValue **)
- malloc(newSize * sizeof(PGresAttValue *));
+ PQpgresult_malloc(newSize * sizeof(PGresAttValue *));
else
newTuples = (PGresAttValue **)
- realloc(res->tuples, newSize * sizeof(PGresAttValue *));
+ PQpgresult_realloc(res->tuples,
+ newSize * sizeof(PGresAttValue *));
if (!newTuples)
return FALSE; /* malloc or realloc failed */
res->tupArrSize = newSize;
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index d13a5b9..c958df1 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -226,6 +226,14 @@ typedef struct pgresAttDesc
} PGresAttDesc;
/* ----------------
+ * malloc/realloc/free for PGResult is replasable for in-backend use
+ * ----------------
+ */
+extern void *(*PQpgresult_malloc)(size_t size);
+extern void *(*PQpgresult_realloc)(void *ptr, size_t size);
+extern void (*PQpgresult_free)(void *ptr);
+
+/* ----------------
* Exported functions of libpq
* ----------------
*/