+ outobj = context.addrs->refs;
+ outrefs = 0;
+ for (oldref = 0; oldref < context.addrs->numrefs; oldref++)
+ {
+ ObjectAddress *thisobj = context.addrs->refs + oldref;
+
+ if (thisobj->classId == RelationRelationId &&
+ thisobj->objectId == relId)
+ {
+ /* Move this ref into self_addrs */
+ add_exact_object_address(thisobj, self_addrs);
+ }
+ else
+ {
+ /* Keep it in context.addrs */
+ *outobj = *thisobj;
+ outobj++;
+ outrefs++;
+ }
+ }
+ context.addrs->numrefs = outrefs;
+
+ /* Record the self-dependencies */
+ recordMultipleDependencies(depender,
+ self_addrs->refs, self_addrs->numrefs,
+ self_behavior);
+
+ free_object_addresses(self_addrs);
+ }
+
+ /* Record the external dependencies */
+ recordMultipleDependencies(depender,
+ context.addrs->refs, context.addrs->numrefs,
+ behavior);
+
+ free_object_addresses(context.addrs);
+}
+
+/*
+ * Recursively search an expression tree for object references.
+ *
+ * Note: we avoid creating references to columns of tables that participate
+ * in an SQL JOIN construct, but are not actually used anywhere in the query.
+ * To do so, we do not scan the joinaliasvars list of a join RTE while
+ * scanning the query rangetable, but instead scan each individual entry
+ * of the alias list when we find a reference to it.
+ *
+ * Note: in many cases we do not need to create dependencies on the datatypes
+ * involved in an expression, because we'll have an indirect dependency via
+ * some other object. For instance Var nodes depend on a column which depends
+ * on the datatype, and OpExpr nodes depend on the operator which depends on
+ * the datatype. However we do need a type dependency if there is no such
+ * indirect dependency, as for example in Const and CoerceToDomain nodes.
+ */
+static bool
+find_expr_references_walker(Node *node,
+ find_expr_references_context *context)
+{
+ if (node == NULL)
+ return false;
+ if (IsA(node, Var))
+ {
+ 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);
+
+ /*
+ * A whole-row Var references no specific columns, so adds no new
+ * dependency.
+ */
+ 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 (IsA(node, Const))
+ {
+ 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);
+
+ /*
+ * 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 (SearchSysCacheExists(PROCOID,
+ ObjectIdGetDatum(objoid),
+ 0, 0, 0))
+ add_object_address(OCLASS_PROC, objoid, 0,
+ context->addrs);
+ break;
+ case REGOPEROID:
+ case REGOPERATOROID:
+ objoid = DatumGetObjectId(con->constvalue);
+ if (SearchSysCacheExists(OPEROID,
+ ObjectIdGetDatum(objoid),
+ 0, 0, 0))
+ add_object_address(OCLASS_OPERATOR, objoid, 0,
+ context->addrs);
+ break;
+ case REGCLASSOID:
+ objoid = DatumGetObjectId(con->constvalue);
+ if (SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(objoid),
+ 0, 0, 0))
+ add_object_address(OCLASS_CLASS, objoid, 0,
+ context->addrs);
+ break;
+ case REGTYPEOID:
+ objoid = DatumGetObjectId(con->constvalue);
+ if (SearchSysCacheExists(TYPEOID,
+ ObjectIdGetDatum(objoid),
+ 0, 0, 0))
+ add_object_address(OCLASS_TYPE, objoid, 0,
+ context->addrs);
+ break;
+ case REGCONFIGOID:
+ objoid = DatumGetObjectId(con->constvalue);
+ if (SearchSysCacheExists(TSCONFIGOID,
+ ObjectIdGetDatum(objoid),
+ 0, 0, 0))
+ add_object_address(OCLASS_TSCONFIG, objoid, 0,
+ context->addrs);
+ break;
+ case REGDICTIONARYOID:
+ objoid = DatumGetObjectId(con->constvalue);
+ if (SearchSysCacheExists(TSDICTOID,
+ ObjectIdGetDatum(objoid),
+ 0, 0, 0))
+ add_object_address(OCLASS_TSDICT, objoid, 0,
+ context->addrs);
+ break;
+ }
+ }
+ return false;
+ }
+ 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);
+ }
+ if (IsA(node, FuncExpr))
+ {
+ FuncExpr *funcexpr = (FuncExpr *) node;
+
+ add_object_address(OCLASS_PROC, funcexpr->funcid, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ if (IsA(node, OpExpr))
+ {
+ OpExpr *opexpr = (OpExpr *) node;
+
+ add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ if (IsA(node, DistinctExpr))
+ {
+ DistinctExpr *distinctexpr = (DistinctExpr *) node;
+
+ add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ if (IsA(node, ScalarArrayOpExpr))
+ {
+ ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
+
+ add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ if (IsA(node, NullIfExpr))
+ {
+ NullIfExpr *nullifexpr = (NullIfExpr *) node;
+
+ add_object_address(OCLASS_OPERATOR, nullifexpr->opno, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ if (IsA(node, Aggref))
+ {
+ Aggref *aggref = (Aggref *) node;
+
+ add_object_address(OCLASS_PROC, aggref->aggfnoid, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ if (is_subplan(node))
+ {
+ /* Extra work needed here if we ever need this case */
+ elog(ERROR, "already-planned subqueries not supported");
+ }
+ 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);
+ }
+ 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);