From 558d77f20e4e9ed18101d5d057b770ae22ece855 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Fri, 1 Feb 2019 12:50:32 -0300 Subject: [PATCH] Renaming for new subscripting mechanism Over at patch https://commitfest.postgresql.org/21/1062/ Dmitry wants to introduce a more generic subscription mechanism, which allows subscripting not only arrays but also other object types such as JSONB. That functionality is introduced in a largish invasive patch, out of which this internal renaming patch was extracted. Author: Dmitry Dolgov Reviewed-by: Tom Lane, Arthur Zakirov Discussion: https://postgr.es/m/CA+q6zcUK4EqPAu7XRRO5CCjMwhz5zvg+rfWuLzVoxp_5sKS6=w@mail.gmail.com --- .../pg_stat_statements/pg_stat_statements.c | 12 +- contrib/postgres_fdw/deparse.c | 30 +-- src/backend/executor/execExpr.c | 171 +++++++------- src/backend/executor/execExprInterp.c | 214 +++++++++--------- src/backend/jit/llvm/llvmjit.c | 4 +- src/backend/jit/llvm/llvmjit_expr.c | 18 +- src/backend/jit/llvm/llvmjit_types.c | 2 +- src/backend/nodes/copyfuncs.c | 14 +- src/backend/nodes/equalfuncs.c | 8 +- src/backend/nodes/nodeFuncs.c | 64 +++--- src/backend/nodes/outfuncs.c | 10 +- src/backend/nodes/readfuncs.c | 14 +- src/backend/optimizer/util/clauses.c | 14 +- src/backend/parser/analyze.c | 9 +- src/backend/parser/parse_expr.c | 28 +-- src/backend/parser/parse_node.c | 169 +++++++------- src/backend/parser/parse_target.c | 50 ++-- src/backend/rewrite/rewriteHandler.c | 26 ++- src/backend/utils/adt/ruleutils.c | 88 +++---- src/include/executor/execExpr.h | 56 ++--- src/include/jit/llvmjit.h | 2 +- src/include/nodes/nodes.h | 2 +- src/include/nodes/parsenodes.h | 2 +- src/include/nodes/primnodes.h | 50 ++-- src/include/parser/parse_node.h | 17 +- src/pl/plpgsql/src/pl_exec.c | 4 +- 26 files changed, 555 insertions(+), 523 deletions(-) diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 96d98285fd..ea2e4bc242 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -2579,14 +2579,14 @@ JumbleExpr(pgssJumbleState *jstate, Node *node) JumbleExpr(jstate, (Node *) expr->aggfilter); } break; - case T_ArrayRef: + case T_SubscriptingRef: { - ArrayRef *aref = (ArrayRef *) node; + SubscriptingRef *sbsref = (SubscriptingRef *) node; - JumbleExpr(jstate, (Node *) aref->refupperindexpr); - JumbleExpr(jstate, (Node *) aref->reflowerindexpr); - JumbleExpr(jstate, (Node *) aref->refexpr); - JumbleExpr(jstate, (Node *) aref->refassgnexpr); + JumbleExpr(jstate, (Node *) sbsref->refupperindexpr); + JumbleExpr(jstate, (Node *) sbsref->reflowerindexpr); + JumbleExpr(jstate, (Node *) sbsref->refexpr); + JumbleExpr(jstate, (Node *) sbsref->refassgnexpr); } break; case T_FuncExpr: diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c index b0e44e5562..92a0ab6da5 100644 --- a/contrib/postgres_fdw/deparse.c +++ b/contrib/postgres_fdw/deparse.c @@ -149,7 +149,7 @@ static void deparseExpr(Expr *expr, deparse_expr_cxt *context); static void deparseVar(Var *node, deparse_expr_cxt *context); static void deparseConst(Const *node, deparse_expr_cxt *context, int showtype); static void deparseParam(Param *node, deparse_expr_cxt *context); -static void deparseArrayRef(ArrayRef *node, deparse_expr_cxt *context); +static void deparseSubscriptingRef(SubscriptingRef *node, deparse_expr_cxt *context); static void deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context); static void deparseOpExpr(OpExpr *node, deparse_expr_cxt *context); static void deparseOperatorName(StringInfo buf, Form_pg_operator opform); @@ -401,34 +401,34 @@ foreign_expr_walker(Node *node, state = FDW_COLLATE_UNSAFE; } break; - case T_ArrayRef: + case T_SubscriptingRef: { - ArrayRef *ar = (ArrayRef *) node; + SubscriptingRef *sr = (SubscriptingRef *) node; /* Assignment should not be in restrictions. */ - if (ar->refassgnexpr != NULL) + if (sr->refassgnexpr != NULL) return false; /* - * Recurse to remaining subexpressions. Since the array + * Recurse to remaining subexpressions. Since the container * subscripts must yield (noncollatable) integers, they won't * affect the inner_cxt state. */ - if (!foreign_expr_walker((Node *) ar->refupperindexpr, + if (!foreign_expr_walker((Node *) sr->refupperindexpr, glob_cxt, &inner_cxt)) return false; - if (!foreign_expr_walker((Node *) ar->reflowerindexpr, + if (!foreign_expr_walker((Node *) sr->reflowerindexpr, glob_cxt, &inner_cxt)) return false; - if (!foreign_expr_walker((Node *) ar->refexpr, + if (!foreign_expr_walker((Node *) sr->refexpr, glob_cxt, &inner_cxt)) return false; /* - * Array subscripting should yield same collation as input, - * but for safety use same logic as for function nodes. + * Container subscripting should yield same collation as + * input, but for safety use same logic as for function nodes. */ - collation = ar->refcollid; + collation = sr->refcollid; if (collation == InvalidOid) state = FDW_COLLATE_NONE; else if (inner_cxt.state == FDW_COLLATE_SAFE && @@ -2270,8 +2270,8 @@ deparseExpr(Expr *node, deparse_expr_cxt *context) case T_Param: deparseParam((Param *) node, context); break; - case T_ArrayRef: - deparseArrayRef((ArrayRef *) node, context); + case T_SubscriptingRef: + deparseSubscriptingRef((SubscriptingRef *) node, context); break; case T_FuncExpr: deparseFuncExpr((FuncExpr *) node, context); @@ -2518,10 +2518,10 @@ deparseParam(Param *node, deparse_expr_cxt *context) } /* - * Deparse an array subscript expression. + * Deparse a container subscript expression. */ static void -deparseArrayRef(ArrayRef *node, deparse_expr_cxt *context) +deparseSubscriptingRef(SubscriptingRef *node, deparse_expr_cxt *context) { StringInfo buf = context->buf; ListCell *lowlist_item; diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index e52b806372..db3777d15e 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -67,9 +67,10 @@ static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info); static void ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op); static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state); -static void ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref, - ExprState *state, - Datum *resv, bool *resnull); +static void ExecInitSubscriptingRef(ExprEvalStep *scratch, + SubscriptingRef *sbsref, + ExprState *state, + Datum *resv, bool *resnull); static bool isAssignmentIndirectionExpr(Expr *expr); static void ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest, ExprState *state, @@ -867,11 +868,11 @@ ExecInitExprRec(Expr *node, ExprState *state, break; } - case T_ArrayRef: + case T_SubscriptingRef: { - ArrayRef *aref = (ArrayRef *) node; + SubscriptingRef *sbsref = (SubscriptingRef *) node; - ExecInitArrayRef(&scratch, aref, state, resv, resnull); + ExecInitSubscriptingRef(&scratch, sbsref, state, resv, resnull); break; } @@ -1186,13 +1187,14 @@ ExecInitExprRec(Expr *node, ExprState *state, /* * Use the CaseTestExpr mechanism to pass down the old * value of the field being replaced; this is needed in - * case the newval is itself a FieldStore or ArrayRef that - * has to obtain and modify the old value. It's safe to - * reuse the CASE mechanism because there cannot be a CASE - * between here and where the value would be needed, and a - * field assignment can't be within a CASE either. (So - * saving and restoring innermost_caseval is just - * paranoia, but let's do it anyway.) + * case the newval is itself a FieldStore or + * SubscriptingRef that has to obtain and modify the old + * value. It's safe to reuse the CASE mechanism because + * there cannot be a CASE between here and where the value + * would be needed, and a field assignment can't be within + * a CASE either. (So saving and restoring + * innermost_caseval is just paranoia, but let's do it + * anyway.) * * Another non-obvious point is that it's safe to use the * field's values[]/nulls[] entries as both the caseval @@ -2528,34 +2530,34 @@ ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state) } /* - * Prepare evaluation of an ArrayRef expression. + * Prepare evaluation of a SubscriptingRef expression. */ static void -ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref, - ExprState *state, Datum *resv, bool *resnull) +ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref, + ExprState *state, Datum *resv, bool *resnull) { - bool isAssignment = (aref->refassgnexpr != NULL); - ArrayRefState *arefstate = palloc0(sizeof(ArrayRefState)); + bool isAssignment = (sbsref->refassgnexpr != NULL); + SubscriptingRefState *sbsrefstate = palloc0(sizeof(SubscriptingRefState)); List *adjust_jumps = NIL; ListCell *lc; int i; - /* Fill constant fields of ArrayRefState */ - arefstate->isassignment = isAssignment; - arefstate->refelemtype = aref->refelemtype; - arefstate->refattrlength = get_typlen(aref->refarraytype); - get_typlenbyvalalign(aref->refelemtype, - &arefstate->refelemlength, - &arefstate->refelembyval, - &arefstate->refelemalign); + /* Fill constant fields of SubscriptingRefState */ + sbsrefstate->isassignment = isAssignment; + sbsrefstate->refelemtype = sbsref->refelemtype; + sbsrefstate->refattrlength = get_typlen(sbsref->refcontainertype); + get_typlenbyvalalign(sbsref->refelemtype, + &sbsrefstate->refelemlength, + &sbsrefstate->refelembyval, + &sbsrefstate->refelemalign); /* * Evaluate array input. It's safe to do so into resv/resnull, because we * won't use that as target for any of the other subexpressions, and it'll - * be overwritten by the final EEOP_ARRAYREF_FETCH/ASSIGN step, which is + * be overwritten by the final EEOP_SBSREF_FETCH/ASSIGN step, which is * pushed last. */ - ExecInitExprRec(aref->refexpr, state, resv, resnull); + ExecInitExprRec(sbsref->refexpr, state, resv, resnull); /* * If refexpr yields NULL, and it's a fetch, then result is NULL. We can @@ -2572,87 +2574,87 @@ ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref, } /* Verify subscript list lengths are within limit */ - if (list_length(aref->refupperindexpr) > MAXDIM) + if (list_length(sbsref->refupperindexpr) > MAXDIM) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", - list_length(aref->refupperindexpr), MAXDIM))); + list_length(sbsref->refupperindexpr), MAXDIM))); - if (list_length(aref->reflowerindexpr) > MAXDIM) + if (list_length(sbsref->reflowerindexpr) > MAXDIM) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", - list_length(aref->reflowerindexpr), MAXDIM))); + list_length(sbsref->reflowerindexpr), MAXDIM))); /* Evaluate upper subscripts */ i = 0; - foreach(lc, aref->refupperindexpr) + foreach(lc, sbsref->refupperindexpr) { Expr *e = (Expr *) lfirst(lc); /* When slicing, individual subscript bounds can be omitted */ if (!e) { - arefstate->upperprovided[i] = false; + sbsrefstate->upperprovided[i] = false; i++; continue; } - arefstate->upperprovided[i] = true; + sbsrefstate->upperprovided[i] = true; /* Each subscript is evaluated into subscriptvalue/subscriptnull */ ExecInitExprRec(e, state, - &arefstate->subscriptvalue, &arefstate->subscriptnull); + &sbsrefstate->subscriptvalue, &sbsrefstate->subscriptnull); - /* ... and then ARRAYREF_SUBSCRIPT saves it into step's workspace */ - scratch->opcode = EEOP_ARRAYREF_SUBSCRIPT; - scratch->d.arrayref_subscript.state = arefstate; - scratch->d.arrayref_subscript.off = i; - scratch->d.arrayref_subscript.isupper = true; - scratch->d.arrayref_subscript.jumpdone = -1; /* adjust later */ + /* ... and then SBSREF_SUBSCRIPT saves it into step's workspace */ + scratch->opcode = EEOP_SBSREF_SUBSCRIPT; + scratch->d.sbsref_subscript.state = sbsrefstate; + scratch->d.sbsref_subscript.off = i; + scratch->d.sbsref_subscript.isupper = true; + scratch->d.sbsref_subscript.jumpdone = -1; /* adjust later */ ExprEvalPushStep(state, scratch); adjust_jumps = lappend_int(adjust_jumps, state->steps_len - 1); i++; } - arefstate->numupper = i; + sbsrefstate->numupper = i; /* Evaluate lower subscripts similarly */ i = 0; - foreach(lc, aref->reflowerindexpr) + foreach(lc, sbsref->reflowerindexpr) { Expr *e = (Expr *) lfirst(lc); /* When slicing, individual subscript bounds can be omitted */ if (!e) { - arefstate->lowerprovided[i] = false; + sbsrefstate->lowerprovided[i] = false; i++; continue; } - arefstate->lowerprovided[i] = true; + sbsrefstate->lowerprovided[i] = true; /* Each subscript is evaluated into subscriptvalue/subscriptnull */ ExecInitExprRec(e, state, - &arefstate->subscriptvalue, &arefstate->subscriptnull); + &sbsrefstate->subscriptvalue, &sbsrefstate->subscriptnull); - /* ... and then ARRAYREF_SUBSCRIPT saves it into step's workspace */ - scratch->opcode = EEOP_ARRAYREF_SUBSCRIPT; - scratch->d.arrayref_subscript.state = arefstate; - scratch->d.arrayref_subscript.off = i; - scratch->d.arrayref_subscript.isupper = false; - scratch->d.arrayref_subscript.jumpdone = -1; /* adjust later */ + /* ... and then SBSREF_SUBSCRIPT saves it into step's workspace */ + scratch->opcode = EEOP_SBSREF_SUBSCRIPT; + scratch->d.sbsref_subscript.state = sbsrefstate; + scratch->d.sbsref_subscript.off = i; + scratch->d.sbsref_subscript.isupper = false; + scratch->d.sbsref_subscript.jumpdone = -1; /* adjust later */ ExprEvalPushStep(state, scratch); adjust_jumps = lappend_int(adjust_jumps, state->steps_len - 1); i++; } - arefstate->numlower = i; + sbsrefstate->numlower = i; /* Should be impossible if parser is sane, but check anyway: */ - if (arefstate->numlower != 0 && - arefstate->numupper != arefstate->numlower) + if (sbsrefstate->numlower != 0 && + sbsrefstate->numupper != sbsrefstate->numlower) elog(ERROR, "upper and lower index lists are not same length"); if (isAssignment) @@ -2662,49 +2664,51 @@ ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref, /* * We might have a nested-assignment situation, in which the - * refassgnexpr is itself a FieldStore or ArrayRef that needs to - * obtain and modify the previous value of the array element or slice - * being replaced. If so, we have to extract that value from the - * array and pass it down via the CaseTestExpr mechanism. It's safe - * to reuse the CASE mechanism because there cannot be a CASE between - * here and where the value would be needed, and an array assignment - * can't be within a CASE either. (So saving and restoring + * refassgnexpr is itself a FieldStore or SubscriptingRef that needs + * to obtain and modify the previous value of the array element or + * slice being replaced. If so, we have to extract that value from + * the array and pass it down via the CaseTestExpr mechanism. It's + * safe to reuse the CASE mechanism because there cannot be a CASE + * between here and where the value would be needed, and an array + * assignment can't be within a CASE either. (So saving and restoring * innermost_caseval is just paranoia, but let's do it anyway.) * * Since fetching the old element might be a nontrivial expense, do it * only if the argument actually needs it. */ - if (isAssignmentIndirectionExpr(aref->refassgnexpr)) + if (isAssignmentIndirectionExpr(sbsref->refassgnexpr)) { - scratch->opcode = EEOP_ARRAYREF_OLD; - scratch->d.arrayref.state = arefstate; + scratch->opcode = EEOP_SBSREF_OLD; + scratch->d.sbsref.state = sbsrefstate; ExprEvalPushStep(state, scratch); } - /* ARRAYREF_OLD puts extracted value into prevvalue/prevnull */ + /* SBSREF_OLD puts extracted value into prevvalue/prevnull */ save_innermost_caseval = state->innermost_caseval; save_innermost_casenull = state->innermost_casenull; - state->innermost_caseval = &arefstate->prevvalue; - state->innermost_casenull = &arefstate->prevnull; + state->innermost_caseval = &sbsrefstate->prevvalue; + state->innermost_casenull = &sbsrefstate->prevnull; /* evaluate replacement value into replacevalue/replacenull */ - ExecInitExprRec(aref->refassgnexpr, state, - &arefstate->replacevalue, &arefstate->replacenull); + ExecInitExprRec(sbsref->refassgnexpr, state, + &sbsrefstate->replacevalue, &sbsrefstate->replacenull); state->innermost_caseval = save_innermost_caseval; state->innermost_casenull = save_innermost_casenull; /* and perform the assignment */ - scratch->opcode = EEOP_ARRAYREF_ASSIGN; - scratch->d.arrayref.state = arefstate; + scratch->opcode = EEOP_SBSREF_ASSIGN; + scratch->d.sbsref.state = sbsrefstate; ExprEvalPushStep(state, scratch); + } else { /* array fetch is much simpler */ - scratch->opcode = EEOP_ARRAYREF_FETCH; - scratch->d.arrayref.state = arefstate; + scratch->opcode = EEOP_SBSREF_FETCH; + scratch->d.sbsref.state = sbsrefstate; ExprEvalPushStep(state, scratch); + } /* adjust jump targets */ @@ -2712,10 +2716,10 @@ ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref, { ExprEvalStep *as = &state->steps[lfirst_int(lc)]; - if (as->opcode == EEOP_ARRAYREF_SUBSCRIPT) + if (as->opcode == EEOP_SBSREF_SUBSCRIPT) { - Assert(as->d.arrayref_subscript.jumpdone == -1); - as->d.arrayref_subscript.jumpdone = state->steps_len; + Assert(as->d.sbsref_subscript.jumpdone == -1); + as->d.sbsref_subscript.jumpdone = state->steps_len; } else { @@ -2727,8 +2731,9 @@ ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref, } /* - * Helper for preparing ArrayRef expressions for evaluation: is expr a nested - * FieldStore or ArrayRef that needs the old element value passed down? + * Helper for preparing SubscriptingRef expressions for evaluation: is expr + * a nested FieldStore or SubscriptingRef that needs the old element value + * passed down? * * (We could use this in FieldStore too, but in that case passing the old * value is so cheap there's no need.) @@ -2751,11 +2756,11 @@ isAssignmentIndirectionExpr(Expr *expr) if (fstore->arg && IsA(fstore->arg, CaseTestExpr)) return true; } - else if (IsA(expr, ArrayRef)) + else if (IsA(expr, SubscriptingRef)) { - ArrayRef *arrayRef = (ArrayRef *) expr; + SubscriptingRef *sbsRef = (SubscriptingRef *) expr; - if (arrayRef->refexpr && IsA(arrayRef->refexpr, CaseTestExpr)) + if (sbsRef->refexpr && IsA(sbsRef->refexpr, CaseTestExpr)) return true; } return false; diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 5c5f655645..a018925d4e 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -370,10 +370,10 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) &&CASE_EEOP_FIELDSELECT, &&CASE_EEOP_FIELDSTORE_DEFORM, &&CASE_EEOP_FIELDSTORE_FORM, - &&CASE_EEOP_ARRAYREF_SUBSCRIPT, - &&CASE_EEOP_ARRAYREF_OLD, - &&CASE_EEOP_ARRAYREF_ASSIGN, - &&CASE_EEOP_ARRAYREF_FETCH, + &&CASE_EEOP_SBSREF_SUBSCRIPT, + &&CASE_EEOP_SBSREF_OLD, + &&CASE_EEOP_SBSREF_ASSIGN, + &&CASE_EEOP_SBSREF_FETCH, &&CASE_EEOP_DOMAIN_TESTVAL, &&CASE_EEOP_DOMAIN_NOTNULL, &&CASE_EEOP_DOMAIN_CHECK, @@ -1347,43 +1347,43 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } - EEO_CASE(EEOP_ARRAYREF_SUBSCRIPT) + EEO_CASE(EEOP_SBSREF_SUBSCRIPT) { /* Process an array subscript */ /* too complex for an inline implementation */ - if (ExecEvalArrayRefSubscript(state, op)) + if (ExecEvalSubscriptingRef(state, op)) { EEO_NEXT(); } else { - /* Subscript is null, short-circuit ArrayRef to NULL */ - EEO_JUMP(op->d.arrayref_subscript.jumpdone); + /* Subscript is null, short-circuit SubscriptingRef to NULL */ + EEO_JUMP(op->d.sbsref_subscript.jumpdone); } } - EEO_CASE(EEOP_ARRAYREF_OLD) + EEO_CASE(EEOP_SBSREF_OLD) { /* - * Fetch the old value in an arrayref assignment, in case it's + * 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 */ - ExecEvalArrayRefOld(state, op); + ExecEvalSubscriptingRefOld(state, op); EEO_NEXT(); } /* - * Perform ArrayRef assignment + * Perform SubscriptingRef assignment */ - EEO_CASE(EEOP_ARRAYREF_ASSIGN) + EEO_CASE(EEOP_SBSREF_ASSIGN) { /* too complex for an inline implementation */ - ExecEvalArrayRefAssign(state, op); + ExecEvalSubscriptingRefAssign(state, op); EEO_NEXT(); } @@ -1391,10 +1391,10 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) /* * Fetch subset of an array. */ - EEO_CASE(EEOP_ARRAYREF_FETCH) + EEO_CASE(EEOP_SBSREF_FETCH) { /* too complex for an inline implementation */ - ExecEvalArrayRefFetch(state, op); + ExecEvalSubscriptingRefFetch(state, op); EEO_NEXT(); } @@ -3044,27 +3044,27 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext } /* - * Process a subscript in an ArrayRef expression. + * 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 ArrayRef sequence). + * 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 -ExecEvalArrayRefSubscript(ExprState *state, ExprEvalStep *op) +ExecEvalSubscriptingRef(ExprState *state, ExprEvalStep *op) { - ArrayRefState *arefstate = op->d.arrayref_subscript.state; + SubscriptingRefState *sbsrefstate = op->d.sbsref_subscript.state; int *indexes; int off; /* If any index expr yields NULL, result is NULL or error */ - if (arefstate->subscriptnull) + if (sbsrefstate->subscriptnull) { - if (arefstate->isassignment) + if (sbsrefstate->isassignment) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("array subscript in assignment must not be null"))); @@ -3073,124 +3073,124 @@ ExecEvalArrayRefSubscript(ExprState *state, ExprEvalStep *op) } /* Convert datum to int, save in appropriate place */ - if (op->d.arrayref_subscript.isupper) - indexes = arefstate->upperindex; + if (op->d.sbsref_subscript.isupper) + indexes = sbsrefstate->upperindex; else - indexes = arefstate->lowerindex; - off = op->d.arrayref_subscript.off; + indexes = sbsrefstate->lowerindex; + off = op->d.sbsref_subscript.off; - indexes[off] = DatumGetInt32(arefstate->subscriptvalue); + indexes[off] = DatumGetInt32(sbsrefstate->subscriptvalue); return true; } /* - * Evaluate ArrayRef fetch. + * Evaluate SubscriptingRef fetch. * - * Source array is in step's result variable. + * Source container is in step's result variable. */ void -ExecEvalArrayRefFetch(ExprState *state, ExprEvalStep *op) +ExecEvalSubscriptingRefFetch(ExprState *state, ExprEvalStep *op) { - ArrayRefState *arefstate = op->d.arrayref.state; + SubscriptingRefState *sbsrefstate = op->d.sbsref.state; - /* Should not get here if source array (or any subscript) is null */ + /* Should not get here if source container (or any subscript) is null */ Assert(!(*op->resnull)); - if (arefstate->numlower == 0) + if (sbsrefstate->numlower == 0) { /* Scalar case */ *op->resvalue = array_get_element(*op->resvalue, - arefstate->numupper, - arefstate->upperindex, - arefstate->refattrlength, - arefstate->refelemlength, - arefstate->refelembyval, - arefstate->refelemalign, + sbsrefstate->numupper, + sbsrefstate->upperindex, + sbsrefstate->refattrlength, + sbsrefstate->refelemlength, + sbsrefstate->refelembyval, + sbsrefstate->refelemalign, op->resnull); } else { /* Slice case */ *op->resvalue = array_get_slice(*op->resvalue, - arefstate->numupper, - arefstate->upperindex, - arefstate->lowerindex, - arefstate->upperprovided, - arefstate->lowerprovided, - arefstate->refattrlength, - arefstate->refelemlength, - arefstate->refelembyval, - arefstate->refelemalign); + sbsrefstate->numupper, + sbsrefstate->upperindex, + sbsrefstate->lowerindex, + sbsrefstate->upperprovided, + sbsrefstate->lowerprovided, + sbsrefstate->refattrlength, + sbsrefstate->refelemlength, + sbsrefstate->refelembyval, + sbsrefstate->refelemalign); } } /* - * Compute old array element/slice value for an ArrayRef assignment - * expression. Will only be generated if the new-value subexpression - * contains ArrayRef or FieldStore. The value is stored into the - * ArrayRefState's prevvalue/prevnull fields. + * 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 -ExecEvalArrayRefOld(ExprState *state, ExprEvalStep *op) +ExecEvalSubscriptingRefOld(ExprState *state, ExprEvalStep *op) { - ArrayRefState *arefstate = op->d.arrayref.state; + SubscriptingRefState *sbsrefstate = op->d.sbsref.state; if (*op->resnull) { /* whole array is null, so any element or slice is too */ - arefstate->prevvalue = (Datum) 0; - arefstate->prevnull = true; + sbsrefstate->prevvalue = (Datum) 0; + sbsrefstate->prevnull = true; } - else if (arefstate->numlower == 0) + else if (sbsrefstate->numlower == 0) { /* Scalar case */ - arefstate->prevvalue = array_get_element(*op->resvalue, - arefstate->numupper, - arefstate->upperindex, - arefstate->refattrlength, - arefstate->refelemlength, - arefstate->refelembyval, - arefstate->refelemalign, - &arefstate->prevnull); + 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 */ - arefstate->prevvalue = array_get_slice(*op->resvalue, - arefstate->numupper, - arefstate->upperindex, - arefstate->lowerindex, - arefstate->upperprovided, - arefstate->lowerprovided, - arefstate->refattrlength, - arefstate->refelemlength, - arefstate->refelembyval, - arefstate->refelemalign); - arefstate->prevnull = false; + 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 ArrayRef assignment. + * Evaluate SubscriptingRef assignment. * - * Input array (possibly null) is in result area, replacement value is in - * ArrayRefState's replacevalue/replacenull. + * Input container (possibly null) is in result area, replacement value is in + * SubscriptingRefState's replacevalue/replacenull. */ void -ExecEvalArrayRefAssign(ExprState *state, ExprEvalStep *op) +ExecEvalSubscriptingRefAssign(ExprState *state, ExprEvalStep *op) { - ArrayRefState *arefstate = op->d.arrayref.state; + SubscriptingRefState *sbsrefstate = op->d.sbsref_subscript.state; /* - * For an assignment to a fixed-length array type, both the original array - * and the value to be assigned into it must be non-NULL, else we punt and - * return the original array. + * 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 (arefstate->refattrlength > 0) /* fixed-length array? */ + if (sbsrefstate->refattrlength > 0) { - if (*op->resnull || arefstate->replacenull) + if (*op->resnull || sbsrefstate->replacenull) return; } @@ -3202,38 +3202,38 @@ ExecEvalArrayRefAssign(ExprState *state, ExprEvalStep *op) */ if (*op->resnull) { - *op->resvalue = PointerGetDatum(construct_empty_array(arefstate->refelemtype)); + *op->resvalue = PointerGetDatum(construct_empty_array(sbsrefstate->refelemtype)); *op->resnull = false; } - if (arefstate->numlower == 0) + if (sbsrefstate->numlower == 0) { /* Scalar case */ *op->resvalue = array_set_element(*op->resvalue, - arefstate->numupper, - arefstate->upperindex, - arefstate->replacevalue, - arefstate->replacenull, - arefstate->refattrlength, - arefstate->refelemlength, - arefstate->refelembyval, - arefstate->refelemalign); + 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, - arefstate->numupper, - arefstate->upperindex, - arefstate->lowerindex, - arefstate->upperprovided, - arefstate->lowerprovided, - arefstate->replacevalue, - arefstate->replacenull, - arefstate->refattrlength, - arefstate->refelemlength, - arefstate->refelembyval, - arefstate->refelemalign); + sbsrefstate->numupper, + sbsrefstate->upperindex, + sbsrefstate->lowerindex, + sbsrefstate->upperprovided, + sbsrefstate->lowerprovided, + sbsrefstate->replacevalue, + sbsrefstate->replacenull, + sbsrefstate->refattrlength, + sbsrefstate->refelemlength, + sbsrefstate->refelembyval, + sbsrefstate->refelemalign); } } diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c index c4d38a64a4..82c4afb701 100644 --- a/src/backend/jit/llvm/llvmjit.c +++ b/src/backend/jit/llvm/llvmjit.c @@ -85,7 +85,7 @@ LLVMValueRef FuncVarsizeAny; LLVMValueRef FuncSlotGetsomeattrsInt; LLVMValueRef FuncSlotGetmissingattrs; LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal; -LLVMValueRef FuncExecEvalArrayRefSubscript; +LLVMValueRef FuncExecEvalSubscriptingRef; LLVMValueRef FuncExecEvalSysVar; LLVMValueRef FuncExecAggTransReparent; LLVMValueRef FuncExecAggInitGroup; @@ -829,7 +829,7 @@ llvm_create_types(void) FuncSlotGetsomeattrsInt = LLVMGetNamedFunction(mod, "slot_getsomeattrs_int"); FuncSlotGetmissingattrs = LLVMGetNamedFunction(mod, "slot_getmissingattrs"); FuncMakeExpandedObjectReadOnlyInternal = LLVMGetNamedFunction(mod, "MakeExpandedObjectReadOnlyInternal"); - FuncExecEvalArrayRefSubscript = LLVMGetNamedFunction(mod, "ExecEvalArrayRefSubscript"); + FuncExecEvalSubscriptingRef = LLVMGetNamedFunction(mod, "ExecEvalSubscriptingRef"); FuncExecEvalSysVar = LLVMGetNamedFunction(mod, "ExecEvalSysVar"); FuncExecAggTransReparent = LLVMGetNamedFunction(mod, "ExecAggTransReparent"); FuncExecAggInitGroup = LLVMGetNamedFunction(mod, "ExecAggInitGroup"); diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c index df7e620da7..1bb58e3e61 100644 --- a/src/backend/jit/llvm/llvmjit_expr.c +++ b/src/backend/jit/llvm/llvmjit_expr.c @@ -1144,20 +1144,20 @@ llvm_compile_expr(ExprState *state) break; } - case EEOP_ARRAYREF_OLD: - build_EvalXFunc(b, mod, "ExecEvalArrayRefOld", + case EEOP_SBSREF_OLD: + build_EvalXFunc(b, mod, "ExecEvalSubscriptingRefOld", v_state, v_econtext, op); LLVMBuildBr(b, opblocks[i + 1]); break; - case EEOP_ARRAYREF_ASSIGN: - build_EvalXFunc(b, mod, "ExecEvalArrayRefAssign", + case EEOP_SBSREF_ASSIGN: + build_EvalXFunc(b, mod, "ExecEvalSubscriptingRefAssign", v_state, v_econtext, op); LLVMBuildBr(b, opblocks[i + 1]); break; - case EEOP_ARRAYREF_FETCH: - build_EvalXFunc(b, mod, "ExecEvalArrayRefFetch", + case EEOP_SBSREF_FETCH: + build_EvalXFunc(b, mod, "ExecEvalSubscriptingRefFetch", v_state, v_econtext, op); LLVMBuildBr(b, opblocks[i + 1]); break; @@ -1775,14 +1775,14 @@ llvm_compile_expr(ExprState *state) LLVMBuildBr(b, opblocks[i + 1]); break; - case EEOP_ARRAYREF_SUBSCRIPT: + case EEOP_SBSREF_SUBSCRIPT: { LLVMValueRef v_fn; - int jumpdone = op->d.arrayref_subscript.jumpdone; + int jumpdone = op->d.sbsref_subscript.jumpdone; LLVMValueRef v_params[2]; LLVMValueRef v_ret; - v_fn = llvm_get_decl(mod, FuncExecEvalArrayRefSubscript); + v_fn = llvm_get_decl(mod, FuncExecEvalSubscriptingRef); v_params[0] = v_state; v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep)); diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c index c814bc7b3e..9522b972c1 100644 --- a/src/backend/jit/llvm/llvmjit_types.c +++ b/src/backend/jit/llvm/llvmjit_types.c @@ -103,7 +103,7 @@ void *referenced_functions[] = slot_getsomeattrs_int, slot_getmissingattrs, MakeExpandedObjectReadOnlyInternal, - ExecEvalArrayRefSubscript, + ExecEvalSubscriptingRef, ExecEvalSysVar, ExecAggTransReparent, ExecAggInitGroup diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 807393dfaa..b44ead269f 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -1486,14 +1486,14 @@ _copyWindowFunc(const WindowFunc *from) } /* - * _copyArrayRef + * _copySubscriptingRef */ -static ArrayRef * -_copyArrayRef(const ArrayRef *from) +static SubscriptingRef * +_copySubscriptingRef(const SubscriptingRef *from) { - ArrayRef *newnode = makeNode(ArrayRef); + SubscriptingRef *newnode = makeNode(SubscriptingRef); - COPY_SCALAR_FIELD(refarraytype); + COPY_SCALAR_FIELD(refcontainertype); COPY_SCALAR_FIELD(refelemtype); COPY_SCALAR_FIELD(reftypmod); COPY_SCALAR_FIELD(refcollid); @@ -4963,8 +4963,8 @@ copyObjectImpl(const void *from) case T_WindowFunc: retval = _copyWindowFunc(from); break; - case T_ArrayRef: - retval = _copyArrayRef(from); + case T_SubscriptingRef: + retval = _copySubscriptingRef(from); break; case T_FuncExpr: retval = _copyFuncExpr(from); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index a397de155e..1e169e0b9c 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -265,9 +265,9 @@ _equalWindowFunc(const WindowFunc *a, const WindowFunc *b) } static bool -_equalArrayRef(const ArrayRef *a, const ArrayRef *b) +_equalSubscriptingRef(const SubscriptingRef *a, const SubscriptingRef *b) { - COMPARE_SCALAR_FIELD(refarraytype); + COMPARE_SCALAR_FIELD(refcontainertype); COMPARE_SCALAR_FIELD(refelemtype); COMPARE_SCALAR_FIELD(reftypmod); COMPARE_SCALAR_FIELD(refcollid); @@ -3041,8 +3041,8 @@ equal(const void *a, const void *b) case T_WindowFunc: retval = _equalWindowFunc(a, b); break; - case T_ArrayRef: - retval = _equalArrayRef(a, b); + case T_SubscriptingRef: + retval = _equalSubscriptingRef(a, b); break; case T_FuncExpr: retval = _equalFuncExpr(a, b); diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index 1275c7168f..2385d02602 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -66,15 +66,15 @@ exprType(const Node *expr) case T_WindowFunc: type = ((const WindowFunc *) expr)->wintype; break; - case T_ArrayRef: + case T_SubscriptingRef: { - const ArrayRef *arrayref = (const ArrayRef *) expr; + const SubscriptingRef *sbsref = (const SubscriptingRef *) expr; - /* slice and/or store operations yield the array type */ - if (arrayref->reflowerindexpr || arrayref->refassgnexpr) - type = arrayref->refarraytype; + /* slice and/or store operations yield the container type */ + if (sbsref->reflowerindexpr || sbsref->refassgnexpr) + type = sbsref->refcontainertype; else - type = arrayref->refelemtype; + type = sbsref->refelemtype; } break; case T_FuncExpr: @@ -286,9 +286,9 @@ exprTypmod(const Node *expr) return ((const Const *) expr)->consttypmod; case T_Param: return ((const Param *) expr)->paramtypmod; - case T_ArrayRef: - /* typmod is the same for array or element */ - return ((const ArrayRef *) expr)->reftypmod; + case T_SubscriptingRef: + /* typmod is the same for container or element */ + return ((const SubscriptingRef *) expr)->reftypmod; case T_FuncExpr: { int32 coercedTypmod; @@ -744,8 +744,8 @@ exprCollation(const Node *expr) case T_WindowFunc: coll = ((const WindowFunc *) expr)->wincollid; break; - case T_ArrayRef: - coll = ((const ArrayRef *) expr)->refcollid; + case T_SubscriptingRef: + coll = ((const SubscriptingRef *) expr)->refcollid; break; case T_FuncExpr: coll = ((const FuncExpr *) expr)->funccollid; @@ -992,8 +992,8 @@ exprSetCollation(Node *expr, Oid collation) case T_WindowFunc: ((WindowFunc *) expr)->wincollid = collation; break; - case T_ArrayRef: - ((ArrayRef *) expr)->refcollid = collation; + case T_SubscriptingRef: + ((SubscriptingRef *) expr)->refcollid = collation; break; case T_FuncExpr: ((FuncExpr *) expr)->funccollid = collation; @@ -1223,9 +1223,9 @@ exprLocation(const Node *expr) /* function name should always be the first thing */ loc = ((const WindowFunc *) expr)->location; break; - case T_ArrayRef: - /* just use array argument's location */ - loc = exprLocation((Node *) ((const ArrayRef *) expr)->refexpr); + case T_SubscriptingRef: + /* just use container argument's location */ + loc = exprLocation((Node *) ((const SubscriptingRef *) expr)->refexpr); break; case T_FuncExpr: { @@ -1916,21 +1916,22 @@ expression_tree_walker(Node *node, return true; } break; - case T_ArrayRef: + case T_SubscriptingRef: { - ArrayRef *aref = (ArrayRef *) node; + SubscriptingRef *sbsref = (SubscriptingRef *) node; - /* recurse directly for upper/lower array index lists */ - if (expression_tree_walker((Node *) aref->refupperindexpr, + /* recurse directly for upper/lower container index lists */ + if (expression_tree_walker((Node *) sbsref->refupperindexpr, walker, context)) return true; - if (expression_tree_walker((Node *) aref->reflowerindexpr, + if (expression_tree_walker((Node *) sbsref->reflowerindexpr, walker, context)) return true; /* walker must see the refexpr and refassgnexpr, however */ - if (walker(aref->refexpr, context)) + if (walker(sbsref->refexpr, context)) return true; - if (walker(aref->refassgnexpr, context)) + + if (walker(sbsref->refassgnexpr, context)) return true; } break; @@ -2554,20 +2555,21 @@ expression_tree_mutator(Node *node, return (Node *) newnode; } break; - case T_ArrayRef: + case T_SubscriptingRef: { - ArrayRef *arrayref = (ArrayRef *) node; - ArrayRef *newnode; + SubscriptingRef *sbsref = (SubscriptingRef *) node; + SubscriptingRef *newnode; - FLATCOPY(newnode, arrayref, ArrayRef); - MUTATE(newnode->refupperindexpr, arrayref->refupperindexpr, + FLATCOPY(newnode, sbsref, SubscriptingRef); + MUTATE(newnode->refupperindexpr, sbsref->refupperindexpr, List *); - MUTATE(newnode->reflowerindexpr, arrayref->reflowerindexpr, + MUTATE(newnode->reflowerindexpr, sbsref->reflowerindexpr, List *); - MUTATE(newnode->refexpr, arrayref->refexpr, + MUTATE(newnode->refexpr, sbsref->refexpr, Expr *); - MUTATE(newnode->refassgnexpr, arrayref->refassgnexpr, + MUTATE(newnode->refassgnexpr, sbsref->refassgnexpr, Expr *); + return (Node *) newnode; } break; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 9d44e3e4c6..f97cf37f1f 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -1153,11 +1153,11 @@ _outWindowFunc(StringInfo str, const WindowFunc *node) } static void -_outArrayRef(StringInfo str, const ArrayRef *node) +_outSubscriptingRef(StringInfo str, const SubscriptingRef *node) { - WRITE_NODE_TYPE("ARRAYREF"); + WRITE_NODE_TYPE("SUBSCRIPTINGREF"); - WRITE_OID_FIELD(refarraytype); + WRITE_OID_FIELD(refcontainertype); WRITE_OID_FIELD(refelemtype); WRITE_INT_FIELD(reftypmod); WRITE_OID_FIELD(refcollid); @@ -3789,8 +3789,8 @@ outNode(StringInfo str, const void *obj) case T_WindowFunc: _outWindowFunc(str, obj); break; - case T_ArrayRef: - _outArrayRef(str, obj); + case T_SubscriptingRef: + _outSubscriptingRef(str, obj); break; case T_FuncExpr: _outFuncExpr(str, obj); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 43491e297b..3b002778ad 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -657,14 +657,14 @@ _readWindowFunc(void) } /* - * _readArrayRef + * _readSubscriptingRef */ -static ArrayRef * -_readArrayRef(void) +static SubscriptingRef * +_readSubscriptingRef(void) { - READ_LOCALS(ArrayRef); + READ_LOCALS(SubscriptingRef); - READ_OID_FIELD(refarraytype); + READ_OID_FIELD(refcontainertype); READ_OID_FIELD(refelemtype); READ_INT_FIELD(reftypmod); READ_OID_FIELD(refcollid); @@ -2597,8 +2597,8 @@ parseNodeString(void) return_value = _readGroupingFunc(); else if (MATCH("WINDOWFUNC", 10)) return_value = _readWindowFunc(); - else if (MATCH("ARRAYREF", 8)) - return_value = _readArrayRef(); + else if (MATCH("SUBSCRIPTINGREF", 15)) + return_value = _readSubscriptingRef(); else if (MATCH("FUNCEXPR", 8)) return_value = _readFuncExpr(); else if (MATCH("NAMEDARGEXPR", 12)) diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 86c346bc38..663fa7cd33 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -1120,11 +1120,15 @@ contain_nonstrict_functions_walker(Node *node, void *context) /* a window function could return non-null with null input */ return true; } - if (IsA(node, ArrayRef)) + if (IsA(node, SubscriptingRef)) { - /* array assignment is nonstrict, but subscripting is strict */ - if (((ArrayRef *) node)->refassgnexpr != NULL) + /* + * subscripting assignment is nonstrict, but subscripting itself is + * strict + */ + if (((SubscriptingRef *) node)->refassgnexpr != NULL) return true; + /* else fall through to check args */ } if (IsA(node, DistinctExpr)) @@ -1328,7 +1332,6 @@ contain_leaked_vars_walker(Node *node, void *context) case T_Var: case T_Const: case T_Param: - case T_ArrayRef: case T_ArrayExpr: case T_FieldSelect: case T_FieldStore: @@ -1358,6 +1361,7 @@ contain_leaked_vars_walker(Node *node, void *context) case T_ScalarArrayOpExpr: case T_CoerceViaIO: case T_ArrayCoerceExpr: + case T_SubscriptingRef: /* * If node contains a leaky function call, and there's any Var @@ -3181,7 +3185,7 @@ eval_const_expressions_mutator(Node *node, else return copyObject(node); } - case T_ArrayRef: + case T_SubscriptingRef: case T_ArrayExpr: case T_RowExpr: case T_MinMaxExpr: diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 125ee5d84b..7f5773582b 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -976,13 +976,14 @@ transformInsertRow(ParseState *pstate, List *exprlist, expr = (Expr *) linitial(fstore->newvals); } - else if (IsA(expr, ArrayRef)) + else if (IsA(expr, SubscriptingRef)) { - ArrayRef *aref = (ArrayRef *) expr; + SubscriptingRef *sbsref = (SubscriptingRef *) expr; - if (aref->refassgnexpr == NULL) + if (sbsref->refassgnexpr == NULL) break; - expr = aref->refassgnexpr; + + expr = sbsref->refassgnexpr; } else break; diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 7fc8d63ff0..e559353529 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -465,13 +465,13 @@ transformIndirection(ParseState *pstate, A_Indirection *ind) /* process subscripts before this field selection */ if (subscripts) - result = (Node *) transformArraySubscripts(pstate, - result, - exprType(result), - InvalidOid, - exprTypmod(result), - subscripts, - NULL); + result = (Node *) transformContainerSubscripts(pstate, + result, + exprType(result), + InvalidOid, + exprTypmod(result), + subscripts, + NULL); subscripts = NIL; newresult = ParseFuncOrColumn(pstate, @@ -488,13 +488,13 @@ transformIndirection(ParseState *pstate, A_Indirection *ind) } /* process trailing subscripts, if any */ if (subscripts) - result = (Node *) transformArraySubscripts(pstate, - result, - exprType(result), - InvalidOid, - exprTypmod(result), - subscripts, - NULL); + result = (Node *) transformContainerSubscripts(pstate, + result, + exprType(result), + InvalidOid, + exprTypmod(result), + subscripts, + NULL); return result; } diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index ece81697e6..3a7a858e3a 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -203,121 +203,126 @@ make_var(ParseState *pstate, RangeTblEntry *rte, int attrno, int location) } /* - * transformArrayType() - * Identify the types involved in a subscripting operation + * transformContainerType() + * Identify the types involved in a subscripting operation for container * - * On entry, arrayType/arrayTypmod identify the type of the input value - * to be subscripted (which could be a domain type). These are modified - * if necessary to identify the actual array type and typmod, and the - * array's element type is returned. An error is thrown if the input isn't + * + * On entry, containerType/containerTypmod identify the type of the input value + * to be subscripted (which could be a domain type). These are modified if + * necessary to identify the actual container type and typmod, and the + * container's element type is returned. An error is thrown if the input isn't * an array type. */ Oid -transformArrayType(Oid *arrayType, int32 *arrayTypmod) +transformContainerType(Oid *containerType, int32 *containerTypmod) { - Oid origArrayType = *arrayType; + Oid origContainerType = *containerType; Oid elementType; - HeapTuple type_tuple_array; - Form_pg_type type_struct_array; + HeapTuple type_tuple_container; + Form_pg_type type_struct_container; /* * If the input is a domain, smash to base type, and extract the actual - * typmod to be applied to the base type. Subscripting a domain is an - * operation that necessarily works on the base array type, not the domain - * itself. (Note that we provide no method whereby the creator of a - * domain over an array type could hide its ability to be subscripted.) + * typmod to be applied to the base type. Subscripting a domain is an + * operation that necessarily works on the base container type, not the + * domain itself. (Note that we provide no method whereby the creator of a + * domain over a container type could hide its ability to be subscripted.) */ - *arrayType = getBaseTypeAndTypmod(*arrayType, arrayTypmod); + *containerType = getBaseTypeAndTypmod(*containerType, containerTypmod); /* - * We treat int2vector and oidvector as though they were domains over - * int2[] and oid[]. This is needed because array slicing could create an - * array that doesn't satisfy the dimensionality constraints of the - * xxxvector type; so we want the result of a slice operation to be - * considered to be of the more general type. + * Here is an array specific code. We treat int2vector and oidvector as + * though they were domains over int2[] and oid[]. This is needed because + * array slicing could create an array that doesn't satisfy the + * dimensionality constraints of the xxxvector type; so we want the result + * of a slice operation to be considered to be of the more general type. */ - if (*arrayType == INT2VECTOROID) - *arrayType = INT2ARRAYOID; - else if (*arrayType == OIDVECTOROID) - *arrayType = OIDARRAYOID; + if (*containerType == INT2VECTOROID) + *containerType = INT2ARRAYOID; + else if (*containerType == OIDVECTOROID) + *containerType = OIDARRAYOID; - /* Get the type tuple for the array */ - type_tuple_array = SearchSysCache1(TYPEOID, ObjectIdGetDatum(*arrayType)); - if (!HeapTupleIsValid(type_tuple_array)) - elog(ERROR, "cache lookup failed for type %u", *arrayType); - type_struct_array = (Form_pg_type) GETSTRUCT(type_tuple_array); + /* Get the type tuple for the container */ + type_tuple_container = SearchSysCache1(TYPEOID, ObjectIdGetDatum(*containerType)); + if (!HeapTupleIsValid(type_tuple_container)) + elog(ERROR, "cache lookup failed for type %u", *containerType); + type_struct_container = (Form_pg_type) GETSTRUCT(type_tuple_container); /* needn't check typisdefined since this will fail anyway */ - elementType = type_struct_array->typelem; + elementType = type_struct_container->typelem; if (elementType == InvalidOid) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("cannot subscript type %s because it is not an array", - format_type_be(origArrayType)))); + format_type_be(origContainerType)))); - ReleaseSysCache(type_tuple_array); + ReleaseSysCache(type_tuple_container); return elementType; } /* - * transformArraySubscripts() - * Transform array subscripting. This is used for both - * array fetch and array assignment. + * transformContainerSubscripts() + * Transform container (array, etc) subscripting. This is used for both + * container fetch and container assignment. * - * In an array fetch, we are given a source array value and we produce an - * expression that represents the result of extracting a single array element - * or an array slice. + * In a container fetch, we are given a source container value and we produce + * an expression that represents the result of extracting a single container + * element or a container slice. * - * In an array assignment, we are given a destination array value plus a - * source value that is to be assigned to a single element or a slice of - * that array. We produce an expression that represents the new array value - * with the source data inserted into the right part of the array. + * In a container assignment, we are given a destination container value plus a + * source value that is to be assigned to a single element or a slice of that + * container. We produce an expression that represents the new container value + * with the source data inserted into the right part of the container. * - * For both cases, if the source array is of a domain-over-array type, + * For both cases, if the source container is of a domain-over-array type, * the result is of the base array type or its element type; essentially, * we must fold a domain to its base type before applying subscripting. * (Note that int2vector and oidvector are treated as domains here.) * - * pstate Parse state - * arrayBase Already-transformed expression for the array as a whole - * arrayType OID of array's datatype (should match type of arrayBase, - * or be the base type of arrayBase's domain type) - * elementType OID of array's element type (fetch with transformArrayType, - * or pass InvalidOid to do it here) - * arrayTypMod typmod for the array (which is also typmod for the elements) - * indirection Untransformed list of subscripts (must not be NIL) - * assignFrom NULL for array fetch, else transformed expression for source. + * pstate Parse state + * containerBase Already-transformed expression for the container as a whole + * containerType OID of container's datatype (should match type of + * containerBase, or be the base type of containerBase's + * domain type) + * elementType OID of container's element type (fetch with + * transformContainerType, or pass InvalidOid to do it here) + * containerTypMod typmod for the container (which is also typmod for the + * elements) + * indirection Untransformed list of subscripts (must not be NIL) + * assignFrom NULL for container fetch, else transformed expression for + * source. */ -ArrayRef * -transformArraySubscripts(ParseState *pstate, - Node *arrayBase, - Oid arrayType, - Oid elementType, - int32 arrayTypMod, - List *indirection, - Node *assignFrom) +SubscriptingRef * +transformContainerSubscripts(ParseState *pstate, + Node *containerBase, + Oid containerType, + Oid elementType, + int32 containerTypMod, + List *indirection, + Node *assignFrom) { bool isSlice = false; List *upperIndexpr = NIL; List *lowerIndexpr = NIL; + List *indexprSlice = NIL; ListCell *idx; - ArrayRef *aref; + SubscriptingRef *sbsref; /* * Caller may or may not have bothered to determine elementType. Note - * that if the caller did do so, arrayType/arrayTypMod must be as modified - * by transformArrayType, ie, smash domain to base type. + * that if the caller did do so, containerType/containerTypMod must be as + * modified by transformContainerType, ie, smash domain to base type. */ if (!OidIsValid(elementType)) - elementType = transformArrayType(&arrayType, &arrayTypMod); + elementType = transformContainerType(&containerType, &containerTypMod); /* - * A list containing only simple subscripts refers to a single array + * A list containing only simple subscripts refers to a single container * element. If any of the items are slice specifiers (lower:upper), then - * the subscript expression means an array slice operation. In this case, - * we convert any non-slice items to slices by treating the single + * the subscript expression means a container slice operation. In this + * case, we convert any non-slice items to slices by treating the single * subscript as the upper bound and supplying an assumed lower bound of 1. * We have to prescan the list to see if there are any slice items. */ @@ -411,12 +416,12 @@ transformArraySubscripts(ParseState *pstate, if (assignFrom != NULL) { Oid typesource = exprType(assignFrom); - Oid typeneeded = isSlice ? arrayType : elementType; + Oid typeneeded = isSlice ? containerType : elementType; Node *newFrom; newFrom = coerce_to_target_type(pstate, assignFrom, typesource, - typeneeded, arrayTypMod, + typeneeded, containerTypMod, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1); @@ -433,19 +438,23 @@ transformArraySubscripts(ParseState *pstate, } /* - * Ready to build the ArrayRef node. + * Ready to build the SubscriptingRef node. */ - aref = makeNode(ArrayRef); - aref->refarraytype = arrayType; - aref->refelemtype = elementType; - aref->reftypmod = arrayTypMod; - /* refcollid will be set by parse_collate.c */ - aref->refupperindexpr = upperIndexpr; - aref->reflowerindexpr = lowerIndexpr; - aref->refexpr = (Expr *) arrayBase; - aref->refassgnexpr = (Expr *) assignFrom; + sbsref = (SubscriptingRef *) makeNode(SubscriptingRef); + if (assignFrom != NULL) + sbsref->refassgnexpr = (Expr *) assignFrom; - return aref; + sbsref->refcontainertype = containerType; + sbsref->refelemtype = elementType; + sbsref->reftypmod = containerTypMod; + /* refcollid will be set by parse_collate.c */ + sbsref->refupperindexpr = upperIndexpr; + sbsref->reflowerindexpr = lowerIndexpr; + sbsref->refindexprslice = indexprSlice; + sbsref->refexpr = (Expr *) containerBase; + sbsref->refassgnexpr = (Expr *) assignFrom; + + return sbsref; } /* diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 561d8774f4..0e9598ebfe 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -655,7 +655,7 @@ updateTargetListEntry(ParseState *pstate, * needed. * * targetName is the name of the field or subfield we're assigning to, and - * targetIsArray is true if we're subscripting it. These are just for + * targetIsSubscripting is true if we're subscripting it. These are just for * error reporting. * * targetTypeId, targetTypMod, targetCollation indicate the datatype and @@ -677,7 +677,7 @@ static Node * transformAssignmentIndirection(ParseState *pstate, Node *basenode, const char *targetName, - bool targetIsArray, + bool targetIsSubscripting, Oid targetTypeId, int32 targetTypMod, Oid targetCollation, @@ -855,7 +855,7 @@ transformAssignmentIndirection(ParseState *pstate, -1); if (result == NULL) { - if (targetIsArray) + if (targetIsSubscripting) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("array assignment to \"%s\" requires type %s" @@ -881,7 +881,7 @@ transformAssignmentIndirection(ParseState *pstate, } /* - * helper for transformAssignmentIndirection: process array assignment + * helper for transformAssignmentIndirection: process container assignment */ static Node * transformAssignmentSubscripts(ParseState *pstate, @@ -897,8 +897,8 @@ transformAssignmentSubscripts(ParseState *pstate, int location) { Node *result; - Oid arrayType; - int32 arrayTypMod; + Oid containerType; + int32 containerTypMod; Oid elementTypeId; Oid typeNeeded; Oid collationNeeded; @@ -906,46 +906,46 @@ transformAssignmentSubscripts(ParseState *pstate, Assert(subscripts != NIL); /* Identify the actual array type and element type involved */ - arrayType = targetTypeId; - arrayTypMod = targetTypMod; - elementTypeId = transformArrayType(&arrayType, &arrayTypMod); + containerType = targetTypeId; + containerTypMod = targetTypMod; + elementTypeId = transformContainerType(&containerType, &containerTypMod); /* Identify type that RHS must provide */ - typeNeeded = isSlice ? arrayType : elementTypeId; + typeNeeded = isSlice ? containerType : elementTypeId; /* - * Array normally has same collation as elements, but there's an - * exception: we might be subscripting a domain over an array type. In + * container normally has same collation as elements, but there's an + * exception: we might be subscripting a domain over a container type. In * that case use collation of the base type. */ - if (arrayType == targetTypeId) + if (containerType == targetTypeId) collationNeeded = targetCollation; else - collationNeeded = get_typcollation(arrayType); + collationNeeded = get_typcollation(containerType); - /* recurse to create appropriate RHS for array assign */ + /* recurse to create appropriate RHS for container assign */ rhs = transformAssignmentIndirection(pstate, NULL, targetName, true, typeNeeded, - arrayTypMod, + containerTypMod, collationNeeded, next_indirection, rhs, location); /* process subscripts */ - result = (Node *) transformArraySubscripts(pstate, - basenode, - arrayType, - elementTypeId, - arrayTypMod, - subscripts, - rhs); + result = (Node *) transformContainerSubscripts(pstate, + basenode, + containerType, + elementTypeId, + containerTypMod, + subscripts, + rhs); - /* If target was a domain over array, need to coerce up to the domain */ - if (arrayType != targetTypeId) + /* If target was a domain over container, need to coerce up to the domain */ + if (containerType != targetTypeId) { Oid resulttype = exprType(result); diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 1eca69873b..0338e4e1ad 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -951,7 +951,7 @@ process_matched_tle(TargetEntry *src_tle, /*---------- * Multiple assignments to same attribute. Allow only if all are - * FieldStore or ArrayRef assignment operations. This is a bit + * FieldStore or SubscriptingRef assignment operations. This is a bit * tricky because what we may actually be looking at is a nest of * such nodes; consider * UPDATE tab SET col.fld1.subfld1 = x, col.fld2.subfld2 = y @@ -959,7 +959,7 @@ process_matched_tle(TargetEntry *src_tle, * FieldStore(col, fld1, FieldStore(placeholder, subfld1, x)) * FieldStore(col, fld2, FieldStore(placeholder, subfld2, y)) * However, we can ignore the substructure and just consider the top - * FieldStore or ArrayRef from each assignment, because it works to + * FieldStore or SubscriptingRef from each assignment, because it works to * combine these as * FieldStore(FieldStore(col, fld1, * FieldStore(placeholder, subfld1, x)), @@ -969,7 +969,7 @@ process_matched_tle(TargetEntry *src_tle, * * For FieldStore, instead of nesting we can generate a single * FieldStore with multiple target fields. We must nest when - * ArrayRefs are involved though. + * SubscriptingRefs are involved though. * * As a further complication, the destination column might be a domain, * resulting in each assignment containing a CoerceToDomain node over a @@ -1048,13 +1048,13 @@ process_matched_tle(TargetEntry *src_tle, } newexpr = (Node *) fstore; } - else if (IsA(src_expr, ArrayRef)) + else if (IsA(src_expr, SubscriptingRef)) { - ArrayRef *aref = makeNode(ArrayRef); + SubscriptingRef *sbsref = makeNode(SubscriptingRef); - memcpy(aref, src_expr, sizeof(ArrayRef)); - aref->refexpr = (Expr *) prior_expr; - newexpr = (Node *) aref; + memcpy(sbsref, src_expr, sizeof(SubscriptingRef)); + sbsref->refexpr = (Expr *) prior_expr; + newexpr = (Node *) sbsref; } else { @@ -1091,14 +1091,16 @@ get_assignment_input(Node *node) return (Node *) fstore->arg; } - else if (IsA(node, ArrayRef)) + else if (IsA(node, SubscriptingRef)) { - ArrayRef *aref = (ArrayRef *) node; + SubscriptingRef *sbsref = (SubscriptingRef *) node; - if (aref->refassgnexpr == NULL) + if (sbsref->refassgnexpr == NULL) return NULL; - return (Node *) aref->refexpr; + + return (Node *) sbsref->refexpr; } + return NULL; } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 51e4c275ab..17a28c2651 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -456,7 +456,7 @@ static void get_tablesample_def(TableSampleClause *tablesample, static void get_opclass_name(Oid opclass, Oid actual_datatype, StringInfo buf); static Node *processIndirection(Node *node, deparse_context *context); -static void printSubscripts(ArrayRef *aref, deparse_context *context); +static void printSubscripts(SubscriptingRef *sbsref, deparse_context *context); static char *get_relation_name(Oid relid); static char *generate_relation_name(Oid relid, List *namespaces); static char *generate_qualified_relation_name(Oid relid); @@ -6400,12 +6400,12 @@ get_update_query_targetlist_def(Query *query, List *targetList, { /* * We must dig down into the expr to see if it's a PARAM_MULTIEXPR - * Param. That could be buried under FieldStores and ArrayRefs - * and CoerceToDomains (cf processIndirection()), and underneath - * those there could be an implicit type coercion. Because we - * would ignore implicit type coercions anyway, we don't need to - * be as careful as processIndirection() is about descending past - * implicit CoerceToDomains. + * Param. That could be buried under FieldStores and + * SubscriptingRefs and CoerceToDomains (cf processIndirection()), + * and underneath those there could be an implicit type coercion. + * Because we would ignore implicit type coercions anyway, we + * don't need to be as careful as processIndirection() is about + * descending past implicit CoerceToDomains. */ expr = (Node *) tle->expr; while (expr) @@ -6416,13 +6416,14 @@ get_update_query_targetlist_def(Query *query, List *targetList, expr = (Node *) linitial(fstore->newvals); } - else if (IsA(expr, ArrayRef)) + else if (IsA(expr, SubscriptingRef)) { - ArrayRef *aref = (ArrayRef *) expr; + SubscriptingRef *sbsref = (SubscriptingRef *) expr; - if (aref->refassgnexpr == NULL) + if (sbsref->refassgnexpr == NULL) break; - expr = (Node *) aref->refassgnexpr; + + expr = (Node *) sbsref->refassgnexpr; } else if (IsA(expr, CoerceToDomain)) { @@ -7456,7 +7457,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags) /* single words: always simple */ return true; - case T_ArrayRef: + case T_SubscriptingRef: case T_ArrayExpr: case T_RowExpr: case T_CoalesceExpr: @@ -7574,7 +7575,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags) return true; /* own parentheses */ } case T_BoolExpr: /* lower precedence */ - case T_ArrayRef: /* other separators */ + case T_SubscriptingRef: /* other separators */ case T_ArrayExpr: /* other separators */ case T_RowExpr: /* other separators */ case T_CoalesceExpr: /* own parentheses */ @@ -7624,7 +7625,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags) return false; return true; /* own parentheses */ } - case T_ArrayRef: /* other separators */ + case T_SubscriptingRef: /* other separators */ case T_ArrayExpr: /* other separators */ case T_RowExpr: /* other separators */ case T_CoalesceExpr: /* own parentheses */ @@ -7810,9 +7811,9 @@ get_rule_expr(Node *node, deparse_context *context, get_windowfunc_expr((WindowFunc *) node, context); break; - case T_ArrayRef: + case T_SubscriptingRef: { - ArrayRef *aref = (ArrayRef *) node; + SubscriptingRef *sbsref = (SubscriptingRef *) node; bool need_parens; /* @@ -7823,37 +7824,38 @@ get_rule_expr(Node *node, deparse_context *context, * here too, and display only the assignment source * expression. */ - if (IsA(aref->refexpr, CaseTestExpr)) + if (IsA(sbsref->refexpr, CaseTestExpr)) { - Assert(aref->refassgnexpr); - get_rule_expr((Node *) aref->refassgnexpr, + Assert(sbsref->refassgnexpr); + get_rule_expr((Node *) sbsref->refassgnexpr, context, showimplicit); break; } /* * Parenthesize the argument unless it's a simple Var or a - * FieldSelect. (In particular, if it's another ArrayRef, we - * *must* parenthesize to avoid confusion.) + * FieldSelect. (In particular, if it's another + * SubscriptingRef, we *must* parenthesize to avoid + * confusion.) */ - need_parens = !IsA(aref->refexpr, Var) && - !IsA(aref->refexpr, FieldSelect); + need_parens = !IsA(sbsref->refexpr, Var) && + !IsA(sbsref->refexpr, FieldSelect); if (need_parens) appendStringInfoChar(buf, '('); - get_rule_expr((Node *) aref->refexpr, context, showimplicit); + get_rule_expr((Node *) sbsref->refexpr, context, showimplicit); if (need_parens) appendStringInfoChar(buf, ')'); /* * If there's a refassgnexpr, we want to print the node in the - * format "array[subscripts] := refassgnexpr". This is not - * legal SQL, so decompilation of INSERT or UPDATE statements - * should always use processIndirection as part of the - * statement-level syntax. We should only see this when + * format "container[subscripts] := refassgnexpr". This is + * not legal SQL, so decompilation of INSERT or UPDATE + * statements should always use processIndirection as part of + * the statement-level syntax. We should only see this when * EXPLAIN tries to print the targetlist of a plan resulting * from such a statement. */ - if (aref->refassgnexpr) + if (sbsref->refassgnexpr) { Node *refassgnexpr; @@ -7869,8 +7871,8 @@ get_rule_expr(Node *node, deparse_context *context, } else { - /* Just an ordinary array fetch, so print subscripts */ - printSubscripts(aref, context); + /* Just an ordinary container fetch, so print subscripts */ + printSubscripts(sbsref, context); } } break; @@ -8068,12 +8070,13 @@ get_rule_expr(Node *node, deparse_context *context, bool need_parens; /* - * Parenthesize the argument unless it's an ArrayRef or + * Parenthesize the argument unless it's an SubscriptingRef or * another FieldSelect. Note in particular that it would be * WRONG to not parenthesize a Var argument; simplicity is not * the issue here, having the right number of names is. */ - need_parens = !IsA(arg, ArrayRef) &&!IsA(arg, FieldSelect); + need_parens = !IsA(arg, SubscriptingRef) && + !IsA(arg, FieldSelect); if (need_parens) appendStringInfoChar(buf, '('); get_rule_expr(arg, context, true); @@ -10437,7 +10440,7 @@ get_opclass_name(Oid opclass, Oid actual_datatype, /* * processIndirection - take care of array and subfield assignment * - * We strip any top-level FieldStore or assignment ArrayRef nodes that + * We strip any top-level FieldStore or assignment SubscriptingRef nodes that * appear in the input, printing them as decoration for the base column * name (which we assume the caller just printed). We might also need to * strip CoerceToDomain nodes, but only ones that appear above assignment @@ -10483,19 +10486,20 @@ processIndirection(Node *node, deparse_context *context) */ node = (Node *) linitial(fstore->newvals); } - else if (IsA(node, ArrayRef)) + else if (IsA(node, SubscriptingRef)) { - ArrayRef *aref = (ArrayRef *) node; + SubscriptingRef *sbsref = (SubscriptingRef *) node; - if (aref->refassgnexpr == NULL) + if (sbsref->refassgnexpr == NULL) break; - printSubscripts(aref, context); + + printSubscripts(sbsref, context); /* * We ignore refexpr since it should be an uninteresting reference * to the target column or subcolumn. */ - node = (Node *) aref->refassgnexpr; + node = (Node *) sbsref->refassgnexpr; } else if (IsA(node, CoerceToDomain)) { @@ -10523,14 +10527,14 @@ processIndirection(Node *node, deparse_context *context) } static void -printSubscripts(ArrayRef *aref, deparse_context *context) +printSubscripts(SubscriptingRef *sbsref, deparse_context *context) { StringInfo buf = context->buf; ListCell *lowlist_item; ListCell *uplist_item; - lowlist_item = list_head(aref->reflowerindexpr); /* could be NULL */ - foreach(uplist_item, aref->refupperindexpr) + lowlist_item = list_head(sbsref->reflowerindexpr); /* could be NULL */ + foreach(uplist_item, sbsref->refupperindexpr) { appendStringInfoChar(buf, '['); if (lowlist_item) diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h index 2c1697dd76..7aacdc5d04 100644 --- a/src/include/executor/execExpr.h +++ b/src/include/executor/execExpr.h @@ -19,7 +19,7 @@ /* forward references to avoid circularity */ struct ExprEvalStep; -struct ArrayRefState; +struct SubscriptingRefState; /* Bits in ExprState->flags (see also execnodes.h for public flag bits): */ /* expression's interpreter has been initialized */ @@ -185,21 +185,21 @@ typedef enum ExprEvalOp */ EEOP_FIELDSTORE_FORM, - /* Process an array subscript; short-circuit expression to NULL if NULL */ - EEOP_ARRAYREF_SUBSCRIPT, + /* Process a container subscript; short-circuit expression to NULL if NULL */ + EEOP_SBSREF_SUBSCRIPT, /* - * Compute old array element/slice when an ArrayRef assignment expression - * contains ArrayRef/FieldStore subexpressions. Value is accessed using - * the CaseTest mechanism. + * Compute old container element/slice when a SubscriptingRef assignment + * expression contains SubscriptingRef/FieldStore subexpressions. Value is + * accessed using the CaseTest mechanism. */ - EEOP_ARRAYREF_OLD, + EEOP_SBSREF_OLD, - /* compute new value for ArrayRef assignment expression */ - EEOP_ARRAYREF_ASSIGN, + /* compute new value for SubscriptingRef assignment expression */ + EEOP_SBSREF_ASSIGN, - /* compute element/slice for ArrayRef fetch expression */ - EEOP_ARRAYREF_FETCH, + /* compute element/slice for SubscriptingRef fetch expression */ + EEOP_SBSREF_FETCH, /* evaluate value for CoerceToDomainValue */ EEOP_DOMAIN_TESTVAL, @@ -492,22 +492,22 @@ typedef struct ExprEvalStep int ncolumns; } fieldstore; - /* for EEOP_ARRAYREF_SUBSCRIPT */ + /* for EEOP_SBSREF_SUBSCRIPT */ struct { /* too big to have inline */ - struct ArrayRefState *state; + struct SubscriptingRefState *state; int off; /* 0-based index of this subscript */ bool isupper; /* is it upper or lower subscript? */ int jumpdone; /* jump here on null */ - } arrayref_subscript; + } sbsref_subscript; - /* for EEOP_ARRAYREF_OLD / ASSIGN / FETCH */ + /* for EEOP_SBSREF_OLD / ASSIGN / FETCH */ struct { /* too big to have inline */ - struct ArrayRefState *state; - } arrayref; + struct SubscriptingRefState *state; + } sbsref; /* for EEOP_DOMAIN_NOTNULL / DOMAIN_CHECK */ struct @@ -658,14 +658,14 @@ typedef struct ExprEvalStep } ExprEvalStep; -/* Non-inline data for array operations */ -typedef struct ArrayRefState +/* Non-inline data for container operations */ +typedef struct SubscriptingRefState { bool isassignment; /* is it assignment, or just fetch? */ - Oid refelemtype; /* OID of the array element type */ - int16 refattrlength; /* typlen of array type */ - int16 refelemlength; /* typlen of the array element type */ + Oid refelemtype; /* OID of the container element type */ + int16 refattrlength; /* typlen of container type */ + int16 refelemlength; /* typlen of the container element type */ bool refelembyval; /* is the element type pass-by-value? */ char refelemalign; /* typalign of the element type */ @@ -688,10 +688,10 @@ typedef struct ArrayRefState Datum replacevalue; bool replacenull; - /* if we have a nested assignment, ARRAYREF_OLD puts old value here */ + /* if we have a nested assignment, SBSREF_OLD puts old value here */ Datum prevvalue; bool prevnull; -} ArrayRefState; +} SubscriptingRefState; /* functions in execExpr.c */ @@ -735,10 +735,10 @@ extern void ExecEvalFieldStoreDeForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext); extern void ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext); -extern bool ExecEvalArrayRefSubscript(ExprState *state, ExprEvalStep *op); -extern void ExecEvalArrayRefFetch(ExprState *state, ExprEvalStep *op); -extern void ExecEvalArrayRefOld(ExprState *state, ExprEvalStep *op); -extern void ExecEvalArrayRefAssign(ExprState *state, ExprEvalStep *op); +extern bool ExecEvalSubscriptingRef(ExprState *state, ExprEvalStep *op); +extern void ExecEvalSubscriptingRefFetch(ExprState *state, ExprEvalStep *op); +extern void ExecEvalSubscriptingRefOld(ExprState *state, ExprEvalStep *op); +extern void ExecEvalSubscriptingRefAssign(ExprState *state, ExprEvalStep *op); extern void ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op, ExprContext *econtext); extern void ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op); diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h index 726ec99130..6178864b2e 100644 --- a/src/include/jit/llvmjit.h +++ b/src/include/jit/llvmjit.h @@ -85,7 +85,7 @@ extern LLVMValueRef FuncVarsizeAny; extern LLVMValueRef FuncSlotGetmissingattrs; extern LLVMValueRef FuncSlotGetsomeattrsInt; extern LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal; -extern LLVMValueRef FuncExecEvalArrayRefSubscript; +extern LLVMValueRef FuncExecEvalSubscriptingRef; extern LLVMValueRef FuncExecEvalSysVar; extern LLVMValueRef FuncExecAggTransReparent; extern LLVMValueRef FuncExecAggInitGroup; diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index fbe2dc14a7..e215ad4978 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -154,7 +154,7 @@ typedef enum NodeTag T_Aggref, T_GroupingFunc, T_WindowFunc, - T_ArrayRef, + T_SubscriptingRef, T_FuncExpr, T_NamedArgExpr, T_OpExpr, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 4ec8a83541..2fe14d7db2 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -224,7 +224,7 @@ typedef struct TypeName * Currently, A_Star must appear only as the last list element --- the grammar * is responsible for enforcing this! * - * Note: any array subscripting or selection of fields from composite columns + * Note: any container subscripting or selection of fields from composite columns * is represented by an A_Indirection node above the ColumnRef. However, * for simplicity in the normal case, initial field selection from a table * name is represented within ColumnRef and not by adding A_Indirection. diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 78fb0e414e..a7efae7038 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -368,18 +368,19 @@ typedef struct WindowFunc } WindowFunc; /* ---------------- - * ArrayRef: describes an array subscripting operation + * SubscriptingRef: describes a subscripting operation over a container + * (array, etc). * - * An ArrayRef can describe fetching a single element from an array, - * fetching a subarray (array slice), storing a single element into - * an array, or storing a slice. The "store" cases work with an - * initial array value and a source value that is inserted into the - * appropriate part of the array; the result of the operation is an - * entire new modified array value. + * A SubscriptingRef can describe fetching a single element from a container, + * fetching a part of container (e.g. array slice), storing a single element into + * a container, or storing a slice. The "store" cases work with an + * initial container value and a source value that is inserted into the + * appropriate part of the container; the result of the operation is an + * entire new modified container value. * - * If reflowerindexpr = NIL, then we are fetching or storing a single array - * element at the subscripts given by refupperindexpr. Otherwise we are - * fetching or storing an array slice, that is a rectangular subarray + * If reflowerindexpr = NIL, then we are fetching or storing a single container + * element at the subscripts given by refupperindexpr. Otherwise we are + * fetching or storing a container slice, that is a rectangular subcontainer * with lower and upper bounds given by the index expressions. * reflowerindexpr must be the same length as refupperindexpr when it * is not NIL. @@ -391,28 +392,31 @@ typedef struct WindowFunc * element; but it is the array type when doing subarray fetch or either * type of store. * - * Note: for the cases where an array is returned, if refexpr yields a R/W - * expanded array, then the implementation is allowed to modify that object + * Note: for the cases where a container is returned, if refexpr yields a R/W + * expanded container, then the implementation is allowed to modify that object * in-place and return the same object.) * ---------------- */ -typedef struct ArrayRef +typedef struct SubscriptingRef { Expr xpr; - Oid refarraytype; /* type of the array proper */ - Oid refelemtype; /* type of the array elements */ - int32 reftypmod; /* typmod of the array (and elements too) */ + Oid refcontainertype; /* type of the container proper */ + Oid refelemtype; /* type of the container elements */ + int32 reftypmod; /* typmod of the container (and elements too) */ Oid refcollid; /* OID of collation, or InvalidOid if none */ List *refupperindexpr; /* expressions that evaluate to upper - * array indexes */ + * container indexes */ List *reflowerindexpr; /* expressions that evaluate to lower - * array indexes, or NIL for single array - * element */ - Expr *refexpr; /* the expression that evaluates to an array - * value */ + * container indexes, or NIL for single + * container element */ + List *refindexprslice; /* whether or not related indexpr from + * reflowerindexpr is a slice */ + Expr *refexpr; /* the expression that evaluates to a + * container value */ + Expr *refassgnexpr; /* expression for the source value, or NULL if * fetch */ -} ArrayRef; +} SubscriptingRef; /* * CoercionContext - distinguishes the allowed set of type casts @@ -755,7 +759,7 @@ typedef struct FieldSelect * * FieldStore represents the operation of modifying one field in a tuple * value, yielding a new tuple value (the input is not touched!). Like - * the assign case of ArrayRef, this is used to implement UPDATE of a + * the assign case of SubscriptingRef, this is used to implement UPDATE of a * portion of a column. * * resulttype is always a named composite type (not a domain). To update diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index b95489379c..ea99a0954b 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -273,14 +273,15 @@ extern void cancel_parser_errposition_callback(ParseCallbackState *pcbstate); extern Var *make_var(ParseState *pstate, RangeTblEntry *rte, int attrno, int location); -extern Oid transformArrayType(Oid *arrayType, int32 *arrayTypmod); -extern ArrayRef *transformArraySubscripts(ParseState *pstate, - Node *arrayBase, - Oid arrayType, - Oid elementType, - int32 arrayTypMod, - List *indirection, - Node *assignFrom); +extern Oid transformContainerType(Oid *containerType, int32 *containerTypmod); + +extern SubscriptingRef *transformContainerSubscripts(ParseState *pstate, + Node *containerBase, + Oid containerType, + Oid elementType, + int32 containerTypMod, + List *indirection, + Node *assignFrom); extern Const *make_const(ParseState *pstate, Value *value, int location); #endif /* PARSE_NODE_H */ diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 85aa61371d..a5aafa8c09 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5207,8 +5207,8 @@ exec_assign_value(PLpgSQL_execstate *estate, /* * Evaluate the subscripts, switch into left-to-right order. - * Like the expression built by ExecInitArrayRef(), complain - * if any subscript is null. + * Like the expression built by ExecInitSubscriptingRef(), + * complain if any subscript is null. */ for (i = 0; i < nsubscripts; i++) {