2828
2929#define MAX_INT32_LEN 11
3030
31- static char * format_type_internal (Oid type_oid ,int32 typemod ,
32- bool typemod_given ,bool allow_invalid ,
33- bool force_qualify );
3431static char * printTypmod (const char * typname ,int32 typmod ,Oid typmodout );
3532
3633
@@ -72,81 +69,52 @@ format_type(PG_FUNCTION_ARGS)
7269PG_RETURN_NULL ();
7370
7471type_oid = PG_GETARG_OID (0 );
72+ typemod = PG_ARGISNULL (1 ) ?-1 :PG_GETARG_INT32 (1 );
7573
76- if (PG_ARGISNULL (1 ))
77- result = format_type_internal (type_oid ,-1 , false, true, false);
78- else
79- {
80- typemod = PG_GETARG_INT32 (1 );
81- result = format_type_internal (type_oid ,typemod , true, true, false);
82- }
74+ result = format_type_extended (type_oid ,typemod ,
75+ FORMAT_TYPE_TYPEMOD_GIVEN |
76+ FORMAT_TYPE_ALLOW_INVALID );
8377
8478PG_RETURN_TEXT_P (cstring_to_text (result ));
8579}
8680
8781/*
88- *This version is for use within the backend in error messages, etc.
89- * One difference is that it will fail for an invalid type.
82+ *format_type_extended
83+ *Generate a possibly-qualified type name .
9084 *
91- * The result is always a palloc'd string.
92- */
93- char *
94- format_type_be (Oid type_oid )
95- {
96- return format_type_internal (type_oid ,-1 , false, false, false);
97- }
98-
99- /*
100- * This version returns a name that is always qualified (unless it's one
101- * of the SQL-keyword type names, such as TIMESTAMP WITH TIME ZONE).
102- */
103- char *
104- format_type_be_qualified (Oid type_oid )
105- {
106- return format_type_internal (type_oid ,-1 , false, false, true);
107- }
108-
109- /*
110- * This version allows a nondefault typemod to be specified.
111- */
112- char *
113- format_type_with_typemod (Oid type_oid ,int32 typemod )
114- {
115- return format_type_internal (type_oid ,typemod , true, false, false);
116- }
117-
118- /*
119- * This version allows a nondefault typemod to be specified, and forces
120- * qualification of normal type names.
85+ * The default is to only qualify if the type is not in the search path, to
86+ * ignore the given typmod, and to raise an error if a non-existent type_oid is
87+ * given.
88+ *
89+ * The following bits in 'flags' modify the behavior:
90+ * - FORMAT_TYPE_TYPEMOD_GIVEN
91+ *consider the given typmod in the output (may be -1 to request
92+ *the default behavior)
93+ *
94+ * - FORMAT_TYPE_ALLOW_INVALID
95+ *if the type OID is invalid or unknown, return ??? or such instead
96+ *of failing
97+ *
98+ * - FORMAT_TYPE_FORCE_QUALIFY
99+ *always schema-qualify type names, regardless of search_path
121100 */
122101char *
123- format_type_with_typemod_qualified (Oid type_oid ,int32 typemod )
102+ format_type_extended (Oid type_oid ,int32 typemod , bits16 flags )
124103{
125- return format_type_internal (type_oid ,typemod , true, false, true);
126- }
127-
128- /*
129- * Common workhorse.
130- */
131- static char *
132- format_type_internal (Oid type_oid ,int32 typemod ,
133- bool typemod_given ,bool allow_invalid ,
134- bool force_qualify )
135- {
136- bool with_typemod = typemod_given && (typemod >=0 );
137104HeapTuple tuple ;
138105Form_pg_type typeform ;
139106Oid array_base_type ;
140107bool is_array ;
141108char * buf ;
109+ bool with_typemod ;
142110
143- if (type_oid == InvalidOid && allow_invalid )
111+ if (type_oid == InvalidOid && ( flags & FORMAT_TYPE_ALLOW_INVALID ) != 0 )
144112return pstrdup ("-" );
145113
146114tuple = SearchSysCache1 (TYPEOID ,ObjectIdGetDatum (type_oid ));
147115if (!HeapTupleIsValid (tuple ))
148116{
149- if (allow_invalid )
117+ if (( flags & FORMAT_TYPE_ALLOW_INVALID ) != 0 )
150118return pstrdup ("???" );
151119else
152120elog (ERROR ,"cache lookup failed for type %u" ,type_oid );
@@ -162,15 +130,14 @@ format_type_internal(Oid type_oid, int32 typemod,
162130 */
163131array_base_type = typeform -> typelem ;
164132
165- if (array_base_type != InvalidOid &&
166- typeform -> typstorage != 'p' )
133+ if (array_base_type != InvalidOid && typeform -> typstorage != 'p' )
167134{
168135/* Switch our attention to the array element type */
169136ReleaseSysCache (tuple );
170137tuple = SearchSysCache1 (TYPEOID ,ObjectIdGetDatum (array_base_type ));
171138if (!HeapTupleIsValid (tuple ))
172139{
173- if (allow_invalid )
140+ if (( flags & FORMAT_TYPE_ALLOW_INVALID ) != 0 )
174141return pstrdup ("???[]" );
175142else
176143elog (ERROR ,"cache lookup failed for type %u" ,type_oid );
@@ -182,6 +149,8 @@ format_type_internal(Oid type_oid, int32 typemod,
182149else
183150is_array = false;
184151
152+ with_typemod = (flags & FORMAT_TYPE_TYPEMOD_GIVEN )!= 0 && (typemod >=0 );
153+
185154/*
186155 * See if we want to special-case the output for certain built-in types.
187156 * Note that these special cases should all correspond to special
@@ -200,7 +169,7 @@ format_type_internal(Oid type_oid, int32 typemod,
200169case BITOID :
201170if (with_typemod )
202171buf = printTypmod ("bit" ,typemod ,typeform -> typmodout );
203- else if (typemod_given )
172+ else if (( flags & FORMAT_TYPE_TYPEMOD_GIVEN ) != 0 )
204173{
205174/*
206175 * bit with typmod -1 is not the same as BIT, which means
@@ -219,7 +188,7 @@ format_type_internal(Oid type_oid, int32 typemod,
219188case BPCHAROID :
220189if (with_typemod )
221190buf = printTypmod ("character" ,typemod ,typeform -> typmodout );
222- else if (typemod_given )
191+ else if (( flags & FORMAT_TYPE_TYPEMOD_GIVEN ) != 0 )
223192{
224193/*
225194 * bpchar with typmod -1 is not the same as CHARACTER, which
@@ -313,13 +282,14 @@ format_type_internal(Oid type_oid, int32 typemod,
313282/*
314283 * Default handling: report the name as it appears in the catalog.
315284 * Here, we must qualify the name if it is not visible in the search
316- * path, and we must double-quote it if it's not a standard identifier
317- * or if it matches any keyword.
285+ * path or if caller requests it; and we must double-quote it if it's
286+ *not a standard identifier or if it matches any keyword.
318287 */
319288char * nspname ;
320289char * typname ;
321290
322- if (!force_qualify && TypeIsVisible (type_oid ))
291+ if ((flags & FORMAT_TYPE_FORCE_QUALIFY )== 0 &&
292+ TypeIsVisible (type_oid ))
323293nspname = NULL ;
324294else
325295nspname = get_namespace_name_or_temp (typeform -> typnamespace );
@@ -340,6 +310,36 @@ format_type_internal(Oid type_oid, int32 typemod,
340310return buf ;
341311}
342312
313+ /*
314+ * This version is for use within the backend in error messages, etc.
315+ * One difference is that it will fail for an invalid type.
316+ *
317+ * The result is always a palloc'd string.
318+ */
319+ char *
320+ format_type_be (Oid type_oid )
321+ {
322+ return format_type_extended (type_oid ,-1 ,0 );
323+ }
324+
325+ /*
326+ * This version returns a name that is always qualified (unless it's one
327+ * of the SQL-keyword type names, such as TIMESTAMP WITH TIME ZONE).
328+ */
329+ char *
330+ format_type_be_qualified (Oid type_oid )
331+ {
332+ return format_type_extended (type_oid ,-1 ,FORMAT_TYPE_FORCE_QUALIFY );
333+ }
334+
335+ /*
336+ * This version allows a nondefault typemod to be specified.
337+ */
338+ char *
339+ format_type_with_typemod (Oid type_oid ,int32 typemod )
340+ {
341+ return format_type_extended (type_oid ,typemod ,FORMAT_TYPE_TYPEMOD_GIVEN );
342+ }
343343
344344/*
345345 * Add typmod decoration to the basic type name
@@ -437,8 +437,8 @@ oidvectortypes(PG_FUNCTION_ARGS)
437437
438438for (num = 0 ;num < numargs ;num ++ )
439439{
440- char * typename = format_type_internal (oidArray -> values [num ],-1 ,
441- false, true, false );
440+ char * typename = format_type_extended (oidArray -> values [num ],-1 ,
441+ FORMAT_TYPE_ALLOW_INVALID );
442442size_t slen = strlen (typename );
443443
444444if (left < (slen + 2 ))