From fd33019e5e0c41aa8b64e7ed429fcf468695ce99 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Thu, 17 Oct 2019 10:25:39 +0900 Subject: [PATCH v19 2/3] Refactor format procedure and operator APIs to be more modular This introduce a new set of extended routines for procedure and operator lookups, with a flags bitmask argument that can modify the default behavior: - Force schema qualification - Force NULL as result instead of a numeric OID for an undefined object. --- src/include/utils/regproc.h | 10 ++++++ src/backend/utils/adt/regproc.c | 61 +++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/include/utils/regproc.h b/src/include/utils/regproc.h index 383dfe641e..bb8a151b11 100644 --- a/src/include/utils/regproc.h +++ b/src/include/utils/regproc.h @@ -15,6 +15,16 @@ #include "nodes/pg_list.h" +/* Control flags for format_procedure_extended */ +#define FORMAT_PROC_INVALID_AS_NULL 0x01 /* NULL if undefined */ +#define FORMAT_PROC_FORCE_QUALIFY 0x02 /* force qualification */ +extern char *format_procedure_extended(Oid type_oid, bits16 flags); + +/* Control flags for format_operator_extended */ +#define FORMAT_OPERATOR_INVALID_AS_NULL 0x01 /* NULL if undefined */ +#define FORMAT_OPERATOR_FORCE_QUALIFY 0x02 /* force qualification */ +extern char *format_operator_extended(Oid type_oid, bits16 flags); + extern List *stringToQualifiedNameList(const char *string); extern char *format_procedure(Oid procedure_oid); extern char *format_procedure_qualified(Oid procedure_oid); diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index c800d797ac..f9352ccca7 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -41,8 +41,6 @@ #include "utils/syscache.h" #include "utils/varlena.h" -static char *format_operator_internal(Oid operator_oid, bool force_qualify); -static char *format_procedure_internal(Oid procedure_oid, bool force_qualify); static void parseNameAndArgTypes(const char *string, bool allowNone, List **names, int *nargs, Oid *argtypes); @@ -323,24 +321,27 @@ to_regprocedure(PG_FUNCTION_ARGS) char * format_procedure(Oid procedure_oid) { - return format_procedure_internal(procedure_oid, false); + return format_procedure_extended(procedure_oid, 0); } char * format_procedure_qualified(Oid procedure_oid) { - return format_procedure_internal(procedure_oid, true); + return format_procedure_extended(procedure_oid, FORMAT_PROC_FORCE_QUALIFY); } /* * Routine to produce regprocedure names; see format_procedure above. * - * force_qualify says whether to schema-qualify; if true, the name is always - * qualified regardless of search_path visibility. Otherwise the name is only - * qualified if the function is not in path. + * The following bits in 'flags' modify the behavior: + * - FORMAT_PROC_INVALID_AS_NULL + * if the type OID is invalid or unknown, return NULL instead of + * the numeric OID. + * - FORMAT_PROC_FORCE_QUALIFY + * always schema-qualify type names, regardless of search_path */ -static char * -format_procedure_internal(Oid procedure_oid, bool force_qualify) +char * +format_procedure_extended(Oid procedure_oid, bits16 flags) { char *result; HeapTuple proctup; @@ -365,7 +366,8 @@ format_procedure_internal(Oid procedure_oid, bool force_qualify) * Would this proc be found (given the right args) by regprocedurein? * If not, or if caller requests it, we need to qualify it. */ - if (!force_qualify && FunctionIsVisible(procedure_oid)) + if ((flags & FORMAT_PROC_FORCE_QUALIFY) == 0 && + FunctionIsVisible(procedure_oid)) nspname = NULL; else nspname = get_namespace_name(procform->pronamespace); @@ -379,7 +381,7 @@ format_procedure_internal(Oid procedure_oid, bool force_qualify) if (i > 0) appendStringInfoChar(&buf, ','); appendStringInfoString(&buf, - force_qualify ? + (flags & FORMAT_PROC_FORCE_QUALIFY) != 0 ? format_type_be_qualified(thisargtype) : format_type_be(thisargtype)); } @@ -389,6 +391,11 @@ format_procedure_internal(Oid procedure_oid, bool force_qualify) ReleaseSysCache(proctup); } + else if ((flags & FORMAT_PROC_INVALID_AS_NULL) != 0) + { + /* If object is undefined, return NULL as wanted by caller */ + result = NULL; + } else { /* If OID doesn't match any pg_proc entry, return it numerically */ @@ -747,13 +754,22 @@ to_regoperator(PG_FUNCTION_ARGS) } /* - * format_operator - converts operator OID to "opr_name(args)" + * format_operator_extended + * + * Converts operator OID to "opr_name(args)" * * This exports the useful functionality of regoperatorout for use * in other backend modules. The result is a palloc'd string. + * + * The following bits in 'flags' modify the behavior: + * - FORMAT_OPERATOR_INVALID_AS_NULL + * if the type OID is invalid or unknown, return NULL instead of + * the numeric OID. + * - FORMAT_OPERATOR_FORCE_QUALIFY + * always schema-qualify type names, regardless of search_path */ -static char * -format_operator_internal(Oid operator_oid, bool force_qualify) +char * +format_operator_extended(Oid operator_oid, bits16 flags) { char *result; HeapTuple opertup; @@ -776,7 +792,8 @@ format_operator_internal(Oid operator_oid, bool force_qualify) * Would this oper be found (given the right args) by regoperatorin? * If not, or if caller explicitly requests it, we need to qualify it. */ - if (force_qualify || !OperatorIsVisible(operator_oid)) + if ((flags & FORMAT_OPERATOR_FORCE_QUALIFY) != 0 || + !OperatorIsVisible(operator_oid)) { nspname = get_namespace_name(operform->oprnamespace); appendStringInfo(&buf, "%s.", @@ -787,7 +804,7 @@ format_operator_internal(Oid operator_oid, bool force_qualify) if (operform->oprleft) appendStringInfo(&buf, "%s,", - force_qualify ? + (flags & FORMAT_OPERATOR_FORCE_QUALIFY) != 0 ? format_type_be_qualified(operform->oprleft) : format_type_be(operform->oprleft)); else @@ -795,7 +812,7 @@ format_operator_internal(Oid operator_oid, bool force_qualify) if (operform->oprright) appendStringInfo(&buf, "%s)", - force_qualify ? + (flags & FORMAT_OPERATOR_FORCE_QUALIFY) != 0 ? format_type_be_qualified(operform->oprright) : format_type_be(operform->oprright)); else @@ -805,6 +822,11 @@ format_operator_internal(Oid operator_oid, bool force_qualify) ReleaseSysCache(opertup); } + else if ((flags & FORMAT_OPERATOR_INVALID_AS_NULL) != 0) + { + /* If object is undefined, return NULL as wanted by caller */ + result = NULL; + } else { /* @@ -820,13 +842,14 @@ format_operator_internal(Oid operator_oid, bool force_qualify) char * format_operator(Oid operator_oid) { - return format_operator_internal(operator_oid, false); + return format_operator_extended(operator_oid, 0); } char * format_operator_qualified(Oid operator_oid) { - return format_operator_internal(operator_oid, true); + return format_operator_extended(operator_oid, + FORMAT_OPERATOR_FORCE_QUALIFY); } void -- 2.27.0