diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index 2a07be49f8e..9fa0097a936 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.51 1999/05/25 16:06:35 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.52 1999/06/12 14:05:36 momjian Exp $ * * NOTES * The old interface functions have been converted to macros @@ -27,6 +27,11 @@ #include #include +#ifdef FREE_TUPLE_MEMORY +#include +#include +#endif + #ifndef HAVE_MEMMOVE #include #else @@ -93,6 +98,9 @@ DataFill(char *data, int i; int numberOfAttributes = tupleDesc->natts; Form_pg_attribute *att = tupleDesc->attrs; +#ifdef FREE_TUPLE_MEMORY + bool free_tuple_memory = pg_options[OPT_FREE_TUPLE_MEMORY]; +#endif if (bit != NULL) { @@ -131,6 +139,14 @@ DataFill(char *data, *infomask |= HEAP_HASVARLENA; data_length = VARSIZE(DatumGetPointer(value[i])); memmove(data, DatumGetPointer(value[i]), data_length); +#ifdef FREE_TUPLE_MEMORY + /* try to pfree value[i] - dz */ + if (free_tuple_memory && + PortalHeapMemoryIsValid(CurrentMemoryContext, + (Pointer) value[i])) { + pfree(value[i]); + } +#endif break; case sizeof(char): *data = att[i]->attbyval ? @@ -147,8 +163,15 @@ DataFill(char *data, *((int32 *) value[i])); break; default: - memmove(data, DatumGetPointer(value[i]), - att[i]->attlen); + memmove(data, DatumGetPointer(value[i]), att[i]->attlen); +#ifdef FREE_TUPLE_MEMORY + /* try to pfree value[i] - dz */ + if (free_tuple_memory && + PortalHeapMemoryIsValid(CurrentMemoryContext, + (Pointer) value[i])) { + pfree(value[i]); + } +#endif break; } data = (char *) att_addlength((long) data, att[i]->attlen, value[i]); diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index a47a9ad5492..9d0f4ea1036 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -31,6 +31,11 @@ #include "utils/syscache.h" #include "optimizer/clauses.h" +#ifdef FREE_TUPLE_MEMORY +#include +#include +#endif + /* * AggFuncInfo - * keeps the transition functions information around @@ -113,7 +118,9 @@ ExecAgg(Agg *node) isNull1 = FALSE, isNull2 = FALSE; bool qual_result; - +#ifdef FREE_TUPLE_MEMORY + bool free_tuple_memory = pg_options[OPT_FREE_TUPLE_MEMORY]; +#endif /* --------------------- * get state info from node @@ -241,6 +248,10 @@ ExecAgg(Agg *node) for (;;) { TupleTableSlot *outerslot; +#ifdef FREE_TUPLE_MEMORY + Oid valueType; + bool isByValue = 0; +#endif isNull = isNull1 = isNull2 = 0; outerslot = ExecProcNode(outerPlan, (Plan *) node); @@ -293,6 +304,31 @@ ExecAgg(Agg *node) newVal = ExecEvalExpr(aggref->target, econtext, &isNull, &isDone); } +#ifdef FREE_TUPLE_MEMORY + if (free_tuple_memory) { + switch (nodeTag(aggref->target)) { + case T_Const: + isByValue = ((Const*) (aggref->target))->constbyval; + break; + case T_Var: + valueType = ((Var*) (aggref->target))->vartype; + isByValue = typeByVal(typeidType(valueType)); + break; + case T_Array: + isByValue = ((Array*)(aggref->target))->arrayelembyval; + break; + case T_ArrayRef: + isByValue =((ArrayRef*)(aggref->target))->refelembyval; + break; + case T_Expr: + valueType = ((Expr*) (aggref->target))->typeOid; + isByValue = typeByVal(typeidType(valueType)); + break; + default: + break; + } + } +#endif if (isNull && !aggref->usenulls) continue; /* ignore this tuple for this agg */ @@ -353,6 +389,16 @@ ExecAgg(Agg *node) (FmgrValues *) args, &isNull2); Assert(!isNull2); } + +#ifdef FREE_TUPLE_MEMORY + /* try to pfree newVal if not isByValue - dz */ + if (free_tuple_memory && !isByValue && + PortalHeapMemoryIsValid(CurrentMemoryContext, + (Pointer) newVal)) + { + pfree(newVal); + } +#endif } /* diff --git a/src/backend/utils/misc/trace.c b/src/backend/utils/misc/trace.c index 9676ca570a0..5a18a213900 100644 --- a/src/backend/utils/misc/trace.c +++ b/src/backend/utils/misc/trace.c @@ -73,6 +73,9 @@ static char *opt_names[] = { "syslog", /* use syslog for error messages */ "hostlookup", /* enable hostname lookup in ps_status */ "showportnumber", /* show port number in ps_status */ +#ifdef FREE_TUPLE_MEMORY + "free_tuple_memory", /* try to pfree memory for each tuple */ +#endif /* NUM_PG_OPTIONS */ /* must be the last item of enum */ }; @@ -404,9 +407,9 @@ read_pg_options(SIGNAL_ARGS) } /* - * Local variables: - * tab-width: 4 - * c-indent-level: 4 - * c-basic-offset: 4 + * Local Variables: + * tab-width: 4 + * c-indent-level: 4 + * c-basic-offset: 4 * End: */ diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c index d4cc93482f8..d5296ae0f60 100644 --- a/src/backend/utils/mmgr/portalmem.c +++ b/src/backend/utils/mmgr/portalmem.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.19 1999/05/25 16:12:55 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.20 1999/06/12 14:05:39 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -289,6 +289,24 @@ PortalHeapMemoryFree(PortalHeapMemory this, } } +#ifdef FREE_TUPLE_MEMORY +/* + * PortalHeapMemoryIsValid -- + * + * Check if a pointer is allocated in a memory context. + * + */ +bool +PortalHeapMemoryIsValid(MemoryContext context, Pointer pointer) +{ + HeapMemoryBlock block = HEAPMEMBLOCK((PortalHeapMemory) context); + + AssertState(PointerIsValid(block)); + + return (AllocSetContains(&block->setData, pointer)); +} +#endif + /* ---------------- * PortalHeapMemoryRealloc * ---------------- diff --git a/src/include/utils/portal.h b/src/include/utils/portal.h index 9d2677c4548..390ee2116d5 100644 --- a/src/include/utils/portal.h +++ b/src/include/utils/portal.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: portal.h,v 1.13 1999/05/25 16:14:57 momjian Exp $ + * $Id: portal.h,v 1.14 1999/06/12 14:05:40 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -80,6 +80,10 @@ extern void EndPortalAllocMode(void); extern PortalVariableMemory PortalGetVariableMemory(Portal portal); extern PortalHeapMemory PortalGetHeapMemory(Portal portal); +#ifdef FREE_TUPLE_MEMORY +bool PortalHeapMemoryIsValid(MemoryContext context, Pointer pointer); +#endif + /* estimate of the maximum number of open portals a user would have, * used in initially sizing the PortalHashTable in EnablePortalManager() */ diff --git a/src/include/utils/trace.h b/src/include/utils/trace.h index 3174026ca5c..1affd968b7e 100644 --- a/src/include/utils/trace.h +++ b/src/include/utils/trace.h @@ -64,6 +64,9 @@ enum pg_option_enum { OPT_SYSLOG, /* use syslog for error messages */ OPT_HOSTLOOKUP, /* enable hostname lookup in ps_status */ OPT_SHOWPORTNUMBER, /* show port number in ps_status */ +#ifdef FREE_TUPLE_MEMORY + OPT_FREE_TUPLE_MEMORY, /* try to pfree memory for each tuple */ +#endif NUM_PG_OPTIONS /* must be the last item of enum */ }; @@ -83,9 +86,9 @@ extern int pg_options[NUM_PG_OPTIONS]; #endif /* TRACE_H */ /* - * Local variables: - * tab-width: 4 - * c-indent-level: 4 - * c-basic-offset: 4 + * Local Variables: + * tab-width: 4 + * c-indent-level: 4 + * c-basic-offset: 4 * End: */