]> granicus.if.org Git - postgresql/blobdiff - src/backend/utils/adt/format_type.c
Fix initialization of fake LSN for unlogged relations
[postgresql] / src / backend / utils / adt / format_type.c
index a0ea23307a13e324667212b97f9fd2e6e5743ef1..6ae2a31345f457921d460e6dc54965cc29caa6d8 100644 (file)
@@ -4,11 +4,11 @@
  *       Display type names "nicely".
  *
  *
- * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.51 2009/01/01 17:23:49 momjian Exp $
+ *       src/backend/utils/adt/format_type.c
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 
 #include <ctype.h>
 
+#include "access/htup_details.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_type.h"
 #include "utils/builtins.h"
 #include "utils/syscache.h"
 #include "mb/pg_wchar.h"
 
-#define MAX_INT32_LEN 11
-
-static char *format_type_internal(Oid type_oid, int32 typemod,
-                                        bool typemod_given, bool allow_invalid);
 static char *printTypmod(const char *typname, int32 typmod, Oid typmodout);
-static char *
-psnprintf(size_t len, const char *fmt,...)
-/* This lets gcc check the format string for consistency. */
-__attribute__((format(printf, 2, 3)));
 
 
 /*
@@ -46,14 +39,14 @@ __attribute__((format(printf, 2, 3)));
  * double quoted if it contains funny characters or matches a keyword.
  *
  * If typemod is NULL then we are formatting a type name in a context where
- * no typemod is available, eg a function argument or result type.     This
+ * no typemod is available, eg a function argument or result type.  This
  * yields a slightly different result from specifying typemod = -1 in some
  * cases.  Given typemod = -1 we feel compelled to produce an output that
  * the parser will interpret as having typemod -1, so that pg_dump will
- * produce CREATE TABLE commands that recreate the original state.     But
+ * produce CREATE TABLE commands that recreate the original state.  But
  * given NULL typemod, we assume that the parser's interpretation of
  * typemod doesn't matter, and so we are willing to output a slightly
- * "prettier" representation of the same type. For example, type = bpchar
+ * "prettier" representation of the same type.  For example, type = bpchar
  * and typemod = NULL gets you "character", whereas typemod = -1 gets you
  * "bpchar" --- the former will be interpreted as character(1) by the
  * parser, which does not yield typemod -1.
@@ -68,6 +61,7 @@ format_type(PG_FUNCTION_ARGS)
        Oid                     type_oid;
        int32           typemod;
        char       *result;
+       bits16          flags = FORMAT_TYPE_ALLOW_INVALID;
 
        /* Since this function is not strict, we must test for null args */
        if (PG_ARGISNULL(0))
@@ -76,59 +70,57 @@ format_type(PG_FUNCTION_ARGS)
        type_oid = PG_GETARG_OID(0);
 
        if (PG_ARGISNULL(1))
-               result = format_type_internal(type_oid, -1, false, true);
+               typemod = -1;
        else
        {
                typemod = PG_GETARG_INT32(1);
-               result = format_type_internal(type_oid, typemod, true, true);
+               flags |= FORMAT_TYPE_TYPEMOD_GIVEN;
        }
 
+       result = format_type_extended(type_oid, typemod, flags);
+
        PG_RETURN_TEXT_P(cstring_to_text(result));
 }
 
 /*
- * This version is for use within the backend in error messages, etc.
- * One difference is that it will fail for an invalid type.
+ * format_type_extended
+ *             Generate a possibly-qualified type name.
  *
- * The result is always a palloc'd string.
- */
-char *
-format_type_be(Oid type_oid)
-{
-       return format_type_internal(type_oid, -1, false, false);
-}
-
-/*
- * This version allows a nondefault typemod to be specified.
+ * The default behavior is to only qualify if the type is not in the search
+ * path, to ignore the given typmod, and to raise an error if a non-existent
+ * type_oid is given.
+ *
+ * The following bits in 'flags' modify the behavior:
+ * - FORMAT_TYPE_TYPEMOD_GIVEN
+ *                     include the typmod in the output (typmod could still be -1 though)
+ * - FORMAT_TYPE_ALLOW_INVALID
+ *                     if the type OID is invalid or unknown, return ??? or such instead
+ *                     of failing
+ * - FORMAT_TYPE_FORCE_QUALIFY
+ *                     always schema-qualify type names, regardless of search_path
+ *
+ * Note that TYPEMOD_GIVEN is not interchangeable with "typemod == -1";
+ * see the comments above for format_type().
+ *
+ * Returns a palloc'd string.
  */
 char *
-format_type_with_typemod(Oid type_oid, int32 typemod)
-{
-       return format_type_internal(type_oid, typemod, true, false);
-}
-
-
-
-static char *
-format_type_internal(Oid type_oid, int32 typemod,
-                                        bool typemod_given, bool allow_invalid)
+format_type_extended(Oid type_oid, int32 typemod, bits16 flags)
 {
-       bool            with_typemod = typemod_given && (typemod >= 0);
        HeapTuple       tuple;
        Form_pg_type typeform;
        Oid                     array_base_type;
        bool            is_array;
        char       *buf;
+       bool            with_typemod;
 
-       if (type_oid == InvalidOid && allow_invalid)
+       if (type_oid == InvalidOid && (flags & FORMAT_TYPE_ALLOW_INVALID) != 0)
                return pstrdup("-");
 
-       tuple = SearchSysCache(TYPEOID,
-                                                  ObjectIdGetDatum(type_oid),
-                                                  0, 0, 0);
+       tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
        if (!HeapTupleIsValid(tuple))
        {
-               if (allow_invalid)
+               if ((flags & FORMAT_TYPE_ALLOW_INVALID) != 0)
                        return pstrdup("???");
                else
                        elog(ERROR, "cache lookup failed for type %u", type_oid);
@@ -136,27 +128,22 @@ format_type_internal(Oid type_oid, int32 typemod,
        typeform = (Form_pg_type) GETSTRUCT(tuple);
 
        /*
-        * Check if it's an array (and not a domain --- we don't want to show the
-        * substructure of a domain type).      Fixed-length array types such as
-        * "name" shouldn't get deconstructed either.  As of Postgres 8.1, rather
-        * than checking typlen we check the toast property, and don't deconstruct
-        * "plain storage" array types --- this is because we don't want to show
-        * oidvector as oid[].
+        * Check if it's a regular (variable length) array type.  Fixed-length
+        * array types such as "name" shouldn't get deconstructed.  As of Postgres
+        * 8.1, rather than checking typlen we check the toast property, and don't
+        * deconstruct "plain storage" array types --- this is because we don't
+        * want to show oidvector as oid[].
         */
        array_base_type = typeform->typelem;
 
-       if (array_base_type != InvalidOid &&
-               typeform->typstorage != 'p' &&
-               typeform->typtype != TYPTYPE_DOMAIN)
+       if (array_base_type != InvalidOid && typeform->typstorage != 'p')
        {
                /* Switch our attention to the array element type */
                ReleaseSysCache(tuple);
-               tuple = SearchSysCache(TYPEOID,
-                                                          ObjectIdGetDatum(array_base_type),
-                                                          0, 0, 0);
+               tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(array_base_type));
                if (!HeapTupleIsValid(tuple))
                {
-                       if (allow_invalid)
+                       if ((flags & FORMAT_TYPE_ALLOW_INVALID) != 0)
                                return pstrdup("???[]");
                        else
                                elog(ERROR, "cache lookup failed for type %u", type_oid);
@@ -168,6 +155,8 @@ format_type_internal(Oid type_oid, int32 typemod,
        else
                is_array = false;
 
+       with_typemod = (flags & FORMAT_TYPE_TYPEMOD_GIVEN) != 0 && (typemod >= 0);
+
        /*
         * See if we want to special-case the output for certain built-in types.
         * Note that these special cases should all correspond to special
@@ -186,7 +175,7 @@ format_type_internal(Oid type_oid, int32 typemod,
                case BITOID:
                        if (with_typemod)
                                buf = printTypmod("bit", typemod, typeform->typmodout);
-                       else if (typemod_given)
+                       else if ((flags & FORMAT_TYPE_TYPEMOD_GIVEN) != 0)
                        {
                                /*
                                 * bit with typmod -1 is not the same as BIT, which means
@@ -205,7 +194,7 @@ format_type_internal(Oid type_oid, int32 typemod,
                case BPCHAROID:
                        if (with_typemod)
                                buf = printTypmod("character", typemod, typeform->typmodout);
-                       else if (typemod_given)
+                       else if ((flags & FORMAT_TYPE_TYPEMOD_GIVEN) != 0)
                        {
                                /*
                                 * bpchar with typmod -1 is not the same as CHARACTER, which
@@ -299,16 +288,17 @@ format_type_internal(Oid type_oid, int32 typemod,
                /*
                 * Default handling: report the name as it appears in the catalog.
                 * Here, we must qualify the name if it is not visible in the search
-                * path, and we must double-quote it if it's not a standard identifier
-                * or if it matches any keyword.
+                * path or if caller requests it; and we must double-quote it if it's
+                * not a standard identifier or if it matches any keyword.
                 */
                char       *nspname;
                char       *typname;
 
-               if (TypeIsVisible(type_oid))
+               if ((flags & FORMAT_TYPE_FORCE_QUALIFY) == 0 &&
+                       TypeIsVisible(type_oid))
                        nspname = NULL;
                else
-                       nspname = get_namespace_name(typeform->typnamespace);
+                       nspname = get_namespace_name_or_temp(typeform->typnamespace);
 
                typname = NameStr(typeform->typname);
 
@@ -319,13 +309,43 @@ format_type_internal(Oid type_oid, int32 typemod,
        }
 
        if (is_array)
-               buf = psnprintf(strlen(buf) + 3, "%s[]", buf);
+               buf = psprintf("%s[]", buf);
 
        ReleaseSysCache(tuple);
 
        return buf;
 }
 
+/*
+ * This version is for use within the backend in error messages, etc.
+ * One difference is that it will fail for an invalid type.
+ *
+ * The result is always a palloc'd string.
+ */
+char *
+format_type_be(Oid type_oid)
+{
+       return format_type_extended(type_oid, -1, 0);
+}
+
+/*
+ * This version returns a name that is always qualified (unless it's one
+ * of the SQL-keyword type names, such as TIMESTAMP WITH TIME ZONE).
+ */
+char *
+format_type_be_qualified(Oid type_oid)
+{
+       return format_type_extended(type_oid, -1, FORMAT_TYPE_FORCE_QUALIFY);
+}
+
+/*
+ * This version allows a nondefault typemod to be specified.
+ */
+char *
+format_type_with_typemod(Oid type_oid, int32 typemod)
+{
+       return format_type_extended(type_oid, typemod, FORMAT_TYPE_TYPEMOD_GIVEN);
+}
 
 /*
  * Add typmod decoration to the basic type name
@@ -341,8 +361,7 @@ printTypmod(const char *typname, int32 typmod, Oid typmodout)
        if (typmodout == InvalidOid)
        {
                /* Default behavior: just print the integer typmod with parens */
-               res = psnprintf(strlen(typname) + MAX_INT32_LEN + 3, "%s(%d)",
-                                               typname, (int) typmod);
+               res = psprintf("%s(%d)", typname, (int) typmod);
        }
        else
        {
@@ -351,8 +370,7 @@ printTypmod(const char *typname, int32 typmod, Oid typmodout)
 
                tmstr = DatumGetCString(OidFunctionCall1(typmodout,
                                                                                                 Int32GetDatum(typmod)));
-               res = psnprintf(strlen(typname) + strlen(tmstr) + 1, "%s%s",
-                                               typname, tmstr);
+               res = psprintf("%s%s", typname, tmstr);
        }
 
        return res;
@@ -391,15 +409,7 @@ type_maximum_size(Oid type_oid, int32 typemod)
                                + VARHDRSZ;
 
                case NUMERICOID:
-                       /* precision (ie, max # of digits) is in upper bits of typmod */
-                       if (typemod > VARHDRSZ)
-                       {
-                               int                     precision = ((typemod - VARHDRSZ) >> 16) & 0xffff;
-
-                               /* Numeric stores 2 decimal digits/byte, plus header */
-                               return (precision + 1) / 2 + NUMERIC_HDRSZ;
-                       }
-                       break;
+                       return numeric_maximum_size(typemod);
 
                case VARBITOID:
                case BITOID:
@@ -433,8 +443,8 @@ oidvectortypes(PG_FUNCTION_ARGS)
 
        for (num = 0; num < numargs; num++)
        {
-               char       *typename = format_type_internal(oidArray->values[num], -1,
-                                                                                                       false, true);
+               char       *typename = format_type_extended(oidArray->values[num], -1,
+                                                                                                       FORMAT_TYPE_ALLOW_INVALID);
                size_t          slen = strlen(typename);
 
                if (left < (slen + 2))
@@ -455,20 +465,3 @@ oidvectortypes(PG_FUNCTION_ARGS)
 
        PG_RETURN_TEXT_P(cstring_to_text(result));
 }
-
-
-/* snprintf into a palloc'd string */
-static char *
-psnprintf(size_t len, const char *fmt,...)
-{
-       va_list         ap;
-       char       *buf;
-
-       buf = palloc(len);
-
-       va_start(ap, fmt);
-       vsnprintf(buf, len, fmt, ap);
-       va_end(ap);
-
-       return buf;
-}