1 /*-------------------------------------------------------------------------
4 * Display type names "nicely".
7 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.5 2000/08/26 21:53:41 tgl 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 = SearchSysCacheTuple(TYPEOID, 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 tuple = SearchSysCacheTuple(TYPEOID,
112 ObjectIdGetDatum(array_base_type),
114 if (!HeapTupleIsValid(tuple))
115 return pstrdup("???[]");
117 type_oid = array_base_type;
125 buf = pstrdup("boolean");
130 buf = psnprintf(11 + MAX_INT32_LEN + 1, "character(%d)",
131 (int) (typemod - VARHDRSZ));
133 buf = pstrdup("character");
137 /* This char type is the single-byte version. You have to
138 * double-quote it to get at it in the parser.
140 buf = pstrdup("\"char\"");
144 buf = pstrdup("real");
148 buf = pstrdup("double precision");
152 buf = pstrdup("smallint");
156 buf = pstrdup("integer");
160 buf = pstrdup("bigint");
165 buf = psnprintf(10 + 2 * MAX_INT32_LEN + 1, "numeric(%d,%d)",
166 ((typemod - VARHDRSZ) >> 16) & 0xffff,
167 (typemod - VARHDRSZ) & 0xffff);
169 buf = pstrdup("numeric");
173 buf = pstrdup("time with time zone");
178 buf = psnprintf(13 + MAX_INT32_LEN + 1, "bit varying(%d)",
181 buf = pstrdup("bit varying");
186 buf = psnprintf(19 + MAX_INT32_LEN + 1,
187 "character varying(%d)",
188 (int) (typemod - VARHDRSZ));
190 buf = pstrdup("character varying");
195 buf = psnprintf(5 + MAX_INT32_LEN + 1, "bit(%d)",
198 buf = pstrdup("bit");
202 name = NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname);
203 if (strspn(name, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(name)
204 || isdigit((int) name[0]))
205 buf = psnprintf(strlen(name) + 3, "\"%s\"", name);
212 buf = psnprintf(strlen(buf) + 3, "%s[]", buf);
219 * type_maximum_size --- determine maximum length of a varlena column
221 * If the max length is indeterminate, return -1. In particular, we return
222 * -1 for any type not known to this routine. We assume the caller has
223 * already determined that the type is a varlena type, so it's not
224 * necessary to look up the type's pg_type tuple here.
226 * This may appear unrelated to format_type(), but in fact the two routines
227 * share knowledge of the encoding of typmod for different types, so it's
228 * convenient to keep them together.
231 type_maximum_size(Oid type_oid, int32 typemod)
240 /* typemod includes varlena header */
244 /* precision (ie, max # of digits) is in upper bits of typmod */
245 if (typemod > VARHDRSZ)
247 int precision = ((typemod - VARHDRSZ) >> 16) & 0xffff;
249 /* Numeric stores 2 decimal digits/byte, plus header */
250 return (precision + 1) / 2 + NUMERIC_HDRSZ;
256 /* typemod is the (max) number of bits */
257 return (typemod + (BITS_PER_BYTE-1)) / BITS_PER_BYTE
261 /* Unknown type, or unlimited-length type such as 'text' */
267 * oidvectortypes - converts a vector of type OIDs to "typname" list
269 * The interface for this function is wrong: it should be told how many
270 * OIDs are significant in the input vector, so that trailing InvalidOid
271 * argument types can be recognized.
274 oidvectortypes(PG_FUNCTION_ARGS)
276 Oid *oidArray = (Oid *) PG_GETARG_POINTER(0);
283 /* Try to guess how many args there are :-( */
285 for (num = 0; num < FUNC_MAX_ARGS; num++)
287 if (oidArray[num] != InvalidOid)
291 total = 20 * numargs + 1;
292 result = palloc(total);
296 for (num = 0; num < numargs; num++)
298 char * typename = format_type_internal(oidArray[num], -1);
300 if (left < strlen(typename) + 2)
302 total += strlen(typename) + 2;
303 result = repalloc(result, total);
304 left += strlen(typename) + 2;
309 strcat(result, ", ");
312 strcat(result, typename);
313 left -= strlen(typename);
316 PG_RETURN_DATUM(_textin(result));