diff options
-rw-r--r-- | src/backend/commands/opclasscmds.c | 98 | ||||
-rw-r--r-- | src/include/access/amapi.h | 4 |
2 files changed, 102 insertions, 0 deletions
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index 5f7ee238863..3c0acfafbd2 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -66,6 +66,7 @@ static void storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators, bool isAdd); static void storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *procedures, bool isAdd); +static bool typeDepNeeded(Oid typid, OpFamilyMember *member); static void dropOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators); static void dropProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, @@ -1508,6 +1509,29 @@ storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, recordDependencyOn(&myself, &referenced, op->ref_is_hard ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO); + if (typeDepNeeded(op->lefttype, op)) + { + referenced.classId = TypeRelationId; + referenced.objectId = op->lefttype; + referenced.objectSubId = 0; + + /* see comments in amapi.h about dependency strength */ + recordDependencyOn(&myself, &referenced, + op->ref_is_hard ? DEPENDENCY_NORMAL : DEPENDENCY_AUTO); + } + + if (op->lefttype != op->righttype && + typeDepNeeded(op->righttype, op)) + { + referenced.classId = TypeRelationId; + referenced.objectId = op->righttype; + referenced.objectSubId = 0; + + /* see comments in amapi.h about dependency strength */ + recordDependencyOn(&myself, &referenced, + op->ref_is_hard ? DEPENDENCY_NORMAL : DEPENDENCY_AUTO); + } + /* A search operator also needs a dep on the referenced opfamily */ if (OidIsValid(op->sortfamily)) { @@ -1609,6 +1633,29 @@ storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, recordDependencyOn(&myself, &referenced, proc->ref_is_hard ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO); + if (typeDepNeeded(proc->lefttype, proc)) + { + referenced.classId = TypeRelationId; + referenced.objectId = proc->lefttype; + referenced.objectSubId = 0; + + /* see comments in amapi.h about dependency strength */ + recordDependencyOn(&myself, &referenced, + proc->ref_is_hard ? DEPENDENCY_NORMAL : DEPENDENCY_AUTO); + } + + if (proc->lefttype != proc->righttype && + typeDepNeeded(proc->righttype, proc)) + { + referenced.classId = TypeRelationId; + referenced.objectId = proc->righttype; + referenced.objectSubId = 0; + + /* see comments in amapi.h about dependency strength */ + recordDependencyOn(&myself, &referenced, + proc->ref_is_hard ? DEPENDENCY_NORMAL : DEPENDENCY_AUTO); + } + /* Post create hook of access method procedure */ InvokeObjectPostCreateHook(AccessMethodProcedureRelationId, entryoid, 0); @@ -1617,6 +1664,57 @@ storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, table_close(rel, RowExclusiveLock); } +/* + * Detect whether a pg_amop or pg_amproc entry needs an explicit dependency + * on its lefttype or righttype. + * + * We make such a dependency unless the entry has an indirect dependency + * via its referenced operator or function. That's nearly always true + * for operators, but might well not be true for support functions. + */ +static bool +typeDepNeeded(Oid typid, OpFamilyMember *member) +{ + bool result = true; + + /* + * If the type is pinned, we don't need a dependency. This is a bit of a + * layering violation perhaps (recordDependencyOn would ignore the request + * anyway), but it's a cheap test and will frequently save a syscache + * lookup here. + */ + if (IsPinnedObject(TypeRelationId, typid)) + return false; + + /* Nope, so check the input types of the function or operator. */ + if (member->is_func) + { + Oid *argtypes; + int nargs; + + (void) get_func_signature(member->object, &argtypes, &nargs); + for (int i = 0; i < nargs; i++) + { + if (typid == argtypes[i]) + { + result = false; /* match, no dependency needed */ + break; + } + } + pfree(argtypes); + } + else + { + Oid lefttype, + righttype; + + op_input_types(member->object, &lefttype, &righttype); + if (typid == lefttype || typid == righttype) + result = false; /* match, no dependency needed */ + } + return result; +} + /* * Remove operator entries from an opfamily. diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h index 4476ff7fba1..2d70c5678c3 100644 --- a/src/include/access/amapi.h +++ b/src/include/access/amapi.h @@ -76,6 +76,10 @@ typedef enum IndexAMProperty * opfamily. This allows ALTER OPERATOR FAMILY DROP, and causes that to * happen automatically if the operator or support func is dropped. This * is the right behavior for inessential ("loose") objects. + * + * We also make dependencies on lefttype/righttype, of the same strength as + * the dependency on the operator or support func, unless these dependencies + * are redundant with the dependency on the operator or support func. */ typedef struct OpFamilyMember { |