Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions

format_type.c File Reference

#include "postgres.h"
#include <ctype.h>
#include "access/htup_details.h"
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/numeric.h"
#include "utils/syscache.h"
#include "mb/pg_wchar.h"
Include dependency graph for format_type.c:

Go to the source code of this file.

Defines

#define MAX_INT32_LEN   11

Functions

static char * format_type_internal (Oid type_oid, int32 typemod, bool typemod_given, bool allow_invalid, bool force_qualify)
static char * printTypmod (const char *typname, int32 typmod, Oid typmodout)
static char * psnprintf (size_t len, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE
static char Datum format_type (PG_FUNCTION_ARGS)
char * format_type_be (Oid type_oid)
char * format_type_be_qualified (Oid type_oid)
char * format_type_with_typemod (Oid type_oid, int32 typemod)
int32 type_maximum_size (Oid type_oid, int32 typemod)
Datum oidvectortypes (PG_FUNCTION_ARGS)

Define Documentation

#define MAX_INT32_LEN   11

Definition at line 29 of file format_type.c.

Referenced by printTypmod().


Function Documentation

static char Datum format_type ( PG_FUNCTION_ARGS   ) 

Definition at line 68 of file format_type.c.

References cstring_to_text(), format_type_internal(), PG_ARGISNULL, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_NULL, and PG_RETURN_TEXT_P.

{
    Oid         type_oid;
    int32       typemod;
    char       *result;

    /* Since this function is not strict, we must test for null args */
    if (PG_ARGISNULL(0))
        PG_RETURN_NULL();

    type_oid = PG_GETARG_OID(0);

    if (PG_ARGISNULL(1))
        result = format_type_internal(type_oid, -1, false, true, false);
    else
    {
        typemod = PG_GETARG_INT32(1);
        result = format_type_internal(type_oid, typemod, true, true, false);
    }

    PG_RETURN_TEXT_P(cstring_to_text(result));
}

char* format_type_be ( Oid  type_oid  ) 

Definition at line 98 of file format_type.c.

References format_type_internal().

Referenced by aclcheck_error_type(), addFamilyMember(), addRangeTableEntryForFunction(), AggregateCreate(), AlterTypeNamespace(), AlterTypeNamespace_oid(), AlterTypeNamespaceInternal(), AlterTypeOwner(), appendTypeNameToBuffer(), array_cat(), array_cmp(), array_contain_compare(), array_eq(), array_recv(), array_replace_internal(), array_send(), ATAddForeignKeyConstraint(), ATExecAlterColumnType(), ATExecSetStorage(), ATPrepAlterColumnType(), build_column_default(), build_subplan(), check_object_ownership(), check_of_type(), check_sql_fn_retval(), CheckAttributeType(), checkDomainOwner(), checkEnumOwner(), coerce_record_to_complex(), coerce_to_boolean(), coerce_to_common_type(), coerce_to_specific_type(), coerce_type(), compare_values_of_enum(), compile_plperl_function(), compile_pltcl_function(), ComputeIndexAttrs(), convert_tuples_by_name(), cookDefault(), CreateCast(), CreateFunction(), DefineAggregate(), DefineDomain(), DefineRange(), DefineType(), do_compile(), does_not_exist_skipping(), domain_check_input(), domain_state_setup(), dropOperators(), dropProcedures(), enforce_generic_type_consistency(), enum_first(), enum_in(), enum_last(), enum_recv(), EvaluateParams(), exec_stmt_foreach_a(), ExecCheckPlanOutput(), ExecEvalArray(), ExecEvalCoerceToDomain(), ExecEvalFieldSelect(), ExecEvalParamExtern(), ExecEvalScalarVar(), ExecEvalWholeRowVar(), ExecInitExpr(), exprType(), fetch_cursor_param_value(), findRangeSubOpclass(), findTypeOutputFunction(), fmgr_sql_validator(), format_operator_internal(), format_procedure_internal(), funcname_signature_string(), get_cast_oid(), get_domain_constraint_oid(), get_range_io_data(), get_rels_with_domain(), get_sort_group_operators(), get_ts_parser_func(), get_ts_template_func(), GetColumnDefCollation(), GetDefaultOpClass(), GetIndexOpClass(), getObjectDescription(), getTypeBinaryInputInfo(), getTypeBinaryOutputInfo(), getTypeInputInfo(), getTypeOutputInfo(), hash_array(), hash_range(), init_sql_fcache(), internal_get_result_type(), intorel_startup(), load_enum_cache_data(), lookup_rowtype_tupdesc_internal(), LookupTypeName(), make_row_comparison_op(), make_scalar_array_op(), MergeAttributes(), op_signature_string(), ParseFuncOrColumn(), pg_collation_for(), plperl_array_to_datum(), plperl_sv_to_datum(), plperl_validator(), plpgsql_build_variable(), plpgsql_validator(), PLy_output_datum_func2(), PLy_procedure_create(), prepare_sql_fn_parse_info(), print_function_arguments(), print_function_rettype(), ProcedureCreate(), processIndirection(), record_cmp(), record_eq(), regtypeout(), RenameConstraintById(), RenameType(), resolve_generic_type(), ri_HashCompareOp(), select_common_type(), storeOperators(), storeProcedures(), transformAggregateCall(), transformArrayExpr(), transformArraySubscripts(), transformArrayType(), transformAssignedExpr(), transformAssignmentIndirection(), transformAssignmentSubscripts(), transformCollateClause(), transformColumnType(), transformTypeCast(), transformXmlSerialize(), tupledesc_match(), unknown_attribute(), validateConnectbyTupleDesc(), and variable_coerce_param_hook().

{
    return format_type_internal(type_oid, -1, false, false, false);
}

char* format_type_be_qualified ( Oid  type_oid  ) 

Definition at line 104 of file format_type.c.

References format_type_internal().

Referenced by format_operator_internal(), format_procedure_internal(), and getObjectIdentity().

{
    return format_type_internal(type_oid, -1, false, false, true);
}

static char * format_type_internal ( Oid  type_oid,
int32  typemod,
bool  typemod_given,
bool  allow_invalid,
bool  force_qualify 
) [static]

Definition at line 119 of file format_type.c.

References BITOID, BOOLOID, BPCHAROID, buf, elog, ERROR, FLOAT4OID, FLOAT8OID, get_namespace_name(), GETSTRUCT, HeapTupleIsValid, INT2OID, INT4OID, INT8OID, INTERVALOID, InvalidOid, NameStr, NULL, NUMERICOID, ObjectIdGetDatum, printTypmod(), psnprintf(), pstrdup(), quote_qualified_identifier(), ReleaseSysCache(), SearchSysCache1, TIMEOID, TIMESTAMPOID, TIMESTAMPTZOID, TIMETZOID, TypeIsVisible(), TYPEOID, VARBITOID, and VARCHAROID.

Referenced by format_type(), format_type_be(), format_type_be_qualified(), format_type_with_typemod(), and oidvectortypes().

{
    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 = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
    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 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')
    {
        /* Switch our attention to the array element type */
        ReleaseSysCache(tuple);
        tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(array_base_type));
        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 (!force_qualify && 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;
}

char* format_type_with_typemod ( Oid  type_oid,
int32  typemod 
)
Datum oidvectortypes ( PG_FUNCTION_ARGS   ) 

Definition at line 413 of file format_type.c.

References cstring_to_text(), oidvector::dim1, format_type_internal(), palloc(), PG_GETARG_POINTER, PG_RETURN_TEXT_P, repalloc(), and oidvector::values.

{
    oidvector  *oidArray = (oidvector *) PG_GETARG_POINTER(0);
    char       *result;
    int         numargs = oidArray->dim1;
    int         num;
    size_t      total;
    size_t      left;

    total = 20 * numargs + 1;
    result = palloc(total);
    result[0] = '\0';
    left = total - 1;

    for (num = 0; num < numargs; num++)
    {
        char       *typename = format_type_internal(oidArray->values[num], -1,
                                                    false, true, false);
        size_t      slen = strlen(typename);

        if (left < (slen + 2))
        {
            total += slen + 2;
            result = repalloc(result, total);
            left += slen + 2;
        }

        if (num > 0)
        {
            strcat(result, ", ");
            left -= 2;
        }
        strcat(result, typename);
        left -= slen;
    }

    PG_RETURN_TEXT_P(cstring_to_text(result));
}

static char * printTypmod ( const char *  typname,
int32  typmod,
Oid  typmodout 
) [static]

Definition at line 335 of file format_type.c.

References Assert, DatumGetCString, Int32GetDatum, InvalidOid, MAX_INT32_LEN, OidFunctionCall1, and psnprintf().

Referenced by format_type_internal().

{
    char       *res;

    /* Shouldn't be called if typmod is -1 */
    Assert(typmod >= 0);

    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);
    }
    else
    {
        /* Use the type-specific typmodout procedure */
        char       *tmstr;

        tmstr = DatumGetCString(OidFunctionCall1(typmodout,
                                                 Int32GetDatum(typmod)));
        res = psnprintf(strlen(typname) + strlen(tmstr) + 1, "%s%s",
                        typname, tmstr);
    }

    return res;
}

static char * psnprintf ( size_t  len,
const char *  fmt,
  ... 
) [static]

Definition at line 455 of file format_type.c.

References buf, palloc(), and vsnprintf().

Referenced by format_type_internal(), and printTypmod().

{
    va_list     ap;
    char       *buf;

    buf = palloc(len);

    va_start(ap, fmt);
    vsnprintf(buf, len, fmt, ap);
    va_end(ap);

    return buf;
}

int32 type_maximum_size ( Oid  type_oid,
int32  typemod 
)

Definition at line 378 of file format_type.c.

References BITOID, BITS_PER_BYTE, BPCHAROID, GetDatabaseEncoding(), numeric_maximum_size(), NUMERICOID, pg_encoding_max_length(), VARBITOID, VARCHAROID, and VARHDRSZ.

Referenced by get_typavgwidth(), and needs_toast_table().

{
    if (typemod < 0)
        return -1;

    switch (type_oid)
    {
        case BPCHAROID:
        case VARCHAROID:
            /* typemod includes varlena header */

            /* typemod is in characters not bytes */
            return (typemod - VARHDRSZ) *
                pg_encoding_max_length(GetDatabaseEncoding())
                + VARHDRSZ;

        case NUMERICOID:
            return numeric_maximum_size(typemod);

        case VARBITOID:
        case BITOID:
            /* typemod is the (max) number of bits */
            return (typemod + (BITS_PER_BYTE - 1)) / BITS_PER_BYTE
                + 2 * sizeof(int32);
    }

    /* Unknown type, or unlimited-width type such as 'text' */
    return -1;
}