amproc-description-change-3.patch
text/x-patch
Filename: amproc-description-change-3.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/catalog/dependency.c | 0 | 0 |
| src/backend/commands/opclasscmds.c | 0 | 0 |
| src/include/commands/defrem.h | 0 | 0 |
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index ec8eb74954a9cc0ec3623dc42dfed462dc1a3533..d02b58dcc2933a278959727f55d93e1e9101c1f1 100644
*** a/src/backend/catalog/dependency.c
--- b/src/backend/catalog/dependency.c
*************** getObjectDescription(const ObjectAddress
*** 2337,2351 ****
initStringInfo(&opfam);
getOpFamilyDescription(&opfam, amopForm->amopfamily);
! /*
! * translator: %d is the operator strategy (a number), the
! * first %s is the textual form of the operator, and the
! * second %s is the description of the operator family.
! */
! appendStringInfo(&buffer, _("operator %d %s of %s"),
! amopForm->amopstrategy,
! format_operator(amopForm->amopopr),
! opfam.data);
pfree(opfam.data);
systable_endscan(amscan);
--- 2337,2372 ----
initStringInfo(&opfam);
getOpFamilyDescription(&opfam, amopForm->amopfamily);
! if (opfamily_op_has_default_types(amopForm->amopfamily,
! amopForm->amoplefttype,
! amopForm->amoprighttype,
! amopForm->amopopr))
! {
! /*
! * translator: %d is the operator strategy (a number), the
! * first %s is the textual form of the operator, and the
! * second %s is the description of the operator family.
! */
! appendStringInfo(&buffer, _("operator %d %s of %s"),
! amopForm->amopstrategy,
! format_operator(amopForm->amopopr),
! opfam.data);
! }
! else
! {
! /*
! * translator: %d is the operator strategy (a number), the
! * first two %s's are data type names, the third %s is the
! * textual form of the operator, and the last %s is the
! * description of the operator family.
! */
! appendStringInfo(&buffer, _("operator %d (%s, %s) %s of %s"),
! amopForm->amopstrategy,
! format_type_be(amopForm->amoplefttype),
! format_type_be(amopForm->amoprighttype),
! format_operator(amopForm->amopopr),
! opfam.data);
! }
pfree(opfam.data);
systable_endscan(amscan);
*************** getObjectDescription(const ObjectAddress
*** 2384,2398 ****
initStringInfo(&opfam);
getOpFamilyDescription(&opfam, amprocForm->amprocfamily);
! /*
! * translator: %d is the function number, the first %s is the
! * textual form of the function with arguments, and the second
! * %s is the description of the operator family.
! */
! appendStringInfo(&buffer, _("function %d %s of %s"),
! amprocForm->amprocnum,
! format_procedure(amprocForm->amproc),
! opfam.data);
pfree(opfam.data);
systable_endscan(amscan);
--- 2405,2441 ----
initStringInfo(&opfam);
getOpFamilyDescription(&opfam, amprocForm->amprocfamily);
! if (opfamily_proc_has_default_types(amprocForm->amprocfamily,
! amprocForm->amproclefttype,
! amprocForm->amprocrighttype,
! amprocForm->amproc))
! {
! /*
! * translator: %d is the function number, the first %s is
! * the textual form of the function with arguments, and
! * the second %s is the description of the operator
! * family.
! */
! appendStringInfo(&buffer, _("function %d %s of %s"),
! amprocForm->amprocnum,
! format_procedure(amprocForm->amproc),
! opfam.data);
! }
! else
! {
! /*
! * translator: %d is the function number, the first two
! * %s's are data type names, the third %s is the textual
! * form of the function with arguments, and the last %s is
! * the description of the operator family.
! */
! appendStringInfo(&buffer, _("function %d (%s, %s) %s of %s"),
! amprocForm->amprocnum,
! format_type_be(amprocForm->amproclefttype),
! format_type_be(amprocForm->amprocrighttype),
! format_procedure(amprocForm->amproc),
! opfam.data);
! }
pfree(opfam.data);
systable_endscan(amscan);
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index 662b9420387f90bf3c9b6e656ed7b90583319d98..48b641f35a1ab901c092feedc53b25abf4d329e3 100644
*** a/src/backend/commands/opclasscmds.c
--- b/src/backend/commands/opclasscmds.c
*************** static void AlterOpFamilyDrop(List *opfa
*** 69,74 ****
--- 69,75 ----
static void processTypesSpec(List *args, Oid *lefttype, Oid *righttype);
static void assignOperTypes(OpFamilyMember *member, Oid amoid, Oid typeoid);
static void assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid);
+ static Oid get_opfamily_input_type(Oid opfamily, Oid amoid);
static void addFamilyMember(List **list, OpFamilyMember *member, bool isProc);
static void storeOperators(List *opfamilyname, Oid amoid,
Oid opfamilyoid, Oid opclassoid,
*************** assignProcTypes(OpFamilyMember *member,
*** 1209,1214 ****
--- 1210,1374 ----
}
/*
+ * Test whether a pg_amop entry has the default lefttype/righttype that
+ * would be deduced from its opfamily and operator.
+ *
+ * This is here because it must match the logic in assignOperTypes.
+ */
+ bool
+ opfamily_op_has_default_types(Oid opfamily, Oid lefttype, Oid righttype,
+ Oid operatorId)
+ {
+ bool result = false;
+ Operator optup;
+ Form_pg_operator opform;
+
+ /* Fetch the operator definition */
+ optup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operatorId));
+ if (optup == NULL)
+ elog(ERROR, "cache lookup failed for operator %u", operatorId);
+ opform = (Form_pg_operator) GETSTRUCT(optup);
+
+ /*
+ * Default types are the operator's input types
+ */
+ if (opform->oprkind == 'b' &&
+ lefttype == opform->oprleft &&
+ righttype == opform->oprright)
+ result = true;
+
+ ReleaseSysCache(optup);
+
+ return result;
+ }
+
+ /*
+ * Test whether a pg_amproc entry has the default lefttype/righttype that
+ * would be deduced from its opfamily and procedure.
+ *
+ * This is here because it must match the logic in assignProcTypes.
+ */
+ bool
+ opfamily_proc_has_default_types(Oid opfamily, Oid lefttype, Oid righttype,
+ Oid procedureId)
+ {
+ bool result = false;
+ Oid amoid;
+ Oid opcintype;
+ HeapTuple opfTup;
+ Form_pg_opfamily opfForm;
+ HeapTuple proctup;
+ Form_pg_proc procform;
+
+ /* We need to know the opfamily's AM to know which rules apply */
+ opfTup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamily));
+ if (!HeapTupleIsValid(opfTup))
+ elog(ERROR, "cache lookup failed for opfamily %u", opfamily);
+ opfForm = (Form_pg_opfamily) GETSTRUCT(opfTup);
+
+ amoid = opfForm->opfmethod;
+
+ ReleaseSysCache(opfTup);
+
+ /* Fetch the procedure definition */
+ proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procedureId));
+ if (proctup == NULL)
+ elog(ERROR, "cache lookup failed for function %u", procedureId);
+ procform = (Form_pg_proc) GETSTRUCT(proctup);
+
+ if (amoid == BTREE_AM_OID)
+ {
+ /* Default types are the comparison procedure's input types */
+ if (procform->pronargs == 2 &&
+ lefttype == procform->proargtypes.values[0] &&
+ righttype == procform->proargtypes.values[1])
+ result = true;
+ }
+ else if (amoid == HASH_AM_OID)
+ {
+ /* Default types are the hash procedure's (single) input type */
+ if (procform->pronargs == 1 &&
+ lefttype == procform->proargtypes.values[0] &&
+ righttype == procform->proargtypes.values[0])
+ result = true;
+ }
+ else
+ {
+ /*
+ * For GiST and GIN, the default (and actually the only useful case)
+ * is for lefttype/righttype to be the opcintype of the associated
+ * opclass. So first we have to look that up. The support function's
+ * signature may not contain any instance of the opcintype.
+ */
+ opcintype = get_opfamily_input_type(opfamily, amoid);
+ if (OidIsValid(opcintype) &&
+ lefttype == opcintype &&
+ righttype == opcintype)
+ result = true;
+ }
+
+ ReleaseSysCache(proctup);
+
+ return result;
+ }
+
+ /*
+ * If the specified opfamily contains exactly one opclass, return that
+ * opclass's opcintype. Otherwise, return InvalidOid.
+ *
+ * GiST and GIN indexes have no particular use for opfamilies, since there
+ * is no expectation of common behavior across different opclasses. So
+ * generally this can be expected to succeed on a GiST or GIN opfamily.
+ */
+ static Oid
+ get_opfamily_input_type(Oid opfamily, Oid amoid)
+ {
+ Oid result = InvalidOid;
+ int nmatch = 0;
+ Relation rel;
+ ScanKeyData skey[1];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ /*
+ * We must scan through all the opclasses available for the access method,
+ * since there's no index that would let us look at just those for the
+ * opfamily.
+ */
+ rel = heap_open(OperatorClassRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_opclass_opcmethod,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(amoid));
+
+ scan = systable_beginscan(rel, OpclassAmNameNspIndexId, true,
+ SnapshotNow, 1, skey);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup);
+
+ if (opclass->opcfamily == opfamily)
+ {
+ if (++nmatch > 1)
+ {
+ /* more than one opclass in family, so fail */
+ result = InvalidOid;
+ break;
+ }
+ result = opclass->opcintype;
+ }
+ }
+
+ systable_endscan(scan);
+
+ heap_close(rel, AccessShareLock);
+
+ return result;
+ }
+
+ /*
* Add a new family member to the appropriate list, after checking for
* duplicated strategy or proc number.
*/
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 01f271bff43f3c3d8560cb9169e85afe9545d41b..fb48530c32a9f93aea106bf9ce2147b99b8d89e4 100644
*** a/src/include/commands/defrem.h
--- b/src/include/commands/defrem.h
*************** extern void AlterOpFamilyNamespace(List
*** 106,111 ****
--- 106,115 ----
extern Oid get_am_oid(const char *amname, bool missing_ok);
extern Oid get_opclass_oid(Oid amID, List *opclassname, bool missing_ok);
extern Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok);
+ extern bool opfamily_op_has_default_types(Oid opfamily, Oid lefttype, Oid righttype,
+ Oid operatorId);
+ extern bool opfamily_proc_has_default_types(Oid opfamily, Oid lefttype, Oid righttype,
+ Oid procedureId);
/* commands/tsearchcmds.c */
extern void DefineTSParser(List *names, List *parameters);