1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-07 00:36:50 +03:00

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
This commit is contained in:
Alvaro Herrera
2019-02-01 12:50:32 -03:00
parent f831d4accd
commit 558d77f20e
26 changed files with 555 additions and 523 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
/*

View File

@ -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);