aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/analyze.c9
-rw-r--r--src/backend/parser/parse_expr.c28
-rw-r--r--src/backend/parser/parse_node.c167
-rw-r--r--src/backend/parser/parse_target.c52
4 files changed, 133 insertions, 123 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 125ee5d84b2..7f5773582b0 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 7fc8d63ff0e..e5593535292 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 ece81697e6a..3a7a858e3ad 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;
+ sbsref = (SubscriptingRef *) makeNode(SubscriptingRef);
+ if (assignFrom != NULL)
+ sbsref->refassgnexpr = (Expr *) assignFrom;
+
+ sbsref->refcontainertype = containerType;
+ sbsref->refelemtype = elementType;
+ sbsref->reftypmod = containerTypMod;
/* refcollid will be set by parse_collate.c */
- aref->refupperindexpr = upperIndexpr;
- aref->reflowerindexpr = lowerIndexpr;
- aref->refexpr = (Expr *) arrayBase;
- aref->refassgnexpr = (Expr *) assignFrom;
+ sbsref->refupperindexpr = upperIndexpr;
+ sbsref->reflowerindexpr = lowerIndexpr;
+ sbsref->refindexprslice = indexprSlice;
+ sbsref->refexpr = (Expr *) containerBase;
+ sbsref->refassgnexpr = (Expr *) assignFrom;
- return aref;
+ return sbsref;
}
/*
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 561d8774f47..0e9598ebfe4 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);
-
- /* If target was a domain over array, need to coerce up to the domain */
- if (arrayType != targetTypeId)
+ result = (Node *) transformContainerSubscripts(pstate,
+ basenode,
+ containerType,
+ elementTypeId,
+ containerTypMod,
+ subscripts,
+ rhs);
+
+ /* If target was a domain over container, need to coerce up to the domain */
+ if (containerType != targetTypeId)
{
Oid resulttype = exprType(result);