Tweak palloc/repalloc to allow zero bytes to be requested, as per recent

proposal.  Eliminate several dozen now-unnecessary hacks to avoid palloc(0).
(It's likely there are more that I didn't find.)
This commit is contained in:
Tom Lane 2004-06-05 19:48:09 +00:00
parent 24a1e20f14
commit c3a153afed
19 changed files with 113 additions and 113 deletions

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.117 2004/06/02 17:28:17 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.118 2004/06/05 19:48:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -693,7 +693,7 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
/* No point in remembering more than MaxFSMPages pages */
maxFreePages = MaxFSMPages;
if ((BlockNumber) maxFreePages > num_pages)
maxFreePages = (int) num_pages + 1; /* +1 to avoid palloc(0) */
maxFreePages = (int) num_pages;
freePages = (BlockNumber *) palloc(maxFreePages * sizeof(BlockNumber));
nFreePages = 0;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.73 2004/05/26 04:41:09 neilc Exp $
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.74 2004/06/05 19:48:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -226,9 +226,8 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
else
{
attr_cnt = onerel->rd_att->natts;
/* +1 here is just to avoid palloc(0) with zero-column table */
vacattrstats = (VacAttrStats **) palloc((attr_cnt + 1) *
sizeof(VacAttrStats *));
vacattrstats = (VacAttrStats **)
palloc(attr_cnt * sizeof(VacAttrStats *));
tcnt = 0;
for (i = 1; i <= attr_cnt; i++)
{
@ -505,8 +504,8 @@ compute_index_stats(Relation onerel, double totalrows,
estate);
/* Compute and save index expression values */
exprvals = (Datum *) palloc((numrows * attr_cnt + 1) * sizeof(Datum));
exprnulls = (bool *) palloc((numrows * attr_cnt + 1) * sizeof(bool));
exprvals = (Datum *) palloc(numrows * attr_cnt * sizeof(Datum));
exprnulls = (bool *) palloc(numrows * attr_cnt * sizeof(bool));
numindexrows = 0;
tcnt = 0;
for (rowno = 0; rowno < numrows; rowno++)

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.224 2004/05/26 04:41:10 neilc Exp $
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.225 2004/06/05 19:48:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1158,13 +1158,11 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
/*
* Get info about the columns we need to process.
*
* +1's here are to avoid palloc(0) in a zero-column table.
*/
out_functions = (FmgrInfo *) palloc((num_phys_attrs + 1) * sizeof(FmgrInfo));
elements = (Oid *) palloc((num_phys_attrs + 1) * sizeof(Oid));
isvarlena = (bool *) palloc((num_phys_attrs + 1) * sizeof(bool));
force_quote = (bool *) palloc((num_phys_attrs + 1) * sizeof(bool));
out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
isvarlena = (bool *) palloc(num_phys_attrs * sizeof(bool));
force_quote = (bool *) palloc(num_phys_attrs * sizeof(bool));
foreach(cur, attnumlist)
{
int attnum = lfirst_int(cur);
@ -1501,14 +1499,13 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
* relation, including the input function, the element type (to pass
* to the input function), and info about defaults and constraints.
* (Which input function we use depends on text/binary format choice.)
* +1's here are to avoid palloc(0) in a zero-column table.
*/
in_functions = (FmgrInfo *) palloc((num_phys_attrs + 1) * sizeof(FmgrInfo));
elements = (Oid *) palloc((num_phys_attrs + 1) * sizeof(Oid));
defmap = (int *) palloc((num_phys_attrs + 1) * sizeof(int));
defexprs = (ExprState **) palloc((num_phys_attrs + 1) * sizeof(ExprState *));
constraintexprs = (ExprState **) palloc0((num_phys_attrs + 1) * sizeof(ExprState *));
force_notnull = (bool *) palloc((num_phys_attrs + 1) * sizeof(bool));
in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
defmap = (int *) palloc(num_phys_attrs * sizeof(int));
defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
constraintexprs = (ExprState **) palloc0(num_phys_attrs * sizeof(ExprState *));
force_notnull = (bool *) palloc(num_phys_attrs * sizeof(bool));
for (attnum = 1; attnum <= num_phys_attrs; attnum++)
{
@ -1635,8 +1632,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
fmgr_info(in_func_oid, &oid_in_function);
}
values = (Datum *) palloc((num_phys_attrs + 1) * sizeof(Datum));
nulls = (char *) palloc((num_phys_attrs + 1) * sizeof(char));
values = (Datum *) palloc(num_phys_attrs * sizeof(Datum));
nulls = (char *) palloc(num_phys_attrs * sizeof(char));
/* Make room for a PARAM_EXEC value for domain constraint checks */
if (hasConstraints)

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.110 2004/06/04 20:35:21 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.111 2004/06/05 19:48:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -727,10 +727,10 @@ MergeAttributes(List *schema, List *supers, bool istemp,
* newattno[] will contain the child-table attribute numbers for
* the attributes of this parent table. (They are not the same
* for parents after the first one, nor if we have dropped
* columns.) +1 is to prevent error if parent has zero columns.
* columns.)
*/
newattno = (AttrNumber *)
palloc((tupleDesc->natts + 1) * sizeof(AttrNumber));
palloc(tupleDesc->natts * sizeof(AttrNumber));
for (parent_attno = 1; parent_attno <= tupleDesc->natts;
parent_attno++)

View File

@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.279 2004/05/31 19:24:05 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.280 2004/06/05 19:48:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -2883,9 +2883,8 @@ vac_update_fsm(Relation onerel, VacPageList fraged_pages,
*/
threshold = GetAvgFSMRequestSize(&onerel->rd_node);
/* +1 to avoid palloc(0) */
pageSpaces = (PageFreeSpaceInfo *)
palloc((nPages + 1) * sizeof(PageFreeSpaceInfo));
palloc(nPages * sizeof(PageFreeSpaceInfo));
outPages = 0;
for (i = 0; i < nPages; i++)

View File

@ -31,7 +31,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.41 2004/05/31 19:24:05 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.42 2004/06/05 19:48:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -918,9 +918,6 @@ lazy_space_alloc(LVRelStats *vacrelstats, BlockNumber relblocks)
/* No need to allocate more pages than the relation has blocks */
if (relblocks < (BlockNumber) maxpages)
maxpages = (int) relblocks;
/* avoid palloc(0) */
if (maxpages < 1)
maxpages = 1;
vacrelstats->fs_is_heap = false;
vacrelstats->num_free_pages = 0;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.162 2004/06/01 03:28:41 tgl Exp $
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.163 2004/06/05 19:48:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -2129,8 +2129,6 @@ ExecEvalRow(RowExprState *rstate,
/* Allocate workspace */
nargs = list_length(rstate->args);
if (nargs == 0) /* avoid palloc(0) if no fields */
nargs = 1;
values = (Datum *) palloc(nargs * sizeof(Datum));
nulls = (char *) palloc(nargs * sizeof(char));

View File

@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.113 2004/06/05 01:55:04 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.114 2004/06/05 19:48:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -538,9 +538,9 @@ generate_append_tlist(List *colTypes, bool flag,
* First extract typmods to use.
*
* If the inputs all agree on type and typmod of a particular column, use
* that typmod; else use -1. (+1 here in case of zero columns.)
* that typmod; else use -1.
*/
colTypmods = (int32 *) palloc(list_length(colTypes) * sizeof(int32) + 1);
colTypmods = (int32 *) palloc(list_length(colTypes) * sizeof(int32));
foreach(planl, input_plans)
{

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.173 2004/06/01 04:47:45 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.174 2004/06/05 19:48:08 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -2016,7 +2016,7 @@ inline_function(Oid funcid, Oid result_type, List *args,
* actual substitution of the inputs. So start building expression
* with inputs substituted.
*/
usecounts = (int *) palloc0((funcform->pronargs + 1) * sizeof(int));
usecounts = (int *) palloc0(funcform->pronargs * sizeof(int));
newexpr = substitute_actual_parameters(newexpr, funcform->pronargs,
args, usecounts);

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.30 2004/01/26 22:35:32 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.31 2004/06/05 19:48:08 tgl Exp $
*
*
* NOTES:
@ -893,7 +893,7 @@ LoadFreeSpaceMap(void)
len = nPages * sizeof(IndexFSMPageData);
else
len = nPages * sizeof(FSMPageData);
data = (char *) palloc(len + 1); /* +1 to avoid palloc(0) */
data = (char *) palloc(len);
if (fread(data, 1, len, fp) != len)
{
elog(LOG, "premature EOF in \"%s\"", cachefilename);

View File

@ -12,7 +12,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.27 2003/12/01 21:59:25 momjian Exp $
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.28 2004/06/05 19:48:08 tgl Exp $
*
* Interface:
*
@ -147,11 +147,10 @@ InitDeadLockChecking(void)
* We need to consider rearranging at most MaxBackends/2 wait queues
* (since it takes at least two waiters in a queue to create a soft
* edge), and the expanded form of the wait queues can't involve more
* than MaxBackends total waiters. (But avoid palloc(0) if
* MaxBackends = 1.)
* than MaxBackends total waiters.
*/
waitOrders = (WAIT_ORDER *)
palloc(((MaxBackends + 1) / 2) * sizeof(WAIT_ORDER));
palloc((MaxBackends / 2) * sizeof(WAIT_ORDER));
waitOrderProcs = (PGPROC **) palloc(MaxBackends * sizeof(PGPROC *));
/*

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.132 2004/05/28 05:13:05 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.133 2004/06/05 19:48:08 tgl Exp $
*
* NOTES
* Outside modules can create a lock table and acquire/release
@ -1361,9 +1361,6 @@ GetLockStatusData(void)
data->nelements = i = proclockTable->hctl->nentries;
if (i == 0)
i = 1; /* avoid palloc(0) if empty table */
data->proclockaddrs = (SHMEM_OFFSET *) palloc(sizeof(SHMEM_OFFSET) * i);
data->proclocks = (PROCLOCK *) palloc(sizeof(PROCLOCK) * i);
data->procs = (PGPROC *) palloc(sizeof(PGPROC) * i);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.79 2004/05/26 18:54:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.80 2004/06/05 19:48:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -347,10 +347,9 @@ PortalSetResultFormat(Portal portal, int nFormats, int16 *formats)
if (portal->tupDesc == NULL)
return;
natts = portal->tupDesc->natts;
/* +1 avoids palloc(0) if no columns */
portal->formats = (int16 *)
MemoryContextAlloc(PortalGetHeapMemory(portal),
(natts + 1) * sizeof(int16));
natts * sizeof(int16));
if (nFormats > 1)
{
/* format specified for each column */

View File

@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/name.c,v 1.52 2004/05/30 23:40:35 neilc Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/name.c,v 1.53 2004/06/05 19:48:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -358,9 +358,7 @@ current_schemas(PG_FUNCTION_ARGS)
int i;
ArrayType *array;
/* +1 here is just to avoid palloc(0) error */
names = (Datum *) palloc((list_length(search_path) + 1) * sizeof(Datum));
names = (Datum *) palloc(list_length(search_path) * sizeof(Datum));
i = 0;
foreach(l, search_path)
{

View File

@ -1,4 +1,4 @@
$PostgreSQL: pgsql/src/backend/utils/mmgr/README,v 1.5 2003/11/29 19:52:04 pgsql Exp $
$PostgreSQL: pgsql/src/backend/utils/mmgr/README,v 1.6 2004/06/05 19:48:09 tgl Exp $
Notes about memory allocation redesign
--------------------------------------
@ -53,6 +53,26 @@ that can be reset or deleted at strategic times within a query, such as
after each tuple.
Some notes about the palloc API versus standard C library
---------------------------------------------------------
The behavior of palloc and friends is similar to the standard C library's
malloc and friends, but there are some deliberate differences too. Here
are some notes to clarify the behavior.
* If out of memory, palloc and repalloc exit via elog(ERROR). They never
return NULL, and it is not necessary or useful to test for such a result.
* palloc(0) is explicitly a valid operation. It does not return a NULL
pointer, but a valid chunk of which no bytes may be used. (However, the
chunk might later be repalloc'd larger; it can also be pfree'd without
error.) (Note: this behavior is new in Postgres 7.5; earlier versions
disallowed palloc(0). It seems more consistent to allow it, however.)
Similarly, repalloc allows realloc'ing to zero size.
* pfree and repalloc do not accept a NULL pointer. This is intentional.
pfree/repalloc no longer depend on CurrentMemoryContext
-------------------------------------------------------

View File

@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mmgr/mcxt.c,v 1.44 2003/11/29 19:52:04 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/utils/mmgr/mcxt.c,v 1.45 2004/06/05 19:48:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -565,7 +565,7 @@ pfree(void *pointer)
/*
* repalloc
*
* Adjust the size of a previously allocated chunk.
*/
void *
repalloc(void *pointer, Size size)

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/memutils.h,v 1.54 2003/11/29 22:41:15 pgsql Exp $
* $PostgreSQL: pgsql/src/include/utils/memutils.h,v 1.55 2004/06/05 19:48:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -31,10 +31,13 @@
*
* XXX This is deliberately chosen to correspond to the limiting size
* of varlena objects under TOAST. See VARATT_MASK_SIZE in postgres.h.
*
* XXX Also, various places in aset.c assume they can compute twice an
* allocation's size without overflow, so beware of raising this.
*/
#define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
#define AllocSizeIsValid(size) (0 < (size) && (size) <= MaxAllocSize)
#define AllocSizeIsValid(size) ((Size) (size) <= MaxAllocSize)
/*
* All chunks allocated by any memory context manager are required to be

View File

@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.104 2004/06/04 02:37:06 tgl Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.105 2004/06/05 19:48:09 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@ -1942,10 +1942,8 @@ exec_prepare_plan(PLpgSQL_execstate * estate,
/*
* We need a temporary argtypes array to load with data. (The finished
* plan structure will contain a copy of it.)
*
* +1 is just to avoid palloc(0) error.
*/
argtypes = (Oid *) palloc(sizeof(Oid) * (expr->nparams + 1));
argtypes = (Oid *) palloc(expr->nparams * sizeof(Oid));
for (i = 0; i < expr->nparams; i++)
{
@ -1998,8 +1996,8 @@ exec_stmt_execsql(PLpgSQL_execstate * estate,
/*
* Now build up the values and nulls arguments for SPI_execp()
*/
values = palloc(sizeof(Datum) * (expr->nparams + 1));
nulls = palloc(expr->nparams + 1);
values = (Datum *) palloc(expr->nparams * sizeof(Datum));
nulls = (char *) palloc(expr->nparams * sizeof(char));
for (i = 0; i < expr->nparams; i++)
{
@ -2479,8 +2477,8 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
* refcursor opened with OPEN ... FOR SELECT ...;
* ----------
*/
values = palloc(sizeof(Datum) * (query->nparams + 1));
nulls = palloc(query->nparams + 1);
values = (Datum *) palloc(query->nparams * sizeof(Datum));
nulls = (char *) palloc(query->nparams * sizeof(char));
for (i = 0; i < query->nparams; i++)
{
@ -3324,8 +3322,8 @@ exec_run_select(PLpgSQL_execstate * estate,
/*
* Now build up the values and nulls arguments for SPI_execp()
*/
values = palloc(sizeof(Datum) * (expr->nparams + 1));
nulls = palloc(expr->nparams + 1);
values = (Datum *) palloc(expr->nparams * sizeof(Datum));
nulls = (char *) palloc(expr->nparams * sizeof(char));
for (i = 0; i < expr->nparams; i++)
{
@ -3528,8 +3526,7 @@ exec_move_row(PLpgSQL_execstate * estate,
/* If we have a tupdesc but no data, form an all-nulls tuple */
char *nulls;
/* +1 to avoid possible palloc(0) if no attributes */
nulls = (char *) palloc(tupdesc->natts * sizeof(char) + 1);
nulls = (char *) palloc(tupdesc->natts * sizeof(char));
memset(nulls, 'n', tupdesc->natts * sizeof(char));
rec->tup = heap_formtuple(tupdesc, NULL, nulls);

View File

@ -29,7 +29,7 @@
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.47 2004/05/07 00:24:59 tgl Exp $
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.48 2004/06/05 19:48:09 tgl Exp $
*
*********************************************************************
*/
@ -531,10 +531,9 @@ PLy_modify_tuple(PLyProcedure * proc, PyObject * pltd, TriggerData *tdata,
plkeys = PyDict_Keys(plntup);
natts = PyList_Size(plkeys);
/* +1 to avoid palloc(0) on empty tuple */
modattrs = palloc(natts * sizeof(int) + 1);
modvalues = palloc(natts * sizeof(Datum) + 1);
modnulls = palloc(natts + 1);
modattrs = (int *) palloc(natts * sizeof(int));
modvalues = (Datum *) palloc(natts * sizeof(Datum));
modnulls = (char *) palloc(natts * sizeof(char));
tupdesc = tdata->tg_relation->rd_att;
@ -2174,48 +2173,46 @@ PLy_spi_execute_plan(PyObject * ob, PyObject * list, int limit)
RERAISE_EXC();
}
if (nargs)
nulls = palloc(nargs * sizeof(char));
for (i = 0; i < nargs; i++)
{
nulls = palloc((nargs + 1) * sizeof(char));
PyObject *elem,
*so;
char *sv;
for (i = 0; i < nargs; i++)
elem = PySequence_GetItem(list, i);
if (elem != Py_None)
{
PyObject *elem,
*so;
char *sv;
so = PyObject_Str(elem);
sv = PyString_AsString(so);
elem = PySequence_GetItem(list, i);
if (elem != Py_None)
{
so = PyObject_Str(elem);
sv = PyString_AsString(so);
/*
* FIXME -- if this can elog, we have leak
*/
plan->values[i] =
FunctionCall3(&(plan->args[i].out.d.typfunc),
CStringGetDatum(sv),
ObjectIdGetDatum(plan->args[i].out.d.typelem),
Int32GetDatum(-1));
/*
* FIXME -- if this can elog, we have leak
*/
plan->values[i] = FunctionCall3(&(plan->args[i].out.d.typfunc),
CStringGetDatum(sv),
ObjectIdGetDatum(plan->args[i].out.d.typelem),
Int32GetDatum(-1));
Py_DECREF(so);
Py_DECREF(elem);
Py_DECREF(so);
Py_DECREF(elem);
nulls[i] = ' ';
}
else
{
Py_DECREF(elem);
plan->values[i] = (Datum) 0;
nulls[i] = 'n';
}
nulls[i] = ' ';
}
else
{
Py_DECREF(elem);
plan->values[i] = (Datum) 0;
nulls[i] = 'n';
}
nulls[i] = '\0';
}
else
nulls = NULL;
rv = SPI_execp(plan->plan, plan->values, nulls, limit);
pfree(nulls);
RESTORE_EXC();
for (i = 0; i < nargs; i++)