Header And Logo

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

Defines | Typedefs | Functions

parse_type.h File Reference

#include "access/htup.h"
#include "parser/parse_node.h"
Include dependency graph for parse_type.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define ISCOMPLEX(typeid)   (typeidTypeRelid(typeid) != InvalidOid)

Typedefs

typedef HeapTuple Type

Functions

Type LookupTypeName (ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
Type typenameType (ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
Oid typenameTypeId (ParseState *pstate, const TypeName *typeName)
void typenameTypeIdAndMod (ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
char * TypeNameToString (const TypeName *typeName)
char * TypeNameListToString (List *typenames)
Oid LookupCollation (ParseState *pstate, List *collnames, int location)
Oid GetColumnDefCollation (ParseState *pstate, ColumnDef *coldef, Oid typeOid)
Type typeidType (Oid id)
Oid typeTypeId (Type tp)
int16 typeLen (Type t)
bool typeByVal (Type t)
char * typeTypeName (Type t)
Oid typeTypeRelid (Type typ)
Oid typeTypeCollation (Type typ)
Datum stringTypeDatum (Type tp, char *string, int32 atttypmod)
Oid typeidTypeRelid (Oid type_id)
void parseTypeString (const char *str, Oid *typeid_p, int32 *typmod_p)

Define Documentation

#define ISCOMPLEX (   typeid  )     (typeidTypeRelid(typeid) != InvalidOid)

Typedef Documentation

typedef HeapTuple Type

Definition at line 20 of file parse_type.h.


Function Documentation

Oid GetColumnDefCollation ( ParseState pstate,
ColumnDef coldef,
Oid  typeOid 
)

Definition at line 471 of file parse_type.c.

References ColumnDef::collClause, CollateClause::collname, ColumnDef::collOid, ereport, errcode(), errmsg(), ERROR, format_type_be(), get_typcollation(), CollateClause::location, LookupCollation(), OidIsValid, and parser_errposition().

Referenced by addRangeTableEntryForFunction(), ATExecAddColumn(), ATExecAlterColumnType(), ATPrepAlterColumnType(), BuildDescForRelation(), and MergeAttributes().

{
    Oid         result;
    Oid         typcollation = get_typcollation(typeOid);
    int         location = -1;

    if (coldef->collClause)
    {
        /* We have a raw COLLATE clause, so look up the collation */
        location = coldef->collClause->location;
        result = LookupCollation(pstate, coldef->collClause->collname,
                                 location);
    }
    else if (OidIsValid(coldef->collOid))
    {
        /* Precooked collation spec, use that */
        result = coldef->collOid;
    }
    else
    {
        /* Use the type's default collation if any */
        result = typcollation;
    }

    /* Complain if COLLATE is applied to an uncollatable type */
    if (OidIsValid(result) && !OidIsValid(typcollation))
        ereport(ERROR,
                (errcode(ERRCODE_DATATYPE_MISMATCH),
                 errmsg("collations are not supported by type %s",
                        format_type_be(typeOid)),
                 parser_errposition(pstate, location)));

    return result;
}

Oid LookupCollation ( ParseState pstate,
List collnames,
int  location 
)

Definition at line 446 of file parse_type.c.

References cancel_parser_errposition_callback(), get_collation_oid(), and setup_parser_errposition_callback().

Referenced by GetColumnDefCollation(), transformCollateClause(), and transformColumnType().

{
    Oid         colloid;
    ParseCallbackState pcbstate;

    if (pstate)
        setup_parser_errposition_callback(&pcbstate, pstate, location);

    colloid = get_collation_oid(collnames, false);

    if (pstate)
        cancel_parser_errposition_callback(&pcbstate);

    return colloid;
}

Type LookupTypeName ( ParseState pstate,
const TypeName typeName,
int32 typmod_p 
)

Definition at line 58 of file parse_type.c.

References TypeName::arrayBounds, Assert, RangeVar::catalogname, DeconstructQualifiedName(), elog, ereport, errcode(), errmsg(), ERROR, format_type_be(), get_array_type(), get_attnum(), get_atttype(), GetSysCacheOid2, HeapTupleIsValid, InvalidAttrNumber, lfourth, linitial, list_length(), TypeName::location, LookupExplicitNamespace(), lsecond, lthird, makeRangeVar(), NameListToString(), TypeName::names, NIL, NoLock, NOTICE, NULL, ObjectIdGetDatum, OidIsValid, parser_errposition(), TypeName::pct_type, PointerGetDatum, RangeVarGetRelid, RangeVar::relname, RangeVar::schemaname, SearchSysCache1, strVal, TypenameGetTypid(), TYPENAMENSP, TypeNameToString(), typenameTypeMod(), TYPEOID, and TypeName::typeOid.

Referenced by AlterTypeOwner(), compute_return_type(), examine_parameter_list(), FuncNameAsType(), get_object_address_type(), LookupTypeNameOid(), plpgsql_parse_wordtype(), and typenameType().

{
    Oid         typoid;
    HeapTuple   tup;
    int32       typmod;

    if (typeName->names == NIL)
    {
        /* We have the OID already if it's an internally generated TypeName */
        typoid = typeName->typeOid;
    }
    else if (typeName->pct_type)
    {
        /* Handle %TYPE reference to type of an existing field */
        RangeVar   *rel = makeRangeVar(NULL, NULL, typeName->location);
        char       *field = NULL;
        Oid         relid;
        AttrNumber  attnum;

        /* deconstruct the name list */
        switch (list_length(typeName->names))
        {
            case 1:
                ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                errmsg("improper %%TYPE reference (too few dotted names): %s",
                       NameListToString(typeName->names)),
                         parser_errposition(pstate, typeName->location)));
                break;
            case 2:
                rel->relname = strVal(linitial(typeName->names));
                field = strVal(lsecond(typeName->names));
                break;
            case 3:
                rel->schemaname = strVal(linitial(typeName->names));
                rel->relname = strVal(lsecond(typeName->names));
                field = strVal(lthird(typeName->names));
                break;
            case 4:
                rel->catalogname = strVal(linitial(typeName->names));
                rel->schemaname = strVal(lsecond(typeName->names));
                rel->relname = strVal(lthird(typeName->names));
                field = strVal(lfourth(typeName->names));
                break;
            default:
                ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("improper %%TYPE reference (too many dotted names): %s",
                                NameListToString(typeName->names)),
                         parser_errposition(pstate, typeName->location)));
                break;
        }

        /*
         * Look up the field.
         *
         * XXX: As no lock is taken here, this might fail in the presence of
         * concurrent DDL.  But taking a lock would carry a performance
         * penalty and would also require a permissions check.
         */
        relid = RangeVarGetRelid(rel, NoLock, false);
        attnum = get_attnum(relid, field);
        if (attnum == InvalidAttrNumber)
            ereport(ERROR,
                    (errcode(ERRCODE_UNDEFINED_COLUMN),
                     errmsg("column \"%s\" of relation \"%s\" does not exist",
                            field, rel->relname),
                     parser_errposition(pstate, typeName->location)));
        typoid = get_atttype(relid, attnum);

        /* this construct should never have an array indicator */
        Assert(typeName->arrayBounds == NIL);

        /* emit nuisance notice (intentionally not errposition'd) */
        ereport(NOTICE,
                (errmsg("type reference %s converted to %s",
                        TypeNameToString(typeName),
                        format_type_be(typoid))));
    }
    else
    {
        /* Normal reference to a type name */
        char       *schemaname;
        char       *typname;

        /* deconstruct the name list */
        DeconstructQualifiedName(typeName->names, &schemaname, &typname);

        if (schemaname)
        {
            /* Look in specific schema only */
            Oid         namespaceId;

            namespaceId = LookupExplicitNamespace(schemaname, false);
            typoid = GetSysCacheOid2(TYPENAMENSP,
                                     PointerGetDatum(typname),
                                     ObjectIdGetDatum(namespaceId));
        }
        else
        {
            /* Unqualified type name, so search the search path */
            typoid = TypenameGetTypid(typname);
        }

        /* If an array reference, return the array type instead */
        if (typeName->arrayBounds != NIL)
            typoid = get_array_type(typoid);
    }

    if (!OidIsValid(typoid))
    {
        if (typmod_p)
            *typmod_p = -1;
        return NULL;
    }

    tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid));
    if (!HeapTupleIsValid(tup)) /* should not happen */
        elog(ERROR, "cache lookup failed for type %u", typoid);

    typmod = typenameTypeMod(pstate, typeName, (Type) tup);

    if (typmod_p)
        *typmod_p = typmod;

    return (Type) tup;
}

void parseTypeString ( const char *  str,
Oid typeid_p,
int32 typmod_p 
)

Definition at line 664 of file parse_type.c.

References appendStringInfo(), TypeCast::arg, ErrorContextCallback::arg, buf, ErrorContextCallback::callback, StringInfoData::data, SelectStmt::distinctClause, ereport, errcode(), errmsg(), ERROR, error_context_stack, SelectStmt::fromClause, SelectStmt::groupClause, SelectStmt::havingClause, ResTarget::indirection, initStringInfo(), SelectStmt::intoClause, IsA, SelectStmt::limitCount, SelectStmt::limitOffset, linitial, list_length(), SelectStmt::lockingClause, ResTarget::name, NIL, NULL, SelectStmt::op, pfree(), ErrorContextCallback::previous, raw_parser(), TypeName::setof, SelectStmt::sortClause, SelectStmt::targetList, TypeCast::typeName, typenameTypeIdAndMod(), ResTarget::val, SelectStmt::valuesLists, SelectStmt::whereClause, SelectStmt::windowClause, and SelectStmt::withClause.

Referenced by parseNameAndArgTypes(), plperl_spi_prepare(), pltcl_SPI_prepare(), PLy_spi_prepare(), and regtypein().

{
    StringInfoData buf;
    List       *raw_parsetree_list;
    SelectStmt *stmt;
    ResTarget  *restarget;
    TypeCast   *typecast;
    TypeName   *typeName;
    ErrorContextCallback ptserrcontext;

    /* make sure we give useful error for empty input */
    if (strspn(str, " \t\n\r\f") == strlen(str))
        goto fail;

    initStringInfo(&buf);
    appendStringInfo(&buf, "SELECT NULL::%s", str);

    /*
     * Setup error traceback support in case of ereport() during parse
     */
    ptserrcontext.callback = pts_error_callback;
    ptserrcontext.arg = (void *) str;
    ptserrcontext.previous = error_context_stack;
    error_context_stack = &ptserrcontext;

    raw_parsetree_list = raw_parser(buf.data);

    error_context_stack = ptserrcontext.previous;

    /*
     * Make sure we got back exactly what we expected and no more; paranoia is
     * justified since the string might contain anything.
     */
    if (list_length(raw_parsetree_list) != 1)
        goto fail;
    stmt = (SelectStmt *) linitial(raw_parsetree_list);
    if (stmt == NULL ||
        !IsA(stmt, SelectStmt) ||
        stmt->distinctClause != NIL ||
        stmt->intoClause != NULL ||
        stmt->fromClause != NIL ||
        stmt->whereClause != NULL ||
        stmt->groupClause != NIL ||
        stmt->havingClause != NULL ||
        stmt->windowClause != NIL ||
        stmt->valuesLists != NIL ||
        stmt->sortClause != NIL ||
        stmt->limitOffset != NULL ||
        stmt->limitCount != NULL ||
        stmt->lockingClause != NIL ||
        stmt->withClause != NULL ||
        stmt->op != SETOP_NONE)
        goto fail;
    if (list_length(stmt->targetList) != 1)
        goto fail;
    restarget = (ResTarget *) linitial(stmt->targetList);
    if (restarget == NULL ||
        !IsA(restarget, ResTarget) ||
        restarget->name != NULL ||
        restarget->indirection != NIL)
        goto fail;
    typecast = (TypeCast *) restarget->val;
    if (typecast == NULL ||
        !IsA(typecast, TypeCast) ||
        typecast->arg == NULL ||
        !IsA(typecast->arg, A_Const))
        goto fail;
    typeName = typecast->typeName;
    if (typeName == NULL ||
        !IsA(typeName, TypeName))
        goto fail;
    if (typeName->setof)
        goto fail;

    typenameTypeIdAndMod(NULL, typeName, typeid_p, typmod_p);

    pfree(buf.data);

    return;

fail:
    ereport(ERROR,
            (errcode(ERRCODE_SYNTAX_ERROR),
             errmsg("invalid type name \"%s\"", str)));
}

Datum stringTypeDatum ( Type  tp,
char *  string,
int32  atttypmod 
)

Definition at line 585 of file parse_type.c.

References datumIsEqual(), elog, GETSTRUCT, getTypeIOParam(), NameStr, OidInputFunctionCall(), and WARNING.

Referenced by coerce_type().

{
    Form_pg_type typform = (Form_pg_type) GETSTRUCT(tp);
    Oid         typinput = typform->typinput;
    Oid         typioparam = getTypeIOParam(tp);
    Datum       result;

    result = OidInputFunctionCall(typinput, string,
                                  typioparam, atttypmod);

#ifdef RANDOMIZE_ALLOCATED_MEMORY

    /*
     * For pass-by-reference data types, repeat the conversion to see if the
     * input function leaves any uninitialized bytes in the result.  We can
     * only detect that reliably if RANDOMIZE_ALLOCATED_MEMORY is enabled, so
     * we don't bother testing otherwise.  The reason we don't want any
     * instability in the input function is that comparison of Const nodes
     * relies on bytewise comparison of the datums, so if the input function
     * leaves garbage then subexpressions that should be identical may not get
     * recognized as such.  See pgsql-hackers discussion of 2008-04-04.
     */
    if (string && !typform->typbyval)
    {
        Datum       result2;

        result2 = OidInputFunctionCall(typinput, string,
                                       typioparam, atttypmod);
        if (!datumIsEqual(result, result2, typform->typbyval, typform->typlen))
            elog(WARNING, "type %s has unstable input conversion for \"%s\"",
                 NameStr(typform->typname), string);
    }
#endif

    return result;
}

bool typeByVal ( Type  t  ) 

Definition at line 540 of file parse_type.c.

References GETSTRUCT.

Referenced by coerce_type().

{
    Form_pg_type typ;

    typ = (Form_pg_type) GETSTRUCT(t);
    return typ->typbyval;
}

Type typeidType ( Oid  id  ) 

Definition at line 509 of file parse_type.c.

References elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum, SearchSysCache1, and TYPEOID.

Referenced by coerce_type(), and find_typmod_coercion_function().

{
    HeapTuple   tup;

    tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(id));
    if (!HeapTupleIsValid(tup))
        elog(ERROR, "cache lookup failed for type %u", id);
    return (Type) tup;
}

Oid typeidTypeRelid ( Oid  type_id  ) 

Definition at line 624 of file parse_type.c.

References elog, ERROR, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and TYPEOID.

Referenced by get_rte_attribute_is_dropped(), PLy_input_tuple_funcs(), PLy_output_tuple_funcs(), ProcedureCreate(), transformAssignmentIndirection(), typeInheritsFrom(), and typeIsOfTypedTable().

{
    HeapTuple   typeTuple;
    Form_pg_type type;
    Oid         result;

    typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
    if (!HeapTupleIsValid(typeTuple))
        elog(ERROR, "cache lookup failed for type %u", type_id);

    type = (Form_pg_type) GETSTRUCT(typeTuple);
    result = type->typrelid;
    ReleaseSysCache(typeTuple);
    return result;
}

int16 typeLen ( Type  t  ) 

Definition at line 530 of file parse_type.c.

References GETSTRUCT.

Referenced by coerce_type().

{
    Form_pg_type typ;

    typ = (Form_pg_type) GETSTRUCT(t);
    return typ->typlen;
}

char* TypeNameListToString ( List typenames  ) 

Definition at line 422 of file parse_type.c.

References appendStringInfoChar(), appendTypeNameToBuffer(), Assert, initStringInfo(), IsA, lfirst, and list_head().

Referenced by does_not_exist_skipping().

{
    StringInfoData string;
    ListCell   *l;

    initStringInfo(&string);
    foreach(l, typenames)
    {
        TypeName   *typeName = (TypeName *) lfirst(l);

        Assert(IsA(typeName, TypeName));
        if (l != list_head(typenames))
            appendStringInfoChar(&string, ',');
        appendTypeNameToBuffer(typeName, &string);
    }
    return string.data;
}

char* TypeNameToString ( const TypeName typeName  ) 
Type typenameType ( ParseState pstate,
const TypeName typeName,
int32 typmod_p 
)

Definition at line 195 of file parse_type.c.

References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, TypeName::location, LookupTypeName(), NULL, parser_errposition(), and TypeNameToString().

Referenced by ATExecAddColumn(), ATExecAddOf(), ATExecAlterColumnType(), DefineDomain(), DefineType(), transformColumnType(), transformOfType(), typenameTypeId(), and typenameTypeIdAndMod().

{
    Type        tup;

    tup = LookupTypeName(pstate, typeName, typmod_p);
    if (tup == NULL)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("type \"%s\" does not exist",
                        TypeNameToString(typeName)),
                 parser_errposition(pstate, typeName->location)));
    if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_OBJECT),
                 errmsg("type \"%s\" is only a shell",
                        TypeNameToString(typeName)),
                 parser_errposition(pstate, typeName->location)));
    return tup;
}

Oid typenameTypeId ( ParseState pstate,
const TypeName typeName 
)
void typenameTypeIdAndMod ( ParseState pstate,
const TypeName typeName,
Oid typeid_p,
int32 typmod_p 
)
Oid typeTypeCollation ( Type  typ  ) 

Definition at line 571 of file parse_type.c.

References GETSTRUCT.

Referenced by coerce_type().

{
    Form_pg_type typtup;

    typtup = (Form_pg_type) GETSTRUCT(typ);
    return typtup->typcollation;
}

Oid typeTypeId ( Type  tp  ) 

Definition at line 521 of file parse_type.c.

References elog, ERROR, HeapTupleGetOid, and NULL.

Referenced by AlterTypeOwner(), compute_return_type(), examine_parameter_list(), FuncNameAsType(), get_object_address_type(), and LookupTypeNameOid().

{
    if (tp == NULL)             /* probably useless */
        elog(ERROR, "typeTypeId() called with NULL type struct");
    return HeapTupleGetOid(tp);
}

char* typeTypeName ( Type  t  ) 

Definition at line 550 of file parse_type.c.

References GETSTRUCT, NameStr, and pstrdup().

{
    Form_pg_type typ;

    typ = (Form_pg_type) GETSTRUCT(t);
    /* pstrdup here because result may need to outlive the syscache entry */
    return pstrdup(NameStr(typ->typname));
}

Oid typeTypeRelid ( Type  typ  ) 

Definition at line 561 of file parse_type.c.

References GETSTRUCT.

Referenced by FuncNameAsType().

{
    Form_pg_type typtup;

    typtup = (Form_pg_type) GETSTRUCT(typ);
    return typtup->typrelid;
}