From 3af74aa118e81dc5b9a84d670fb973026d532227 Mon Sep 17 00:00:00 2001
From: Jim Jones <jim.jones@uni-muenster.de>
Date: Wed, 5 Nov 2025 09:55:31 +0100
Subject: [PATCH v6 1/2] Refactor dependency recording to enable dependency
 collection

Add new function collectDependenciesFromExpr() that collects object
dependencies into caller-supplied ObjectAddresses structures without
immediately recording them.

This enables more flexible dependency handling patterns where callers
need to examine, filter, or modify dependencies before recording them.
The caller is responsible for calling eliminate_duplicate_dependencies()
on the collected dependencies before recording them. This design avoids
redundant deduplication work when collecting dependencies from multiple
sources.

The existing recordDependencyOnExpr() function is reimplemented using
the new collection function, maintaining full backward compatibility.

This refactoring lays the groundwork for enhanced dependency validation
in SQL functions while preserving all existing functionality.
---
 src/backend/catalog/dependency.c | 54 +++++++++++++++++++++++++-------
 src/include/catalog/dependency.h |  3 ++
 2 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 7dded634eb..bd5d705936 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -1554,25 +1554,57 @@ recordDependencyOnExpr(const ObjectAddress *depender,
 					   Node *expr, List *rtable,
 					   DependencyType behavior)
 {
-	find_expr_references_context context;
+	ObjectAddresses *addrs;
 
-	context.addrs = new_object_addresses();
+	addrs = new_object_addresses();
 
-	/* Set up interpretation for Vars at varlevelsup = 0 */
-	context.rtables = list_make1(rtable);
+	/* Collect all dependencies from the expression */
+	collectDependenciesFromExpr(addrs, expr, rtable);
 
-	/* Scan the expression tree for referenceable objects */
-	find_expr_references_walker(expr, &context);
-
-	/* Remove any duplicates */
-	eliminate_duplicate_dependencies(context.addrs);
+	/* Remove duplicates */
+	eliminate_duplicate_dependencies(addrs);
 
 	/* And record 'em */
 	recordMultipleDependencies(depender,
-							   context.addrs->refs, context.addrs->numrefs,
+							   addrs->refs, addrs->numrefs,
 							   behavior);
 
-	free_object_addresses(context.addrs);
+	free_object_addresses(addrs);
+}
+
+/*
+ * collectDependenciesFromExpr - collect expression dependencies
+ *
+ * This function analyzes an expression or query in node-tree form to
+ * find all the objects it refers to (tables, columns, operators,
+ * functions, etc.) and adds them to the provided ObjectAddresses
+ * structure. Unlike recordDependencyOnExpr, this function does not
+ * immediately record the dependencies, allowing the caller to examine,
+ * filter, or modify the collected dependencies before recording them.
+ *
+ * This is particularly useful when dependency recording needs to be
+ * conditional or when dependencies from multiple sources need to be
+ * merged before recording.
+ *
+ * Note: the caller is responsible for calling
+ * eliminate_duplicate_dependencies() on the ObjectAddresses structure
+ * before recording the dependencies, if duplicate elimination is
+ * desired. This design allows collecting dependencies from multiple
+ * sources without redundant deduplication work.
+ */
+void
+collectDependenciesFromExpr(ObjectAddresses *addrs,
+							Node *expr, List *rtable)
+{
+	find_expr_references_context context;
+
+	context.addrs = addrs;
+
+	/* Set up interpretation for Vars at varlevelsup = 0 */
+	context.rtables = list_make1(rtable);
+
+	/* Scan the expression tree for referenceable objects */
+	find_expr_references_walker(expr, &context);
 }
 
 /*
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 0ea7ccf524..f5061605dd 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -114,6 +114,9 @@ extern void recordDependencyOnExpr(const ObjectAddress *depender,
 								   Node *expr, List *rtable,
 								   DependencyType behavior);
 
+extern void collectDependenciesFromExpr(ObjectAddresses *addrs,
+										Node *expr, List *rtable);
+
 extern void recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
 											Node *expr, Oid relId,
 											DependencyType behavior,
-- 
2.43.0

