* Prepare evaluation of a SubscriptingRef expression. */
| 2938 | * Prepare evaluation of a SubscriptingRef expression. |
| 2939 | */ |
| 2940 | static void |
| 2941 | ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref, |
| 2942 | ExprState *state, Datum *resv, bool *resnull) |
| 2943 | { |
| 2944 | bool isAssignment = (sbsref->refassgnexpr != NULL); |
| 2945 | int nupper = list_length(sbsref->refupperindexpr); |
| 2946 | int nlower = list_length(sbsref->reflowerindexpr); |
| 2947 | const SubscriptRoutines *sbsroutines; |
| 2948 | SubscriptingRefState *sbsrefstate; |
| 2949 | SubscriptExecSteps methods; |
| 2950 | char *ptr; |
| 2951 | List *adjust_jumps = NIL; |
| 2952 | ListCell *lc; |
| 2953 | int i; |
| 2954 | |
| 2955 | /* Look up the subscripting support methods */ |
| 2956 | sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype, NULL); |
| 2957 | if (!sbsroutines) |
| 2958 | ereport(ERROR, |
| 2959 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
| 2960 | errmsg("cannot subscript type %s because it does not support subscripting", |
| 2961 | format_type_be(sbsref->refcontainertype)), |
| 2962 | state->parent ? |
| 2963 | executor_errposition(state->parent->state, |
| 2964 | exprLocation((Node *) sbsref)) : 0)); |
| 2965 | |
| 2966 | /* Allocate sbsrefstate, with enough space for per-subscript arrays too */ |
| 2967 | sbsrefstate = palloc0(MAXALIGN(sizeof(SubscriptingRefState)) + |
| 2968 | (nupper + nlower) * (sizeof(Datum) + |
| 2969 | 2 * sizeof(bool))); |
| 2970 | |
| 2971 | /* Fill constant fields of SubscriptingRefState */ |
| 2972 | sbsrefstate->isassignment = isAssignment; |
| 2973 | sbsrefstate->numupper = nupper; |
| 2974 | sbsrefstate->numlower = nlower; |
| 2975 | /* Set up per-subscript arrays */ |
| 2976 | ptr = ((char *) sbsrefstate) + MAXALIGN(sizeof(SubscriptingRefState)); |
| 2977 | sbsrefstate->upperindex = (Datum *) ptr; |
| 2978 | ptr += nupper * sizeof(Datum); |
| 2979 | sbsrefstate->lowerindex = (Datum *) ptr; |
| 2980 | ptr += nlower * sizeof(Datum); |
| 2981 | sbsrefstate->upperprovided = (bool *) ptr; |
| 2982 | ptr += nupper * sizeof(bool); |
| 2983 | sbsrefstate->lowerprovided = (bool *) ptr; |
| 2984 | ptr += nlower * sizeof(bool); |
| 2985 | sbsrefstate->upperindexnull = (bool *) ptr; |
| 2986 | ptr += nupper * sizeof(bool); |
| 2987 | sbsrefstate->lowerindexnull = (bool *) ptr; |
| 2988 | /* ptr += nlower * sizeof(bool); */ |
| 2989 | |
| 2990 | /* |
| 2991 | * Let the container-type-specific code have a chance. It must fill the |
| 2992 | * "methods" struct with function pointers for us to possibly use in |
| 2993 | * execution steps below; and it can optionally set up some data pointed |
| 2994 | * to by the workspace field. |
| 2995 | */ |
| 2996 | memset(&methods, 0, sizeof(methods)); |
| 2997 | sbsroutines->exec_setup(sbsref, sbsrefstate, &methods); |
no test coverage detected