summaryrefslogtreecommitdiff
path: root/src/backend/catalog/dependency.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/catalog/dependency.c')
-rw-r--r--src/backend/catalog/dependency.c182
1 files changed, 155 insertions, 27 deletions
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 1a927377e7..b0d037600e 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -76,6 +76,7 @@
#include "rewrite/rewriteRemove.h"
#include "storage/lmgr.h"
#include "utils/acl.h"
+#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
@@ -435,6 +436,84 @@ performMultipleDeletions(const ObjectAddresses *objects,
}
/*
+ * Call a function for all objects that 'object' depend on. If the function
+ * returns true, refobjversion will be updated in the catalog.
+ */
+void
+visitDependenciesOf(const ObjectAddress *object,
+ VisitDependenciesOfCB callback,
+ void *userdata)
+{
+ Relation depRel;
+ ScanKeyData key[3];
+ SysScanDesc scan;
+ HeapTuple tup;
+ ObjectAddress otherObject;
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+ ScanKeyInit(&key[2],
+ Anum_pg_depend_objsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(object->objectSubId));
+
+ depRel = table_open(DependRelationId, RowExclusiveLock);
+ scan = systable_beginscan(depRel, DependDependerIndexId, true,
+ NULL, 3, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
+ char *new_version;
+ Datum depversion;
+ bool isnull;
+
+ otherObject.classId = foundDep->refclassid;
+ otherObject.objectId = foundDep->refobjid;
+ otherObject.objectSubId = foundDep->refobjsubid;
+
+ depversion = heap_getattr(tup, Anum_pg_depend_refobjversion,
+ RelationGetDescr(depRel), &isnull);
+
+ /* Does the callback want to update the version? */
+ if (callback(&otherObject,
+ isnull ? NULL : TextDatumGetCString(depversion),
+ &new_version,
+ userdata))
+ {
+ Datum values[Natts_pg_depend];
+ bool nulls[Natts_pg_depend];
+ bool replaces[Natts_pg_depend];
+
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ if (new_version)
+ values[Anum_pg_depend_refobjversion - 1] =
+ CStringGetTextDatum(new_version);
+ else
+ nulls[Anum_pg_depend_refobjversion - 1] = true;
+ replaces[Anum_pg_depend_refobjversion - 1] = true;
+
+ tup = heap_modify_tuple(tup, RelationGetDescr(depRel), values,
+ nulls, replaces);
+ CatalogTupleUpdate(depRel, &tup->t_self, tup);
+
+ heap_freetuple(tup);
+ }
+ }
+ systable_endscan(scan);
+ table_close(depRel, RowExclusiveLock);
+}
+
+/*
* findDependentObjects - find all objects that depend on 'object'
*
* For every object that depends on the starting object, acquire a deletion
@@ -1567,6 +1646,38 @@ ReleaseDeletionLock(const ObjectAddress *object)
}
/*
+ * Record dependencies on a list of collations, optionally with their current
+ * version.
+ */
+void
+recordDependencyOnCollations(ObjectAddress *myself,
+ List *collations,
+ bool record_version)
+{
+ ObjectAddresses *addrs;
+ ListCell *lc;
+
+ if (list_length(collations) == 0)
+ return;
+
+ addrs = new_object_addresses();
+ foreach(lc, collations)
+ {
+ ObjectAddress referenced;
+
+ ObjectAddressSet(referenced, CollationRelationId, lfirst_oid(lc));
+
+ add_exact_object_address(&referenced, addrs);
+ }
+
+ eliminate_duplicate_dependencies(addrs);
+ recordMultipleDependencies(myself, addrs->refs, addrs->numrefs,
+ DEPENDENCY_NORMAL, record_version);
+
+ free_object_addresses(addrs);
+}
+
+/*
* recordDependencyOnExpr - find expression dependencies
*
* This is used to find the dependencies of rules, constraint expressions,
@@ -1602,8 +1713,8 @@ recordDependencyOnExpr(const ObjectAddress *depender,
recordMultipleDependencies(depender,
context.addrs->refs,
context.addrs->numrefs,
- NULL,
- behavior);
+ behavior,
+ false);
free_object_addresses(context.addrs);
}
@@ -1630,7 +1741,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
Node *expr, Oid relId,
DependencyType behavior,
DependencyType self_behavior,
- bool reverse_self)
+ bool reverse_self,
+ bool record_version)
{
find_expr_references_context context;
RangeTblEntry rte;
@@ -1691,8 +1803,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
recordMultipleDependencies(depender,
self_addrs->refs,
self_addrs->numrefs,
- NULL,
- self_behavior);
+ self_behavior,
+ record_version);
else
{
/* Can't use recordMultipleDependencies, so do it the hard way */
@@ -1713,8 +1825,8 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
recordMultipleDependencies(depender,
context.addrs->refs,
context.addrs->numrefs,
- NULL,
- behavior);
+ behavior,
+ record_version);
free_object_addresses(context.addrs);
}
@@ -1770,6 +1882,29 @@ find_expr_references_walker(Node *node,
/* If it's a plain relation, reference this column */
add_object_address(OCLASS_CLASS, rte->relid, var->varattno,
context->addrs);
+
+ /* Top-level collation if valid */
+ if (OidIsValid(var->varcollid))
+ add_object_address(OCLASS_COLLATION, var->varcollid, 0,
+ context->addrs);
+ /* Otherwise, it may be a type with internal collations */
+ else if (var->vartype >= FirstNormalObjectId)
+ {
+ List *collations;
+ ListCell *lc;
+
+ collations = GetTypeCollations(var->vartype);
+
+ foreach(lc, collations)
+ {
+ Oid coll = lfirst_oid(lc);
+
+ if (OidIsValid(coll))
+ add_object_address(OCLASS_COLLATION,
+ lfirst_oid(lc), 0,
+ context->addrs);
+ }
+ }
}
/*
@@ -1794,11 +1929,9 @@ find_expr_references_walker(Node *node,
/*
* 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.
+ * a simple constant.
*/
- if (OidIsValid(con->constcollid) &&
- con->constcollid != DEFAULT_COLLATION_OID)
+ if (OidIsValid(con->constcollid))
add_object_address(OCLASS_COLLATION, con->constcollid, 0,
context->addrs);
@@ -1887,8 +2020,7 @@ find_expr_references_walker(Node *node,
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)
+ if (OidIsValid(param->paramcollid))
add_object_address(OCLASS_COLLATION, param->paramcollid, 0,
context->addrs);
}
@@ -1975,8 +2107,7 @@ find_expr_references_walker(Node *node,
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)
+ if (OidIsValid(fselect->resultcollid))
add_object_address(OCLASS_COLLATION, fselect->resultcollid, 0,
context->addrs);
}
@@ -2006,8 +2137,7 @@ find_expr_references_walker(Node *node,
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)
+ if (OidIsValid(relab->resultcollid))
add_object_address(OCLASS_COLLATION, relab->resultcollid, 0,
context->addrs);
}
@@ -2019,8 +2149,7 @@ find_expr_references_walker(Node *node,
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)
+ if (OidIsValid(iocoerce->resultcollid))
add_object_address(OCLASS_COLLATION, iocoerce->resultcollid, 0,
context->addrs);
}
@@ -2032,8 +2161,7 @@ find_expr_references_walker(Node *node,
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)
+ if (OidIsValid(acoerce->resultcollid))
add_object_address(OCLASS_COLLATION, acoerce->resultcollid, 0,
context->addrs);
/* fall through to examine arguments */
@@ -2121,8 +2249,7 @@ find_expr_references_walker(Node *node,
if (OidIsValid(wc->endInRangeFunc))
add_object_address(OCLASS_PROC, wc->endInRangeFunc, 0,
context->addrs);
- if (OidIsValid(wc->inRangeColl) &&
- wc->inRangeColl != DEFAULT_COLLATION_OID)
+ if (OidIsValid(wc->inRangeColl))
add_object_address(OCLASS_COLLATION, wc->inRangeColl, 0,
context->addrs);
/* fall through to examine substructure */
@@ -2267,7 +2394,7 @@ find_expr_references_walker(Node *node,
{
Oid collid = lfirst_oid(ct);
- if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID)
+ if (OidIsValid(collid))
add_object_address(OCLASS_COLLATION, collid, 0,
context->addrs);
}
@@ -2289,7 +2416,7 @@ find_expr_references_walker(Node *node,
{
Oid collid = lfirst_oid(ct);
- if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID)
+ if (OidIsValid(collid))
add_object_address(OCLASS_COLLATION, collid, 0,
context->addrs);
}
@@ -2685,8 +2812,9 @@ record_object_address_dependencies(const ObjectAddress *depender,
{
eliminate_duplicate_dependencies(referenced);
recordMultipleDependencies(depender,
- referenced->refs, referenced->numrefs, NULL,
- behavior);
+ referenced->refs, referenced->numrefs,
+ behavior,
+ false);
}
/*