4444#include "catalog/pg_language.h"
4545#include "catalog/pg_largeobject.h"
4646#include "catalog/pg_namespace.h"
47+ #include "catalog/namespace.h"
4748#include "catalog/pg_opclass.h"
4849#include "catalog/pg_operator.h"
4950#include "catalog/pg_opfamily.h"
@@ -1553,10 +1554,41 @@ void
15531554recordDependencyOnExpr (const ObjectAddress * depender ,
15541555 Node * expr , List * rtable ,
15551556 DependencyType behavior )
1557+ {
1558+ ObjectAddresses * addrs ;
1559+
1560+ addrs = new_object_addresses ();
1561+
1562+ /* Collect all dependencies from the expression */
1563+ collectDependenciesFromExpr (addrs , expr , rtable );
1564+
1565+ /* And record 'em */
1566+ recordMultipleDependencies (depender ,
1567+ addrs -> refs , addrs -> numrefs ,
1568+ behavior );
1569+
1570+ free_object_addresses (addrs );
1571+ }
1572+
1573+ /*
1574+ * collectDependenciesFromExpr - collect expression dependencies
1575+ *
1576+ * This function analyzes an expression or query in node-tree form to find all
1577+ * the objects it refers to (tables, columns, operators, functions, etc.) and
1578+ * adds them to the provided ObjectAddresses structure. Unlike recordDependencyOnExpr,
1579+ * this function does not immediately record the dependencies, allowing the caller
1580+ * to examine, filter, or modify the collected dependencies before recording them.
1581+ *
1582+ * This is particularly useful when dependency recording needs to be conditional
1583+ * or when dependencies from multiple sources need to be merged before recording.
1584+ */
1585+ void
1586+ collectDependenciesFromExpr (ObjectAddresses * addrs ,
1587+ Node * expr , List * rtable )
15561588{
15571589 find_expr_references_context context ;
15581590
1559- context .addrs = new_object_addresses () ;
1591+ context .addrs = addrs ;
15601592
15611593 /* Set up interpretation for Vars at varlevelsup = 0 */
15621594 context .rtables = list_make1 (rtable );
@@ -1565,14 +1597,7 @@ recordDependencyOnExpr(const ObjectAddress *depender,
15651597 find_expr_references_walker (expr , & context );
15661598
15671599 /* Remove any duplicates */
1568- eliminate_duplicate_dependencies (context .addrs );
1569-
1570- /* And record 'em */
1571- recordMultipleDependencies (depender ,
1572- context .addrs -> refs , context .addrs -> numrefs ,
1573- behavior );
1574-
1575- free_object_addresses (context .addrs );
1600+ eliminate_duplicate_dependencies (addrs );
15761601}
15771602
15781603/*
@@ -1599,10 +1624,12 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
15991624 DependencyType self_behavior ,
16001625 bool reverse_self )
16011626{
1627+ ObjectAddresses * addrs ;
16021628 find_expr_references_context context ;
16031629 RangeTblEntry rte = {0 };
16041630
1605- context .addrs = new_object_addresses ();
1631+ addrs = new_object_addresses ();
1632+ context .addrs = addrs ;
16061633
16071634 /* We gin up a rather bogus rangetable list to handle Vars */
16081635 rte .type = T_RangeTblEntry ;
@@ -1617,11 +1644,11 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
16171644 find_expr_references_walker (expr , & context );
16181645
16191646 /* Remove any duplicates */
1620- eliminate_duplicate_dependencies (context . addrs );
1647+ eliminate_duplicate_dependencies (addrs );
16211648
16221649 /* Separate self-dependencies if necessary */
16231650 if ((behavior != self_behavior || reverse_self ) &&
1624- context . addrs -> numrefs > 0 )
1651+ addrs -> numrefs > 0 )
16251652 {
16261653 ObjectAddresses * self_addrs ;
16271654 ObjectAddress * outobj ;
@@ -1630,11 +1657,11 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
16301657
16311658 self_addrs = new_object_addresses ();
16321659
1633- outobj = context . addrs -> refs ;
1660+ outobj = addrs -> refs ;
16341661 outrefs = 0 ;
1635- for (oldref = 0 ; oldref < context . addrs -> numrefs ; oldref ++ )
1662+ for (oldref = 0 ; oldref < addrs -> numrefs ; oldref ++ )
16361663 {
1637- ObjectAddress * thisobj = context . addrs -> refs + oldref ;
1664+ ObjectAddress * thisobj = addrs -> refs + oldref ;
16381665
16391666 if (thisobj -> classId == RelationRelationId &&
16401667 thisobj -> objectId == relId )
@@ -1644,13 +1671,13 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
16441671 }
16451672 else
16461673 {
1647- /* Keep it in context. addrs */
1674+ /* Keep it in addrs */
16481675 * outobj = * thisobj ;
16491676 outobj ++ ;
16501677 outrefs ++ ;
16511678 }
16521679 }
1653- context . addrs -> numrefs = outrefs ;
1680+ addrs -> numrefs = outrefs ;
16541681
16551682 /* Record the self-dependencies with the appropriate direction */
16561683 if (!reverse_self )
@@ -1675,10 +1702,10 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
16751702
16761703 /* Record the external dependencies */
16771704 recordMultipleDependencies (depender ,
1678- context . addrs -> refs , context . addrs -> numrefs ,
1705+ addrs -> refs , addrs -> numrefs ,
16791706 behavior );
16801707
1681- free_object_addresses (context . addrs );
1708+ free_object_addresses (addrs );
16821709}
16831710
16841711/*
@@ -2462,6 +2489,87 @@ eliminate_duplicate_dependencies(ObjectAddresses *addrs)
24622489 addrs -> numrefs = newrefs ;
24632490}
24642491
2492+ /*
2493+ * filter_temp_objects - detect and reject temporary objects in an ObjectAddresses array
2494+ *
2495+ * This function checks if any dependencies on temporary objects (objects in
2496+ * temporary namespaces) exist in the given ObjectAddresses array. If temp objects
2497+ * are found, it raises an error to prevent them from being used in SQL functions
2498+ * with BEGIN ATOMIC bodies, as such dependencies would be inappropriate for
2499+ * permanent function definitions.
2500+ *
2501+ * Currently checks for temporary tables, views, types, and functions by examining
2502+ * their containing namespaces. The function raises an error with a descriptive
2503+ * message if any temporary object dependency is detected.
2504+ */
2505+ void filter_temp_objects (ObjectAddresses * addrs )
2506+ {
2507+ int oldref ;
2508+
2509+ if (addrs -> numrefs <= 0 )
2510+ return ; /* nothing to do */
2511+
2512+ /* Check all dependencies for temp objects */
2513+ for (oldref = 0 ; oldref < addrs -> numrefs ; oldref ++ )
2514+ {
2515+ ObjectAddress * thisobj = addrs -> refs + oldref ;
2516+ bool is_temp = false;
2517+ char * objname = NULL ;
2518+
2519+ /* Check if this dependency is on a temporary object */
2520+ if (thisobj -> classId == RelationRelationId )
2521+ {
2522+ /* For relations, check if they're in a temp namespace */
2523+ Oid relnamespace = get_rel_namespace (thisobj -> objectId );
2524+ if (OidIsValid (relnamespace ) && isAnyTempNamespace (relnamespace ))
2525+ {
2526+ is_temp = true;
2527+ objname = get_rel_name (thisobj -> objectId );
2528+ }
2529+ }
2530+ else if (thisobj -> classId == TypeRelationId )
2531+ {
2532+ /* For types, check if they're in a temp namespace */
2533+ HeapTuple tup ;
2534+ Form_pg_type typform ;
2535+ Oid typnamespace = InvalidOid ;
2536+
2537+ tup = SearchSysCache1 (TYPEOID , ObjectIdGetDatum (thisobj -> objectId ));
2538+ if (HeapTupleIsValid (tup ))
2539+ {
2540+ typform = (Form_pg_type )GETSTRUCT (tup );
2541+ typnamespace = typform -> typnamespace ;
2542+ if (OidIsValid (typnamespace ) && isAnyTempNamespace (typnamespace ))
2543+ {
2544+ is_temp = true;
2545+ objname = NameStr (typform -> typname );
2546+ }
2547+ ReleaseSysCache (tup );
2548+ }
2549+ }
2550+ else if (thisobj -> classId == ProcedureRelationId )
2551+ {
2552+ /* For functions, check if they're in a temp namespace */
2553+ Oid funcnamespace = get_func_namespace (thisobj -> objectId );
2554+ if (OidIsValid (funcnamespace ) && isAnyTempNamespace (funcnamespace ))
2555+ {
2556+ is_temp = true;
2557+ objname = get_func_name (thisobj -> objectId );
2558+ }
2559+ }
2560+
2561+ /* Raise error if temp object found */
2562+ if (is_temp )
2563+ {
2564+ ereport (ERROR ,
2565+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
2566+ errmsg ("cannot use temporary object \"%s\" in SQL function with BEGIN ATOMIC" ,
2567+ objname ? objname : "unknown" ),
2568+ errdetail ("SQL functions with BEGIN ATOMIC cannot depend on temporary objects." )));
2569+ }
2570+ }
2571+ }
2572+
24652573/*
24662574 * qsort comparator for ObjectAddress items
24672575 */
0 commit comments