0002-Base-implementation-of-subscripting-mechanism-v6.patch
application/octet-stream
Filename: 0002-Base-implementation-of-subscripting-mechanism-v6.patch
Type: application/octet-stream
Part: 1
Patch
Format: format-patch
Series: patch v6-0002
Subject: Base implementation of subscripting mechanism
| File | + | − |
|---|---|---|
| contrib/pg_stat_statements/pg_stat_statements.c | 1 | 0 |
| src/backend/catalog/heap.c | 4 | 2 |
| src/backend/catalog/pg_type.c | 15 | 1 |
| src/backend/commands/typecmds.c | 70 | 8 |
| src/backend/executor/execExpr.c | 16 | 18 |
| src/backend/executor/execExprInterp.c | 51 | 130 |
| src/backend/nodes/copyfuncs.c | 2 | 0 |
| src/backend/nodes/equalfuncs.c | 2 | 0 |
| src/backend/nodes/nodeFuncs.c | 3 | 3 |
| src/backend/nodes/outfuncs.c | 2 | 0 |
| src/backend/nodes/readfuncs.c | 2 | 0 |
| src/backend/parser/parse_expr.c | 33 | 17 |
| src/backend/parser/parse_node.c | 88 | 171 |
| src/backend/parser/parse_target.c | 57 | 49 |
| src/backend/utils/adt/ruleutils.c | 10 | 10 |
| src/backend/utils/cache/lsyscache.c | 23 | 0 |
| src/include/catalog/pg_class.h | 1 | 1 |
| src/include/catalog/pg_type_fn.h | 3 | 1 |
| src/include/catalog/pg_type.h | 178 | 172 |
| src/include/c.h | 2 | 0 |
| src/include/executor/execExpr.h | 44 | 39 |
| src/include/nodes/primnodes.h | 24 | 17 |
| src/include/nodes/subscripting.h | 42 | 0 |
| src/include/parser/parse_node.h | 11 | 8 |
| src/include/utils/lsyscache.h | 1 | 0 |
From 8e52131b04f928d74e280bfe46271ef0fcca35a1 Mon Sep 17 00:00:00 2001
From: erthalion <9erthalion6@gmail.com>
Date: Sun, 28 Jan 2018 17:58:20 +0100
Subject: [PATCH 2/5] Base implementation of subscripting mechanism
---
contrib/pg_stat_statements/pg_stat_statements.c | 1 +
src/backend/catalog/heap.c | 6 +-
src/backend/catalog/pg_type.c | 16 +-
src/backend/commands/typecmds.c | 78 +++++-
src/backend/executor/execExpr.c | 34 ++-
src/backend/executor/execExprInterp.c | 181 ++++--------
src/backend/nodes/copyfuncs.c | 2 +
src/backend/nodes/equalfuncs.c | 2 +
src/backend/nodes/nodeFuncs.c | 6 +-
src/backend/nodes/outfuncs.c | 2 +
src/backend/nodes/readfuncs.c | 2 +
src/backend/parser/parse_expr.c | 50 ++--
src/backend/parser/parse_node.c | 259 ++++++------------
src/backend/parser/parse_target.c | 106 +++----
src/backend/utils/adt/ruleutils.c | 20 +-
src/backend/utils/cache/lsyscache.c | 23 ++
src/include/c.h | 2 +
src/include/catalog/pg_class.h | 2 +-
src/include/catalog/pg_type.h | 350 ++++++++++++------------
src/include/catalog/pg_type_fn.h | 4 +-
src/include/executor/execExpr.h | 83 +++---
src/include/nodes/primnodes.h | 41 +--
src/include/nodes/subscripting.h | 42 +++
src/include/parser/parse_node.h | 19 +-
src/include/utils/lsyscache.h | 1 +
25 files changed, 685 insertions(+), 647 deletions(-)
create mode 100644 src/include/nodes/subscripting.h
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 0d42eb4d57..a87054d4db 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -2512,6 +2512,7 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
JumbleExpr(jstate, (Node *) sbsref->reflowerindexpr);
JumbleExpr(jstate, (Node *) sbsref->refexpr);
JumbleExpr(jstate, (Node *) sbsref->refassgnexpr);
+ APP_JUMB(sbsref->refnestedfunc);
}
break;
case T_FuncExpr:
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 774c07b03a..3cdd69ce82 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -981,7 +981,8 @@ AddNewRelationType(const char *typeName,
-1, /* typmod */
0, /* array dimensions for typBaseType */
false, /* Type NOT NULL */
- InvalidOid); /* rowtypes never have a collation */
+ InvalidOid, /* rowtypes never have a collation */
+ InvalidOid); /* typsubshandler - none */
}
/* --------------------------------
@@ -1251,7 +1252,8 @@ heap_create_with_catalog(const char *relname,
-1, /* typmod */
0, /* array dimensions for typBaseType */
false, /* Type NOT NULL */
- InvalidOid); /* rowtypes never have a collation */
+ InvalidOid, /* rowtypes never have a collation */
+ F_ARRAY_SUBSCRIPT_HANDLER); /* array implementation */
pfree(relarrayname);
}
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 660ac5b7c9..71d26ce344 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -118,6 +118,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(-1);
values[Anum_pg_type_typndims - 1] = Int32GetDatum(0);
values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_type_typsubshandler - 1] = ObjectIdGetDatum(InvalidOid);
nulls[Anum_pg_type_typdefaultbin - 1] = true;
nulls[Anum_pg_type_typdefault - 1] = true;
nulls[Anum_pg_type_typacl - 1] = true;
@@ -164,6 +165,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
false,
InvalidOid,
InvalidOid,
+ InvalidOid,
NULL,
false);
@@ -222,7 +224,8 @@ TypeCreate(Oid newTypeOid,
int32 typeMod,
int32 typNDims, /* Array dimensions for baseType */
bool typeNotNull,
- Oid typeCollation)
+ Oid typeCollation,
+ Oid subscriptingHandlerProcedure)
{
Relation pg_type_desc;
Oid typeObjectId;
@@ -362,6 +365,7 @@ TypeCreate(Oid newTypeOid,
values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(typeMod);
values[Anum_pg_type_typndims - 1] = Int32GetDatum(typNDims);
values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(typeCollation);
+ values[Anum_pg_type_typsubshandler - 1] = ObjectIdGetDatum(subscriptingHandlerProcedure);
/*
* initialize the default binary value for this type. Check for nulls of
@@ -479,6 +483,7 @@ TypeCreate(Oid newTypeOid,
isImplicitArray,
baseType,
typeCollation,
+ subscriptingHandlerProcedure,
(defaultTypeBin ?
stringToNode(defaultTypeBin) :
NULL),
@@ -525,6 +530,7 @@ GenerateTypeDependencies(Oid typeNamespace,
bool isImplicitArray,
Oid baseType,
Oid typeCollation,
+ Oid subscriptingHandlerProcedure,
Node *defaultExpr,
bool rebuild)
{
@@ -677,6 +683,14 @@ GenerateTypeDependencies(Oid typeNamespace,
/* Normal dependency on the default expression. */
if (defaultExpr)
recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
+
+ if (OidIsValid(subscriptingHandlerProcedure))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = subscriptingHandlerProcedure;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
}
/*
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 899a5c4cd4..4681a3e050 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -94,6 +94,7 @@ static Oid findTypeSendFunction(List *procname, Oid typeOid);
static Oid findTypeTypmodinFunction(List *procname);
static Oid findTypeTypmodoutFunction(List *procname);
static Oid findTypeAnalyzeFunction(List *procname, Oid typeOid);
+static Oid findTypeSubscriptingFunction(List *procname, Oid typeOid, bool parseFunc);
static Oid findRangeSubOpclass(List *opcname, Oid subtype);
static Oid findRangeCanonicalFunction(List *procname, Oid typeOid);
static Oid findRangeSubtypeDiffFunction(List *procname, Oid subtype);
@@ -125,6 +126,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
List *typmodinName = NIL;
List *typmodoutName = NIL;
List *analyzeName = NIL;
+ List *subscriptingParseName = NIL;
char category = TYPCATEGORY_USER;
bool preferred = false;
char delimiter = DEFAULT_TYPDELIM;
@@ -143,6 +145,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
DefElem *typmodinNameEl = NULL;
DefElem *typmodoutNameEl = NULL;
DefElem *analyzeNameEl = NULL;
+ DefElem *subscriptingParseNameEl = NULL;
DefElem *categoryEl = NULL;
DefElem *preferredEl = NULL;
DefElem *delimiterEl = NULL;
@@ -165,6 +168,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
Oid resulttype;
ListCell *pl;
ObjectAddress address;
+ Oid subscriptingParseOid = InvalidOid;
/*
* As of Postgres 8.4, we require superuser privilege to create a base
@@ -264,6 +268,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
else if (strcmp(defel->defname, "analyze") == 0 ||
strcmp(defel->defname, "analyse") == 0)
defelp = &analyzeNameEl;
+ else if (strcmp(defel->defname, "subscripting_handler") == 0)
+ defelp = &subscriptingParseNameEl;
else if (strcmp(defel->defname, "category") == 0)
defelp = &categoryEl;
else if (strcmp(defel->defname, "preferred") == 0)
@@ -334,6 +340,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
typmodoutName = defGetQualifiedName(typmodoutNameEl);
if (analyzeNameEl)
analyzeName = defGetQualifiedName(analyzeNameEl);
+ if (subscriptingParseNameEl)
+ subscriptingParseName = defGetQualifiedName(subscriptingParseNameEl);
if (categoryEl)
{
char *p = defGetString(categoryEl);
@@ -515,6 +523,10 @@ DefineType(ParseState *pstate, List *names, List *parameters)
if (analyzeName)
analyzeOid = findTypeAnalyzeFunction(analyzeName, typoid);
+ if (subscriptingParseName)
+ subscriptingParseOid = findTypeSubscriptingFunction(subscriptingParseName,
+ typoid, true);
+
/*
* Check permissions on functions. We choose to require the creator/owner
* of a type to also own the underlying functions. Since creating a type
@@ -634,7 +646,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
-1, /* typMod (Domains only) */
0, /* Array Dimensions of typbasetype */
false, /* Type NOT NULL */
- collation); /* type's collation */
+ collation, /* type's collation */
+ subscriptingParseOid); /* subscripting procedure */
Assert(typoid == address.objectId);
/*
@@ -675,7 +688,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
-1, /* typMod (Domains only) */
0, /* Array dimensions of typbasetype */
false, /* Type NOT NULL */
- collation); /* type's collation */
+ collation, /* type's collation */
+ F_ARRAY_SUBSCRIPT_HANDLER);
pfree(array_type);
@@ -738,6 +752,7 @@ DefineDomain(CreateDomainStmt *stmt)
Oid receiveProcedure;
Oid sendProcedure;
Oid analyzeProcedure;
+ Oid subscriptingHandlerProcedure;
bool byValue;
char category;
char delimiter;
@@ -865,6 +880,9 @@ DefineDomain(CreateDomainStmt *stmt)
/* Analysis function */
analyzeProcedure = baseType->typanalyze;
+ /* Subscripting functions */
+ subscriptingHandlerProcedure = baseType->typsubshandler;
+
/* Inherited default value */
datum = SysCacheGetAttr(TYPEOID, typeTup,
Anum_pg_type_typdefault, &isnull);
@@ -1069,7 +1087,8 @@ DefineDomain(CreateDomainStmt *stmt)
basetypeMod, /* typeMod value */
typNDims, /* Array dimensions for base type */
typNotNull, /* Type NOT NULL */
- domaincoll); /* type's collation */
+ domaincoll, /* type's collation */
+ subscriptingHandlerProcedure); /* subscripting procedure */
/*
* Create the array type that goes with it.
@@ -1109,7 +1128,8 @@ DefineDomain(CreateDomainStmt *stmt)
-1, /* typMod (Domains only) */
0, /* Array dimensions of typbasetype */
false, /* Type NOT NULL */
- domaincoll); /* type's collation */
+ domaincoll, /* type's collation */
+ F_ARRAY_SUBSCRIPT_HANDLER); /* array subscripting implementation */
pfree(domainArrayName);
@@ -1224,7 +1244,8 @@ DefineEnum(CreateEnumStmt *stmt)
-1, /* typMod (Domains only) */
0, /* Array dimensions of typbasetype */
false, /* Type NOT NULL */
- InvalidOid); /* type's collation */
+ InvalidOid, /* type's collation */
+ InvalidOid); /* typsubshandler - none */
/* Enter the enum's values into pg_enum */
EnumValuesCreate(enumTypeAddr.objectId, stmt->vals);
@@ -1264,7 +1285,8 @@ DefineEnum(CreateEnumStmt *stmt)
-1, /* typMod (Domains only) */
0, /* Array dimensions of typbasetype */
false, /* Type NOT NULL */
- InvalidOid); /* type's collation */
+ InvalidOid, /* type's collation */
+ F_ARRAY_SUBSCRIPT_HANDLER); /* array subscripting implementation */
pfree(enumArrayName);
@@ -1573,7 +1595,8 @@ DefineRange(CreateRangeStmt *stmt)
-1, /* typMod (Domains only) */
0, /* Array dimensions of typbasetype */
false, /* Type NOT NULL */
- InvalidOid); /* type's collation (ranges never have one) */
+ InvalidOid, /* type's collation (ranges never have one) */
+ InvalidOid); /* typsubshandler - none */
Assert(typoid == address.objectId);
/* Create the entry in pg_range */
@@ -1615,7 +1638,8 @@ DefineRange(CreateRangeStmt *stmt)
-1, /* typMod (Domains only) */
0, /* Array dimensions of typbasetype */
false, /* Type NOT NULL */
- InvalidOid); /* typcollation */
+ InvalidOid, /* typcollation */
+ F_ARRAY_SUBSCRIPT_HANDLER); /* array subscripting implementation */
pfree(rangeArrayName);
@@ -1959,6 +1983,43 @@ findTypeAnalyzeFunction(List *procname, Oid typeOid)
return procOid;
}
+static Oid
+findTypeSubscriptingFunction(List *procname, Oid typeOid, bool parseFunc)
+{
+ Oid argList[2];
+ Oid procOid;
+ int nargs;
+
+ if (parseFunc)
+ {
+ /*
+ * Subscripting function parse always take two INTERNAL argument and
+ * return INTERNAL.
+ */
+ argList[0] = INTERNALOID;
+ nargs = 1;
+ }
+ else
+ {
+ /*
+ * Subscripting functions fetch/assign always take one typeOid
+ * argument, one INTERNAL argument and return typeOid.
+ */
+ argList[0] = typeOid;
+ argList[1] = INTERNALOID;
+ nargs = 2;
+ }
+
+ procOid = LookupFuncName(procname, nargs, argList, true);
+ if (!OidIsValid(procOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("function %s does not exist",
+ func_signature_string(procname, nargs, NIL, argList))));
+
+ return procOid;
+}
+
/*
* Find suitable support functions and opclasses for a range type.
*/
@@ -2312,6 +2373,7 @@ AlterDomainDefault(List *names, Node *defaultRaw)
false, /* a domain isn't an implicit array */
typTup->typbasetype,
typTup->typcollation,
+ typTup->typsubshandler,
defaultExpr,
true); /* Rebuild is true */
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 4e733f52a0..1561aa61dd 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -2420,34 +2420,32 @@ ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state)
}
/*
- * Prepare evaluation of an ArrayRef expression.
+ * Prepare evaluation of a SubscriptingRef expression.
*/
static void
-ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref,
+ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref,
ExprState *state, Datum *resv, bool *resnull)
{
- bool isAssignment = (aref->refassgnexpr != NULL);
- ArrayRefState *arefstate = palloc0(sizeof(ArrayRefState));
- List *adjust_jumps = NIL;
- ListCell *lc;
- int i;
-
- /* Fill constant fields of ArrayRefState */
- arefstate->isassignment = isAssignment;
- arefstate->refelemtype = aref->refelemtype;
- arefstate->refattrlength = get_typlen(aref->refarraytype);
- get_typlenbyvalalign(aref->refelemtype,
- &arefstate->refelemlength,
- &arefstate->refelembyval,
- &arefstate->refelemalign);
+ bool isAssignment = (sbsref->refassgnexpr != NULL);
+ SubscriptingRefState *sbsrefstate = palloc0(sizeof(SubscriptingRefState));
+ List *adjust_jumps = NIL;
+ ListCell *lc;
+ int i;
+ RegProcedure typsubshandler = get_typsubsprocs(sbsref->refcontainertype);
+
+ /* Fill constant fields of SubscriptingRefState */
+ sbsrefstate->isassignment = isAssignment;
+ sbsrefstate->refelemtype = sbsref->refelemtype;
+ sbsrefstate->refattrlength = get_typlen(sbsref->refcontainertype);
+ sbsrefstate->sbsroutines = (SbsRoutines *) OidFunctionCall0(typsubshandler);
/*
* Evaluate array input. It's safe to do so into resv/resnull, because we
* won't use that as target for any of the other subexpressions, and it'll
- * be overwritten by the final EEOP_ARRAYREF_FETCH/ASSIGN step, which is
+ * be overwritten by the final EEOP_SBSREF_FETCH/ASSIGN step, which is
* pushed last.
*/
- ExecInitExprRec(aref->refexpr, state, resv, resnull);
+ ExecInitExprRec(sbsref->refexpr, state, resv, resnull);
/*
* If refexpr yields NULL, and it's a fetch, then result is NULL. We can
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 6bcbf0e0cf..8d57cf5df8 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -2943,197 +2943,118 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext
}
/*
- * Process a subscript in an ArrayRef expression.
+ * Process a subscript in a SubscriptingRef expression.
*
* If subscript is NULL, throw error in assignment case, or in fetch case
* set result to NULL and return false (instructing caller to skip the rest
- * of the ArrayRef sequence).
+ * of the SubscriptingRef sequence).
*
* Subscript expression result is in subscriptvalue/subscriptnull.
* On success, integer subscript value has been saved in upperindex[] or
* lowerindex[] for use later.
*/
bool
-ExecEvalArrayRefSubscript(ExprState *state, ExprEvalStep *op)
+ExecEvalSubscriptingRef(ExprState *state, ExprEvalStep *op)
{
- ArrayRefState *arefstate = op->d.arrayref_subscript.state;
- int *indexes;
- int off;
+ SubscriptingRefState *sbsrefstate = op->d.sbsref_subscript.state;
+ Datum *indexes;
+ int off;
/* If any index expr yields NULL, result is NULL or error */
- if (arefstate->subscriptnull)
+ if (sbsrefstate->subscriptnull)
{
- if (arefstate->isassignment)
+ if (sbsrefstate->isassignment)
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
- errmsg("array subscript in assignment must not be null")));
+ errmsg("subscript in assignment must not be null")));
*op->resnull = true;
return false;
}
/* Convert datum to int, save in appropriate place */
- if (op->d.arrayref_subscript.isupper)
- indexes = arefstate->upperindex;
+ if (op->d.sbsref_subscript.isupper)
+ indexes = sbsrefstate->upper;
else
- indexes = arefstate->lowerindex;
- off = op->d.arrayref_subscript.off;
+ indexes = sbsrefstate->lower;
+ off = op->d.sbsref_subscript.off;
- indexes[off] = DatumGetInt32(arefstate->subscriptvalue);
+ indexes[off] = sbsrefstate->subscriptvalue;
return true;
}
/*
- * Evaluate ArrayRef fetch.
+ * Evaluate SubscriptingRef fetch.
*
- * Source array is in step's result variable.
+ * Source container is in step's result variable.
*/
void
-ExecEvalArrayRefFetch(ExprState *state, ExprEvalStep *op)
+ExecEvalSubscriptingRefFetch(ExprState *state, ExprEvalStep *op)
{
- ArrayRefState *arefstate = op->d.arrayref.state;
+ SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
+ SbsRoutines *sbsroutines = sbsrefstate->sbsroutines;
- /* Should not get here if source array (or any subscript) is null */
+ /* Should not get here if source container (or any subscript) is null */
Assert(!(*op->resnull));
- if (arefstate->numlower == 0)
- {
- /* Scalar case */
- *op->resvalue = array_get_element(*op->resvalue,
- arefstate->numupper,
- arefstate->upperindex,
- arefstate->refattrlength,
- arefstate->refelemlength,
- arefstate->refelembyval,
- arefstate->refelemalign,
- op->resnull);
- }
- else
- {
- /* Slice case */
- *op->resvalue = array_get_slice(*op->resvalue,
- arefstate->numupper,
- arefstate->upperindex,
- arefstate->lowerindex,
- arefstate->upperprovided,
- arefstate->lowerprovided,
- arefstate->refattrlength,
- arefstate->refelemlength,
- arefstate->refelembyval,
- arefstate->refelemalign);
- }
+ *op->resvalue = sbsroutines->fetch(*op->resvalue, sbsrefstate);
+ *op->resnull = sbsrefstate->resnull;
}
/*
- * Compute old array element/slice value for an ArrayRef assignment
- * expression. Will only be generated if the new-value subexpression
- * contains ArrayRef or FieldStore. The value is stored into the
- * ArrayRefState's prevvalue/prevnull fields.
+ * Compute old container element/slice value for a SubscriptingRef assignment
+ * expression. Will only be generated if the new-value subexpression
+ * contains SubscriptingRef or FieldStore. The value is stored into the
+ * SubscriptingRefState's prevvalue/prevnull fields.
*/
void
-ExecEvalArrayRefOld(ExprState *state, ExprEvalStep *op)
+ExecEvalSubscriptingRefOld(ExprState *state, ExprEvalStep *op)
{
- ArrayRefState *arefstate = op->d.arrayref.state;
+ SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
+ SbsRoutines *sbsroutines = sbsrefstate->sbsroutines;
if (*op->resnull)
{
- /* whole array is null, so any element or slice is too */
- arefstate->prevvalue = (Datum) 0;
- arefstate->prevnull = true;
- }
- else if (arefstate->numlower == 0)
- {
- /* Scalar case */
- arefstate->prevvalue = array_get_element(*op->resvalue,
- arefstate->numupper,
- arefstate->upperindex,
- arefstate->refattrlength,
- arefstate->refelemlength,
- arefstate->refelembyval,
- arefstate->refelemalign,
- &arefstate->prevnull);
+ /* whole container is null, so any element or slice is too */
+ sbsrefstate->prevvalue = (Datum) 0;
+ sbsrefstate->prevnull = true;
}
else
{
- /* Slice case */
- /* this is currently unreachable */
- arefstate->prevvalue = array_get_slice(*op->resvalue,
- arefstate->numupper,
- arefstate->upperindex,
- arefstate->lowerindex,
- arefstate->upperprovided,
- arefstate->lowerprovided,
- arefstate->refattrlength,
- arefstate->refelemlength,
- arefstate->refelembyval,
- arefstate->refelemalign);
- arefstate->prevnull = false;
+ sbsrefstate->prevvalue = sbsroutines->fetch(*op->resvalue, sbsrefstate);
+
+ if (sbsrefstate->numlower != 0)
+ sbsrefstate->prevnull = false;
+
}
}
/*
- * Evaluate ArrayRef assignment.
+ * Evaluate SubscriptingRef assignment.
*
- * Input array (possibly null) is in result area, replacement value is in
- * ArrayRefState's replacevalue/replacenull.
+ * Input container (possibly null) is in result area, replacement value is in
+ * SubscriptingRefState's replacevalue/replacenull.
*/
void
-ExecEvalArrayRefAssign(ExprState *state, ExprEvalStep *op)
+ExecEvalSubscriptingRefAssign(ExprState *state, ExprEvalStep *op)
{
- ArrayRefState *arefstate = op->d.arrayref.state;
+ SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
+ SbsRoutines *sbsroutines = sbsrefstate->sbsroutines;
/*
- * For an assignment to a fixed-length array type, both the original array
- * and the value to be assigned into it must be non-NULL, else we punt and
- * return the original array.
+ * For an assignment to a fixed-length container type, both the original
+ * container and the value to be assigned into it must be non-NULL, else we
+ * punt and return the original container.
*/
- if (arefstate->refattrlength > 0) /* fixed-length array? */
+ if (sbsrefstate->refattrlength > 0)
{
- if (*op->resnull || arefstate->replacenull)
+ if (*op->resnull || sbsrefstate->replacenull)
return;
}
- /*
- * For assignment to varlena arrays, we handle a NULL original array by
- * substituting an empty (zero-dimensional) array; insertion of the new
- * element will result in a singleton array value. It does not matter
- * whether the new element is NULL.
- */
- if (*op->resnull)
- {
- *op->resvalue = PointerGetDatum(construct_empty_array(arefstate->refelemtype));
- *op->resnull = false;
- }
-
- if (arefstate->numlower == 0)
- {
- /* Scalar case */
- *op->resvalue = array_set_element(*op->resvalue,
- arefstate->numupper,
- arefstate->upperindex,
- arefstate->replacevalue,
- arefstate->replacenull,
- arefstate->refattrlength,
- arefstate->refelemlength,
- arefstate->refelembyval,
- arefstate->refelemalign);
- }
- else
- {
- /* Slice case */
- *op->resvalue = array_set_slice(*op->resvalue,
- arefstate->numupper,
- arefstate->upperindex,
- arefstate->lowerindex,
- arefstate->upperprovided,
- arefstate->lowerprovided,
- arefstate->replacevalue,
- arefstate->replacenull,
- arefstate->refattrlength,
- arefstate->refelemlength,
- arefstate->refelembyval,
- arefstate->refelemalign);
- }
+ sbsrefstate->resnull = *op->resnull;
+ *op->resvalue = sbsroutines->assign(*op->resvalue, sbsrefstate);
+ *op->resnull = sbsrefstate->resnull;
}
/*
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 2e8702b643..2c95423203 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -1427,8 +1427,10 @@ _copySubscriptingRef(const SubscriptingRef *from)
COPY_SCALAR_FIELD(refcontainertype);
COPY_SCALAR_FIELD(refelemtype);
+ COPY_SCALAR_FIELD(refassgntype);
COPY_SCALAR_FIELD(reftypmod);
COPY_SCALAR_FIELD(refcollid);
+ COPY_SCALAR_FIELD(refnestedfunc);
COPY_NODE_FIELD(refupperindexpr);
COPY_NODE_FIELD(reflowerindexpr);
COPY_NODE_FIELD(refexpr);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index f206a7d324..3a6fb549a7 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -268,8 +268,10 @@ _equalSubscriptingRef(const SubscriptingRef *a, const SubscriptingRef *b)
{
COMPARE_SCALAR_FIELD(refcontainertype);
COMPARE_SCALAR_FIELD(refelemtype);
+ COMPARE_SCALAR_FIELD(refassgntype);
COMPARE_SCALAR_FIELD(reftypmod);
COMPARE_SCALAR_FIELD(refcollid);
+ COMPARE_SCALAR_FIELD(refnestedfunc);
COMPARE_NODE_FIELD(refupperindexpr);
COMPARE_NODE_FIELD(reflowerindexpr);
COMPARE_NODE_FIELD(refexpr);
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index ab3b021da2..f99235225b 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -70,9 +70,9 @@ exprType(const Node *expr)
{
const SubscriptingRef *sbsref = (const SubscriptingRef *) expr;
- /* slice and/or store operations yield the array type */
- if (arrayref->reflowerindexpr || arrayref->refassgnexpr)
- type = arrayref->refarraytype;
+ /* slice and/or store operations yield the container type */
+ if (IsAssignment(sbsref) || sbsref->reflowerindexpr)
+ type = sbsref->refcontainertype;
else
type = sbsref->refelemtype;
}
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 3cb0576f7b..3830ea5674 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -1187,8 +1187,10 @@ _outSubscriptingRef(StringInfo str, const SubscriptingRef *node)
WRITE_OID_FIELD(refcontainertype);
WRITE_OID_FIELD(refelemtype);
+ WRITE_OID_FIELD(refassgntype);
WRITE_INT_FIELD(reftypmod);
WRITE_OID_FIELD(refcollid);
+ WRITE_OID_FIELD(refnestedfunc);
WRITE_NODE_FIELD(refupperindexpr);
WRITE_NODE_FIELD(reflowerindexpr);
WRITE_NODE_FIELD(refexpr);
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 99c63ad29a..4ff3f44d6d 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -649,8 +649,10 @@ _readSubscriptingRef(void)
READ_OID_FIELD(refcontainertype);
READ_OID_FIELD(refelemtype);
+ READ_OID_FIELD(refassgntype);
READ_INT_FIELD(reftypmod);
READ_OID_FIELD(refcollid);
+ READ_OID_FIELD(refnestedfunc);
READ_NODE_FIELD(refupperindexpr);
READ_NODE_FIELD(reflowerindexpr);
READ_NODE_FIELD(refexpr);
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index b2f5e46e3b..fa9ce4dbd4 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -434,15 +434,17 @@ unknown_attribute(ParseState *pstate, Node *relref, const char *attname,
static Node *
transformIndirection(ParseState *pstate, A_Indirection *ind)
{
- Node *last_srf = pstate->p_last_srf;
- Node *result = transformExprRecurse(pstate, ind->arg);
+ Node *last_srf = pstate->p_last_srf;
+ Node *result = transformExprRecurse(pstate, ind->arg);
+ SbsRoutines *sbsroutines;
+ SubscriptingRef *sbsref;
List *subscripts = NIL;
int location = exprLocation(result);
ListCell *i;
/*
* We have to split any field-selection operations apart from
- * subscripting. Adjacent A_Indices nodes have to be treated as a single
+ * subscripting. Adjacent A_Indices nodes have to be treated as a single
* multidimensional subscript operation.
*/
foreach(i, ind->indirection)
@@ -466,13 +468,20 @@ 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);
+ {
+ sbsref = transformContainerSubscripts(pstate,
+ result,
+ exprType(result),
+ InvalidOid,
+ exprTypmod(result),
+ subscripts,
+ NULL);
+
+ sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype);
+ sbsref = sbsroutines->prepare(false, sbsref);
+ sbsroutines->validate(false, sbsref, pstate);
+ result = (Node *) sbsref;
+ }
subscripts = NIL;
newresult = ParseFuncOrColumn(pstate,
@@ -489,13 +498,20 @@ 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);
+ {
+ sbsref = transformContainerSubscripts(pstate,
+ result,
+ exprType(result),
+ InvalidOid,
+ exprTypmod(result),
+ subscripts,
+ NULL);
+
+ sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype);
+ sbsref = sbsroutines->prepare(false, sbsref);
+ sbsroutines->validate(false, sbsref, pstate);
+ result = (Node *) sbsref;
+ }
return result;
}
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index d2672882d7..e72e35450e 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -203,31 +203,23 @@ 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
- * an array type.
+ * On entry, containerType/containerTypmod are modified if necessary to
+ * identify the actual container type and typmod.
*/
-Oid
-transformArrayType(Oid *arrayType, int32 *arrayTypmod)
+void
+transformContainerType(Oid *containerType, int32 *containerTypmod)
{
- Oid origArrayType = *arrayType;
- Oid elementType;
- HeapTuple type_tuple_array;
- Form_pg_type type_struct_array;
-
/*
* 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
@@ -236,87 +228,70 @@ transformArrayType(Oid *arrayType, int32 *arrayTypmod)
* 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;
-
- /* 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);
-
- /* needn't check typisdefined since this will fail anyway */
-
- elementType = type_struct_array->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))));
-
- ReleaseSysCache(type_tuple_array);
-
- return elementType;
+ if (*containerType == INT2VECTOROID)
+ *containerType = INT2ARRAYOID;
+ else if (*containerType == OIDVECTOROID)
+ *containerType = OIDARRAYOID;
}
/*
- * transformArraySubscripts()
- * Transform array subscripting. This is used for both
- * array fetch and array assignment.
+ * transformContainerSubscripts()
+ * Transform container 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,
- * 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.)
+ * For both cases, this function contains only general subscripting logic while
+ * type-specific logic (e.g. type verifications and coersion) is placen in
+ * separate procedure indicated by typsubshandler. There is only one exception
+ * for now about domain-over-container, if the source container is of a
+ * domain-over-container type, the result is of the base container 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.) An error will appear in case if current container type
+ * doesn't have a subscripting procedure.
*
- * 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;
- ListCell *idx;
- ArrayRef *aref;
+ bool isSlice = false;
+ List *upperIndexpr = NIL;
+ List *lowerIndexpr = NIL;
+ List *indexprSlice = NIL;
+ ListCell *idx;
+ 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.
- */
- if (!OidIsValid(elementType))
- elementType = transformArrayType(&arrayType, &arrayTypMod);
+ /* Identify the actual container type and element type involved */
+ 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,
+ * the subscript expression means an 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.
@@ -345,29 +320,6 @@ transformArraySubscripts(ParseState *pstate,
if (ai->lidx)
{
subexpr = transformExpr(pstate, ai->lidx, pstate->p_expr_kind);
- /* If it's not int4 already, try to coerce */
- subexpr = coerce_to_target_type(pstate,
- subexpr, exprType(subexpr),
- INT4OID, -1,
- COERCION_ASSIGNMENT,
- COERCE_IMPLICIT_CAST,
- -1);
- if (subexpr == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("array subscript must have type integer"),
- parser_errposition(pstate, exprLocation(ai->lidx))));
- }
- else if (!ai->is_slice)
- {
- /* Make a constant 1 */
- subexpr = (Node *) makeConst(INT4OID,
- -1,
- InvalidOid,
- sizeof(int32),
- Int32GetDatum(1),
- false,
- true); /* pass by value */
}
else
{
@@ -375,77 +327,42 @@ transformArraySubscripts(ParseState *pstate,
subexpr = NULL;
}
lowerIndexpr = lappend(lowerIndexpr, subexpr);
+ indexprSlice = lappend(indexprSlice, ai);
}
- else
- Assert(ai->lidx == NULL && !ai->is_slice);
-
- if (ai->uidx)
- {
- subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind);
- /* If it's not int4 already, try to coerce */
- subexpr = coerce_to_target_type(pstate,
- subexpr, exprType(subexpr),
- INT4OID, -1,
- COERCION_ASSIGNMENT,
- COERCE_IMPLICIT_CAST,
- -1);
- if (subexpr == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("array subscript must have type integer"),
- parser_errposition(pstate, exprLocation(ai->uidx))));
- }
- else
- {
- /* Slice with omitted upper bound, put NULL into the list */
- Assert(isSlice && ai->is_slice);
- subexpr = NULL;
- }
+ subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind);
upperIndexpr = lappend(upperIndexpr, subexpr);
}
/*
- * If doing an array store, coerce the source value to the right type.
- * (This should agree with the coercion done by transformAssignedExpr.)
+ * Ready to build the SubscriptingRef node.
*/
+ sbsref = (SubscriptingRef *) makeNode(SubscriptingRef);
if (assignFrom != NULL)
- {
- Oid typesource = exprType(assignFrom);
- Oid typeneeded = isSlice ? arrayType : elementType;
- Node *newFrom;
-
- newFrom = coerce_to_target_type(pstate,
- assignFrom, typesource,
- typeneeded, arrayTypMod,
- COERCION_ASSIGNMENT,
- COERCE_IMPLICIT_CAST,
- -1);
- if (newFrom == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("array assignment requires type %s"
- " but expression is of type %s",
- format_type_be(typeneeded),
- format_type_be(typesource)),
- errhint("You will need to rewrite or cast the expression."),
- parser_errposition(pstate, exprLocation(assignFrom))));
- assignFrom = newFrom;
- }
+ sbsref->refassgnexpr = (Expr *) assignFrom;
- /*
- * Ready to build the ArrayRef node.
- */
- aref = makeNode(ArrayRef);
- aref->refarraytype = arrayType;
- aref->refelemtype = elementType;
- aref->reftypmod = arrayTypMod;
+ sbsref->refcontainertype = containerType;
+ 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;
+
+ return sbsref;
+}
+
+SbsRoutines*
+getSubscriptingRoutines(Oid containerType)
+{
+ RegProcedure typsubshandler = get_typsubsprocs(containerType);
+
+ if (!OidIsValid(typsubshandler))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("cannot subscript type %s because it does not support subscripting",
+ format_type_be(containerType))));
- return aref;
+ return (SbsRoutines *) OidFunctionCall0(typsubshandler);
}
/*
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index e4c8a8386e..0dcb467b94 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -838,27 +838,22 @@ transformAssignmentIndirection(ParseState *pstate,
location);
}
- /* base case: just coerce RHS to match target type ID */
-
- result = coerce_to_target_type(pstate,
- rhs, exprType(rhs),
- targetTypeId, targetTypMod,
- COERCION_ASSIGNMENT,
- COERCE_IMPLICIT_CAST,
- -1);
- if (result == NULL)
+ /*
+ * Base case: just coerce RHS to match target type ID.
+ * It's necessary only for field selection, since for
+ * subscripting it's custom code who should define types.
+ */
+ if (!targetIsSubscripting)
{
- if (targetIsArray)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("array assignment to \"%s\" requires type %s"
- " but expression is of type %s",
- targetName,
- format_type_be(targetTypeId),
- format_type_be(exprType(rhs))),
- errhint("You will need to rewrite or cast the expression."),
- parser_errposition(pstate, location)));
- else
+ result = coerce_to_target_type(pstate,
+ rhs, exprType(rhs),
+ targetTypeId, targetTypMod,
+ COERCION_ASSIGNMENT,
+ COERCE_IMPLICIT_CAST,
+ -1);
+
+ if (result == NULL)
+ {
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("subfield \"%s\" is of type %s"
@@ -868,7 +863,10 @@ transformAssignmentIndirection(ParseState *pstate,
format_type_be(exprType(rhs))),
errhint("You will need to rewrite or cast the expression."),
parser_errposition(pstate, location)));
+ }
}
+ else
+ result = rhs;
return result;
}
@@ -890,57 +888,67 @@ transformAssignmentSubscripts(ParseState *pstate,
int location)
{
Node *result;
- Oid arrayType;
- int32 arrayTypMod;
- Oid elementTypeId;
- Oid typeNeeded;
+ Oid containerType;
+ int32 containerTypMod;
Oid collationNeeded;
+ SubscriptingRef *sbsref;
+ SbsRoutines *sbsroutines;
Assert(subscripts != NIL);
- /* Identify the actual array type and element type involved */
- arrayType = targetTypeId;
- arrayTypMod = targetTypMod;
- elementTypeId = transformArrayType(&arrayType, &arrayTypMod);
+ /* Identify the actual container type and element type involved */
+ containerType = targetTypeId;
+ containerTypMod = targetTypMod;
+
+ /* process subscripts */
+ sbsref = transformContainerSubscripts(pstate,
+ basenode,
+ containerType,
+ exprType(rhs),
+ containerTypMod,
+ subscripts,
+ rhs);
+
+ sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype);
- /* Identify type that RHS must provide */
- typeNeeded = isSlice ? arrayType : elementTypeId;
+ /*
+ * Let custom code provide necessary information about required types:
+ * refelemtype and refassgntype
+ */
+ sbsref = sbsroutines->prepare(rhs != NULL, sbsref);
/*
- * 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 an container type. In
* that case use collation of the base type.
*/
- if (arrayType == targetTypeId)
+ if (sbsref->refcontainertype == containerType)
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,
+ sbsref->refassgntype,
+ sbsref->reftypmod,
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)
+ /* Provide fully prepared subscriptinng information for custom validation */
+ sbsref->refassgnexpr = (Expr *) rhs;
+ sbsroutines->validate(rhs != NULL, sbsref, pstate);
+
+ result = (Node *) sbsref;
+
+ /* If target was a domain over container, need to coerce up to the domain */
+ if (sbsref->refcontainertype != targetTypeId)
{
- Oid resulttype = exprType(result);
+ Oid resulttype = exprType(result);
result = coerce_to_target_type(pstate,
result, resulttype,
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index f068a02526..20020eff14 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -7699,17 +7699,17 @@ get_rule_expr(Node *node, deparse_context *context,
if (need_parens)
appendStringInfoChar(buf, ')');
- /*
- * If there's a refassgnexpr, we want to print the node in the
- * format "array[subscripts] := refassgnexpr". This is not
- * legal SQL, so decompilation of INSERT or UPDATE statements
- * should always use processIndirection as part of the
- * statement-level syntax. We should only see this when
- * EXPLAIN tries to print the targetlist of a plan resulting
- * from such a statement.
- */
- if (aref->refassgnexpr)
+ if (IsAssignment(sbsref))
{
+ /*
+ * If there's a refassgnexpr, we want to print the node in the
+ * format "container[subscripts] := refassgnexpr". This is not
+ * legal SQL, so decompilation of INSERT or UPDATE statements
+ * should always use processIndirection as part of the
+ * statement-level syntax. We should only see this when
+ * EXPLAIN tries to print the targetlist of a plan resulting
+ * from such a statement.
+ */
Node *refassgnexpr;
/*
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index e8aa179347..c601b9deb7 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -3121,3 +3121,26 @@ get_range_subtype(Oid rangeOid)
else
return InvalidOid;
}
+
+/*
+ * get_typsubshandler
+ *
+ * Given the type OID, return the type's subscripting procedures, if any,
+ * through pointers in arguments.
+ */
+RegProcedure
+get_typsubsprocs(Oid typid)
+{
+ HeapTuple tp;
+
+ tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
+ if (HeapTupleIsValid(tp))
+ {
+ RegProcedure handler = ((Form_pg_type) GETSTRUCT(tp))->typsubshandler;
+ ReleaseSysCache(tp);
+
+ return handler;
+ }
+ else
+ return InvalidOid;
+}
diff --git a/src/include/c.h b/src/include/c.h
index 9b7fe87f32..f9b944e394 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -487,6 +487,8 @@ typedef struct
int indx[MAXDIM];
} IntArray;
+#define MAX_SUBSCRIPT_DEPTH 12
+
/* ----------------
* Variable-length datatypes all share the 'struct varlena' header.
*
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 26b1866c69..8ddacf8c94 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -147,7 +147,7 @@ typedef FormData_pg_class *Form_pg_class;
* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId;
* similarly, "1" in relminmxid stands for FirstMultiXactId
*/
-DATA(insert OID = 1247 ( pg_type PGNSP 71 0 PGUID 0 0 0 0 0 0 0 f f p r 30 0 t f f f f f f t n f 3 1 _null_ _null_ _null_));
+DATA(insert OID = 1247 ( pg_type PGNSP 71 0 PGUID 0 0 0 0 0 0 0 f f p r 31 0 t f f f f f f t n f 3 1 _null_ _null_ _null_));
DESCR("");
DATA(insert OID = 1249 ( pg_attribute PGNSP 75 0 PGUID 0 0 0 0 0 0 0 f f p r 22 0 f f f f f f f t n f 3 1 _null_ _null_ _null_));
DESCR("");
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 5b5b1218de..4145c6a7e7 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -199,6 +199,12 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71) BKI_SCHEMA_MACRO
*/
Oid typcollation;
+ /*
+ * Type specific subscripting logic. If typsubshandler is none, it means
+ * that this type doesn't support subscripting.
+ */
+ regproc typsubshandler;
+
#ifdef CATALOG_VARLEN /* variable-length fields start here */
/*
@@ -236,7 +242,7 @@ typedef FormData_pg_type *Form_pg_type;
* compiler constants for pg_type
* ----------------
*/
-#define Natts_pg_type 30
+#define Natts_pg_type 31
#define Anum_pg_type_typname 1
#define Anum_pg_type_typnamespace 2
#define Anum_pg_type_typowner 3
@@ -264,10 +270,10 @@ typedef FormData_pg_type *Form_pg_type;
#define Anum_pg_type_typtypmod 25
#define Anum_pg_type_typndims 26
#define Anum_pg_type_typcollation 27
-#define Anum_pg_type_typdefaultbin 28
-#define Anum_pg_type_typdefault 29
-#define Anum_pg_type_typacl 30
-
+#define Anum_pg_type_typsubshandler 28
+#define Anum_pg_type_typdefaultbin 29
+#define Anum_pg_type_typdefault 30
+#define Anum_pg_type_typacl 31
/* ----------------
* initial contents of pg_type
@@ -283,102 +289,102 @@ typedef FormData_pg_type *Form_pg_type;
*/
/* OIDS 1 - 99 */
-DATA(insert OID = 16 ( bool PGNSP PGUID 1 t b B t t \054 0 0 1000 boolin boolout boolrecv boolsend - - - c p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 16 ( bool PGNSP PGUID 1 t b B t t \054 0 0 1000 boolin boolout boolrecv boolsend - - - c p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("boolean, 'true'/'false'");
#define BOOLOID 16
-DATA(insert OID = 17 ( bytea PGNSP PGUID -1 f b U f t \054 0 0 1001 byteain byteaout bytearecv byteasend - - - i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 17 ( bytea PGNSP PGUID -1 f b U f t \054 0 0 1001 byteain byteaout bytearecv byteasend - - - i x f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("variable-length string, binary values escaped");
#define BYTEAOID 17
-DATA(insert OID = 18 ( char PGNSP PGUID 1 t b S f t \054 0 0 1002 charin charout charrecv charsend - - - c p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 18 ( char PGNSP PGUID 1 t b S f t \054 0 0 1002 charin charout charrecv charsend - - - c p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("single character");
#define CHAROID 18
-DATA(insert OID = 19 ( name PGNSP PGUID NAMEDATALEN f b S f t \054 0 18 1003 namein nameout namerecv namesend - - - c p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 19 ( name PGNSP PGUID NAMEDATALEN f b S f t \054 0 18 1003 namein nameout namerecv namesend - - - c p f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
DESCR("63-byte type for storing system identifiers");
#define NAMEOID 19
-DATA(insert OID = 20 ( int8 PGNSP PGUID 8 FLOAT8PASSBYVAL b N f t \054 0 0 1016 int8in int8out int8recv int8send - - - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 20 ( int8 PGNSP PGUID 8 FLOAT8PASSBYVAL b N f t \054 0 0 1016 int8in int8out int8recv int8send - - - d p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("~18 digit integer, 8-byte storage");
#define INT8OID 20
-DATA(insert OID = 21 ( int2 PGNSP PGUID 2 t b N f t \054 0 0 1005 int2in int2out int2recv int2send - - - s p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 21 ( int2 PGNSP PGUID 2 t b N f t \054 0 0 1005 int2in int2out int2recv int2send - - - s p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("-32 thousand to 32 thousand, 2-byte storage");
#define INT2OID 21
-DATA(insert OID = 22 ( int2vector PGNSP PGUID -1 f b A f t \054 0 21 1006 int2vectorin int2vectorout int2vectorrecv int2vectorsend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 22 ( int2vector PGNSP PGUID -1 f b A f t \054 0 21 1006 int2vectorin int2vectorout int2vectorrecv int2vectorsend - - - i p f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
DESCR("array of int2, used in system tables");
#define INT2VECTOROID 22
-DATA(insert OID = 23 ( int4 PGNSP PGUID 4 t b N f t \054 0 0 1007 int4in int4out int4recv int4send - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 23 ( int4 PGNSP PGUID 4 t b N f t \054 0 0 1007 int4in int4out int4recv int4send - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("-2 billion to 2 billion integer, 4-byte storage");
#define INT4OID 23
-DATA(insert OID = 24 ( regproc PGNSP PGUID 4 t b N f t \054 0 0 1008 regprocin regprocout regprocrecv regprocsend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 24 ( regproc PGNSP PGUID 4 t b N f t \054 0 0 1008 regprocin regprocout regprocrecv regprocsend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("registered procedure");
#define REGPROCOID 24
-DATA(insert OID = 25 ( text PGNSP PGUID -1 f b S t t \054 0 0 1009 textin textout textrecv textsend - - - i x f 0 -1 0 100 _null_ _null_ _null_ ));
+DATA(insert OID = 25 ( text PGNSP PGUID -1 f b S t t \054 0 0 1009 textin textout textrecv textsend - - - i x f 0 -1 0 100 - _null_ _null_ _null_ ));
DESCR("variable-length string, no limit specified");
#define TEXTOID 25
-DATA(insert OID = 26 ( oid PGNSP PGUID 4 t b N t t \054 0 0 1028 oidin oidout oidrecv oidsend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 26 ( oid PGNSP PGUID 4 t b N t t \054 0 0 1028 oidin oidout oidrecv oidsend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("object identifier(oid), maximum 4 billion");
#define OIDOID 26
-DATA(insert OID = 27 ( tid PGNSP PGUID 6 f b U f t \054 0 0 1010 tidin tidout tidrecv tidsend - - - s p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 27 ( tid PGNSP PGUID 6 f b U f t \054 0 0 1010 tidin tidout tidrecv tidsend - - - s p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("(block, offset), physical location of tuple");
#define TIDOID 27
-DATA(insert OID = 28 ( xid PGNSP PGUID 4 t b U f t \054 0 0 1011 xidin xidout xidrecv xidsend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 28 ( xid PGNSP PGUID 4 t b U f t \054 0 0 1011 xidin xidout xidrecv xidsend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("transaction id");
#define XIDOID 28
-DATA(insert OID = 29 ( cid PGNSP PGUID 4 t b U f t \054 0 0 1012 cidin cidout cidrecv cidsend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 29 ( cid PGNSP PGUID 4 t b U f t \054 0 0 1012 cidin cidout cidrecv cidsend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("command identifier type, sequence in transaction id");
#define CIDOID 29
-DATA(insert OID = 30 ( oidvector PGNSP PGUID -1 f b A f t \054 0 26 1013 oidvectorin oidvectorout oidvectorrecv oidvectorsend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 30 ( oidvector PGNSP PGUID -1 f b A f t \054 0 26 1013 oidvectorin oidvectorout oidvectorrecv oidvectorsend - - - i p f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
DESCR("array of oids, used in system tables");
#define OIDVECTOROID 30
/* hand-built rowtype entries for bootstrapped catalogs */
/* NB: OIDs assigned here must match the BKI_ROWTYPE_OID declarations */
-DATA(insert OID = 71 ( pg_type PGNSP PGUID -1 f c C f t \054 1247 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 75 ( pg_attribute PGNSP PGUID -1 f c C f t \054 1249 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 81 ( pg_proc PGNSP PGUID -1 f c C f t \054 1255 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 83 ( pg_class PGNSP PGUID -1 f c C f t \054 1259 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 71 ( pg_type PGNSP PGUID -1 f c C f t \054 1247 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 0 - _null_ _null_ _null_ ));
+DATA(insert OID = 75 ( pg_attribute PGNSP PGUID -1 f c C f t \054 1249 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 0 - _null_ _null_ _null_ ));
+DATA(insert OID = 81 ( pg_proc PGNSP PGUID -1 f c C f t \054 1255 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 0 - _null_ _null_ _null_ ));
+DATA(insert OID = 83 ( pg_class PGNSP PGUID -1 f c C f t \054 1259 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 0 - _null_ _null_ _null_ ));
/* OIDS 100 - 199 */
-DATA(insert OID = 114 ( json PGNSP PGUID -1 f b U f t \054 0 0 199 json_in json_out json_recv json_send - - - i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 114 ( json PGNSP PGUID -1 f b U f t \054 0 0 199 json_in json_out json_recv json_send - - - i x f 0 -1 0 0 - _null_ _null_ _null_ ));
#define JSONOID 114
-DATA(insert OID = 142 ( xml PGNSP PGUID -1 f b U f t \054 0 0 143 xml_in xml_out xml_recv xml_send - - - i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 142 ( xml PGNSP PGUID -1 f b U f t \054 0 0 143 xml_in xml_out xml_recv xml_send - - - i x f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("XML content");
#define XMLOID 142
-DATA(insert OID = 143 ( _xml PGNSP PGUID -1 f b A f t \054 0 142 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 199 ( _json PGNSP PGUID -1 f b A f t \054 0 114 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 143 ( _xml PGNSP PGUID -1 f b A f t \054 0 142 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 199 ( _json PGNSP PGUID -1 f b A f t \054 0 114 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
-DATA(insert OID = 194 ( pg_node_tree PGNSP PGUID -1 f b S f t \054 0 0 0 pg_node_tree_in pg_node_tree_out pg_node_tree_recv pg_node_tree_send - - - i x f 0 -1 0 100 _null_ _null_ _null_ ));
+DATA(insert OID = 194 ( pg_node_tree PGNSP PGUID -1 f b S f t \054 0 0 0 pg_node_tree_in pg_node_tree_out pg_node_tree_recv pg_node_tree_send - - - i x f 0 -1 0 100 - _null_ _null_ _null_ ));
DESCR("string representing an internal node tree");
#define PGNODETREEOID 194
-DATA(insert OID = 3361 ( pg_ndistinct PGNSP PGUID -1 f b S f t \054 0 0 0 pg_ndistinct_in pg_ndistinct_out pg_ndistinct_recv pg_ndistinct_send - - - i x f 0 -1 0 100 _null_ _null_ _null_ ));
+DATA(insert OID = 3361 ( pg_ndistinct PGNSP PGUID -1 f b S f t \054 0 0 0 pg_ndistinct_in pg_ndistinct_out pg_ndistinct_recv pg_ndistinct_send - - - i x f 0 -1 0 100 - _null_ _null_ _null_ ));
DESCR("multivariate ndistinct coefficients");
#define PGNDISTINCTOID 3361
-DATA(insert OID = 3402 ( pg_dependencies PGNSP PGUID -1 f b S f t \054 0 0 0 pg_dependencies_in pg_dependencies_out pg_dependencies_recv pg_dependencies_send - - - i x f 0 -1 0 100 _null_ _null_ _null_ ));
+DATA(insert OID = 3402 ( pg_dependencies PGNSP PGUID -1 f b S f t \054 0 0 0 pg_dependencies_in pg_dependencies_out pg_dependencies_recv pg_dependencies_send - - - i x f 0 -1 0 100 - _null_ _null_ _null_ ));
DESCR("multivariate dependencies");
#define PGDEPENDENCIESOID 3402
-DATA(insert OID = 32 ( pg_ddl_command PGNSP PGUID SIZEOF_POINTER t p P f t \054 0 0 0 pg_ddl_command_in pg_ddl_command_out pg_ddl_command_recv pg_ddl_command_send - - - ALIGNOF_POINTER p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 32 ( pg_ddl_command PGNSP PGUID SIZEOF_POINTER t p P f t \054 0 0 0 pg_ddl_command_in pg_ddl_command_out pg_ddl_command_recv pg_ddl_command_send - - - ALIGNOF_POINTER p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("internal type for passing CollectedCommand");
#define PGDDLCOMMANDOID 32
/* OIDS 200 - 299 */
-DATA(insert OID = 210 ( smgr PGNSP PGUID 2 t b U f t \054 0 0 0 smgrin smgrout - - - - - s p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 210 ( smgr PGNSP PGUID 2 t b U f t \054 0 0 0 smgrin smgrout - - - - - s p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("storage manager");
/* OIDS 300 - 399 */
@@ -388,280 +394,280 @@ DESCR("storage manager");
/* OIDS 500 - 599 */
/* OIDS 600 - 699 */
-DATA(insert OID = 600 ( point PGNSP PGUID 16 f b G f t \054 0 701 1017 point_in point_out point_recv point_send - - - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 600 ( point PGNSP PGUID 16 f b G f t \054 0 701 1017 point_in point_out point_recv point_send - - - d p f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
DESCR("geometric point '(x, y)'");
#define POINTOID 600
-DATA(insert OID = 601 ( lseg PGNSP PGUID 32 f b G f t \054 0 600 1018 lseg_in lseg_out lseg_recv lseg_send - - - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 601 ( lseg PGNSP PGUID 32 f b G f t \054 0 600 1018 lseg_in lseg_out lseg_recv lseg_send - - - d p f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
DESCR("geometric line segment '(pt1,pt2)'");
#define LSEGOID 601
-DATA(insert OID = 602 ( path PGNSP PGUID -1 f b G f t \054 0 0 1019 path_in path_out path_recv path_send - - - d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 602 ( path PGNSP PGUID -1 f b G f t \054 0 0 1019 path_in path_out path_recv path_send - - - d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
DESCR("geometric path '(pt1,...)'");
#define PATHOID 602
-DATA(insert OID = 603 ( box PGNSP PGUID 32 f b G f t \073 0 600 1020 box_in box_out box_recv box_send - - - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 603 ( box PGNSP PGUID 32 f b G f t \073 0 600 1020 box_in box_out box_recv box_send - - - d p f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
DESCR("geometric box '(lower left,upper right)'");
#define BOXOID 603
-DATA(insert OID = 604 ( polygon PGNSP PGUID -1 f b G f t \054 0 0 1027 poly_in poly_out poly_recv poly_send - - - d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 604 ( polygon PGNSP PGUID -1 f b G f t \054 0 0 1027 poly_in poly_out poly_recv poly_send - - - d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
DESCR("geometric polygon '(pt1,...)'");
#define POLYGONOID 604
-DATA(insert OID = 628 ( line PGNSP PGUID 24 f b G f t \054 0 701 629 line_in line_out line_recv line_send - - - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 628 ( line PGNSP PGUID 24 f b G f t \054 0 701 629 line_in line_out line_recv line_send - - - d p f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
DESCR("geometric line");
#define LINEOID 628
-DATA(insert OID = 629 ( _line PGNSP PGUID -1 f b A f t \054 0 628 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 629 ( _line PGNSP PGUID -1 f b A f t \054 0 628 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
/* OIDS 700 - 799 */
-DATA(insert OID = 700 ( float4 PGNSP PGUID 4 FLOAT4PASSBYVAL b N f t \054 0 0 1021 float4in float4out float4recv float4send - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 700 ( float4 PGNSP PGUID 4 FLOAT4PASSBYVAL b N f t \054 0 0 1021 float4in float4out float4recv float4send - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("single-precision floating point number, 4-byte storage");
#define FLOAT4OID 700
-DATA(insert OID = 701 ( float8 PGNSP PGUID 8 FLOAT8PASSBYVAL b N t t \054 0 0 1022 float8in float8out float8recv float8send - - - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 701 ( float8 PGNSP PGUID 8 FLOAT8PASSBYVAL b N t t \054 0 0 1022 float8in float8out float8recv float8send - - - d p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("double-precision floating point number, 8-byte storage");
#define FLOAT8OID 701
-DATA(insert OID = 702 ( abstime PGNSP PGUID 4 t b D f t \054 0 0 1023 abstimein abstimeout abstimerecv abstimesend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 702 ( abstime PGNSP PGUID 4 t b D f t \054 0 0 1023 abstimein abstimeout abstimerecv abstimesend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("absolute, limited-range date and time (Unix system time)");
#define ABSTIMEOID 702
-DATA(insert OID = 703 ( reltime PGNSP PGUID 4 t b T f t \054 0 0 1024 reltimein reltimeout reltimerecv reltimesend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 703 ( reltime PGNSP PGUID 4 t b T f t \054 0 0 1024 reltimein reltimeout reltimerecv reltimesend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("relative, limited-range time interval (Unix delta time)");
#define RELTIMEOID 703
-DATA(insert OID = 704 ( tinterval PGNSP PGUID 12 f b T f t \054 0 0 1025 tintervalin tintervalout tintervalrecv tintervalsend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 704 ( tinterval PGNSP PGUID 12 f b T f t \054 0 0 1025 tintervalin tintervalout tintervalrecv tintervalsend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("(abstime,abstime), time interval");
#define TINTERVALOID 704
-DATA(insert OID = 705 ( unknown PGNSP PGUID -2 f p X f t \054 0 0 0 unknownin unknownout unknownrecv unknownsend - - - c p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 705 ( unknown PGNSP PGUID -2 f p X f t \054 0 0 0 unknownin unknownout unknownrecv unknownsend - - - c p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("");
#define UNKNOWNOID 705
-DATA(insert OID = 718 ( circle PGNSP PGUID 24 f b G f t \054 0 0 719 circle_in circle_out circle_recv circle_send - - - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 718 ( circle PGNSP PGUID 24 f b G f t \054 0 0 719 circle_in circle_out circle_recv circle_send - - - d p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("geometric circle '(center,radius)'");
#define CIRCLEOID 718
-DATA(insert OID = 719 ( _circle PGNSP PGUID -1 f b A f t \054 0 718 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 790 ( money PGNSP PGUID 8 FLOAT8PASSBYVAL b N f t \054 0 0 791 cash_in cash_out cash_recv cash_send - - - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 719 ( _circle PGNSP PGUID -1 f b A f t \054 0 718 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 790 ( money PGNSP PGUID 8 FLOAT8PASSBYVAL b N f t \054 0 0 791 cash_in cash_out cash_recv cash_send - - - d p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("monetary amounts, $d,ddd.cc");
#define CASHOID 790
-DATA(insert OID = 791 ( _money PGNSP PGUID -1 f b A f t \054 0 790 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 791 ( _money PGNSP PGUID -1 f b A f t \054 0 790 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
/* OIDS 800 - 899 */
-DATA(insert OID = 829 ( macaddr PGNSP PGUID 6 f b U f t \054 0 0 1040 macaddr_in macaddr_out macaddr_recv macaddr_send - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 829 ( macaddr PGNSP PGUID 6 f b U f t \054 0 0 1040 macaddr_in macaddr_out macaddr_recv macaddr_send - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("XX:XX:XX:XX:XX:XX, MAC address");
#define MACADDROID 829
-DATA(insert OID = 869 ( inet PGNSP PGUID -1 f b I t t \054 0 0 1041 inet_in inet_out inet_recv inet_send - - - i m f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 869 ( inet PGNSP PGUID -1 f b I t t \054 0 0 1041 inet_in inet_out inet_recv inet_send - - - i m f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("IP address/netmask, host address, netmask optional");
#define INETOID 869
-DATA(insert OID = 650 ( cidr PGNSP PGUID -1 f b I f t \054 0 0 651 cidr_in cidr_out cidr_recv cidr_send - - - i m f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 650 ( cidr PGNSP PGUID -1 f b I f t \054 0 0 651 cidr_in cidr_out cidr_recv cidr_send - - - i m f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("network IP address/netmask, network address");
#define CIDROID 650
-DATA(insert OID = 774 ( macaddr8 PGNSP PGUID 8 f b U f t \054 0 0 775 macaddr8_in macaddr8_out macaddr8_recv macaddr8_send - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 774 ( macaddr8 PGNSP PGUID 8 f b U f t \054 0 0 775 macaddr8_in macaddr8_out macaddr8_recv macaddr8_send - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("XX:XX:XX:XX:XX:XX:XX:XX, MAC address");
#define MACADDR8OID 774
/* OIDS 900 - 999 */
/* OIDS 1000 - 1099 */
-DATA(insert OID = 1000 ( _bool PGNSP PGUID -1 f b A f t \054 0 16 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1001 ( _bytea PGNSP PGUID -1 f b A f t \054 0 17 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1002 ( _char PGNSP PGUID -1 f b A f t \054 0 18 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1003 ( _name PGNSP PGUID -1 f b A f t \054 0 19 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1005 ( _int2 PGNSP PGUID -1 f b A f t \054 0 21 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1000 ( _bool PGNSP PGUID -1 f b A f t \054 0 16 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1001 ( _bytea PGNSP PGUID -1 f b A f t \054 0 17 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1002 ( _char PGNSP PGUID -1 f b A f t \054 0 18 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1003 ( _name PGNSP PGUID -1 f b A f t \054 0 19 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1005 ( _int2 PGNSP PGUID -1 f b A f t \054 0 21 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
#define INT2ARRAYOID 1005
-DATA(insert OID = 1006 ( _int2vector PGNSP PGUID -1 f b A f t \054 0 22 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1007 ( _int4 PGNSP PGUID -1 f b A f t \054 0 23 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1006 ( _int2vector PGNSP PGUID -1 f b A f t \054 0 22 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1007 ( _int4 PGNSP PGUID -1 f b A f t \054 0 23 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
#define INT4ARRAYOID 1007
-DATA(insert OID = 1008 ( _regproc PGNSP PGUID -1 f b A f t \054 0 24 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1009 ( _text PGNSP PGUID -1 f b A f t \054 0 25 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 100 _null_ _null_ _null_ ));
+DATA(insert OID = 1008 ( _regproc PGNSP PGUID -1 f b A f t \054 0 24 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1009 ( _text PGNSP PGUID -1 f b A f t \054 0 25 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 100 array_subscript_handler _null_ _null_ _null_ ));
#define TEXTARRAYOID 1009
-DATA(insert OID = 1028 ( _oid PGNSP PGUID -1 f b A f t \054 0 26 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1028 ( _oid PGNSP PGUID -1 f b A f t \054 0 26 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
#define OIDARRAYOID 1028
-DATA(insert OID = 1010 ( _tid PGNSP PGUID -1 f b A f t \054 0 27 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1011 ( _xid PGNSP PGUID -1 f b A f t \054 0 28 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1012 ( _cid PGNSP PGUID -1 f b A f t \054 0 29 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1013 ( _oidvector PGNSP PGUID -1 f b A f t \054 0 30 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1014 ( _bpchar PGNSP PGUID -1 f b A f t \054 0 1042 0 array_in array_out array_recv array_send bpchartypmodin bpchartypmodout array_typanalyze i x f 0 -1 0 100 _null_ _null_ _null_ ));
-DATA(insert OID = 1015 ( _varchar PGNSP PGUID -1 f b A f t \054 0 1043 0 array_in array_out array_recv array_send varchartypmodin varchartypmodout array_typanalyze i x f 0 -1 0 100 _null_ _null_ _null_ ));
-DATA(insert OID = 1016 ( _int8 PGNSP PGUID -1 f b A f t \054 0 20 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1017 ( _point PGNSP PGUID -1 f b A f t \054 0 600 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1018 ( _lseg PGNSP PGUID -1 f b A f t \054 0 601 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1019 ( _path PGNSP PGUID -1 f b A f t \054 0 602 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1020 ( _box PGNSP PGUID -1 f b A f t \073 0 603 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1021 ( _float4 PGNSP PGUID -1 f b A f t \054 0 700 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1010 ( _tid PGNSP PGUID -1 f b A f t \054 0 27 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1011 ( _xid PGNSP PGUID -1 f b A f t \054 0 28 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1012 ( _cid PGNSP PGUID -1 f b A f t \054 0 29 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1013 ( _oidvector PGNSP PGUID -1 f b A f t \054 0 30 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1014 ( _bpchar PGNSP PGUID -1 f b A f t \054 0 1042 0 array_in array_out array_recv array_send bpchartypmodin bpchartypmodout array_typanalyze i x f 0 -1 0 100 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1015 ( _varchar PGNSP PGUID -1 f b A f t \054 0 1043 0 array_in array_out array_recv array_send varchartypmodin varchartypmodout array_typanalyze i x f 0 -1 0 100 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1016 ( _int8 PGNSP PGUID -1 f b A f t \054 0 20 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1017 ( _point PGNSP PGUID -1 f b A f t \054 0 600 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1018 ( _lseg PGNSP PGUID -1 f b A f t \054 0 601 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1019 ( _path PGNSP PGUID -1 f b A f t \054 0 602 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1020 ( _box PGNSP PGUID -1 f b A f t \073 0 603 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1021 ( _float4 PGNSP PGUID -1 f b A f t \054 0 700 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
#define FLOAT4ARRAYOID 1021
-DATA(insert OID = 1022 ( _float8 PGNSP PGUID -1 f b A f t \054 0 701 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1023 ( _abstime PGNSP PGUID -1 f b A f t \054 0 702 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1024 ( _reltime PGNSP PGUID -1 f b A f t \054 0 703 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1025 ( _tinterval PGNSP PGUID -1 f b A f t \054 0 704 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1027 ( _polygon PGNSP PGUID -1 f b A f t \054 0 604 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1033 ( aclitem PGNSP PGUID 12 f b U f t \054 0 0 1034 aclitemin aclitemout - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1022 ( _float8 PGNSP PGUID -1 f b A f t \054 0 701 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1023 ( _abstime PGNSP PGUID -1 f b A f t \054 0 702 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1024 ( _reltime PGNSP PGUID -1 f b A f t \054 0 703 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1025 ( _tinterval PGNSP PGUID -1 f b A f t \054 0 704 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1027 ( _polygon PGNSP PGUID -1 f b A f t \054 0 604 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1033 ( aclitem PGNSP PGUID 12 f b U f t \054 0 0 1034 aclitemin aclitemout - - - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("access control list");
#define ACLITEMOID 1033
-DATA(insert OID = 1034 ( _aclitem PGNSP PGUID -1 f b A f t \054 0 1033 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1040 ( _macaddr PGNSP PGUID -1 f b A f t \054 0 829 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 775 ( _macaddr8 PGNSP PGUID -1 f b A f t \054 0 774 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1041 ( _inet PGNSP PGUID -1 f b A f t \054 0 869 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 651 ( _cidr PGNSP PGUID -1 f b A f t \054 0 650 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1263 ( _cstring PGNSP PGUID -1 f b A f t \054 0 2275 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1034 ( _aclitem PGNSP PGUID -1 f b A f t \054 0 1033 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1040 ( _macaddr PGNSP PGUID -1 f b A f t \054 0 829 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 775 ( _macaddr8 PGNSP PGUID -1 f b A f t \054 0 774 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1041 ( _inet PGNSP PGUID -1 f b A f t \054 0 869 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 651 ( _cidr PGNSP PGUID -1 f b A f t \054 0 650 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1263 ( _cstring PGNSP PGUID -1 f b A f t \054 0 2275 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
#define CSTRINGARRAYOID 1263
-DATA(insert OID = 1042 ( bpchar PGNSP PGUID -1 f b S f t \054 0 0 1014 bpcharin bpcharout bpcharrecv bpcharsend bpchartypmodin bpchartypmodout - i x f 0 -1 0 100 _null_ _null_ _null_ ));
+DATA(insert OID = 1042 ( bpchar PGNSP PGUID -1 f b S f t \054 0 0 1014 bpcharin bpcharout bpcharrecv bpcharsend bpchartypmodin bpchartypmodout - i x f 0 -1 0 100 - _null_ _null_ _null_ ));
DESCR("char(length), blank-padded string, fixed storage length");
#define BPCHAROID 1042
-DATA(insert OID = 1043 ( varchar PGNSP PGUID -1 f b S f t \054 0 0 1015 varcharin varcharout varcharrecv varcharsend varchartypmodin varchartypmodout - i x f 0 -1 0 100 _null_ _null_ _null_ ));
+DATA(insert OID = 1043 ( varchar PGNSP PGUID -1 f b S f t \054 0 0 1015 varcharin varcharout varcharrecv varcharsend varchartypmodin varchartypmodout - i x f 0 -1 0 100 - _null_ _null_ _null_ ));
DESCR("varchar(length), non-blank-padded string, variable storage length");
#define VARCHAROID 1043
-DATA(insert OID = 1082 ( date PGNSP PGUID 4 t b D f t \054 0 0 1182 date_in date_out date_recv date_send - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1082 ( date PGNSP PGUID 4 t b D f t \054 0 0 1182 date_in date_out date_recv date_send - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("date");
#define DATEOID 1082
-DATA(insert OID = 1083 ( time PGNSP PGUID 8 FLOAT8PASSBYVAL b D f t \054 0 0 1183 time_in time_out time_recv time_send timetypmodin timetypmodout - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1083 ( time PGNSP PGUID 8 FLOAT8PASSBYVAL b D f t \054 0 0 1183 time_in time_out time_recv time_send timetypmodin timetypmodout - d p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("time of day");
#define TIMEOID 1083
/* OIDS 1100 - 1199 */
-DATA(insert OID = 1114 ( timestamp PGNSP PGUID 8 FLOAT8PASSBYVAL b D f t \054 0 0 1115 timestamp_in timestamp_out timestamp_recv timestamp_send timestamptypmodin timestamptypmodout - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1114 ( timestamp PGNSP PGUID 8 FLOAT8PASSBYVAL b D f t \054 0 0 1115 timestamp_in timestamp_out timestamp_recv timestamp_send timestamptypmodin timestamptypmodout - d p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("date and time");
#define TIMESTAMPOID 1114
-DATA(insert OID = 1115 ( _timestamp PGNSP PGUID -1 f b A f t \054 0 1114 0 array_in array_out array_recv array_send timestamptypmodin timestamptypmodout array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1182 ( _date PGNSP PGUID -1 f b A f t \054 0 1082 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1183 ( _time PGNSP PGUID -1 f b A f t \054 0 1083 0 array_in array_out array_recv array_send timetypmodin timetypmodout array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1184 ( timestamptz PGNSP PGUID 8 FLOAT8PASSBYVAL b D t t \054 0 0 1185 timestamptz_in timestamptz_out timestamptz_recv timestamptz_send timestamptztypmodin timestamptztypmodout - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1115 ( _timestamp PGNSP PGUID -1 f b A f t \054 0 1114 0 array_in array_out array_recv array_send timestamptypmodin timestamptypmodout array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1182 ( _date PGNSP PGUID -1 f b A f t \054 0 1082 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1183 ( _time PGNSP PGUID -1 f b A f t \054 0 1083 0 array_in array_out array_recv array_send timetypmodin timetypmodout array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1184 ( timestamptz PGNSP PGUID 8 FLOAT8PASSBYVAL b D t t \054 0 0 1185 timestamptz_in timestamptz_out timestamptz_recv timestamptz_send timestamptztypmodin timestamptztypmodout - d p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("date and time with time zone");
#define TIMESTAMPTZOID 1184
-DATA(insert OID = 1185 ( _timestamptz PGNSP PGUID -1 f b A f t \054 0 1184 0 array_in array_out array_recv array_send timestamptztypmodin timestamptztypmodout array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1186 ( interval PGNSP PGUID 16 f b T t t \054 0 0 1187 interval_in interval_out interval_recv interval_send intervaltypmodin intervaltypmodout - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1185 ( _timestamptz PGNSP PGUID -1 f b A f t \054 0 1184 0 array_in array_out array_recv array_send timestamptztypmodin timestamptztypmodout array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1186 ( interval PGNSP PGUID 16 f b T t t \054 0 0 1187 interval_in interval_out interval_recv interval_send intervaltypmodin intervaltypmodout - d p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("@ <number> <units>, time interval");
#define INTERVALOID 1186
-DATA(insert OID = 1187 ( _interval PGNSP PGUID -1 f b A f t \054 0 1186 0 array_in array_out array_recv array_send intervaltypmodin intervaltypmodout array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1187 ( _interval PGNSP PGUID -1 f b A f t \054 0 1186 0 array_in array_out array_recv array_send intervaltypmodin intervaltypmodout array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
/* OIDS 1200 - 1299 */
-DATA(insert OID = 1231 ( _numeric PGNSP PGUID -1 f b A f t \054 0 1700 0 array_in array_out array_recv array_send numerictypmodin numerictypmodout array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1266 ( timetz PGNSP PGUID 12 f b D f t \054 0 0 1270 timetz_in timetz_out timetz_recv timetz_send timetztypmodin timetztypmodout - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1231 ( _numeric PGNSP PGUID -1 f b A f t \054 0 1700 0 array_in array_out array_recv array_send numerictypmodin numerictypmodout array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1266 ( timetz PGNSP PGUID 12 f b D f t \054 0 0 1270 timetz_in timetz_out timetz_recv timetz_send timetztypmodin timetztypmodout - d p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("time of day with time zone");
#define TIMETZOID 1266
-DATA(insert OID = 1270 ( _timetz PGNSP PGUID -1 f b A f t \054 0 1266 0 array_in array_out array_recv array_send timetztypmodin timetztypmodout array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1270 ( _timetz PGNSP PGUID -1 f b A f t \054 0 1266 0 array_in array_out array_recv array_send timetztypmodin timetztypmodout array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
/* OIDS 1500 - 1599 */
-DATA(insert OID = 1560 ( bit PGNSP PGUID -1 f b V f t \054 0 0 1561 bit_in bit_out bit_recv bit_send bittypmodin bittypmodout - i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1560 ( bit PGNSP PGUID -1 f b V f t \054 0 0 1561 bit_in bit_out bit_recv bit_send bittypmodin bittypmodout - i x f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("fixed-length bit string");
#define BITOID 1560
-DATA(insert OID = 1561 ( _bit PGNSP PGUID -1 f b A f t \054 0 1560 0 array_in array_out array_recv array_send bittypmodin bittypmodout array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 1562 ( varbit PGNSP PGUID -1 f b V t t \054 0 0 1563 varbit_in varbit_out varbit_recv varbit_send varbittypmodin varbittypmodout - i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1561 ( _bit PGNSP PGUID -1 f b A f t \054 0 1560 0 array_in array_out array_recv array_send bittypmodin bittypmodout array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 1562 ( varbit PGNSP PGUID -1 f b V t t \054 0 0 1563 varbit_in varbit_out varbit_recv varbit_send varbittypmodin varbittypmodout - i x f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("variable-length bit string");
#define VARBITOID 1562
-DATA(insert OID = 1563 ( _varbit PGNSP PGUID -1 f b A f t \054 0 1562 0 array_in array_out array_recv array_send varbittypmodin varbittypmodout array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1563 ( _varbit PGNSP PGUID -1 f b A f t \054 0 1562 0 array_in array_out array_recv array_send varbittypmodin varbittypmodout array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
/* OIDS 1600 - 1699 */
/* OIDS 1700 - 1799 */
-DATA(insert OID = 1700 ( numeric PGNSP PGUID -1 f b N f t \054 0 0 1231 numeric_in numeric_out numeric_recv numeric_send numerictypmodin numerictypmodout - i m f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1700 ( numeric PGNSP PGUID -1 f b N f t \054 0 0 1231 numeric_in numeric_out numeric_recv numeric_send numerictypmodin numerictypmodout - i m f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("numeric(precision, decimal), arbitrary precision number");
#define NUMERICOID 1700
-DATA(insert OID = 1790 ( refcursor PGNSP PGUID -1 f b U f t \054 0 0 2201 textin textout textrecv textsend - - - i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 1790 ( refcursor PGNSP PGUID -1 f b U f t \054 0 0 2201 textin textout textrecv textsend - - - i x f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("reference to cursor (portal name)");
#define REFCURSOROID 1790
/* OIDS 2200 - 2299 */
-DATA(insert OID = 2201 ( _refcursor PGNSP PGUID -1 f b A f t \054 0 1790 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2201 ( _refcursor PGNSP PGUID -1 f b A f t \054 0 1790 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
-DATA(insert OID = 2202 ( regprocedure PGNSP PGUID 4 t b N f t \054 0 0 2207 regprocedurein regprocedureout regprocedurerecv regproceduresend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2202 ( regprocedure PGNSP PGUID 4 t b N f t \054 0 0 2207 regprocedurein regprocedureout regprocedurerecv regproceduresend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("registered procedure (with args)");
#define REGPROCEDUREOID 2202
-DATA(insert OID = 2203 ( regoper PGNSP PGUID 4 t b N f t \054 0 0 2208 regoperin regoperout regoperrecv regopersend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2203 ( regoper PGNSP PGUID 4 t b N f t \054 0 0 2208 regoperin regoperout regoperrecv regopersend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("registered operator");
#define REGOPEROID 2203
-DATA(insert OID = 2204 ( regoperator PGNSP PGUID 4 t b N f t \054 0 0 2209 regoperatorin regoperatorout regoperatorrecv regoperatorsend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2204 ( regoperator PGNSP PGUID 4 t b N f t \054 0 0 2209 regoperatorin regoperatorout regoperatorrecv regoperatorsend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("registered operator (with args)");
#define REGOPERATOROID 2204
-DATA(insert OID = 2205 ( regclass PGNSP PGUID 4 t b N f t \054 0 0 2210 regclassin regclassout regclassrecv regclasssend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2205 ( regclass PGNSP PGUID 4 t b N f t \054 0 0 2210 regclassin regclassout regclassrecv regclasssend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("registered class");
#define REGCLASSOID 2205
-DATA(insert OID = 2206 ( regtype PGNSP PGUID 4 t b N f t \054 0 0 2211 regtypein regtypeout regtyperecv regtypesend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2206 ( regtype PGNSP PGUID 4 t b N f t \054 0 0 2211 regtypein regtypeout regtyperecv regtypesend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("registered type");
#define REGTYPEOID 2206
-DATA(insert OID = 4096 ( regrole PGNSP PGUID 4 t b N f t \054 0 0 4097 regrolein regroleout regrolerecv regrolesend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 4096 ( regrole PGNSP PGUID 4 t b N f t \054 0 0 4097 regrolein regroleout regrolerecv regrolesend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("registered role");
#define REGROLEOID 4096
-DATA(insert OID = 4089 ( regnamespace PGNSP PGUID 4 t b N f t \054 0 0 4090 regnamespacein regnamespaceout regnamespacerecv regnamespacesend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 4089 ( regnamespace PGNSP PGUID 4 t b N f t \054 0 0 4090 regnamespacein regnamespaceout regnamespacerecv regnamespacesend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("registered namespace");
#define REGNAMESPACEOID 4089
-DATA(insert OID = 2207 ( _regprocedure PGNSP PGUID -1 f b A f t \054 0 2202 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 2208 ( _regoper PGNSP PGUID -1 f b A f t \054 0 2203 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 2209 ( _regoperator PGNSP PGUID -1 f b A f t \054 0 2204 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 2210 ( _regclass PGNSP PGUID -1 f b A f t \054 0 2205 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 2211 ( _regtype PGNSP PGUID -1 f b A f t \054 0 2206 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2207 ( _regprocedure PGNSP PGUID -1 f b A f t \054 0 2202 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 2208 ( _regoper PGNSP PGUID -1 f b A f t \054 0 2203 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 2209 ( _regoperator PGNSP PGUID -1 f b A f t \054 0 2204 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 2210 ( _regclass PGNSP PGUID -1 f b A f t \054 0 2205 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 2211 ( _regtype PGNSP PGUID -1 f b A f t \054 0 2206 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
#define REGTYPEARRAYOID 2211
-DATA(insert OID = 4097 ( _regrole PGNSP PGUID -1 f b A f t \054 0 4096 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 4090 ( _regnamespace PGNSP PGUID -1 f b A f t \054 0 4089 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 4097 ( _regrole PGNSP PGUID -1 f b A f t \054 0 4096 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 4090 ( _regnamespace PGNSP PGUID -1 f b A f t \054 0 4089 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
/* uuid */
-DATA(insert OID = 2950 ( uuid PGNSP PGUID 16 f b U f t \054 0 0 2951 uuid_in uuid_out uuid_recv uuid_send - - - c p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2950 ( uuid PGNSP PGUID 16 f b U f t \054 0 0 2951 uuid_in uuid_out uuid_recv uuid_send - - - c p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("UUID datatype");
#define UUIDOID 2950
-DATA(insert OID = 2951 ( _uuid PGNSP PGUID -1 f b A f t \054 0 2950 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2951 ( _uuid PGNSP PGUID -1 f b A f t \054 0 2950 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
/* pg_lsn */
-DATA(insert OID = 3220 ( pg_lsn PGNSP PGUID 8 FLOAT8PASSBYVAL b U f t \054 0 0 3221 pg_lsn_in pg_lsn_out pg_lsn_recv pg_lsn_send - - - d p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3220 ( pg_lsn PGNSP PGUID 8 FLOAT8PASSBYVAL b U f t \054 0 0 3221 pg_lsn_in pg_lsn_out pg_lsn_recv pg_lsn_send - - - d p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("PostgreSQL LSN datatype");
#define LSNOID 3220
-DATA(insert OID = 3221 ( _pg_lsn PGNSP PGUID -1 f b A f t \054 0 3220 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3221 ( _pg_lsn PGNSP PGUID -1 f b A f t \054 0 3220 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
/* text search */
-DATA(insert OID = 3614 ( tsvector PGNSP PGUID -1 f b U f t \054 0 0 3643 tsvectorin tsvectorout tsvectorrecv tsvectorsend - - ts_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3614 ( tsvector PGNSP PGUID -1 f b U f t \054 0 0 3643 tsvectorin tsvectorout tsvectorrecv tsvectorsend - - ts_typanalyze i x f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("text representation for text search");
#define TSVECTOROID 3614
-DATA(insert OID = 3642 ( gtsvector PGNSP PGUID -1 f b U f t \054 0 0 3644 gtsvectorin gtsvectorout - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3642 ( gtsvector PGNSP PGUID -1 f b U f t \054 0 0 3644 gtsvectorin gtsvectorout - - - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("GiST index internal text representation for text search");
#define GTSVECTOROID 3642
-DATA(insert OID = 3615 ( tsquery PGNSP PGUID -1 f b U f t \054 0 0 3645 tsqueryin tsqueryout tsqueryrecv tsquerysend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3615 ( tsquery PGNSP PGUID -1 f b U f t \054 0 0 3645 tsqueryin tsqueryout tsqueryrecv tsquerysend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("query representation for text search");
#define TSQUERYOID 3615
-DATA(insert OID = 3734 ( regconfig PGNSP PGUID 4 t b N f t \054 0 0 3735 regconfigin regconfigout regconfigrecv regconfigsend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3734 ( regconfig PGNSP PGUID 4 t b N f t \054 0 0 3735 regconfigin regconfigout regconfigrecv regconfigsend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("registered text search configuration");
#define REGCONFIGOID 3734
-DATA(insert OID = 3769 ( regdictionary PGNSP PGUID 4 t b N f t \054 0 0 3770 regdictionaryin regdictionaryout regdictionaryrecv regdictionarysend - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3769 ( regdictionary PGNSP PGUID 4 t b N f t \054 0 0 3770 regdictionaryin regdictionaryout regdictionaryrecv regdictionarysend - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("registered text search dictionary");
#define REGDICTIONARYOID 3769
-DATA(insert OID = 3643 ( _tsvector PGNSP PGUID -1 f b A f t \054 0 3614 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 3644 ( _gtsvector PGNSP PGUID -1 f b A f t \054 0 3642 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 3645 ( _tsquery PGNSP PGUID -1 f b A f t \054 0 3615 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 3735 ( _regconfig PGNSP PGUID -1 f b A f t \054 0 3734 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 3770 ( _regdictionary PGNSP PGUID -1 f b A f t \054 0 3769 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3643 ( _tsvector PGNSP PGUID -1 f b A f t \054 0 3614 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 3644 ( _gtsvector PGNSP PGUID -1 f b A f t \054 0 3642 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 3645 ( _tsquery PGNSP PGUID -1 f b A f t \054 0 3615 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 3735 ( _regconfig PGNSP PGUID -1 f b A f t \054 0 3734 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 3770 ( _regdictionary PGNSP PGUID -1 f b A f t \054 0 3769 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
/* jsonb */
-DATA(insert OID = 3802 ( jsonb PGNSP PGUID -1 f b U f t \054 0 0 3807 jsonb_in jsonb_out jsonb_recv jsonb_send - - - i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3802 ( jsonb PGNSP PGUID -1 f b U f t \054 0 0 3807 jsonb_in jsonb_out jsonb_recv jsonb_send - - - i x f 0 -1 0 0 jsonb_subscript_handler _null_ _null_ _null_ ));
DESCR("Binary JSON");
#define JSONBOID 3802
-DATA(insert OID = 3807 ( _jsonb PGNSP PGUID -1 f b A f t \054 0 3802 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3807 ( _jsonb PGNSP PGUID -1 f b A f t \054 0 3802 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
-DATA(insert OID = 2970 ( txid_snapshot PGNSP PGUID -1 f b U f t \054 0 0 2949 txid_snapshot_in txid_snapshot_out txid_snapshot_recv txid_snapshot_send - - - d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2970 ( txid_snapshot PGNSP PGUID -1 f b U f t \054 0 0 2949 txid_snapshot_in txid_snapshot_out txid_snapshot_recv txid_snapshot_send - - - d x f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("txid snapshot");
-DATA(insert OID = 2949 ( _txid_snapshot PGNSP PGUID -1 f b A f t \054 0 2970 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2949 ( _txid_snapshot PGNSP PGUID -1 f b A f t \054 0 2970 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
/* range types */
-DATA(insert OID = 3904 ( int4range PGNSP PGUID -1 f r R f t \054 0 0 3905 range_in range_out range_recv range_send - - range_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3904 ( int4range PGNSP PGUID -1 f r R f t \054 0 0 3905 range_in range_out range_recv range_send - - range_typanalyze i x f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("range of integers");
#define INT4RANGEOID 3904
-DATA(insert OID = 3905 ( _int4range PGNSP PGUID -1 f b A f t \054 0 3904 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 3906 ( numrange PGNSP PGUID -1 f r R f t \054 0 0 3907 range_in range_out range_recv range_send - - range_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3905 ( _int4range PGNSP PGUID -1 f b A f t \054 0 3904 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 3906 ( numrange PGNSP PGUID -1 f r R f t \054 0 0 3907 range_in range_out range_recv range_send - - range_typanalyze i x f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("range of numerics");
-DATA(insert OID = 3907 ( _numrange PGNSP PGUID -1 f b A f t \054 0 3906 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 3908 ( tsrange PGNSP PGUID -1 f r R f t \054 0 0 3909 range_in range_out range_recv range_send - - range_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3907 ( _numrange PGNSP PGUID -1 f b A f t \054 0 3906 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 3908 ( tsrange PGNSP PGUID -1 f r R f t \054 0 0 3909 range_in range_out range_recv range_send - - range_typanalyze d x f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("range of timestamps without time zone");
-DATA(insert OID = 3909 ( _tsrange PGNSP PGUID -1 f b A f t \054 0 3908 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 3910 ( tstzrange PGNSP PGUID -1 f r R f t \054 0 0 3911 range_in range_out range_recv range_send - - range_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3909 ( _tsrange PGNSP PGUID -1 f b A f t \054 0 3908 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 3910 ( tstzrange PGNSP PGUID -1 f r R f t \054 0 0 3911 range_in range_out range_recv range_send - - range_typanalyze d x f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("range of timestamps with time zone");
-DATA(insert OID = 3911 ( _tstzrange PGNSP PGUID -1 f b A f t \054 0 3910 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 3912 ( daterange PGNSP PGUID -1 f r R f t \054 0 0 3913 range_in range_out range_recv range_send - - range_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3911 ( _tstzrange PGNSP PGUID -1 f b A f t \054 0 3910 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 3912 ( daterange PGNSP PGUID -1 f r R f t \054 0 0 3913 range_in range_out range_recv range_send - - range_typanalyze i x f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("range of dates");
-DATA(insert OID = 3913 ( _daterange PGNSP PGUID -1 f b A f t \054 0 3912 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ ));
-DATA(insert OID = 3926 ( int8range PGNSP PGUID -1 f r R f t \054 0 0 3927 range_in range_out range_recv range_send - - range_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3913 ( _daterange PGNSP PGUID -1 f b A f t \054 0 3912 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
+DATA(insert OID = 3926 ( int8range PGNSP PGUID -1 f r R f t \054 0 0 3927 range_in range_out range_recv range_send - - range_typanalyze d x f 0 -1 0 0 - _null_ _null_ _null_ ));
DESCR("range of bigints");
-DATA(insert OID = 3927 ( _int8range PGNSP PGUID -1 f b A f t \054 0 3926 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3927 ( _int8range PGNSP PGUID -1 f b A f t \054 0 3926 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
/*
* pseudo-types
@@ -676,41 +682,41 @@ DATA(insert OID = 3927 ( _int8range PGNSP PGUID -1 f b A f t \054 0 3926 0 arr
* but there is now support for it in records and arrays. Perhaps we should
* just treat it as a regular base type?
*/
-DATA(insert OID = 2249 ( record PGNSP PGUID -1 f p P f t \054 0 0 2287 record_in record_out record_recv record_send - - - d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2249 ( record PGNSP PGUID -1 f p P f t \054 0 0 2287 record_in record_out record_recv record_send - - - d x f 0 -1 0 0 - _null_ _null_ _null_ ));
#define RECORDOID 2249
-DATA(insert OID = 2287 ( _record PGNSP PGUID -1 f p P f t \054 0 2249 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2287 ( _record PGNSP PGUID -1 f p P f t \054 0 2249 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 array_subscript_handler _null_ _null_ _null_ ));
#define RECORDARRAYOID 2287
-DATA(insert OID = 2275 ( cstring PGNSP PGUID -2 f p P f t \054 0 0 1263 cstring_in cstring_out cstring_recv cstring_send - - - c p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2275 ( cstring PGNSP PGUID -2 f p P f t \054 0 0 1263 cstring_in cstring_out cstring_recv cstring_send - - - c p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define CSTRINGOID 2275
-DATA(insert OID = 2276 ( any PGNSP PGUID 4 t p P f t \054 0 0 0 any_in any_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2276 ( any PGNSP PGUID 4 t p P f t \054 0 0 0 any_in any_out - - - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define ANYOID 2276
-DATA(insert OID = 2277 ( anyarray PGNSP PGUID -1 f p P f t \054 0 0 0 anyarray_in anyarray_out anyarray_recv anyarray_send - - - d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2277 ( anyarray PGNSP PGUID -1 f p P f t \054 0 0 0 anyarray_in anyarray_out anyarray_recv anyarray_send - - - d x f 0 -1 0 0 - _null_ _null_ _null_ ));
#define ANYARRAYOID 2277
-DATA(insert OID = 2278 ( void PGNSP PGUID 4 t p P f t \054 0 0 0 void_in void_out void_recv void_send - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2278 ( void PGNSP PGUID 4 t p P f t \054 0 0 0 void_in void_out void_recv void_send - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define VOIDOID 2278
-DATA(insert OID = 2279 ( trigger PGNSP PGUID 4 t p P f t \054 0 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2279 ( trigger PGNSP PGUID 4 t p P f t \054 0 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define TRIGGEROID 2279
-DATA(insert OID = 3838 ( event_trigger PGNSP PGUID 4 t p P f t \054 0 0 0 event_trigger_in event_trigger_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3838 ( event_trigger PGNSP PGUID 4 t p P f t \054 0 0 0 event_trigger_in event_trigger_out - - - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define EVTTRIGGEROID 3838
-DATA(insert OID = 2280 ( language_handler PGNSP PGUID 4 t p P f t \054 0 0 0 language_handler_in language_handler_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2280 ( language_handler PGNSP PGUID 4 t p P f t \054 0 0 0 language_handler_in language_handler_out - - - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define LANGUAGE_HANDLEROID 2280
-DATA(insert OID = 2281 ( internal PGNSP PGUID SIZEOF_POINTER t p P f t \054 0 0 0 internal_in internal_out - - - - - ALIGNOF_POINTER p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2281 ( internal PGNSP PGUID SIZEOF_POINTER t p P f t \054 0 0 0 internal_in internal_out - - - - - ALIGNOF_POINTER p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define INTERNALOID 2281
-DATA(insert OID = 2282 ( opaque PGNSP PGUID 4 t p P f t \054 0 0 0 opaque_in opaque_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2282 ( opaque PGNSP PGUID 4 t p P f t \054 0 0 0 opaque_in opaque_out - - - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define OPAQUEOID 2282
-DATA(insert OID = 2283 ( anyelement PGNSP PGUID 4 t p P f t \054 0 0 0 anyelement_in anyelement_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2283 ( anyelement PGNSP PGUID 4 t p P f t \054 0 0 0 anyelement_in anyelement_out - - - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define ANYELEMENTOID 2283
-DATA(insert OID = 2776 ( anynonarray PGNSP PGUID 4 t p P f t \054 0 0 0 anynonarray_in anynonarray_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 2776 ( anynonarray PGNSP PGUID 4 t p P f t \054 0 0 0 anynonarray_in anynonarray_out - - - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define ANYNONARRAYOID 2776
-DATA(insert OID = 3500 ( anyenum PGNSP PGUID 4 t p P f t \054 0 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3500 ( anyenum PGNSP PGUID 4 t p P f t \054 0 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define ANYENUMOID 3500
-DATA(insert OID = 3115 ( fdw_handler PGNSP PGUID 4 t p P f t \054 0 0 0 fdw_handler_in fdw_handler_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3115 ( fdw_handler PGNSP PGUID 4 t p P f t \054 0 0 0 fdw_handler_in fdw_handler_out - - - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define FDW_HANDLEROID 3115
-DATA(insert OID = 325 ( index_am_handler PGNSP PGUID 4 t p P f t \054 0 0 0 index_am_handler_in index_am_handler_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 325 ( index_am_handler PGNSP PGUID 4 t p P f t \054 0 0 0 index_am_handler_in index_am_handler_out - - - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define INDEX_AM_HANDLEROID 325
-DATA(insert OID = 3310 ( tsm_handler PGNSP PGUID 4 t p P f t \054 0 0 0 tsm_handler_in tsm_handler_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3310 ( tsm_handler PGNSP PGUID 4 t p P f t \054 0 0 0 tsm_handler_in tsm_handler_out - - - - - i p f 0 -1 0 0 - _null_ _null_ _null_ ));
#define TSM_HANDLEROID 3310
-DATA(insert OID = 3831 ( anyrange PGNSP PGUID -1 f p P f t \054 0 0 0 anyrange_in anyrange_out - - - - - d x f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3831 ( anyrange PGNSP PGUID -1 f p P f t \054 0 0 0 anyrange_in anyrange_out - - - - - d x f 0 -1 0 0 - _null_ _null_ _null_ ));
#define ANYRANGEOID 3831
diff --git a/src/include/catalog/pg_type_fn.h b/src/include/catalog/pg_type_fn.h
index 0ea0e9029a..63613d9f72 100644
--- a/src/include/catalog/pg_type_fn.h
+++ b/src/include/catalog/pg_type_fn.h
@@ -52,7 +52,8 @@ extern ObjectAddress TypeCreate(Oid newTypeOid,
int32 typeMod,
int32 typNDims,
bool typeNotNull,
- Oid typeCollation);
+ Oid typeCollation,
+ Oid subscriptingParseProcedure);
extern void GenerateTypeDependencies(Oid typeNamespace,
Oid typeObjectId,
@@ -70,6 +71,7 @@ extern void GenerateTypeDependencies(Oid typeNamespace,
bool isImplicitArray,
Oid baseType,
Oid typeCollation,
+ Oid subscriptingParseProcedure,
Node *defaultExpr,
bool rebuild);
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index 6a05c38fed..b7d3c9f749 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -19,7 +19,7 @@
/* forward references to avoid circularity */
struct ExprEvalStep;
-struct ArrayRefState;
+struct SbsRoutines;
/* Bits in ExprState->flags (see also execnodes.h for public flag bits): */
/* expression's interpreter has been initialized */
@@ -27,6 +27,44 @@ struct ArrayRefState;
/* jump-threading is in use */
#define EEO_FLAG_DIRECT_THREADED (1 << 2)
+/* Non-inline data for container operations */
+typedef struct SubscriptingRefState
+{
+ bool isassignment; /* is it assignment, or just fetch? */
+
+ Oid refelemtype; /* OID of the container element type */
+ int16 refattrlength; /* typlen of container type */
+ int16 refelemlength; /* typlen of the container element type */
+ bool refelembyval; /* is the element type pass-by-value? */
+ char refelemalign; /* typalign of the element type */
+
+ /* numupper and upperprovided[] are filled at compile time */
+ /* at runtime, extracted subscript datums get stored in upperindex[] */
+ int numupper;
+ bool upperprovided[MAX_SUBSCRIPT_DEPTH];
+ Datum upper[MAX_SUBSCRIPT_DEPTH];
+
+ /* similarly for lower indexes, if any */
+ int numlower;
+ bool lowerprovided[MAX_SUBSCRIPT_DEPTH];
+ Datum lower[MAX_SUBSCRIPT_DEPTH];
+
+ /* subscript expressions get evaluated into here */
+ Datum subscriptvalue;
+ bool subscriptnull;
+
+ /* for assignment, new value to assign is evaluated into here */
+ Datum replacevalue;
+ bool replacenull;
+
+ /* if we have a nested assignment, SBSREF_OLD puts old value here */
+ Datum prevvalue;
+ bool prevnull;
+
+ bool resnull;
+ struct SbsRoutines *sbsroutines;
+} SubscriptingRefState;
+
/* Typical API for out-of-line evaluation subroutines */
typedef void (*ExecEvalSubroutine) (ExprState *state,
struct ExprEvalStep *op,
@@ -498,8 +536,11 @@ typedef struct ExprEvalStep
struct
{
/* too big to have inline */
- struct ArrayRefState *state;
- } arrayref;
+ FmgrInfo *eval_finfo; /* function to evaluate subscript */
+ FmgrInfo *nested_finfo; /* function to handle nested assignment */
+
+ struct SubscriptingRefState *state;
+ } sbsref;
/* for EEOP_DOMAIN_NOTNULL / DOMAIN_CHECK */
struct
@@ -638,42 +679,6 @@ typedef struct ExprEvalStep
} ExprEvalStep;
-/* Non-inline data for array operations */
-typedef struct ArrayRefState
-{
- bool isassignment; /* is it assignment, or just fetch? */
-
- Oid refelemtype; /* OID of the array element type */
- int16 refattrlength; /* typlen of array type */
- int16 refelemlength; /* typlen of the array element type */
- bool refelembyval; /* is the element type pass-by-value? */
- char refelemalign; /* typalign of the element type */
-
- /* numupper and upperprovided[] are filled at compile time */
- /* at runtime, extracted subscript datums get stored in upperindex[] */
- int numupper;
- bool upperprovided[MAXDIM];
- int upperindex[MAXDIM];
-
- /* similarly for lower indexes, if any */
- int numlower;
- bool lowerprovided[MAXDIM];
- int lowerindex[MAXDIM];
-
- /* subscript expressions get evaluated into here */
- Datum subscriptvalue;
- bool subscriptnull;
-
- /* for assignment, new value to assign is evaluated into here */
- Datum replacevalue;
- bool replacenull;
-
- /* if we have a nested assignment, ARRAYREF_OLD puts old value here */
- Datum prevvalue;
- bool prevnull;
-} ArrayRefState;
-
-
/* functions in execExpr.c */
extern void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s);
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index c991202243..22bed11a4a 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -388,28 +388,35 @@ typedef struct WindowFunc
* element; but it is the array type when doing subarray fetch or either
* type of store.
*
- * Note: for the cases where an array is returned, if refexpr yields a R/W
- * expanded array, then the implementation is allowed to modify that object
+ * Note: for the cases where a container is returned, if refexpr yields a R/W
+ * expanded container, then the implementation is allowed to modify that object
* in-place and return the same object.)
* ----------------
*/
-typedef struct ArrayRef
+
+typedef struct SubscriptingRef
{
Expr xpr;
- Oid refarraytype; /* type of the array proper */
- Oid refelemtype; /* type of the array elements */
- int32 reftypmod; /* typmod of the array (and elements too) */
- Oid refcollid; /* OID of collation, or InvalidOid if none */
- List *refupperindexpr; /* expressions that evaluate to upper
- * array indexes */
- List *reflowerindexpr; /* expressions that evaluate to lower
- * array indexes, or NIL for single array
- * element */
- Expr *refexpr; /* the expression that evaluates to an array
- * value */
- Expr *refassgnexpr; /* expression for the source value, or NULL if
- * fetch */
-} ArrayRef;
+ Oid refcontainertype; /* type of the container proper */
+ Oid refelemtype; /* type of the container elements */
+ Oid refassgntype; /* type of assignment expr that is required */
+ int32 reftypmod; /* typmod of the container (and elements too) */
+ Oid refcollid; /* OID of collation, or InvalidOid if none */
+ Oid refnestedfunc; /* OID of type-specific function to handle nested assignment */
+ List *refupperindexpr; /* expressions that evaluate to upper container
+ * indexes */
+ List *reflowerindexpr; /* expressions that evaluate to lower container
+ * indexes, or NIL for single container element */
+ List *refindexprslice; /* whether or not related indexpr from
+ * reflowerindexpr is a slice */
+ Expr *refexpr; /* the expression that evaluates to a container
+ * value */
+
+ Expr *refassgnexpr; /* expression for the source value, or NULL if
+ * fetch */
+} SubscriptingRef;
+
+#define IsAssignment(expr) ( ((SubscriptingRef*) expr)->refassgnexpr != NULL )
/*
* CoercionContext - distinguishes the allowed set of type casts
diff --git a/src/include/nodes/subscripting.h b/src/include/nodes/subscripting.h
new file mode 100644
index 0000000000..411df414a7
--- /dev/null
+++ b/src/include/nodes/subscripting.h
@@ -0,0 +1,42 @@
+/*-------------------------------------------------------------------------
+ *
+ * subscripting.h
+ * API for generic type subscripting
+ *
+ * Portions Copyright (c) 1996-2018, 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 "parser/parse_node.h"
+#include "nodes/primnodes.h"
+
+struct ParseState;
+struct SubscriptingRefState;
+
+/* Callback function signatures --- see xsubscripting.sgml for more info. */
+typedef SubscriptingRef * (*SubscriptingPrepare) (bool isAssignment, SubscriptingRef *sbsef);
+
+typedef SubscriptingRef * (*SubscriptingValidate) (bool isAssignment, SubscriptingRef *sbsef,
+ struct ParseState *pstate);
+
+typedef Datum (*SubscriptingFetch) (Datum source, struct SubscriptingRefState *sbsefstate);
+
+typedef Datum (*SubscriptingAssign) (Datum source, struct SubscriptingRefState *sbsefstate);
+
+typedef struct SbsRoutines
+{
+ SubscriptingPrepare prepare;
+ SubscriptingValidate validate;
+ SubscriptingFetch fetch;
+ SubscriptingAssign assign;
+
+} SbsRoutines;
+
+
+#endif /* SUBSCRIPTING_H */
diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h
index 4e96fa7907..d8d6d530df 100644
--- a/src/include/parser/parse_node.h
+++ b/src/include/parser/parse_node.h
@@ -15,6 +15,7 @@
#define PARSE_NODE_H
#include "nodes/parsenodes.h"
+#include "nodes/subscripting.h"
#include "utils/queryenvironment.h"
#include "utils/relcache.h"
@@ -270,14 +271,16 @@ extern void cancel_parser_errposition_callback(ParseCallbackState *pcbstate);
extern Var *make_var(ParseState *pstate, RangeTblEntry *rte, int attrno,
int location);
-extern Oid transformArrayType(Oid *arrayType, int32 *arrayTypmod);
-extern ArrayRef *transformArraySubscripts(ParseState *pstate,
- Node *arrayBase,
- Oid arrayType,
- Oid elementType,
- int32 arrayTypMod,
- List *indirection,
- Node *assignFrom);
+extern void transformContainerType(Oid *containerType, int32 *containerTypmod);
+
+extern SubscriptingRef *transformContainerSubscripts(ParseState *pstate,
+ Node *containerBase,
+ Oid containerType,
+ Oid elementType,
+ int32 containerTypMod,
+ List *indirection,
+ Node *assignFrom);
+extern SbsRoutines* getSubscriptingRoutines(Oid containerType);
extern Const *make_const(ParseState *pstate, Value *value, int location);
#endif /* PARSE_NODE_H */
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 9731e6f7ae..aa13f98e33 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -177,6 +177,7 @@ extern void free_attstatsslot(AttStatsSlot *sslot);
extern char *get_namespace_name(Oid nspid);
extern char *get_namespace_name_or_temp(Oid nspid);
extern Oid get_range_subtype(Oid rangeOid);
+extern RegProcedure get_typsubsprocs(Oid typid);
#define type_is_array(typid) (get_element_type(typid) != InvalidOid)
/* type_is_array_domain accepts both plain arrays and domains over arrays */
--
2.13.0