PostgreSQL Source Code git master
arraysubs.c File Reference
#include "postgres.h"
#include "executor/execExpr.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "nodes/subscripting.h"
#include "parser/parse_coerce.h"
#include "parser/parse_expr.h"
#include "utils/array.h"
#include "utils/fmgrprotos.h"
#include "utils/lsyscache.h"
Include dependency graph for arraysubs.c:

Go to the source code of this file.

Data Structures

struct  ArraySubWorkspace
 

Typedefs

typedef struct ArraySubWorkspace ArraySubWorkspace
 

Functions

static void array_subscript_transform (SubscriptingRef *sbsref, List *indirection, ParseState *pstate, bool isSlice, bool isAssignment)
 
static bool array_subscript_check_subscripts (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void array_subscript_fetch (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void array_subscript_fetch_slice (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void array_subscript_assign (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void array_subscript_assign_slice (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void array_subscript_fetch_old (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void array_subscript_fetch_old_slice (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void array_exec_setup (const SubscriptingRef *sbsref, SubscriptingRefState *sbsrefstate, SubscriptExecSteps *methods)
 
Datum array_subscript_handler (PG_FUNCTION_ARGS)
 
Datum raw_array_subscript_handler (PG_FUNCTION_ARGS)
 

Typedef Documentation

◆ ArraySubWorkspace

Function Documentation

◆ array_exec_setup()

static void array_exec_setup ( const SubscriptingRef sbsref,
SubscriptingRefState sbsrefstate,
SubscriptExecSteps methods 
)
static

Definition at line 473 of file arraysubs.c.

476{
477 bool is_slice = (sbsrefstate->numlower != 0);
478 ArraySubWorkspace *workspace;
479
480 /*
481 * Enforce the implementation limit on number of array subscripts. This
482 * check isn't entirely redundant with checking at parse time; conceivably
483 * the expression was stored by a backend with a different MAXDIM value.
484 */
485 if (sbsrefstate->numupper > MAXDIM)
487 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
488 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
489 sbsrefstate->numupper, MAXDIM)));
490
491 /* Should be impossible if parser is sane, but check anyway: */
492 if (sbsrefstate->numlower != 0 &&
493 sbsrefstate->numupper != sbsrefstate->numlower)
494 elog(ERROR, "upper and lower index lists are not same length");
495
496 /*
497 * Allocate type-specific workspace.
498 */
499 workspace = (ArraySubWorkspace *) palloc(sizeof(ArraySubWorkspace));
500 sbsrefstate->workspace = workspace;
501
502 /*
503 * Collect datatype details we'll need at execution.
504 */
505 workspace->refelemtype = sbsref->refelemtype;
506 workspace->refattrlength = get_typlen(sbsref->refcontainertype);
507 get_typlenbyvalalign(sbsref->refelemtype,
508 &workspace->refelemlength,
509 &workspace->refelembyval,
510 &workspace->refelemalign);
511
512 /*
513 * Pass back pointers to appropriate step execution functions.
514 */
516 if (is_slice)
517 {
521 }
522 else
523 {
527 }
528}
#define MAXDIM
Definition: array.h:75
static void array_subscript_assign_slice(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
Definition: arraysubs.c:344
static void array_subscript_fetch_old(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
Definition: arraysubs.c:399
static void array_subscript_assign(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
Definition: arraysubs.c:294
static void array_subscript_fetch(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
Definition: arraysubs.c:236
static void array_subscript_fetch_old_slice(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
Definition: arraysubs.c:439
static void array_subscript_fetch_slice(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
Definition: arraysubs.c:264
static bool array_subscript_check_subscripts(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
Definition: arraysubs.c:180
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2271
int16 get_typlen(Oid typid)
Definition: lsyscache.c:2197
void * palloc(Size size)
Definition: mcxt.c:1317
int16 refattrlength
Definition: arraysubs.c:33
int16 refelemlength
Definition: arraysubs.c:34
ExecEvalSubroutine sbs_fetch_old
Definition: execExpr.h:808
ExecEvalBoolSubroutine sbs_check_subscripts
Definition: execExpr.h:805
ExecEvalSubroutine sbs_assign
Definition: execExpr.h:807
ExecEvalSubroutine sbs_fetch
Definition: execExpr.h:806

References array_subscript_assign(), array_subscript_assign_slice(), array_subscript_check_subscripts(), array_subscript_fetch(), array_subscript_fetch_old(), array_subscript_fetch_old_slice(), array_subscript_fetch_slice(), elog, ereport, errcode(), errmsg(), ERROR, get_typlen(), get_typlenbyvalalign(), MAXDIM, SubscriptingRefState::numlower, SubscriptingRefState::numupper, palloc(), ArraySubWorkspace::refattrlength, ArraySubWorkspace::refelemalign, ArraySubWorkspace::refelembyval, ArraySubWorkspace::refelemlength, ArraySubWorkspace::refelemtype, SubscriptExecSteps::sbs_assign, SubscriptExecSteps::sbs_check_subscripts, SubscriptExecSteps::sbs_fetch, SubscriptExecSteps::sbs_fetch_old, and SubscriptingRefState::workspace.

Referenced by array_subscript_handler(), and raw_array_subscript_handler().

◆ array_subscript_assign()

static void array_subscript_assign ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 294 of file arraysubs.c.

297{
298 SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
299 ArraySubWorkspace *workspace = (ArraySubWorkspace *) sbsrefstate->workspace;
300 Datum arraySource = *op->resvalue;
301
302 /*
303 * For an assignment to a fixed-length array type, both the original array
304 * and the value to be assigned into it must be non-NULL, else we punt and
305 * return the original array.
306 */
307 if (workspace->refattrlength > 0)
308 {
309 if (*op->resnull || sbsrefstate->replacenull)
310 return;
311 }
312
313 /*
314 * For assignment to varlena arrays, we handle a NULL original array by
315 * substituting an empty (zero-dimensional) array; insertion of the new
316 * element will result in a singleton array value. It does not matter
317 * whether the new element is NULL.
318 */
319 if (*op->resnull)
320 {
321 arraySource = PointerGetDatum(construct_empty_array(workspace->refelemtype));
322 *op->resnull = false;
323 }
324
325 *op->resvalue = array_set_element(arraySource,
326 sbsrefstate->numupper,
327 workspace->upperindex,
328 sbsrefstate->replacevalue,
329 sbsrefstate->replacenull,
330 workspace->refattrlength,
331 workspace->refelemlength,
332 workspace->refelembyval,
333 workspace->refelemalign);
334 /* The result is never NULL, so no need to change *op->resnull */
335}
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3580
Datum array_set_element(Datum arraydatum, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:2201
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
int upperindex[MAXDIM]
Definition: arraysubs.c:43
struct SubscriptingRefState * state
Definition: execExpr.h:561
struct ExprEvalStep::@55::@84 sbsref
Datum * resvalue
Definition: execExpr.h:302
union ExprEvalStep::@55 d
bool * resnull
Definition: execExpr.h:303

References array_set_element(), construct_empty_array(), ExprEvalStep::d, if(), SubscriptingRefState::numupper, PointerGetDatum(), ArraySubWorkspace::refattrlength, ArraySubWorkspace::refelemalign, ArraySubWorkspace::refelembyval, ArraySubWorkspace::refelemlength, ArraySubWorkspace::refelemtype, SubscriptingRefState::replacenull, SubscriptingRefState::replacevalue, ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::sbsref, ExprEvalStep::state, ArraySubWorkspace::upperindex, and SubscriptingRefState::workspace.

Referenced by array_exec_setup().

◆ array_subscript_assign_slice()

static void array_subscript_assign_slice ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 344 of file arraysubs.c.

347{
348 SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
349 ArraySubWorkspace *workspace = (ArraySubWorkspace *) sbsrefstate->workspace;
350 Datum arraySource = *op->resvalue;
351
352 /*
353 * For an assignment to a fixed-length array type, both the original array
354 * and the value to be assigned into it must be non-NULL, else we punt and
355 * return the original array.
356 */
357 if (workspace->refattrlength > 0)
358 {
359 if (*op->resnull || sbsrefstate->replacenull)
360 return;
361 }
362
363 /*
364 * For assignment to varlena arrays, we handle a NULL original array by
365 * substituting an empty (zero-dimensional) array; insertion of the new
366 * element will result in a singleton array value. It does not matter
367 * whether the new element is NULL.
368 */
369 if (*op->resnull)
370 {
371 arraySource = PointerGetDatum(construct_empty_array(workspace->refelemtype));
372 *op->resnull = false;
373 }
374
375 *op->resvalue = array_set_slice(arraySource,
376 sbsrefstate->numupper,
377 workspace->upperindex,
378 workspace->lowerindex,
379 sbsrefstate->upperprovided,
380 sbsrefstate->lowerprovided,
381 sbsrefstate->replacevalue,
382 sbsrefstate->replacenull,
383 workspace->refattrlength,
384 workspace->refelemlength,
385 workspace->refelembyval,
386 workspace->refelemalign);
387 /* The result is never NULL, so no need to change *op->resnull */
388}
Datum array_set_slice(Datum arraydatum, int nSubscripts, int *upperIndx, int *lowerIndx, bool *upperProvided, bool *lowerProvided, Datum srcArrayDatum, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:2806
int lowerindex[MAXDIM]
Definition: arraysubs.c:44

References array_set_slice(), construct_empty_array(), ExprEvalStep::d, if(), ArraySubWorkspace::lowerindex, SubscriptingRefState::lowerprovided, SubscriptingRefState::numupper, PointerGetDatum(), ArraySubWorkspace::refattrlength, ArraySubWorkspace::refelemalign, ArraySubWorkspace::refelembyval, ArraySubWorkspace::refelemlength, ArraySubWorkspace::refelemtype, SubscriptingRefState::replacenull, SubscriptingRefState::replacevalue, ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::sbsref, ExprEvalStep::state, ArraySubWorkspace::upperindex, SubscriptingRefState::upperprovided, and SubscriptingRefState::workspace.

Referenced by array_exec_setup().

◆ array_subscript_check_subscripts()

static bool array_subscript_check_subscripts ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 180 of file arraysubs.c.

183{
184 SubscriptingRefState *sbsrefstate = op->d.sbsref_subscript.state;
185 ArraySubWorkspace *workspace = (ArraySubWorkspace *) sbsrefstate->workspace;
186
187 /* Process upper subscripts */
188 for (int i = 0; i < sbsrefstate->numupper; i++)
189 {
190 if (sbsrefstate->upperprovided[i])
191 {
192 /* If any index expr yields NULL, result is NULL or error */
193 if (sbsrefstate->upperindexnull[i])
194 {
195 if (sbsrefstate->isassignment)
197 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
198 errmsg("array subscript in assignment must not be null")));
199 *op->resnull = true;
200 return false;
201 }
202 workspace->upperindex[i] = DatumGetInt32(sbsrefstate->upperindex[i]);
203 }
204 }
205
206 /* Likewise for lower subscripts */
207 for (int i = 0; i < sbsrefstate->numlower; i++)
208 {
209 if (sbsrefstate->lowerprovided[i])
210 {
211 /* If any index expr yields NULL, result is NULL or error */
212 if (sbsrefstate->lowerindexnull[i])
213 {
214 if (sbsrefstate->isassignment)
216 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
217 errmsg("array subscript in assignment must not be null")));
218 *op->resnull = true;
219 return false;
220 }
221 workspace->lowerindex[i] = DatumGetInt32(sbsrefstate->lowerindex[i]);
222 }
223 }
224
225 return true;
226}
for(;;)
int i
Definition: isn.c:72
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:207
struct ExprEvalStep::@55::@83 sbsref_subscript

References ExprEvalStep::d, DatumGetInt32(), ereport, errcode(), errmsg(), ERROR, for(), i, SubscriptingRefState::isassignment, ArraySubWorkspace::lowerindex, SubscriptingRefState::lowerindex, SubscriptingRefState::lowerindexnull, SubscriptingRefState::lowerprovided, SubscriptingRefState::numlower, SubscriptingRefState::numupper, ExprEvalStep::resnull, ExprEvalStep::sbsref_subscript, ExprEvalStep::state, ArraySubWorkspace::upperindex, SubscriptingRefState::upperindex, SubscriptingRefState::upperindexnull, SubscriptingRefState::upperprovided, and SubscriptingRefState::workspace.

Referenced by array_exec_setup().

◆ array_subscript_fetch()

static void array_subscript_fetch ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 236 of file arraysubs.c.

239{
240 SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
241 ArraySubWorkspace *workspace = (ArraySubWorkspace *) sbsrefstate->workspace;
242
243 /* Should not get here if source array (or any subscript) is null */
244 Assert(!(*op->resnull));
245
247 sbsrefstate->numupper,
248 workspace->upperindex,
249 workspace->refattrlength,
250 workspace->refelemlength,
251 workspace->refelembyval,
252 workspace->refelemalign,
253 op->resnull);
254}
Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
Definition: arrayfuncs.c:1820
#define Assert(condition)
Definition: c.h:815

References array_get_element(), Assert, ExprEvalStep::d, SubscriptingRefState::numupper, ArraySubWorkspace::refattrlength, ArraySubWorkspace::refelemalign, ArraySubWorkspace::refelembyval, ArraySubWorkspace::refelemlength, ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::sbsref, ExprEvalStep::state, ArraySubWorkspace::upperindex, and SubscriptingRefState::workspace.

Referenced by array_exec_setup().

◆ array_subscript_fetch_old()

static void array_subscript_fetch_old ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 399 of file arraysubs.c.

402{
403 SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
404 ArraySubWorkspace *workspace = (ArraySubWorkspace *) sbsrefstate->workspace;
405
406 if (*op->resnull)
407 {
408 /* whole array is null, so any element is too */
409 sbsrefstate->prevvalue = (Datum) 0;
410 sbsrefstate->prevnull = true;
411 }
412 else
413 sbsrefstate->prevvalue = array_get_element(*op->resvalue,
414 sbsrefstate->numupper,
415 workspace->upperindex,
416 workspace->refattrlength,
417 workspace->refelemlength,
418 workspace->refelembyval,
419 workspace->refelemalign,
420 &sbsrefstate->prevnull);
421}

References array_get_element(), ExprEvalStep::d, if(), SubscriptingRefState::numupper, SubscriptingRefState::prevnull, SubscriptingRefState::prevvalue, ArraySubWorkspace::refattrlength, ArraySubWorkspace::refelemalign, ArraySubWorkspace::refelembyval, ArraySubWorkspace::refelemlength, ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::sbsref, ExprEvalStep::state, ArraySubWorkspace::upperindex, and SubscriptingRefState::workspace.

Referenced by array_exec_setup().

◆ array_subscript_fetch_old_slice()

static void array_subscript_fetch_old_slice ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 439 of file arraysubs.c.

442{
443 SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
444 ArraySubWorkspace *workspace = (ArraySubWorkspace *) sbsrefstate->workspace;
445
446 if (*op->resnull)
447 {
448 /* whole array is null, so any slice is too */
449 sbsrefstate->prevvalue = (Datum) 0;
450 sbsrefstate->prevnull = true;
451 }
452 else
453 {
454 sbsrefstate->prevvalue = array_get_slice(*op->resvalue,
455 sbsrefstate->numupper,
456 workspace->upperindex,
457 workspace->lowerindex,
458 sbsrefstate->upperprovided,
459 sbsrefstate->lowerprovided,
460 workspace->refattrlength,
461 workspace->refelemlength,
462 workspace->refelembyval,
463 workspace->refelemalign);
464 /* slices of non-null arrays are never null */
465 sbsrefstate->prevnull = false;
466 }
467}
Datum array_get_slice(Datum arraydatum, int nSubscripts, int *upperIndx, int *lowerIndx, bool *upperProvided, bool *lowerProvided, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:2030

References array_get_slice(), ExprEvalStep::d, if(), ArraySubWorkspace::lowerindex, SubscriptingRefState::lowerprovided, SubscriptingRefState::numupper, SubscriptingRefState::prevnull, SubscriptingRefState::prevvalue, ArraySubWorkspace::refattrlength, ArraySubWorkspace::refelemalign, ArraySubWorkspace::refelembyval, ArraySubWorkspace::refelemlength, ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::sbsref, ExprEvalStep::state, ArraySubWorkspace::upperindex, SubscriptingRefState::upperprovided, and SubscriptingRefState::workspace.

Referenced by array_exec_setup().

◆ array_subscript_fetch_slice()

static void array_subscript_fetch_slice ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 264 of file arraysubs.c.

267{
268 SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
269 ArraySubWorkspace *workspace = (ArraySubWorkspace *) sbsrefstate->workspace;
270
271 /* Should not get here if source array (or any subscript) is null */
272 Assert(!(*op->resnull));
273
275 sbsrefstate->numupper,
276 workspace->upperindex,
277 workspace->lowerindex,
278 sbsrefstate->upperprovided,
279 sbsrefstate->lowerprovided,
280 workspace->refattrlength,
281 workspace->refelemlength,
282 workspace->refelembyval,
283 workspace->refelemalign);
284 /* The slice is never NULL, so no need to change *op->resnull */
285}

References array_get_slice(), Assert, ExprEvalStep::d, ArraySubWorkspace::lowerindex, SubscriptingRefState::lowerprovided, SubscriptingRefState::numupper, ArraySubWorkspace::refattrlength, ArraySubWorkspace::refelemalign, ArraySubWorkspace::refelembyval, ArraySubWorkspace::refelemlength, ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::sbsref, ExprEvalStep::state, ArraySubWorkspace::upperindex, SubscriptingRefState::upperprovided, and SubscriptingRefState::workspace.

Referenced by array_exec_setup().

◆ array_subscript_handler()

Datum array_subscript_handler ( PG_FUNCTION_ARGS  )

Definition at line 539 of file arraysubs.c.

540{
541 static const SubscriptRoutines sbsroutines = {
543 .exec_setup = array_exec_setup,
544 .fetch_strict = true, /* fetch returns NULL for NULL inputs */
545 .fetch_leakproof = true, /* fetch returns NULL for bad subscript */
546 .store_leakproof = false /* ... but assignment throws error */
547 };
548
549 PG_RETURN_POINTER(&sbsroutines);
550}
static void array_exec_setup(const SubscriptingRef *sbsref, SubscriptingRefState *sbsrefstate, SubscriptExecSteps *methods)
Definition: arraysubs.c:473
static void array_subscript_transform(SubscriptingRef *sbsref, List *indirection, ParseState *pstate, bool isSlice, bool isAssignment)
Definition: arraysubs.c:55
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
SubscriptTransform transform
Definition: subscripting.h:160

References array_exec_setup(), array_subscript_transform(), PG_RETURN_POINTER, and SubscriptRoutines::transform.

◆ array_subscript_transform()

static void array_subscript_transform ( SubscriptingRef sbsref,
List indirection,
ParseState pstate,
bool  isSlice,
bool  isAssignment 
)
static

Definition at line 55 of file arraysubs.c.

60{
61 List *upperIndexpr = NIL;
62 List *lowerIndexpr = NIL;
64
65 /*
66 * Transform the subscript expressions, and separate upper and lower
67 * bounds into two lists.
68 *
69 * If we have a container slice expression, we convert any non-slice
70 * indirection items to slices by treating the single subscript as the
71 * upper bound and supplying an assumed lower bound of 1.
72 */
73 foreach(idx, indirection)
74 {
76 Node *subexpr;
77
78 if (isSlice)
79 {
80 if (ai->lidx)
81 {
82 subexpr = transformExpr(pstate, ai->lidx, pstate->p_expr_kind);
83 /* If it's not int4 already, try to coerce */
84 subexpr = coerce_to_target_type(pstate,
85 subexpr, exprType(subexpr),
86 INT4OID, -1,
89 -1);
90 if (subexpr == NULL)
92 (errcode(ERRCODE_DATATYPE_MISMATCH),
93 errmsg("array subscript must have type integer"),
94 parser_errposition(pstate, exprLocation(ai->lidx))));
95 }
96 else if (!ai->is_slice)
97 {
98 /* Make a constant 1 */
99 subexpr = (Node *) makeConst(INT4OID,
100 -1,
102 sizeof(int32),
103 Int32GetDatum(1),
104 false,
105 true); /* pass by value */
106 }
107 else
108 {
109 /* Slice with omitted lower bound, put NULL into the list */
110 subexpr = NULL;
111 }
112 lowerIndexpr = lappend(lowerIndexpr, subexpr);
113 }
114 else
115 Assert(ai->lidx == NULL && !ai->is_slice);
116
117 if (ai->uidx)
118 {
119 subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind);
120 /* If it's not int4 already, try to coerce */
121 subexpr = coerce_to_target_type(pstate,
122 subexpr, exprType(subexpr),
123 INT4OID, -1,
126 -1);
127 if (subexpr == NULL)
129 (errcode(ERRCODE_DATATYPE_MISMATCH),
130 errmsg("array subscript must have type integer"),
131 parser_errposition(pstate, exprLocation(ai->uidx))));
132 }
133 else
134 {
135 /* Slice with omitted upper bound, put NULL into the list */
136 Assert(isSlice && ai->is_slice);
137 subexpr = NULL;
138 }
139 upperIndexpr = lappend(upperIndexpr, subexpr);
140 }
141
142 /* ... and store the transformed lists into the SubscriptRef node */
143 sbsref->refupperindexpr = upperIndexpr;
144 sbsref->reflowerindexpr = lowerIndexpr;
145
146 /* Verify subscript list lengths are within implementation limit */
147 if (list_length(upperIndexpr) > MAXDIM)
149 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
150 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
151 list_length(upperIndexpr), MAXDIM)));
152 /* We need not check lowerIndexpr separately */
153
154 /*
155 * Determine the result type of the subscripting operation. It's the same
156 * as the array type if we're slicing, else it's the element type. In
157 * either case, the typmod is the same as the array's, so we need not
158 * change reftypmod.
159 */
160 if (isSlice)
161 sbsref->refrestype = sbsref->refcontainertype;
162 else
163 sbsref->refrestype = sbsref->refelemtype;
164}
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
int32_t int32
Definition: c.h:484
List * lappend(List *list, void *datum)
Definition: list.c:339
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:303
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1388
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
Definition: parse_coerce.c:78
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:118
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
#define InvalidOid
Definition: postgres_ext.h:37
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:752
@ COERCION_ASSIGNMENT
Definition: primnodes.h:731
bool is_slice
Definition: parsenodes.h:470
Node * uidx
Definition: parsenodes.h:472
Node * lidx
Definition: parsenodes.h:471
Definition: pg_list.h:54
Definition: nodes.h:129
ParseExprKind p_expr_kind
Definition: parse_node.h:230
List * refupperindexpr
Definition: primnodes.h:709
List * reflowerindexpr
Definition: primnodes.h:715

References Assert, COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_ASSIGNMENT, ereport, errcode(), errmsg(), ERROR, exprLocation(), exprType(), idx(), Int32GetDatum(), InvalidOid, A_Indices::is_slice, lappend(), lfirst_node, A_Indices::lidx, list_length(), makeConst(), MAXDIM, NIL, ParseState::p_expr_kind, parser_errposition(), SubscriptingRef::reflowerindexpr, SubscriptingRef::refupperindexpr, transformExpr(), and A_Indices::uidx.

Referenced by array_subscript_handler(), and raw_array_subscript_handler().

◆ raw_array_subscript_handler()

Datum raw_array_subscript_handler ( PG_FUNCTION_ARGS  )

Definition at line 566 of file arraysubs.c.

567{
568 static const SubscriptRoutines sbsroutines = {
570 .exec_setup = array_exec_setup,
571 .fetch_strict = true, /* fetch returns NULL for NULL inputs */
572 .fetch_leakproof = true, /* fetch returns NULL for bad subscript */
573 .store_leakproof = false /* ... but assignment throws error */
574 };
575
576 PG_RETURN_POINTER(&sbsroutines);
577}

References array_exec_setup(), array_subscript_transform(), PG_RETURN_POINTER, and SubscriptRoutines::transform.