diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index 03582781f6..f1085b5d4d 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1740,529 +1740,955 @@ find_expr_references_walker(Node *node, { if (node == NULL) return false; - if (IsA(node, Var)) + switch (nodeTag(node)) { - Var *var = (Var *) node; - List *rtable; - RangeTblEntry *rte; - - /* Find matching rtable entry, or complain if not found */ - if (var->varlevelsup >= list_length(context->rtables)) - elog(ERROR, "invalid varlevelsup %d", var->varlevelsup); - rtable = (List *) list_nth(context->rtables, var->varlevelsup); - if (var->varno <= 0 || var->varno > list_length(rtable)) - elog(ERROR, "invalid varno %d", var->varno); - rte = rt_fetch(var->varno, rtable); + case T_Var: + { + Var *var = (Var *) node; + List *rtable; + RangeTblEntry *rte; - /* - * A whole-row Var references no specific columns, so adds no new - * dependency. (We assume that there is a whole-table dependency - * arising from each underlying rangetable entry. While we could - * record such a dependency when finding a whole-row Var that - * references a relation directly, it's quite unclear how to extend - * that to whole-row Vars for JOINs, so it seems better to leave the - * responsibility with the range table. Note that this poses some - * risks for identifying dependencies of stand-alone expressions: - * whole-table references may need to be created separately.) - */ - if (var->varattno == InvalidAttrNumber) + /* Find matching rtable entry, or complain if not found */ + if (var->varlevelsup >= list_length(context->rtables)) + elog(ERROR, "invalid varlevelsup %d", var->varlevelsup); + rtable = (List *) list_nth(context->rtables, var->varlevelsup); + if (var->varno <= 0 || var->varno > list_length(rtable)) + elog(ERROR, "invalid varno %d", var->varno); + rte = rt_fetch(var->varno, rtable); + + /* + * A whole-row Var references no specific columns, so adds no new + * dependency. (We assume that there is a whole-table dependency + * arising from each underlying rangetable entry. While we could + * record such a dependency when finding a whole-row Var that + * references a relation directly, it's quite unclear how to extend + * that to whole-row Vars for JOINs, so it seems better to leave the + * responsibility with the range table. Note that this poses some + * risks for identifying dependencies of stand-alone expressions: + * whole-table references may need to be created separately.) + */ + if (var->varattno == InvalidAttrNumber) + return false; + if (rte->rtekind == RTE_RELATION) + { + /* If it's a plain relation, reference this column */ + add_object_address(OCLASS_CLASS, rte->relid, var->varattno, + context->addrs); + } + else if (rte->rtekind == RTE_JOIN) + { + /* Scan join output column to add references to join inputs */ + List *save_rtables; + + /* We must make the context appropriate for join's level */ + save_rtables = context->rtables; + context->rtables = list_copy_tail(context->rtables, + var->varlevelsup); + if (var->varattno <= 0 || + var->varattno > list_length(rte->joinaliasvars)) + elog(ERROR, "invalid varattno %d", var->varattno); + find_expr_references_walker((Node *) list_nth(rte->joinaliasvars, + var->varattno - 1), + context); + list_free(context->rtables); + context->rtables = save_rtables; + } return false; - if (rte->rtekind == RTE_RELATION) - { - /* If it's a plain relation, reference this column */ - add_object_address(OCLASS_CLASS, rte->relid, var->varattno, - context->addrs); } - else if (rte->rtekind == RTE_JOIN) + break; + case T_Const: { - /* Scan join output column to add references to join inputs */ - List *save_rtables; - - /* We must make the context appropriate for join's level */ - save_rtables = context->rtables; - context->rtables = list_copy_tail(context->rtables, - var->varlevelsup); - if (var->varattno <= 0 || - var->varattno > list_length(rte->joinaliasvars)) - elog(ERROR, "invalid varattno %d", var->varattno); - find_expr_references_walker((Node *) list_nth(rte->joinaliasvars, - var->varattno - 1), - context); - list_free(context->rtables); - context->rtables = save_rtables; - } - return false; - } - else if (IsA(node, Const)) - { - Const *con = (Const *) node; - Oid objoid; + Const *con = (Const *) node; + Oid objoid; - /* A constant must depend on the constant's datatype */ - add_object_address(OCLASS_TYPE, con->consttype, 0, - context->addrs); - - /* - * We must also depend on the constant's collation: it could be - * different from the datatype's, if a CollateExpr was const-folded to - * a simple constant. However we can save work in the most common - * case where the collation is "default", since we know that's pinned. - */ - if (OidIsValid(con->constcollid) && - con->constcollid != DEFAULT_COLLATION_OID) - add_object_address(OCLASS_COLLATION, con->constcollid, 0, + /* A constant must depend on the constant's datatype */ + add_object_address(OCLASS_TYPE, con->consttype, 0, context->addrs); - /* - * If it's a regclass or similar literal referring to an existing - * object, add a reference to that object. (Currently, only the - * regclass and regconfig cases have any likely use, but we may as - * well handle all the OID-alias datatypes consistently.) - */ - if (!con->constisnull) - { - switch (con->consttype) - { - case REGPROCOID: - case REGPROCEDUREOID: - objoid = DatumGetObjectId(con->constvalue); - if (SearchSysCacheExists1(PROCOID, - ObjectIdGetDatum(objoid))) - add_object_address(OCLASS_PROC, objoid, 0, - context->addrs); - break; - case REGOPEROID: - case REGOPERATOROID: - objoid = DatumGetObjectId(con->constvalue); - if (SearchSysCacheExists1(OPEROID, - ObjectIdGetDatum(objoid))) - add_object_address(OCLASS_OPERATOR, objoid, 0, - context->addrs); - break; - case REGCLASSOID: - objoid = DatumGetObjectId(con->constvalue); - if (SearchSysCacheExists1(RELOID, - ObjectIdGetDatum(objoid))) - add_object_address(OCLASS_CLASS, objoid, 0, - context->addrs); - break; - case REGTYPEOID: - objoid = DatumGetObjectId(con->constvalue); - if (SearchSysCacheExists1(TYPEOID, - ObjectIdGetDatum(objoid))) - add_object_address(OCLASS_TYPE, objoid, 0, - context->addrs); - break; - case REGCONFIGOID: - objoid = DatumGetObjectId(con->constvalue); - if (SearchSysCacheExists1(TSCONFIGOID, - ObjectIdGetDatum(objoid))) - add_object_address(OCLASS_TSCONFIG, objoid, 0, - context->addrs); - break; - case REGDICTIONARYOID: - objoid = DatumGetObjectId(con->constvalue); - if (SearchSysCacheExists1(TSDICTOID, - ObjectIdGetDatum(objoid))) - add_object_address(OCLASS_TSDICT, objoid, 0, - context->addrs); - break; - - case REGNAMESPACEOID: - objoid = DatumGetObjectId(con->constvalue); - if (SearchSysCacheExists1(NAMESPACEOID, - ObjectIdGetDatum(objoid))) - add_object_address(OCLASS_SCHEMA, objoid, 0, - context->addrs); - break; + /* + * We must also depend on the constant's collation: it could be + * different from the datatype's, if a CollateExpr was const-folded to + * a simple constant. However we can save work in the most common + * case where the collation is "default", since we know that's pinned. + */ + if (OidIsValid(con->constcollid) && + con->constcollid != DEFAULT_COLLATION_OID) + add_object_address(OCLASS_COLLATION, con->constcollid, 0, + context->addrs); - /* - * Dependencies for regrole should be shared among all - * databases, so explicitly inhibit to have dependencies. - */ - case REGROLEOID: - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("constant of the type %s cannot be used here", - "regrole"))); - break; + /* + * If it's a regclass or similar literal referring to an existing + * object, add a reference to that object. (Currently, only the + * regclass and regconfig cases have any likely use, but we may as + * well handle all the OID-alias datatypes consistently.) + */ + if (!con->constisnull) + { + switch (con->consttype) + { + case REGPROCOID: + case REGPROCEDUREOID: + objoid = DatumGetObjectId(con->constvalue); + if (SearchSysCacheExists1(PROCOID, + ObjectIdGetDatum(objoid))) + add_object_address(OCLASS_PROC, objoid, 0, + context->addrs); + break; + case REGOPEROID: + case REGOPERATOROID: + objoid = DatumGetObjectId(con->constvalue); + if (SearchSysCacheExists1(OPEROID, + ObjectIdGetDatum(objoid))) + add_object_address(OCLASS_OPERATOR, objoid, 0, + context->addrs); + break; + case REGCLASSOID: + objoid = DatumGetObjectId(con->constvalue); + if (SearchSysCacheExists1(RELOID, + ObjectIdGetDatum(objoid))) + add_object_address(OCLASS_CLASS, objoid, 0, + context->addrs); + break; + case REGTYPEOID: + objoid = DatumGetObjectId(con->constvalue); + if (SearchSysCacheExists1(TYPEOID, + ObjectIdGetDatum(objoid))) + add_object_address(OCLASS_TYPE, objoid, 0, + context->addrs); + break; + case REGCONFIGOID: + objoid = DatumGetObjectId(con->constvalue); + if (SearchSysCacheExists1(TSCONFIGOID, + ObjectIdGetDatum(objoid))) + add_object_address(OCLASS_TSCONFIG, objoid, 0, + context->addrs); + break; + case REGDICTIONARYOID: + objoid = DatumGetObjectId(con->constvalue); + if (SearchSysCacheExists1(TSDICTOID, + ObjectIdGetDatum(objoid))) + add_object_address(OCLASS_TSDICT, objoid, 0, + context->addrs); + break; + + case REGNAMESPACEOID: + objoid = DatumGetObjectId(con->constvalue); + if (SearchSysCacheExists1(NAMESPACEOID, + ObjectIdGetDatum(objoid))) + add_object_address(OCLASS_SCHEMA, objoid, 0, + context->addrs); + break; + + /* + * Dependencies for regrole should be shared among all + * databases, so explicitly inhibit to have dependencies. + */ + case REGROLEOID: + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("constant of the type %s cannot be used here", + "regrole"))); + break; + } } + return false; } - return false; - } - else if (IsA(node, Param)) - { - Param *param = (Param *) node; - - /* A parameter must depend on the parameter's datatype */ - add_object_address(OCLASS_TYPE, param->paramtype, 0, - context->addrs); - /* and its collation, just as for Consts */ - if (OidIsValid(param->paramcollid) && - param->paramcollid != DEFAULT_COLLATION_OID) - add_object_address(OCLASS_COLLATION, param->paramcollid, 0, - context->addrs); - } - else if (IsA(node, FuncExpr)) - { - FuncExpr *funcexpr = (FuncExpr *) node; - - add_object_address(OCLASS_PROC, funcexpr->funcid, 0, - context->addrs); - /* fall through to examine arguments */ - } - else if (IsA(node, OpExpr)) - { - OpExpr *opexpr = (OpExpr *) node; - - add_object_address(OCLASS_OPERATOR, opexpr->opno, 0, - context->addrs); - /* fall through to examine arguments */ - } - else if (IsA(node, DistinctExpr)) - { - DistinctExpr *distinctexpr = (DistinctExpr *) node; - - add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0, - context->addrs); - /* fall through to examine arguments */ - } - else if (IsA(node, NullIfExpr)) - { - NullIfExpr *nullifexpr = (NullIfExpr *) node; + break; + case T_Param: + { + Param *param = (Param *) node; - add_object_address(OCLASS_OPERATOR, nullifexpr->opno, 0, - context->addrs); - /* fall through to examine arguments */ - } - else if (IsA(node, ScalarArrayOpExpr)) - { - ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node; + /* A parameter must depend on the parameter's datatype */ + add_object_address(OCLASS_TYPE, param->paramtype, 0, + context->addrs); + /* and its collation, just as for Consts */ + if (OidIsValid(param->paramcollid) && + param->paramcollid != DEFAULT_COLLATION_OID) + add_object_address(OCLASS_COLLATION, param->paramcollid, 0, + context->addrs); + } + break; + case T_FuncExpr: + { + FuncExpr *funcexpr = (FuncExpr *) node; - add_object_address(OCLASS_OPERATOR, opexpr->opno, 0, - context->addrs); - /* fall through to examine arguments */ - } - else if (IsA(node, Aggref)) - { - Aggref *aggref = (Aggref *) node; + add_object_address(OCLASS_PROC, funcexpr->funcid, 0, + context->addrs); + /* fall through to examine arguments */ + } + break; + case T_OpExpr: + { + OpExpr *opexpr = (OpExpr *) node; - add_object_address(OCLASS_PROC, aggref->aggfnoid, 0, - context->addrs); - /* fall through to examine arguments */ - } - else if (IsA(node, WindowFunc)) - { - WindowFunc *wfunc = (WindowFunc *) node; + add_object_address(OCLASS_OPERATOR, opexpr->opno, 0, + context->addrs); + /* fall through to examine arguments */ + } + break; + case T_DistinctExpr: + { + DistinctExpr *distinctexpr = (DistinctExpr *) node; - add_object_address(OCLASS_PROC, wfunc->winfnoid, 0, - context->addrs); - /* fall through to examine arguments */ - } - else if (IsA(node, SubPlan)) - { - /* Extra work needed here if we ever need this case */ - elog(ERROR, "already-planned subqueries not supported"); - } - else if (IsA(node, FieldSelect)) - { - FieldSelect *fselect = (FieldSelect *) node; - Oid argtype = getBaseType(exprType((Node *) fselect->arg)); - Oid reltype = get_typ_typrelid(argtype); + add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0, + context->addrs); + /* fall through to examine arguments */ + } + break; + case T_NullIfExpr: + { + NullIfExpr *nullifexpr = (NullIfExpr *) node; - /* - * We need a dependency on the specific column named in FieldSelect, - * assuming we can identify the pg_class OID for it. (Probably we - * always can at the moment, but in future it might be possible for - * argtype to be RECORDOID.) If we can make a column dependency then - * we shouldn't need a dependency on the column's type; but if we - * can't, make a dependency on the type, as it might not appear - * anywhere else in the expression. - */ - if (OidIsValid(reltype)) - add_object_address(OCLASS_CLASS, reltype, fselect->fieldnum, + add_object_address(OCLASS_OPERATOR, nullifexpr->opno, 0, context->addrs); - else - add_object_address(OCLASS_TYPE, fselect->resulttype, 0, + /* fall through to examine arguments */ + } + break; + case T_ScalarArrayOpExpr: + { + ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node; + + add_object_address(OCLASS_OPERATOR, opexpr->opno, 0, context->addrs); - /* the collation might not be referenced anywhere else, either */ - if (OidIsValid(fselect->resultcollid) && - fselect->resultcollid != DEFAULT_COLLATION_OID) - add_object_address(OCLASS_COLLATION, fselect->resultcollid, 0, + /* fall through to examine arguments */ + } + break; + case T_Aggref: + { + Aggref *aggref = (Aggref *) node; + + add_object_address(OCLASS_PROC, aggref->aggfnoid, 0, context->addrs); - } - else if (IsA(node, FieldStore)) - { - FieldStore *fstore = (FieldStore *) node; - Oid reltype = get_typ_typrelid(fstore->resulttype); + /* fall through to examine arguments */ + } + break; + case T_WindowFunc: + { + WindowFunc *wfunc = (WindowFunc *) node; - /* similar considerations to FieldSelect, but multiple column(s) */ - if (OidIsValid(reltype)) + add_object_address(OCLASS_PROC, wfunc->winfnoid, 0, + context->addrs); + /* fall through to examine arguments */ + } + break; + case T_SubPlan: { - ListCell *l; + /* Extra work needed here if we ever need this case */ + elog(ERROR, "already-planned subqueries not supported"); + } + break; + case T_FieldSelect: + { + FieldSelect *fselect = (FieldSelect *) node; + Oid argtype = getBaseType(exprType((Node *) fselect->arg)); + Oid reltype = get_typ_typrelid(argtype); - foreach(l, fstore->fieldnums) - add_object_address(OCLASS_CLASS, reltype, lfirst_int(l), + /* + * We need a dependency on the specific column named in FieldSelect, + * assuming we can identify the pg_class OID for it. (Probably we + * always can at the moment, but in future it might be possible for + * argtype to be RECORDOID.) If we can make a column dependency then + * we shouldn't need a dependency on the column's type; but if we + * can't, make a dependency on the type, as it might not appear + * anywhere else in the expression. + */ + if (OidIsValid(reltype)) + add_object_address(OCLASS_CLASS, reltype, fselect->fieldnum, + context->addrs); + else + add_object_address(OCLASS_TYPE, fselect->resulttype, 0, + context->addrs); + /* the collation might not be referenced anywhere else, either */ + if (OidIsValid(fselect->resultcollid) && + fselect->resultcollid != DEFAULT_COLLATION_OID) + add_object_address(OCLASS_COLLATION, fselect->resultcollid, 0, context->addrs); } - else - add_object_address(OCLASS_TYPE, fstore->resulttype, 0, - context->addrs); - } - else if (IsA(node, RelabelType)) - { - RelabelType *relab = (RelabelType *) node; - - /* since there is no function dependency, need to depend on type */ - add_object_address(OCLASS_TYPE, relab->resulttype, 0, - context->addrs); - /* the collation might not be referenced anywhere else, either */ - if (OidIsValid(relab->resultcollid) && - relab->resultcollid != DEFAULT_COLLATION_OID) - add_object_address(OCLASS_COLLATION, relab->resultcollid, 0, - context->addrs); - } - else if (IsA(node, CoerceViaIO)) - { - CoerceViaIO *iocoerce = (CoerceViaIO *) node; - - /* since there is no exposed function, need to depend on type */ - add_object_address(OCLASS_TYPE, iocoerce->resulttype, 0, - context->addrs); - /* the collation might not be referenced anywhere else, either */ - if (OidIsValid(iocoerce->resultcollid) && - iocoerce->resultcollid != DEFAULT_COLLATION_OID) - add_object_address(OCLASS_COLLATION, iocoerce->resultcollid, 0, - context->addrs); - } - else if (IsA(node, ArrayCoerceExpr)) - { - ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; - - /* as above, depend on type */ - add_object_address(OCLASS_TYPE, acoerce->resulttype, 0, - context->addrs); - /* the collation might not be referenced anywhere else, either */ - if (OidIsValid(acoerce->resultcollid) && - acoerce->resultcollid != DEFAULT_COLLATION_OID) - add_object_address(OCLASS_COLLATION, acoerce->resultcollid, 0, - context->addrs); - /* fall through to examine arguments */ - } - else if (IsA(node, ConvertRowtypeExpr)) - { - ConvertRowtypeExpr *cvt = (ConvertRowtypeExpr *) node; - - /* since there is no function dependency, need to depend on type */ - add_object_address(OCLASS_TYPE, cvt->resulttype, 0, - context->addrs); - } - else if (IsA(node, CollateExpr)) - { - CollateExpr *coll = (CollateExpr *) node; - - add_object_address(OCLASS_COLLATION, coll->collOid, 0, - context->addrs); - } - else if (IsA(node, RowExpr)) - { - RowExpr *rowexpr = (RowExpr *) node; + break; + case T_FieldStore: + { + FieldStore *fstore = (FieldStore *) node; + Oid reltype = get_typ_typrelid(fstore->resulttype); - add_object_address(OCLASS_TYPE, rowexpr->row_typeid, 0, - context->addrs); - } - else if (IsA(node, RowCompareExpr)) - { - RowCompareExpr *rcexpr = (RowCompareExpr *) node; - ListCell *l; + /* similar considerations to FieldSelect, but multiple column(s) */ + if (OidIsValid(reltype)) + { + ListCell *l; - foreach(l, rcexpr->opnos) + foreach(l, fstore->fieldnums) + add_object_address(OCLASS_CLASS, reltype, lfirst_int(l), + context->addrs); + } + else + add_object_address(OCLASS_TYPE, fstore->resulttype, 0, + context->addrs); + } + break; + case T_RelabelType: { - add_object_address(OCLASS_OPERATOR, lfirst_oid(l), 0, + RelabelType *relab = (RelabelType *) node; + + /* since there is no function dependency, need to depend on type */ + add_object_address(OCLASS_TYPE, relab->resulttype, 0, context->addrs); + /* the collation might not be referenced anywhere else, either */ + if (OidIsValid(relab->resultcollid) && + relab->resultcollid != DEFAULT_COLLATION_OID) + add_object_address(OCLASS_COLLATION, relab->resultcollid, 0, + context->addrs); } - foreach(l, rcexpr->opfamilies) + break; + case T_CoerceViaIO: { - add_object_address(OCLASS_OPFAMILY, lfirst_oid(l), 0, + CoerceViaIO *iocoerce = (CoerceViaIO *) node; + + /* since there is no exposed function, need to depend on type */ + add_object_address(OCLASS_TYPE, iocoerce->resulttype, 0, context->addrs); + /* the collation might not be referenced anywhere else, either */ + if (OidIsValid(iocoerce->resultcollid) && + iocoerce->resultcollid != DEFAULT_COLLATION_OID) + add_object_address(OCLASS_COLLATION, iocoerce->resultcollid, 0, + context->addrs); } - /* fall through to examine arguments */ - } - else if (IsA(node, CoerceToDomain)) - { - CoerceToDomain *cd = (CoerceToDomain *) node; - - add_object_address(OCLASS_TYPE, cd->resulttype, 0, - context->addrs); - } - else if (IsA(node, NextValueExpr)) - { - NextValueExpr *nve = (NextValueExpr *) node; + break; + case T_ArrayCoerceExpr: + { + ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; - add_object_address(OCLASS_CLASS, nve->seqid, 0, - context->addrs); - } - else if (IsA(node, OnConflictExpr)) - { - OnConflictExpr *onconflict = (OnConflictExpr *) node; + /* as above, depend on type */ + add_object_address(OCLASS_TYPE, acoerce->resulttype, 0, + context->addrs); + /* the collation might not be referenced anywhere else, either */ + if (OidIsValid(acoerce->resultcollid) && + acoerce->resultcollid != DEFAULT_COLLATION_OID) + add_object_address(OCLASS_COLLATION, acoerce->resultcollid, 0, + context->addrs); + /* fall through to examine arguments */ + } + break; + case T_ConvertRowtypeExpr: + { + ConvertRowtypeExpr *cvt = (ConvertRowtypeExpr *) node; - if (OidIsValid(onconflict->constraint)) - add_object_address(OCLASS_CONSTRAINT, onconflict->constraint, 0, + /* since there is no function dependency, need to depend on type */ + add_object_address(OCLASS_TYPE, cvt->resulttype, 0, context->addrs); - /* fall through to examine arguments */ - } - else if (IsA(node, SortGroupClause)) - { - SortGroupClause *sgc = (SortGroupClause *) node; + } + break; + case T_CollateExpr: + { + CollateExpr *coll = (CollateExpr *) node; - add_object_address(OCLASS_OPERATOR, sgc->eqop, 0, - context->addrs); - if (OidIsValid(sgc->sortop)) - add_object_address(OCLASS_OPERATOR, sgc->sortop, 0, + add_object_address(OCLASS_COLLATION, coll->collOid, 0, context->addrs); - return false; - } - else if (IsA(node, WindowClause)) - { - WindowClause *wc = (WindowClause *) node; + } + break; + case T_RowExpr: + { + RowExpr *rowexpr = (RowExpr *) node; - if (OidIsValid(wc->startInRangeFunc)) - add_object_address(OCLASS_PROC, wc->startInRangeFunc, 0, + add_object_address(OCLASS_TYPE, rowexpr->row_typeid, 0, context->addrs); - if (OidIsValid(wc->endInRangeFunc)) - add_object_address(OCLASS_PROC, wc->endInRangeFunc, 0, + } + break; + case T_RowCompareExpr: + { + RowCompareExpr *rcexpr = (RowCompareExpr *) node; + ListCell *l; + + foreach(l, rcexpr->opnos) + { + add_object_address(OCLASS_OPERATOR, lfirst_oid(l), 0, + context->addrs); + } + foreach(l, rcexpr->opfamilies) + { + add_object_address(OCLASS_OPFAMILY, lfirst_oid(l), 0, + context->addrs); + } + /* fall through to examine arguments */ + } + break; + case T_CoerceToDomain: + { + CoerceToDomain *cd = (CoerceToDomain *) node; + + add_object_address(OCLASS_TYPE, cd->resulttype, 0, context->addrs); - if (OidIsValid(wc->inRangeColl) && - wc->inRangeColl != DEFAULT_COLLATION_OID) - add_object_address(OCLASS_COLLATION, wc->inRangeColl, 0, + } + break; + case T_NextValueExpr: + { + NextValueExpr *nve = (NextValueExpr *) node; + + add_object_address(OCLASS_CLASS, nve->seqid, 0, context->addrs); - /* fall through to examine substructure */ - } - else if (IsA(node, Query)) - { - /* Recurse into RTE subquery or not-yet-planned sublink subquery */ - Query *query = (Query *) node; - ListCell *lc; - bool result; + } + break; + case T_OnConflictExpr: + { + OnConflictExpr *onconflict = (OnConflictExpr *) node; - /* - * Add whole-relation refs for each plain relation mentioned in the - * subquery's rtable. - * - * Note: query_tree_walker takes care of recursing into RTE_FUNCTION - * RTEs, subqueries, etc, so no need to do that here. But keep it - * from looking at join alias lists. - * - * Note: we don't need to worry about collations mentioned in - * RTE_VALUES or RTE_CTE RTEs, because those must just duplicate - * collations referenced in other parts of the Query. We do have to - * worry about collations mentioned in RTE_FUNCTION, but we take care - * of those when we recurse to the RangeTblFunction node(s). - */ - foreach(lc, query->rtable) + if (OidIsValid(onconflict->constraint)) + add_object_address(OCLASS_CONSTRAINT, onconflict->constraint, 0, + context->addrs); + /* fall through to examine arguments */ + } + break; + case T_SortGroupClause: { - RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); + SortGroupClause *sgc = (SortGroupClause *) node; - switch (rte->rtekind) - { - case RTE_RELATION: - add_object_address(OCLASS_CLASS, rte->relid, 0, - context->addrs); - break; - default: - break; - } + add_object_address(OCLASS_OPERATOR, sgc->eqop, 0, + context->addrs); + if (OidIsValid(sgc->sortop)) + add_object_address(OCLASS_OPERATOR, sgc->sortop, 0, + context->addrs); + return false; } + break; + case T_WindowClause: + { + WindowClause *wc = (WindowClause *) node; - /* - * If the query is an INSERT or UPDATE, we should create a dependency - * on each target column, to prevent the specific target column from - * being dropped. Although we will visit the TargetEntry nodes again - * during query_tree_walker, we won't have enough context to do this - * conveniently, so do it here. - */ - if (query->commandType == CMD_INSERT || - query->commandType == CMD_UPDATE) + if (OidIsValid(wc->startInRangeFunc)) + add_object_address(OCLASS_PROC, wc->startInRangeFunc, 0, + context->addrs); + if (OidIsValid(wc->endInRangeFunc)) + add_object_address(OCLASS_PROC, wc->endInRangeFunc, 0, + context->addrs); + if (OidIsValid(wc->inRangeColl) && + wc->inRangeColl != DEFAULT_COLLATION_OID) + add_object_address(OCLASS_COLLATION, wc->inRangeColl, 0, + context->addrs); + /* fall through to examine substructure */ + } + break; + case T_Query: { - RangeTblEntry *rte; + /* Recurse into RTE subquery or not-yet-planned sublink subquery */ + Query *query = (Query *) node; + ListCell *lc; + bool result; - if (query->resultRelation <= 0 || - query->resultRelation > list_length(query->rtable)) - elog(ERROR, "invalid resultRelation %d", - query->resultRelation); - rte = rt_fetch(query->resultRelation, query->rtable); - if (rte->rtekind == RTE_RELATION) + /* + * Add whole-relation refs for each plain relation mentioned in the + * subquery's rtable. + * + * Note: query_tree_walker takes care of recursing into RTE_FUNCTION + * RTEs, subqueries, etc, so no need to do that here. But keep it + * from looking at join alias lists. + * + * Note: we don't need to worry about collations mentioned in + * RTE_VALUES or RTE_CTE RTEs, because those must just duplicate + * collations referenced in other parts of the Query. We do have to + * worry about collations mentioned in RTE_FUNCTION, but we take care + * of those when we recurse to the RangeTblFunction node(s). + */ + foreach(lc, query->rtable) { - foreach(lc, query->targetList) - { - TargetEntry *tle = (TargetEntry *) lfirst(lc); + RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); - if (tle->resjunk) - continue; /* ignore junk tlist items */ - add_object_address(OCLASS_CLASS, rte->relid, tle->resno, - context->addrs); + switch (rte->rtekind) + { + case RTE_RELATION: + add_object_address(OCLASS_CLASS, rte->relid, 0, + context->addrs); + break; + default: + break; } } - } - /* - * Add dependencies on constraints listed in query's constraintDeps - */ - foreach(lc, query->constraintDeps) - { - add_object_address(OCLASS_CONSTRAINT, lfirst_oid(lc), 0, - context->addrs); - } + /* + * If the query is an INSERT or UPDATE, we should create a dependency + * on each target column, to prevent the specific target column from + * being dropped. Although we will visit the TargetEntry nodes again + * during query_tree_walker, we won't have enough context to do this + * conveniently, so do it here. + */ + if (query->commandType == CMD_INSERT || + query->commandType == CMD_UPDATE) + { + RangeTblEntry *rte; + + if (query->resultRelation <= 0 || + query->resultRelation > list_length(query->rtable)) + elog(ERROR, "invalid resultRelation %d", + query->resultRelation); + rte = rt_fetch(query->resultRelation, query->rtable); + if (rte->rtekind == RTE_RELATION) + { + foreach(lc, query->targetList) + { + TargetEntry *tle = (TargetEntry *) lfirst(lc); - /* Examine substructure of query */ - context->rtables = lcons(query->rtable, context->rtables); - result = query_tree_walker(query, - find_expr_references_walker, - (void *) context, - QTW_IGNORE_JOINALIASES | - QTW_EXAMINE_SORTGROUP); - context->rtables = list_delete_first(context->rtables); - return result; - } - else if (IsA(node, SetOperationStmt)) - { - SetOperationStmt *setop = (SetOperationStmt *) node; + if (tle->resjunk) + continue; /* ignore junk tlist items */ + add_object_address(OCLASS_CLASS, rte->relid, tle->resno, + context->addrs); + } + } + } - /* we need to look at the groupClauses for operator references */ - find_expr_references_walker((Node *) setop->groupClauses, context); - /* fall through to examine child nodes */ - } - else if (IsA(node, RangeTblFunction)) - { - RangeTblFunction *rtfunc = (RangeTblFunction *) node; - ListCell *ct; + /* + * Add dependencies on constraints listed in query's constraintDeps + */ + foreach(lc, query->constraintDeps) + { + add_object_address(OCLASS_CONSTRAINT, lfirst_oid(lc), 0, + context->addrs); + } - /* - * Add refs for any datatypes and collations used in a column - * definition list for a RECORD function. (For other cases, it should - * be enough to depend on the function itself.) - */ - foreach(ct, rtfunc->funccoltypes) + /* Examine substructure of query */ + context->rtables = lcons(query->rtable, context->rtables); + result = query_tree_walker(query, + find_expr_references_walker, + (void *) context, + QTW_IGNORE_JOINALIASES | + QTW_EXAMINE_SORTGROUP); + context->rtables = list_delete_first(context->rtables); + return result; + } + break; + case T_SetOperationStmt: { - add_object_address(OCLASS_TYPE, lfirst_oid(ct), 0, - context->addrs); + SetOperationStmt *setop = (SetOperationStmt *) node; + + /* we need to look at the groupClauses for operator references */ + find_expr_references_walker((Node *) setop->groupClauses, context); + /* fall through to examine child nodes */ } - foreach(ct, rtfunc->funccolcollations) + break; + case T_RangeTblFunction: { - Oid collid = lfirst_oid(ct); + RangeTblFunction *rtfunc = (RangeTblFunction *) node; + ListCell *ct; - if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID) - add_object_address(OCLASS_COLLATION, collid, 0, + /* + * Add refs for any datatypes and collations used in a column + * definition list for a RECORD function. (For other cases, it should + * be enough to depend on the function itself.) + */ + foreach(ct, rtfunc->funccoltypes) + { + add_object_address(OCLASS_TYPE, lfirst_oid(ct), 0, context->addrs); + } + foreach(ct, rtfunc->funccolcollations) + { + Oid collid = lfirst_oid(ct); + + if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID) + add_object_address(OCLASS_COLLATION, collid, 0, + context->addrs); + } } - } - else if (IsA(node, TableSampleClause)) - { - TableSampleClause *tsc = (TableSampleClause *) node; + break; + case T_TableSampleClause: + { + TableSampleClause *tsc = (TableSampleClause *) node; + + add_object_address(OCLASS_PROC, tsc->tsmhandler, 0, + context->addrs); + /* fall through to examine arguments */ + } + break; + + case T_Invalid: + case T_IndexInfo: + case T_ExprContext: + case T_ProjectionInfo: + case T_JunkFilter: + case T_OnConflictSetState: + case T_ResultRelInfo: + case T_EState: + case T_TupleTableSlot: + case T_Plan: + case T_Result: + case T_ProjectSet: + case T_ModifyTable: + case T_Append: + case T_MergeAppend: + case T_RecursiveUnion: + case T_BitmapAnd: + case T_BitmapOr: + case T_Scan: + case T_SeqScan: + case T_SampleScan: + case T_IndexScan: + case T_IndexOnlyScan: + case T_BitmapIndexScan: + case T_BitmapHeapScan: + case T_TidScan: + case T_SubqueryScan: + case T_FunctionScan: + case T_ValuesScan: + case T_TableFuncScan: + case T_CteScan: + case T_NamedTuplestoreScan: + case T_WorkTableScan: + case T_ForeignScan: + case T_CustomScan: + case T_Join: + case T_NestLoop: + case T_MergeJoin: + case T_HashJoin: + case T_Material: + case T_Sort: + case T_Group: + case T_Agg: + case T_WindowAgg: + case T_Unique: + case T_Gather: + case T_GatherMerge: + case T_Hash: + case T_SetOp: + case T_LockRows: + case T_Limit: + case T_NestLoopParam: + case T_PlanRowMark: + case T_PartitionPruneInfo: + case T_PartitionedRelPruneInfo: + case T_PartitionPruneStepOp: + case T_PartitionPruneStepCombine: + case T_PlanInvalItem: + case T_PlanState: + case T_ResultState: + case T_ProjectSetState: + case T_ModifyTableState: + case T_AppendState: + case T_MergeAppendState: + case T_RecursiveUnionState: + case T_BitmapAndState: + case T_BitmapOrState: + case T_ScanState: + case T_SeqScanState: + case T_SampleScanState: + case T_IndexScanState: + case T_IndexOnlyScanState: + case T_BitmapIndexScanState: + case T_BitmapHeapScanState: + case T_TidScanState: + case T_SubqueryScanState: + case T_FunctionScanState: + case T_TableFuncScanState: + case T_ValuesScanState: + case T_CteScanState: + case T_NamedTuplestoreScanState: + case T_WorkTableScanState: + case T_ForeignScanState: + case T_CustomScanState: + case T_JoinState: + case T_NestLoopState: + case T_MergeJoinState: + case T_HashJoinState: + case T_MaterialState: + case T_SortState: + case T_GroupState: + case T_AggState: + case T_WindowAggState: + case T_UniqueState: + case T_GatherState: + case T_GatherMergeState: + case T_HashState: + case T_SetOpState: + case T_LockRowsState: + case T_LimitState: + case T_Alias: + case T_RangeVar: + case T_TableFunc: + case T_Expr: + case T_GroupingFunc: + case T_SubscriptingRef: + case T_NamedArgExpr: + case T_BoolExpr: + case T_SubLink: + case T_AlternativeSubPlan: + case T_CaseExpr: + case T_CaseWhen: + case T_CaseTestExpr: + case T_ArrayExpr: + case T_CoalesceExpr: + case T_MinMaxExpr: + case T_SQLValueFunction: + case T_XmlExpr: + case T_NullTest: + case T_BooleanTest: + case T_CoerceToDomainValue: + case T_SetToDefault: + case T_CurrentOfExpr: + case T_InferenceElem: + case T_TargetEntry: + case T_RangeTblRef: + case T_JoinExpr: + case T_FromExpr: + case T_IntoClause: + case T_ExprState: + case T_AggrefExprState: + case T_WindowFuncExprState: + case T_SetExprState: + case T_SubPlanState: + case T_AlternativeSubPlanState: + case T_DomainConstraintState: + case T_PlannerInfo: + case T_PlannerGlobal: + case T_RelOptInfo: + case T_IndexOptInfo: + case T_ForeignKeyOptInfo: + case T_ParamPathInfo: + case T_Path: + case T_IndexPath: + case T_BitmapHeapPath: + case T_BitmapAndPath: + case T_BitmapOrPath: + case T_TidPath: + case T_SubqueryScanPath: + case T_ForeignPath: + case T_CustomPath: + case T_NestPath: + case T_MergePath: + case T_HashPath: + case T_AppendPath: + case T_MergeAppendPath: + case T_GroupResultPath: + case T_MaterialPath: + case T_UniquePath: + case T_GatherPath: + case T_GatherMergePath: + case T_ProjectionPath: + case T_ProjectSetPath: + case T_SortPath: + case T_GroupPath: + case T_UpperUniquePath: + case T_AggPath: + case T_GroupingSetsPath: + case T_MinMaxAggPath: + case T_WindowAggPath: + case T_SetOpPath: + case T_RecursiveUnionPath: + case T_LockRowsPath: + case T_ModifyTablePath: + case T_LimitPath: + case T_EquivalenceClass: + case T_EquivalenceMember: + case T_PathKey: + case T_PathTarget: + case T_RestrictInfo: + case T_IndexClause: + case T_PlaceHolderVar: + case T_SpecialJoinInfo: + case T_AppendRelInfo: + case T_PlaceHolderInfo: + case T_MinMaxAggInfo: + case T_PlannerParamItem: + case T_RollupData: + case T_GroupingSetData: + case T_StatisticExtInfo: + case T_MemoryContext: + case T_AllocSetContext: + case T_SlabContext: + case T_GenerationContext: + case T_Value: + case T_Integer: + case T_Float: + case T_String: + case T_BitString: + case T_Null: + case T_List: + case T_IntList: + case T_OidList: + case T_ExtensibleNode: + case T_RawStmt: + case T_PlannedStmt: + case T_InsertStmt: + case T_DeleteStmt: + case T_UpdateStmt: + case T_SelectStmt: + case T_AlterTableStmt: + case T_AlterTableCmd: + case T_AlterDomainStmt: + case T_GrantStmt: + case T_GrantRoleStmt: + case T_AlterDefaultPrivilegesStmt: + case T_ClosePortalStmt: + case T_ClusterStmt: + case T_CopyStmt: + case T_CreateStmt: + case T_DefineStmt: + case T_DropStmt: + case T_TruncateStmt: + case T_CommentStmt: + case T_FetchStmt: + case T_IndexStmt: + case T_CreateFunctionStmt: + case T_AlterFunctionStmt: + case T_DoStmt: + case T_RenameStmt: + case T_RuleStmt: + case T_NotifyStmt: + case T_ListenStmt: + case T_UnlistenStmt: + case T_TransactionStmt: + case T_ViewStmt: + case T_LoadStmt: + case T_CreateDomainStmt: + case T_CreatedbStmt: + case T_DropdbStmt: + case T_VacuumStmt: + case T_ExplainStmt: + case T_CreateTableAsStmt: + case T_CreateSeqStmt: + case T_AlterSeqStmt: + case T_VariableSetStmt: + case T_VariableShowStmt: + case T_DiscardStmt: + case T_CreateTrigStmt: + case T_CreatePLangStmt: + case T_CreateRoleStmt: + case T_AlterRoleStmt: + case T_DropRoleStmt: + case T_LockStmt: + case T_ConstraintsSetStmt: + case T_ReindexStmt: + case T_CheckPointStmt: + case T_CreateSchemaStmt: + case T_AlterDatabaseStmt: + case T_AlterDatabaseSetStmt: + case T_AlterRoleSetStmt: + case T_CreateConversionStmt: + case T_CreateCastStmt: + case T_CreateOpClassStmt: + case T_CreateOpFamilyStmt: + case T_AlterOpFamilyStmt: + case T_PrepareStmt: + case T_ExecuteStmt: + case T_DeallocateStmt: + case T_DeclareCursorStmt: + case T_CreateTableSpaceStmt: + case T_DropTableSpaceStmt: + case T_AlterObjectDependsStmt: + case T_AlterObjectSchemaStmt: + case T_AlterOwnerStmt: + case T_AlterOperatorStmt: + case T_DropOwnedStmt: + case T_ReassignOwnedStmt: + case T_CompositeTypeStmt: + case T_CreateEnumStmt: + case T_CreateRangeStmt: + case T_AlterEnumStmt: + case T_AlterTSDictionaryStmt: + case T_AlterTSConfigurationStmt: + case T_CreateFdwStmt: + case T_AlterFdwStmt: + case T_CreateForeignServerStmt: + case T_AlterForeignServerStmt: + case T_CreateUserMappingStmt: + case T_AlterUserMappingStmt: + case T_DropUserMappingStmt: + case T_AlterTableSpaceOptionsStmt: + case T_AlterTableMoveAllStmt: + case T_SecLabelStmt: + case T_CreateForeignTableStmt: + case T_ImportForeignSchemaStmt: + case T_CreateExtensionStmt: + case T_AlterExtensionStmt: + case T_AlterExtensionContentsStmt: + case T_CreateEventTrigStmt: + case T_AlterEventTrigStmt: + case T_RefreshMatViewStmt: + case T_ReplicaIdentityStmt: + case T_AlterSystemStmt: + case T_CreatePolicyStmt: + case T_AlterPolicyStmt: + case T_CreateTransformStmt: + case T_CreateAmStmt: + case T_CreatePublicationStmt: + case T_AlterPublicationStmt: + case T_CreateSubscriptionStmt: + case T_AlterSubscriptionStmt: + case T_DropSubscriptionStmt: + case T_CreateStatsStmt: + case T_AlterCollationStmt: + case T_CallStmt: + case T_AlterStatsStmt: + case T_A_Expr: + case T_ColumnRef: + case T_ParamRef: + case T_A_Const: + case T_FuncCall: + case T_A_Star: + case T_A_Indices: + case T_A_Indirection: + case T_A_ArrayExpr: + case T_ResTarget: + case T_MultiAssignRef: + case T_TypeCast: + case T_CollateClause: + case T_SortBy: + case T_WindowDef: + case T_RangeSubselect: + case T_RangeFunction: + case T_RangeTableSample: + case T_RangeTableFunc: + case T_RangeTableFuncCol: + case T_TypeName: + case T_ColumnDef: + case T_IndexElem: + case T_Constraint: + case T_DefElem: + case T_RangeTblEntry: + case T_WithCheckOption: + case T_GroupingSet: + case T_ObjectWithArgs: + case T_AccessPriv: + case T_CreateOpClassItem: + case T_TableLikeClause: + case T_FunctionParameter: + case T_LockingClause: + case T_RowMarkClause: + case T_XmlSerialize: + case T_WithClause: + case T_InferClause: + case T_OnConflictClause: + case T_CommonTableExpr: + case T_RoleSpec: + case T_TriggerTransition: + case T_PartitionElem: + case T_PartitionSpec: + case T_PartitionBoundSpec: + case T_PartitionRangeDatum: + case T_PartitionCmd: + case T_VacuumRelation: + case T_IdentifySystemCmd: + case T_BaseBackupCmd: + case T_CreateReplicationSlotCmd: + case T_DropReplicationSlotCmd: + case T_StartReplicationCmd: + case T_TimeLineHistoryCmd: + case T_SQLCmd: + case T_TriggerData: + case T_EventTriggerData: + case T_ReturnSetInfo: + case T_WindowObjectData: + case T_TIDBitmap: + case T_InlineCodeBlock: + case T_FdwRoutine: + case T_IndexAmRoutine: + case T_TableAmRoutine: + case T_TsmRoutine: + case T_ForeignKeyCacheInfo: + case T_CallContext: + case T_SupportRequestSimplify: + case T_SupportRequestSelectivity: + case T_SupportRequestCost: + case T_SupportRequestRows: + case T_SupportRequestIndexCondition: + /* no-op */ + break; - add_object_address(OCLASS_PROC, tsc->tsmhandler, 0, - context->addrs); - /* fall through to examine arguments */ + /* Intentionally no default */ } return expression_tree_walker(node, find_expr_references_walker,