1 /*-------------------------------------------------------------------------
4 * Display type names "nicely".
7 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.10 2001/03/22 03:59:50 momjian Exp $
13 *-------------------------------------------------------------------------
21 #include "catalog/pg_type.h"
22 #include "utils/builtins.h"
23 #include "utils/numeric.h"
24 #include "utils/syscache.h"
26 #define MAX_INT32_LEN 11
27 #define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str))
30 static char *format_type_internal(Oid type_oid, int32 typemod);
34 psnprintf(size_t len, const char *fmt,...)
42 vsnprintf(buf, len, fmt, ap);
50 * SQL function: format_type(type_oid, typemod)
52 * `type_oid' is from pg_type.oid, `typemod' is from
53 * pg_attribute.atttypmod. This function will get the type name and
54 * format it and the modifier to canonical SQL format, if the type is
55 * a standard type. Otherwise you just get pg_type.typname back,
56 * double quoted if it contains funny characters.
58 * If typemod is null (in the SQL sense) then you won't get any
59 * "..(x)" type qualifiers. The result is not technically correct,
60 * because the various types interpret missing type modifiers
61 * differently, but it can be used as a convenient way to format
62 * system catalogs, e.g., pg_aggregate, in psql.
65 format_type(PG_FUNCTION_ARGS)
74 type_oid = PG_GETARG_OID(0);
77 typemod = PG_GETARG_INT32(1);
79 typemod = -1; /* default typmod */
81 result = format_type_internal(type_oid, typemod);
83 PG_RETURN_DATUM(_textin(result));
88 format_type_internal(Oid type_oid, int32 typemod)
90 bool with_typemod = (typemod >= 0);
98 if (type_oid == InvalidOid)
101 tuple = SearchSysCache(TYPEOID,
102 ObjectIdGetDatum(type_oid),
104 if (!HeapTupleIsValid(tuple))
105 return pstrdup("???");
107 array_base_type = ((Form_pg_type) GETSTRUCT(tuple))->typelem;
108 typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen;
109 if (array_base_type != 0 && typlen < 0)
111 /* Switch our attention to the array element type */
112 ReleaseSysCache(tuple);
113 tuple = SearchSysCache(TYPEOID,
114 ObjectIdGetDatum(array_base_type),
116 if (!HeapTupleIsValid(tuple))
117 return pstrdup("???[]");
119 type_oid = array_base_type;
127 buf = pstrdup("boolean");
132 buf = psnprintf(11 + MAX_INT32_LEN + 1, "character(%d)",
133 (int) (typemod - VARHDRSZ));
135 buf = pstrdup("character");
141 * This char type is the single-byte version. You have to
142 * double-quote it to get at it in the parser.
144 buf = pstrdup("\"char\"");
148 buf = pstrdup("real");
152 buf = pstrdup("double precision");
156 buf = pstrdup("smallint");
160 buf = pstrdup("integer");
164 buf = pstrdup("bigint");
169 buf = psnprintf(10 + 2 * MAX_INT32_LEN + 1, "numeric(%d,%d)",
170 ((typemod - VARHDRSZ) >> 16) & 0xffff,
171 (typemod - VARHDRSZ) & 0xffff);
173 buf = pstrdup("numeric");
177 buf = pstrdup("time with time zone");
181 buf = pstrdup("timestamp with time zone");
186 buf = psnprintf(13 + MAX_INT32_LEN + 1, "bit varying(%d)",
189 buf = pstrdup("bit varying");
194 buf = psnprintf(19 + MAX_INT32_LEN + 1,
195 "character varying(%d)",
196 (int) (typemod - VARHDRSZ));
198 buf = pstrdup("character varying");
203 buf = psnprintf(5 + MAX_INT32_LEN + 1, "bit(%d)",
206 buf = pstrdup("bit");
210 name = NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname);
211 if (strspn(name, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(name)
212 || isdigit((unsigned char) name[0]))
213 buf = psnprintf(strlen(name) + 3, "\"%s\"", name);
220 buf = psnprintf(strlen(buf) + 3, "%s[]", buf);
222 ReleaseSysCache(tuple);
229 * type_maximum_size --- determine maximum length of a varlena column
231 * If the max length is indeterminate, return -1. In particular, we return
232 * -1 for any type not known to this routine. We assume the caller has
233 * already determined that the type is a varlena type, so it's not
234 * necessary to look up the type's pg_type tuple here.
236 * This may appear unrelated to format_type(), but in fact the two routines
237 * share knowledge of the encoding of typmod for different types, so it's
238 * convenient to keep them together.
241 type_maximum_size(Oid type_oid, int32 typemod)
250 /* typemod includes varlena header */
254 /* precision (ie, max # of digits) is in upper bits of typmod */
255 if (typemod > VARHDRSZ)
257 int precision = ((typemod - VARHDRSZ) >> 16) & 0xffff;
259 /* Numeric stores 2 decimal digits/byte, plus header */
260 return (precision + 1) / 2 + NUMERIC_HDRSZ;
266 /* typemod is the (max) number of bits */
267 return (typemod + (BITS_PER_BYTE - 1)) / BITS_PER_BYTE
271 /* Unknown type, or unlimited-length type such as 'text' */
277 * oidvectortypes - converts a vector of type OIDs to "typname" list
279 * The interface for this function is wrong: it should be told how many
280 * OIDs are significant in the input vector, so that trailing InvalidOid
281 * argument types can be recognized.
284 oidvectortypes(PG_FUNCTION_ARGS)
286 Oid *oidArray = (Oid *) PG_GETARG_POINTER(0);
293 /* Try to guess how many args there are :-( */
295 for (num = 0; num < FUNC_MAX_ARGS; num++)
297 if (oidArray[num] != InvalidOid)
301 total = 20 * numargs + 1;
302 result = palloc(total);
306 for (num = 0; num < numargs; num++)
308 char *typename = format_type_internal(oidArray[num], -1);
310 if (left < strlen(typename) + 2)
312 total += strlen(typename) + 2;
313 result = repalloc(result, total);
314 left += strlen(typename) + 2;
319 strcat(result, ", ");
322 strcat(result, typename);
323 left -= strlen(typename);
326 PG_RETURN_DATUM(_textin(result));