Commit aa384348 authored by Michael Paquier's avatar Michael Paquier

Refactor routines for name lookups of procedures and operators

This introduces a new set of extended routines for procedure and
operator name lookups, with a flag bitmask argument that can modify the
result.  The following options are available:
- Force schema qualification, ignoring search_path.  This is similar to
the existing option for format_{operator|procedure}_qualified().
- Force NULL as result instead of a numeric OID for an undefined
object.  This option is new.

This is a refactoring similar to 1185c782, that will be used for a future
patch to improve the SQL functions providing information using object
addresses for undefined objects.

Author: Michael Paquier
Reviewed-by: Aleksander Alekseev, Dmitry Dolgov, Daniel Gustafsson,
Álvaro Herrera
Discussion: https://postgr.es/m/CAB7nPqSZxrSmdHK-rny7z8mi=EAFXJ5J-0RbzDw6aus=wB5azQ@mail.gmail.com
parent 04c7f414
...@@ -41,8 +41,6 @@ ...@@ -41,8 +41,6 @@
#include "utils/syscache.h" #include "utils/syscache.h"
#include "utils/varlena.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, static void parseNameAndArgTypes(const char *string, bool allowNone,
List **names, int *nargs, Oid *argtypes); List **names, int *nargs, Oid *argtypes);
...@@ -323,24 +321,32 @@ to_regprocedure(PG_FUNCTION_ARGS) ...@@ -323,24 +321,32 @@ to_regprocedure(PG_FUNCTION_ARGS)
char * char *
format_procedure(Oid procedure_oid) format_procedure(Oid procedure_oid)
{ {
return format_procedure_internal(procedure_oid, false); return format_procedure_extended(procedure_oid, 0);
} }
char * char *
format_procedure_qualified(Oid procedure_oid) format_procedure_qualified(Oid procedure_oid)
{ {
return format_procedure_internal(procedure_oid, true); return format_procedure_extended(procedure_oid, FORMAT_PROC_FORCE_QUALIFY);
} }
/* /*
* format_procedure_extended - converts procedure OID to "pro_name(args)"
*
* This exports the useful functionality of regprocedureout for use
* in other backend modules. The result is a palloc'd string, or NULL.
*
* Routine to produce regprocedure names; see format_procedure above. * Routine to produce regprocedure names; see format_procedure above.
* *
* force_qualify says whether to schema-qualify; if true, the name is always * The following bits in 'flags' modify the behavior:
* qualified regardless of search_path visibility. Otherwise the name is only * - FORMAT_PROC_INVALID_AS_NULL
* qualified if the function is not in path. * if the procedure OID is invalid or unknown, return NULL instead
* of the numeric OID.
* - FORMAT_PROC_FORCE_QUALIFY
* always schema-qualify procedure names, regardless of search_path
*/ */
static char * char *
format_procedure_internal(Oid procedure_oid, bool force_qualify) format_procedure_extended(Oid procedure_oid, bits16 flags)
{ {
char *result; char *result;
HeapTuple proctup; HeapTuple proctup;
...@@ -365,7 +371,8 @@ format_procedure_internal(Oid procedure_oid, bool force_qualify) ...@@ -365,7 +371,8 @@ format_procedure_internal(Oid procedure_oid, bool force_qualify)
* Would this proc be found (given the right args) by regprocedurein? * Would this proc be found (given the right args) by regprocedurein?
* If not, or if caller requests it, we need to qualify it. * 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; nspname = NULL;
else else
nspname = get_namespace_name(procform->pronamespace); nspname = get_namespace_name(procform->pronamespace);
...@@ -379,7 +386,7 @@ format_procedure_internal(Oid procedure_oid, bool force_qualify) ...@@ -379,7 +386,7 @@ format_procedure_internal(Oid procedure_oid, bool force_qualify)
if (i > 0) if (i > 0)
appendStringInfoChar(&buf, ','); appendStringInfoChar(&buf, ',');
appendStringInfoString(&buf, appendStringInfoString(&buf,
force_qualify ? (flags & FORMAT_PROC_FORCE_QUALIFY) != 0 ?
format_type_be_qualified(thisargtype) : format_type_be_qualified(thisargtype) :
format_type_be(thisargtype)); format_type_be(thisargtype));
} }
...@@ -389,6 +396,11 @@ format_procedure_internal(Oid procedure_oid, bool force_qualify) ...@@ -389,6 +396,11 @@ format_procedure_internal(Oid procedure_oid, bool force_qualify)
ReleaseSysCache(proctup); ReleaseSysCache(proctup);
} }
else if ((flags & FORMAT_PROC_INVALID_AS_NULL) != 0)
{
/* If object is undefined, return NULL as wanted by caller */
result = NULL;
}
else else
{ {
/* If OID doesn't match any pg_proc entry, return it numerically */ /* If OID doesn't match any pg_proc entry, return it numerically */
...@@ -747,13 +759,20 @@ to_regoperator(PG_FUNCTION_ARGS) ...@@ -747,13 +759,20 @@ 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 * This exports the useful functionality of regoperatorout for use
* in other backend modules. The result is a palloc'd string. * in other backend modules. The result is a palloc'd string, or NULL.
*
* The following bits in 'flags' modify the behavior:
* - FORMAT_OPERATOR_INVALID_AS_NULL
* if the operator OID is invalid or unknown, return NULL instead
* of the numeric OID.
* - FORMAT_OPERATOR_FORCE_QUALIFY
* always schema-qualify operator names, regardless of search_path
*/ */
static char * char *
format_operator_internal(Oid operator_oid, bool force_qualify) format_operator_extended(Oid operator_oid, bits16 flags)
{ {
char *result; char *result;
HeapTuple opertup; HeapTuple opertup;
...@@ -776,7 +795,8 @@ format_operator_internal(Oid operator_oid, bool force_qualify) ...@@ -776,7 +795,8 @@ format_operator_internal(Oid operator_oid, bool force_qualify)
* Would this oper be found (given the right args) by regoperatorin? * 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 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); nspname = get_namespace_name(operform->oprnamespace);
appendStringInfo(&buf, "%s.", appendStringInfo(&buf, "%s.",
...@@ -787,7 +807,7 @@ format_operator_internal(Oid operator_oid, bool force_qualify) ...@@ -787,7 +807,7 @@ format_operator_internal(Oid operator_oid, bool force_qualify)
if (operform->oprleft) if (operform->oprleft)
appendStringInfo(&buf, "%s,", appendStringInfo(&buf, "%s,",
force_qualify ? (flags & FORMAT_OPERATOR_FORCE_QUALIFY) != 0 ?
format_type_be_qualified(operform->oprleft) : format_type_be_qualified(operform->oprleft) :
format_type_be(operform->oprleft)); format_type_be(operform->oprleft));
else else
...@@ -795,7 +815,7 @@ format_operator_internal(Oid operator_oid, bool force_qualify) ...@@ -795,7 +815,7 @@ format_operator_internal(Oid operator_oid, bool force_qualify)
if (operform->oprright) if (operform->oprright)
appendStringInfo(&buf, "%s)", appendStringInfo(&buf, "%s)",
force_qualify ? (flags & FORMAT_OPERATOR_FORCE_QUALIFY) != 0 ?
format_type_be_qualified(operform->oprright) : format_type_be_qualified(operform->oprright) :
format_type_be(operform->oprright)); format_type_be(operform->oprright));
else else
...@@ -805,6 +825,11 @@ format_operator_internal(Oid operator_oid, bool force_qualify) ...@@ -805,6 +825,11 @@ format_operator_internal(Oid operator_oid, bool force_qualify)
ReleaseSysCache(opertup); ReleaseSysCache(opertup);
} }
else if ((flags & FORMAT_OPERATOR_INVALID_AS_NULL) != 0)
{
/* If object is undefined, return NULL as wanted by caller */
result = NULL;
}
else else
{ {
/* /*
...@@ -820,13 +845,14 @@ format_operator_internal(Oid operator_oid, bool force_qualify) ...@@ -820,13 +845,14 @@ format_operator_internal(Oid operator_oid, bool force_qualify)
char * char *
format_operator(Oid operator_oid) format_operator(Oid operator_oid)
{ {
return format_operator_internal(operator_oid, false); return format_operator_extended(operator_oid, 0);
} }
char * char *
format_operator_qualified(Oid operator_oid) format_operator_qualified(Oid operator_oid)
{ {
return format_operator_internal(operator_oid, true); return format_operator_extended(operator_oid,
FORMAT_OPERATOR_FORCE_QUALIFY);
} }
void void
......
...@@ -15,6 +15,16 @@ ...@@ -15,6 +15,16 @@
#include "nodes/pg_list.h" #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 procedure_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 operator_oid, bits16 flags);
extern List *stringToQualifiedNameList(const char *string); extern List *stringToQualifiedNameList(const char *string);
extern char *format_procedure(Oid procedure_oid); extern char *format_procedure(Oid procedure_oid);
extern char *format_procedure_qualified(Oid procedure_oid); extern char *format_procedure_qualified(Oid procedure_oid);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment