static char * format_type_internal(Oid type_oid, int32 typemod, bool typemod_given, bool allow_invalid) { bool with_typemod = typemod_given && (typemod >= 0); HeapTuple tuple; Form_pg_type typeform; Oid array_base_type; bool is_array; char *buf; if (type_oid == InvalidOid && allow_invalid) return pstrdup("-"); tuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(type_oid), 0, 0, 0); if (!HeapTupleIsValid(tuple)) { if (allow_invalid) return pstrdup("???"); else elog(ERROR, "cache lookup failed for type %u", type_oid); } 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[]. */ array_base_type = typeform->typelem; if (array_base_type != InvalidOid && typeform->typstorage != 'p' && typeform->typtype != TYPTYPE_DOMAIN) { /* Switch our attention to the array element type */ ReleaseSysCache(tuple); tuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(array_base_type), 0, 0, 0); if (!HeapTupleIsValid(tuple)) { if (allow_invalid) return pstrdup("???[]"); else elog(ERROR, "cache lookup failed for type %u", type_oid); } typeform = (Form_pg_type) GETSTRUCT(tuple); type_oid = array_base_type; is_array = true; } else is_array = false; /* * See if we want to special-case the output for certain built-in types. * Note that these special cases should all correspond to special * productions in gram.y, to ensure that the type name will be taken as a * system type, not a user type of the same name. * * If we do not provide a special-case output here, the type name will be * handled the same way as a user type name --- in particular, it will be * double-quoted if it matches any lexer keyword. This behavior is * essential for some cases, such as types "bit" and "char". */ buf = NULL; /* flag for no special case */ switch (type_oid) { case BITOID: if (with_typemod) buf = printTypmod("bit", typemod, typeform->typmodout); else if (typemod_given) { /* * bit with typmod -1 is not the same as BIT, which means * BIT(1) per SQL spec. Report it as the quoted typename so * that parser will not assign a bogus typmod. */ } else buf = pstrdup("bit"); break; case BOOLOID: buf = pstrdup("boolean"); break; case BPCHAROID: if (with_typemod) buf = printTypmod("character", typemod, typeform->typmodout); else if (typemod_given) { /* * bpchar with typmod -1 is not the same as CHARACTER, which * means CHARACTER(1) per SQL spec. Report it as bpchar so * that parser will not assign a bogus typmod. */ } else buf = pstrdup("character"); break; case FLOAT4OID: buf = pstrdup("real"); break; case FLOAT8OID: buf = pstrdup("double precision"); break; case INT2OID: buf = pstrdup("smallint"); break; case INT4OID: buf = pstrdup("integer"); break; case INT8OID: buf = pstrdup("bigint"); break; case NUMERICOID: if (with_typemod) buf = printTypmod("numeric", typemod, typeform->typmodout); else buf = pstrdup("numeric"); break; case INTERVALOID: if (with_typemod) buf = printTypmod("interval", typemod, typeform->typmodout); else buf = pstrdup("interval"); break; case TIMEOID: if (with_typemod) buf = printTypmod("time", typemod, typeform->typmodout); else buf = pstrdup("time without time zone"); break; case TIMETZOID: if (with_typemod) buf = printTypmod("time", typemod, typeform->typmodout); else buf = pstrdup("time with time zone"); break; case TIMESTAMPOID: if (with_typemod) buf = printTypmod("timestamp", typemod, typeform->typmodout); else buf = pstrdup("timestamp without time zone"); break; case TIMESTAMPTZOID: if (with_typemod) buf = printTypmod("timestamp", typemod, typeform->typmodout); else buf = pstrdup("timestamp with time zone"); break; case VARBITOID: if (with_typemod) buf = printTypmod("bit varying", typemod, typeform->typmodout); else buf = pstrdup("bit varying"); break; case VARCHAROID: if (with_typemod) buf = printTypmod("character varying", typemod, typeform->typmodout); else buf = pstrdup("character varying"); break; } if (buf == NULL) { /* * 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. */ char *nspname; char *typname; if (TypeIsVisible(type_oid)) nspname = NULL; else nspname = get_namespace_name(typeform->typnamespace); typname = NameStr(typeform->typname); buf = quote_qualified_identifier(nspname, typname); if (with_typemod) buf = printTypmod(buf, typemod, typeform->typmodout); } if (is_array) buf = psnprintf(strlen(buf) + 3, "%s[]", buf); ReleaseSysCache(tuple); return buf; }
static char *format_type_internal(oid_t type_oid, int32 typemod, bool typemod_given, bool allow_invalid) { bool with_typemod = typemod_given && (typemod >= 0); struct heap_tuple * tuple; Form_pg_type typeform; oid_t array_base_type; bool is_array; char *buf; if (type_oid == INVALID_OID && allow_invalid) return pstrdup("-"); tuple = search_syscache1(TYPEOID, OID_TO_D(type_oid)); if (!HT_VALID(tuple)) { if (allow_invalid) return pstrdup("???"); else elog(ERROR, "cache lookup failed for type %u", type_oid); } typeform = (Form_pg_type) GET_STRUCT(tuple); /* * 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 oid_vector_s as oid[]. */ array_base_type = typeform->typelem; if (array_base_type != INVALID_OID && typeform->typstorage != 'p') { /* Switch our attention to the array element type */ release_syscache(tuple); tuple = search_syscache1(TYPEOID, OID_TO_D(array_base_type)); if (!HT_VALID(tuple)) { if (allow_invalid) return pstrdup("???[]"); else elog(ERROR, "cache lookup failed for type %u", type_oid); } typeform = (Form_pg_type) GET_STRUCT(tuple); type_oid = array_base_type; is_array = true; } else { is_array = false; } /* * See if we want to special-case the output for certain built-in types. * Note that these special cases should all correspond to special * productions in gram.y, to ensure that the type name will be taken as * a system type, not a user type of the same name. * * If we do not provide a special-case output here, the type name will * be handled the same way as a user type name --- in particular, it * will be double-quoted if it matches any lexer keyword. * * This behavior is essential for some cases, such as types "bit" and * "char". */ buf = NULL; /* flag for no special case */ switch (type_oid) { case BITOID: if (with_typemod) { buf = printTypmod("bit", typemod, typeform->typmodout); } else if (typemod_given) { /* * bit with typmod -1 is not the same as BIT, which * means BIT(1) per SQL spec. Report it as the quoted * typename so that parser will not assign a bogus * typmod. */ } else { buf = pstrdup("bit"); } break; case BOOLOID: buf = pstrdup("boolean"); break; case BPCHAROID: if (with_typemod) { buf = printTypmod("character", typemod, typeform->typmodout); } else if (typemod_given) { /* * bpchar with typmod -1 is not the same as CHARACTER, * which means CHARACTER(1) per SQL spec. Report it as * bpchar so that parser will not assign a bogus typmod. */ } else { buf = pstrdup("character"); } break; case FLOAT4OID: buf = pstrdup("real"); break; case FLOAT8OID: buf = pstrdup("double precision"); break; case INT2OID: buf = pstrdup("smallint"); break; case INT4OID: buf = pstrdup("integer"); break; case INT8OID: buf = pstrdup("bigint"); break; case NUMERICOID: if (with_typemod) buf = printTypmod("numeric", typemod, typeform->typmodout); else buf = pstrdup("numeric"); break; case INTERVALOID: if (with_typemod) buf = printTypmod("interval", typemod, typeform->typmodout); else buf = pstrdup("interval"); break; case TIMEOID: if (with_typemod) buf = printTypmod("time", typemod, typeform->typmodout); else buf = pstrdup("time without time zone"); break; case TIMETZOID: if (with_typemod) buf = printTypmod("time", typemod, typeform->typmodout); else buf = pstrdup("time with time zone"); break; case TIMESTAMPOID: if (with_typemod) buf = printTypmod("timestamp", typemod, typeform->typmodout); else buf = pstrdup("timestamp without time zone"); break; case TIMESTAMPTZOID: if (with_typemod) buf = printTypmod("timestamp", typemod, typeform->typmodout); else buf = pstrdup("timestamp with time zone"); break; case VARBITOID: if (with_typemod) buf = printTypmod("bit varying", typemod, typeform->typmodout); else buf = pstrdup("bit varying"); break; case VARCHAROID: if (with_typemod) buf = printTypmod("character varying", typemod, typeform->typmodout); else buf = pstrdup("character varying"); break; } if (buf == NULL) { /* * 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. */ char *nspname; char *typname; if (type_is_visible(type_oid)) nspname = NULL; else nspname = get_ns_name(typeform->typnamespace); typname = NAME_TO_STR(typeform->typname); buf = quote_qualified_identifier(nspname, typname); if (with_typemod) buf = printTypmod(buf, typemod, typeform->typmodout); } if (is_array) buf = psnprintf(strlen(buf) + 3, "%s[]", buf); release_syscache(tuple); return buf; }