mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-01 08:31:21 +02:00
27b77ecf9f
Backpatch-through: 10
168 lines
8.4 KiB
C
168 lines
8.4 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* subscripting.h
|
|
* API for generic type subscripting
|
|
*
|
|
* Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/nodes/subscripting.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef SUBSCRIPTING_H
|
|
#define SUBSCRIPTING_H
|
|
|
|
#include "nodes/primnodes.h"
|
|
|
|
/* Forward declarations, to avoid including other headers */
|
|
struct ParseState;
|
|
struct SubscriptingRefState;
|
|
struct SubscriptExecSteps;
|
|
|
|
/*
|
|
* The SQL-visible function that defines a subscripting method is declared
|
|
* subscripting_function(internal) returns internal
|
|
* but it actually is not passed any parameter. It must return a pointer
|
|
* to a "struct SubscriptRoutines" that provides pointers to the individual
|
|
* subscript parsing and execution methods. Typically the pointer will point
|
|
* to a "static const" variable, but at need it can point to palloc'd space.
|
|
* The type (after domain-flattening) of the head variable or expression
|
|
* of a subscripting construct determines which subscripting function is
|
|
* called for that construct.
|
|
*
|
|
* In addition to the method pointers, struct SubscriptRoutines includes
|
|
* several bool flags that specify properties of the subscripting actions
|
|
* this data type can perform:
|
|
*
|
|
* fetch_strict indicates that a fetch SubscriptRef is strict, i.e., returns
|
|
* NULL if any input (either the container or any subscript) is NULL.
|
|
*
|
|
* fetch_leakproof indicates that a fetch SubscriptRef is leakproof, i.e.,
|
|
* will not throw any data-value-dependent errors. Typically this requires
|
|
* silently returning NULL for invalid subscripts.
|
|
*
|
|
* store_leakproof similarly indicates whether an assignment SubscriptRef is
|
|
* leakproof. (It is common to prefer throwing errors for invalid subscripts
|
|
* in assignments; that's fine, but it makes the operation not leakproof.
|
|
* In current usage there is no advantage in making assignments leakproof.)
|
|
*
|
|
* There is no store_strict flag. Such behavior would generally be
|
|
* undesirable, since for example a null subscript in an assignment would
|
|
* cause the entire container to become NULL.
|
|
*
|
|
* Regardless of these flags, all SubscriptRefs are expected to be immutable,
|
|
* that is they must always give the same results for the same inputs.
|
|
* They are expected to always be parallel-safe, as well.
|
|
*/
|
|
|
|
/*
|
|
* The transform method is called during parse analysis of a subscripting
|
|
* construct. The SubscriptingRef node has been constructed, but some of
|
|
* its fields still need to be filled in, and the subscript expression(s)
|
|
* are still in raw form. The transform method is responsible for doing
|
|
* parse analysis of each subscript expression (using transformExpr),
|
|
* coercing the subscripts to whatever type it needs, and building the
|
|
* refupperindexpr and reflowerindexpr lists from those results. The
|
|
* reflowerindexpr list must be empty for an element operation, or the
|
|
* same length as refupperindexpr for a slice operation. Insert NULLs
|
|
* (that is, an empty parse tree, not a null Const node) for any omitted
|
|
* subscripts in a slice operation. (Of course, if the transform method
|
|
* does not care to support slicing, it can just throw an error if isSlice.)
|
|
* See array_subscript_transform() for sample code.
|
|
*
|
|
* The transform method is also responsible for identifying the result type
|
|
* of the subscripting operation. At call, refcontainertype and reftypmod
|
|
* describe the container type (this will be a base type not a domain), and
|
|
* refelemtype is set to the container type's pg_type.typelem value. The
|
|
* transform method must set refrestype and reftypmod to describe the result
|
|
* of subscripting. For arrays, refrestype is set to refelemtype for an
|
|
* element operation or refcontainertype for a slice, while reftypmod stays
|
|
* the same in either case; but other types might use other rules. The
|
|
* transform method should ignore refcollid, as that's determined later on
|
|
* during parsing.
|
|
*
|
|
* At call, refassgnexpr has not been filled in, so the SubscriptingRef node
|
|
* always looks like a fetch; refrestype should be set as though for a
|
|
* fetch, too. (The isAssignment parameter is typically only useful if the
|
|
* transform method wishes to throw an error for not supporting assignment.)
|
|
* To complete processing of an assignment, the core parser will coerce the
|
|
* element/slice source expression to the returned refrestype and reftypmod
|
|
* before putting it into refassgnexpr. It will then set refrestype and
|
|
* reftypmod to again describe the container type, since that's what an
|
|
* assignment must return.
|
|
*/
|
|
typedef void (*SubscriptTransform) (SubscriptingRef *sbsref,
|
|
List *indirection,
|
|
struct ParseState *pstate,
|
|
bool isSlice,
|
|
bool isAssignment);
|
|
|
|
/*
|
|
* The exec_setup method is called during executor-startup compilation of a
|
|
* SubscriptingRef node in an expression. It must fill *methods with pointers
|
|
* to functions that can be called for execution of the node. Optionally,
|
|
* exec_setup can initialize sbsrefstate->workspace to point to some palloc'd
|
|
* workspace for execution. (Typically, such workspace is used to hold
|
|
* looked-up catalog data and/or provide space for the check_subscripts step
|
|
* to pass data forward to the other step functions.) See executor/execExpr.h
|
|
* for the definitions of these structs and other ones used in expression
|
|
* execution.
|
|
*
|
|
* The methods to be provided are:
|
|
*
|
|
* sbs_check_subscripts: examine the just-computed subscript values available
|
|
* in sbsrefstate's arrays, and possibly convert them into another form
|
|
* (stored in sbsrefstate->workspace). Return TRUE to continue with
|
|
* evaluation of the subscripting construct, or FALSE to skip it and return an
|
|
* overall NULL result. If this is a fetch and the data type's fetch_strict
|
|
* flag is true, then sbs_check_subscripts must return FALSE if there are any
|
|
* NULL subscripts. Otherwise it can choose to throw an error, or return
|
|
* FALSE, or let sbs_fetch or sbs_assign deal with the null subscripts.
|
|
*
|
|
* sbs_fetch: perform a subscripting fetch, using the container value in
|
|
* *op->resvalue and the subscripts from sbs_check_subscripts. If
|
|
* fetch_strict is true then all these inputs can be assumed non-NULL,
|
|
* otherwise sbs_fetch must check for null inputs. Place the result in
|
|
* *op->resvalue / *op->resnull.
|
|
*
|
|
* sbs_assign: perform a subscripting assignment, using the original
|
|
* container value in *op->resvalue / *op->resnull, the subscripts from
|
|
* sbs_check_subscripts, and the new element/slice value in
|
|
* sbsrefstate->replacevalue/replacenull. Any of these inputs might be NULL
|
|
* (unless sbs_check_subscripts rejected null subscripts). Place the result
|
|
* (an entire new container value) in *op->resvalue / *op->resnull.
|
|
*
|
|
* sbs_fetch_old: this is only used in cases where an element or slice
|
|
* assignment involves an assignment to a sub-field or sub-element
|
|
* (i.e., nested containers are involved). It must fetch the existing
|
|
* value of the target element or slice. This is exactly the same as
|
|
* sbs_fetch except that (a) it must cope with a NULL container, and
|
|
* with NULL subscripts if sbs_check_subscripts allows them (typically,
|
|
* returning NULL is good enough); and (b) the result must be placed in
|
|
* sbsrefstate->prevvalue/prevnull, without overwriting *op->resvalue.
|
|
*
|
|
* Subscripting implementations that do not support assignment need not
|
|
* provide sbs_assign or sbs_fetch_old methods. It might be reasonable
|
|
* to also omit sbs_check_subscripts, in which case the sbs_fetch method must
|
|
* combine the functionality of sbs_check_subscripts and sbs_fetch. (The
|
|
* main reason to have a separate sbs_check_subscripts method is so that
|
|
* sbs_fetch_old and sbs_assign need not duplicate subscript processing.)
|
|
* Set the relevant pointers to NULL for any omitted methods.
|
|
*/
|
|
typedef void (*SubscriptExecSetup) (const SubscriptingRef *sbsref,
|
|
struct SubscriptingRefState *sbsrefstate,
|
|
struct SubscriptExecSteps *methods);
|
|
|
|
/* Struct returned by the SQL-visible subscript handler function */
|
|
typedef struct SubscriptRoutines
|
|
{
|
|
SubscriptTransform transform; /* parse analysis function */
|
|
SubscriptExecSetup exec_setup; /* expression compilation function */
|
|
bool fetch_strict; /* is fetch SubscriptRef strict? */
|
|
bool fetch_leakproof; /* is fetch SubscriptRef leakproof? */
|
|
bool store_leakproof; /* is assignment SubscriptRef leakproof? */
|
|
} SubscriptRoutines;
|
|
|
|
#endif /* SUBSCRIPTING_H */
|