From 332b2d8e4c6888e806354d43c52e83eae722706b Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Thu, 22 Feb 2018 17:55:15 +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 | 40 +-- 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 | 54 ++-- src/backend/parser/parse_node.c | 259 ++++++------------ src/backend/parser/parse_target.c | 109 ++++---- 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 | 27 +- src/include/nodes/primnodes.h | 65 +++-- src/include/nodes/subscripting.h | 42 +++ src/include/parser/parse_node.h | 19 +- src/include/utils/lsyscache.h | 1 + 25 files changed, 666 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 0d42eb4..a87054d4 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 cf36ce4..033ac42 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 660ac5b..71d26ce 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 899a5c4..4681a3e 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 762af03..db61692 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -2429,20 +2429,18 @@ static void 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 = (SubscriptRoutines *) OidFunctionCall0(typsubshandler); /* * Evaluate array input. It's safe to do so into resv/resnull, because we @@ -2462,23 +2460,11 @@ ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref, scratch->opcode = EEOP_JUMP_IF_NULL; scratch->d.jump.jumpdone = -1; /* adjust later */ ExprEvalPushStep(state, scratch); + adjust_jumps = lappend_int(adjust_jumps, state->steps_len - 1); } - /* Verify subscript list lengths are within limit */ - if (list_length(aref->refupperindexpr) > MAXDIM) - ereport(ERROR, - (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", - list_length(aref->refupperindexpr), MAXDIM))); - - if (list_length(aref->reflowerindexpr) > MAXDIM) - ereport(ERROR, - (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", - list_length(aref->reflowerindexpr), MAXDIM))); - /* Evaluate upper subscripts */ i = 0; foreach(lc, sbsref->refupperindexpr) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index d76e3bc..5ef3880 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -3021,197 +3021,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->upperindex; else - indexes = arefstate->lowerindex; - off = op->d.arrayref_subscript.off; + indexes = sbsrefstate->lowerindex; + 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; + SubscriptRoutines *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; + SubscriptRoutines *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; + SubscriptRoutines *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 abf306b..b0b9fe6 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -1432,8 +1432,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 bdca6a1..83ccac6 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 ab3b021..f992352 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 42b94ce..29fba85 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -1192,8 +1192,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 0569ca8..1bcf33c 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -654,8 +654,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 385e54a..5ef606b 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -434,11 +434,13 @@ 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); - List *subscripts = NIL; - int location = exprLocation(result); - ListCell *i; + Node *last_srf = pstate->p_last_srf; + Node *result = transformExprRecurse(pstate, ind->arg); + SubscriptRoutines *sbsroutines; + SubscriptingRef *sbsref; + List *subscripts = NIL; + int location = exprLocation(result); + ListCell *i; /* * We have to split any field-selection operations apart from @@ -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 d267288..f032f8e 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; +} + +SubscriptRoutines* +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 (SubscriptRoutines *) OidFunctionCall0(typsubshandler); } /* diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 2886734..b1916c4 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -676,7 +676,7 @@ static Node * transformAssignmentIndirection(ParseState *pstate, Node *basenode, const char *targetName, - bool targetIsArray, + bool targetIsSubscripting, Oid targetTypeId, int32 targetTypMod, Oid targetCollation, @@ -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" @@ -892,58 +887,68 @@ transformAssignmentSubscripts(ParseState *pstate, Node *rhs, int location) { - Node *result; - Oid arrayType; - int32 arrayTypMod; - Oid elementTypeId; - Oid typeNeeded; - Oid collationNeeded; + Node *result; + Oid containerType; + int32 containerTypMod; + Oid collationNeeded; + SubscriptingRef *sbsref; + SubscriptRoutines *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; - /* Identify type that RHS must provide */ - typeNeeded = isSlice ? arrayType : elementTypeId; + /* process subscripts */ + sbsref = transformContainerSubscripts(pstate, + basenode, + containerType, + exprType(rhs), + containerTypMod, + subscripts, + rhs); + + sbsroutines = getSubscriptingRoutines(sbsref->refcontainertype); + + /* + * 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 1b7d0e2..a2087dc 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -7719,17 +7719,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 51b6b4f..45c038d 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -3106,3 +3106,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 37c0c39..8d9aa93 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -488,6 +488,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 26b1866..8ddacf8 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 5b5b121..4145c6a 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("@ , 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 0ea0e90..63613d9 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 c0257a4..885c758 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 SubscriptRoutines; /* Bits in ExprState->flags (see also execnodes.h for public flag bits): */ /* expression's interpreter has been initialized */ @@ -638,28 +638,27 @@ typedef struct ExprEvalStep } d; } ExprEvalStep; - -/* Non-inline data for array operations */ -typedef struct ArrayRefState +/* Non-inline data for container operations */ +typedef struct SubscriptingRefState { 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 */ + 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[MAXDIM]; - int upperindex[MAXDIM]; + bool upperprovided[MAX_SUBSCRIPT_DEPTH]; + Datum upperindex[MAX_SUBSCRIPT_DEPTH]; /* similarly for lower indexes, if any */ int numlower; - bool lowerprovided[MAXDIM]; - int lowerindex[MAXDIM]; + bool lowerprovided[MAX_SUBSCRIPT_DEPTH]; + Datum lowerindex[MAX_SUBSCRIPT_DEPTH]; /* subscript expressions get evaluated into here */ Datum subscriptvalue; @@ -669,11 +668,13 @@ typedef struct ArrayRefState Datum replacevalue; bool replacenull; - /* if we have a nested assignment, ARRAYREF_OLD puts old value here */ + /* if we have a nested assignment, SBSREF_OLD puts old value here */ Datum prevvalue; bool prevnull; -} ArrayRefState; + bool resnull; + struct SubscriptRoutines *sbsroutines; +} SubscriptingRefState; /* 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 93719ad..22bed11 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -365,18 +365,18 @@ typedef struct WindowFunc } WindowFunc; /* ---------------- - * ArrayRef: describes an array subscripting operation - * - * An ArrayRef can describe fetching a single element from an array, - * fetching a subarray (array slice), storing a single element into - * an array, or storing a slice. The "store" cases work with an - * initial array value and a source value that is inserted into the - * appropriate part of the array; the result of the operation is an - * entire new modified array value. - * - * If reflowerindexpr = NIL, then we are fetching or storing a single array - * element at the subscripts given by refupperindexpr. Otherwise we are - * fetching or storing an array slice, that is a rectangular subarray + * SubscriptingRef: describes a subscripting operation over a container + * + * A SubscriptingRef can describe fetching a single element from a container, + * fetching a part of container (e.g. array slice), storing a single element into + * a container, or storing a slice. The "store" cases work with an + * initial container value and a source value that is inserted into the + * appropriate part of the container; the result of the operation is an + * entire new modified container value. + * + * If reflowerindexpr = NIL, then we are fetching or storing a single container + * element at the subscripts given by refupperindexpr. Otherwise we are + * fetching or storing a container slice, that is a rectangular subcontainer * with lower and upper bounds given by the index expressions. * reflowerindexpr must be the same length as refupperindexpr when it * is not NIL. @@ -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 0000000..1800d5e --- /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 *sbsrefstate); + +typedef Datum (*SubscriptingAssign) (Datum source, struct SubscriptingRefState *sbrsefstate); + +typedef struct SubscriptRoutines +{ + SubscriptingPrepare prepare; + SubscriptingValidate validate; + SubscriptingFetch fetch; + SubscriptingAssign assign; + +} SubscriptRoutines; + + +#endif /* SUBSCRIPTING_H */ diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index 0230543..62298d9 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" @@ -271,14 +272,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 SubscriptRoutines* 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 1f6c04a..db26e99 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -176,6 +176,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.7.4