aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execExprInterp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execExprInterp.c')
-rw-r--r--src/backend/executor/execExprInterp.c238
1 files changed, 8 insertions, 230 deletions
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index c09371ad58f..6b9fc38134b 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -417,7 +417,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
&&CASE_EEOP_FIELDSELECT,
&&CASE_EEOP_FIELDSTORE_DEFORM,
&&CASE_EEOP_FIELDSTORE_FORM,
- &&CASE_EEOP_SBSREF_SUBSCRIPT,
+ &&CASE_EEOP_SBSREF_SUBSCRIPTS,
&&CASE_EEOP_SBSREF_OLD,
&&CASE_EEOP_SBSREF_ASSIGN,
&&CASE_EEOP_SBSREF_FETCH,
@@ -1396,12 +1396,10 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
EEO_NEXT();
}
- EEO_CASE(EEOP_SBSREF_SUBSCRIPT)
+ EEO_CASE(EEOP_SBSREF_SUBSCRIPTS)
{
- /* Process an array subscript */
-
- /* too complex for an inline implementation */
- if (ExecEvalSubscriptingRef(state, op))
+ /* Precheck SubscriptingRef subscript(s) */
+ if (op->d.sbsref_subscript.subscriptfunc(state, op, econtext))
{
EEO_NEXT();
}
@@ -1413,37 +1411,11 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
}
EEO_CASE(EEOP_SBSREF_OLD)
+ EEO_CASE(EEOP_SBSREF_ASSIGN)
+ EEO_CASE(EEOP_SBSREF_FETCH)
{
- /*
- * Fetch the old value in an sbsref assignment, in case it's
- * referenced (via a CaseTestExpr) inside the assignment
- * expression.
- */
-
- /* too complex for an inline implementation */
- ExecEvalSubscriptingRefOld(state, op);
-
- EEO_NEXT();
- }
-
- /*
- * Perform SubscriptingRef assignment
- */
- EEO_CASE(EEOP_SBSREF_ASSIGN)
- {
- /* too complex for an inline implementation */
- ExecEvalSubscriptingRefAssign(state, op);
-
- EEO_NEXT();
- }
-
- /*
- * Fetch subset of an array.
- */
- EEO_CASE(EEOP_SBSREF_FETCH)
- {
- /* too complex for an inline implementation */
- ExecEvalSubscriptingRefFetch(state, op);
+ /* Perform a SubscriptingRef fetch or assignment */
+ op->d.sbsref.subscriptfunc(state, op, econtext);
EEO_NEXT();
}
@@ -3123,200 +3095,6 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext
}
/*
- * Process a subscript in a SubscriptingRef expression.
- *
- * If subscript is NULL, throw error in assignment case, or in fetch case
- * set result to NULL and return false (instructing caller to skip the rest
- * of the SubscriptingRef sequence).
- *
- * Subscript expression result is in subscriptvalue/subscriptnull.
- * On success, integer subscript value has been saved in upperindex[] or
- * lowerindex[] for use later.
- */
-bool
-ExecEvalSubscriptingRef(ExprState *state, ExprEvalStep *op)
-{
- SubscriptingRefState *sbsrefstate = op->d.sbsref_subscript.state;
- int *indexes;
- int off;
-
- /* If any index expr yields NULL, result is NULL or error */
- if (sbsrefstate->subscriptnull)
- {
- if (sbsrefstate->isassignment)
- ereport(ERROR,
- (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
- errmsg("array subscript in assignment must not be null")));
- *op->resnull = true;
- return false;
- }
-
- /* Convert datum to int, save in appropriate place */
- if (op->d.sbsref_subscript.isupper)
- indexes = sbsrefstate->upperindex;
- else
- indexes = sbsrefstate->lowerindex;
- off = op->d.sbsref_subscript.off;
-
- indexes[off] = DatumGetInt32(sbsrefstate->subscriptvalue);
-
- return true;
-}
-
-/*
- * Evaluate SubscriptingRef fetch.
- *
- * Source container is in step's result variable.
- */
-void
-ExecEvalSubscriptingRefFetch(ExprState *state, ExprEvalStep *op)
-{
- SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
-
- /* Should not get here if source container (or any subscript) is null */
- Assert(!(*op->resnull));
-
- if (sbsrefstate->numlower == 0)
- {
- /* Scalar case */
- *op->resvalue = array_get_element(*op->resvalue,
- sbsrefstate->numupper,
- sbsrefstate->upperindex,
- sbsrefstate->refattrlength,
- sbsrefstate->refelemlength,
- sbsrefstate->refelembyval,
- sbsrefstate->refelemalign,
- op->resnull);
- }
- else
- {
- /* Slice case */
- *op->resvalue = array_get_slice(*op->resvalue,
- sbsrefstate->numupper,
- sbsrefstate->upperindex,
- sbsrefstate->lowerindex,
- sbsrefstate->upperprovided,
- sbsrefstate->lowerprovided,
- sbsrefstate->refattrlength,
- sbsrefstate->refelemlength,
- sbsrefstate->refelembyval,
- sbsrefstate->refelemalign);
- }
-}
-
-/*
- * Compute old container element/slice value for a SubscriptingRef assignment
- * expression. Will only be generated if the new-value subexpression
- * contains SubscriptingRef or FieldStore. The value is stored into the
- * SubscriptingRefState's prevvalue/prevnull fields.
- */
-void
-ExecEvalSubscriptingRefOld(ExprState *state, ExprEvalStep *op)
-{
- SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
-
- if (*op->resnull)
- {
- /* whole array is null, so any element or slice is too */
- sbsrefstate->prevvalue = (Datum) 0;
- sbsrefstate->prevnull = true;
- }
- else if (sbsrefstate->numlower == 0)
- {
- /* Scalar case */
- sbsrefstate->prevvalue = array_get_element(*op->resvalue,
- sbsrefstate->numupper,
- sbsrefstate->upperindex,
- sbsrefstate->refattrlength,
- sbsrefstate->refelemlength,
- sbsrefstate->refelembyval,
- sbsrefstate->refelemalign,
- &sbsrefstate->prevnull);
- }
- else
- {
- /* Slice case */
- /* this is currently unreachable */
- sbsrefstate->prevvalue = array_get_slice(*op->resvalue,
- sbsrefstate->numupper,
- sbsrefstate->upperindex,
- sbsrefstate->lowerindex,
- sbsrefstate->upperprovided,
- sbsrefstate->lowerprovided,
- sbsrefstate->refattrlength,
- sbsrefstate->refelemlength,
- sbsrefstate->refelembyval,
- sbsrefstate->refelemalign);
- sbsrefstate->prevnull = false;
- }
-}
-
-/*
- * Evaluate SubscriptingRef assignment.
- *
- * Input container (possibly null) is in result area, replacement value is in
- * SubscriptingRefState's replacevalue/replacenull.
- */
-void
-ExecEvalSubscriptingRefAssign(ExprState *state, ExprEvalStep *op)
-{
- SubscriptingRefState *sbsrefstate = op->d.sbsref_subscript.state;
-
- /*
- * For an assignment to a fixed-length container type, both the original
- * container and the value to be assigned into it must be non-NULL, else
- * we punt and return the original container.
- */
- if (sbsrefstate->refattrlength > 0)
- {
- if (*op->resnull || sbsrefstate->replacenull)
- return;
- }
-
- /*
- * For assignment to varlena arrays, we handle a NULL original array by
- * substituting an empty (zero-dimensional) array; insertion of the new
- * element will result in a singleton array value. It does not matter
- * whether the new element is NULL.
- */
- if (*op->resnull)
- {
- *op->resvalue = PointerGetDatum(construct_empty_array(sbsrefstate->refelemtype));
- *op->resnull = false;
- }
-
- if (sbsrefstate->numlower == 0)
- {
- /* Scalar case */
- *op->resvalue = array_set_element(*op->resvalue,
- sbsrefstate->numupper,
- sbsrefstate->upperindex,
- sbsrefstate->replacevalue,
- sbsrefstate->replacenull,
- sbsrefstate->refattrlength,
- sbsrefstate->refelemlength,
- sbsrefstate->refelembyval,
- sbsrefstate->refelemalign);
- }
- else
- {
- /* Slice case */
- *op->resvalue = array_set_slice(*op->resvalue,
- sbsrefstate->numupper,
- sbsrefstate->upperindex,
- sbsrefstate->lowerindex,
- sbsrefstate->upperprovided,
- sbsrefstate->lowerprovided,
- sbsrefstate->replacevalue,
- sbsrefstate->replacenull,
- sbsrefstate->refattrlength,
- sbsrefstate->refelemlength,
- sbsrefstate->refelembyval,
- sbsrefstate->refelemalign);
- }
-}
-
-/*
* Evaluate a rowtype coercion operation.
* This may require rearranging field positions.
*