static void ExecReadyExpr(ExprState *state);
static void ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state,
Datum *resv, bool *resnull);
+static void ExprEvalPushStepPrealloc(ExprState *es, size_t n);
static void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s);
static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
Oid funcid, Oid inputcollid, PlanState *parent,
state->expr = (Expr *) targetList;
state->resultslot = slot;
+ ExprEvalPushStepPrealloc(state, list_length(targetList) + 4);
+
/* Insert EEOP_*_FETCHSOME steps as needed */
ExecInitExprSlots(state, (Node *) targetList);
scratch.d.assign_var.attnum = attnum - 1;
scratch.d.assign_var.resultnum = tle->resno - 1;
- ExprEvalPushStep(state, &scratch);
}
else
{
else
scratch.opcode = EEOP_ASSIGN_TMP;
scratch.d.assign_tmp.resultnum = tle->resno - 1;
- ExprEvalPushStep(state, &scratch);
}
+ ExprEvalPushStep(state, &scratch);
}
scratch.opcode = EEOP_DONE;
memcpy(&es->steps[es->steps_len++], s, sizeof(ExprEvalStep));
}
+/*
+ * Preallocate memory for ExprState->steps.
+ *
+ * Preallocating an appropriate amount can reduce memory reallocations during
+ * ExprEvalPushStep, iff a decent estimate about the number of required steps
+ * is possible.
+ */
+static void
+ExprEvalPushStepPrealloc(ExprState *es, size_t n)
+{
+ Assert(es->steps_alloc == 0);
+ Assert(n > 0);
+
+ if (n < 16)
+ n = 16;
+
+ /* should we increase to the next power of two? */
+ es->steps_alloc = n;
+ es->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc);
+}
+
/*
* Perform setup necessary for the evaluation of a function-like expression,
* appending argument evaluation steps to the steps list in *state, and