Re: Distinct types

From: Bruce Momjian <bruce(at)momjian(dot)us>
To: Peter Eisentraut <Peter(dot)Eisentraut(at)Sun(dot)COM>
Cc: PG Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Distinct types
Date: 2009-01-08 20:48:25
Message-ID: 200901082048.n08KmPd26951@momjian.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers


Added to TODO:

Allow the creation of "distinct" types

* http://archives.postgresql.org/pgsql-hackers/2008-10/msg01647.php

---------------------------------------------------------------------------

Peter Eisentraut wrote:
> Here is an implementation of distinct types, known from SQL99 and
> beyond. They are like domains, except that they don't have defaults or
> constraints and they do not allow implicit casting to their base type.
> The latter aspect is what makes them distinct types. They are useful to
> create more type-safe database schemas, to prevent using generic types
> such as text or int for everything and then mixing them in inappropriate
> ways. This is something domains are not useful for. Much of the
> internals are shared with domains nevertheless. The difference is
> really only the casting behavior.
>
> To create a distinct type, just run
>
> CREATE TYPE mystring AS text;

> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/backend/commands/typecmds.c ./src/backend/commands/typecmds.c
> *** ../cvs-pgsql/src/backend/commands/typecmds.c 2008-10-21 13:52:23.000000000 +0300
> --- ./src/backend/commands/typecmds.c 2008-10-31 13:50:50.000000000 +0200
> *************** RemoveTypeById(Oid typeOid)
> *** 648,654 ****
>
> /*
> * DefineDomain
> ! * Registers a new domain.
> */
> void
> DefineDomain(CreateDomainStmt *stmt)
> --- 648,654 ----
>
> /*
> * DefineDomain
> ! * Registers a new domain or distinct type.
> */
> void
> DefineDomain(CreateDomainStmt *stmt)
> *************** DefineDomain(CreateDomainStmt *stmt)
> *** 721,738 ****
> basetypeoid = HeapTupleGetOid(typeTup);
>
> /*
> ! * Base type must be a plain base type, another domain or an enum. Domains
> * over pseudotypes would create a security hole. Domains over composite
> * types might be made to work in the future, but not today.
> */
> typtype = baseType->typtype;
> if (typtype != TYPTYPE_BASE &&
> typtype != TYPTYPE_DOMAIN &&
> typtype != TYPTYPE_ENUM)
> ! ereport(ERROR,
> ! (errcode(ERRCODE_DATATYPE_MISMATCH),
> ! errmsg("\"%s\" is not a valid base type for a domain",
> ! TypeNameToString(stmt->typename))));
>
> /* passed by value */
> byValue = baseType->typbyval;
> --- 721,747 ----
> basetypeoid = HeapTupleGetOid(typeTup);
>
> /*
> ! * Base type must be a plain base type, another domain, distinct type, or an enum. Domains
> * over pseudotypes would create a security hole. Domains over composite
> * types might be made to work in the future, but not today.
> */
> typtype = baseType->typtype;
> if (typtype != TYPTYPE_BASE &&
> typtype != TYPTYPE_DOMAIN &&
> + typtype != TYPTYPE_DISTINCT &&
> typtype != TYPTYPE_ENUM)
> ! {
> ! if (stmt->distinct_type)
> ! ereport(ERROR,
> ! (errcode(ERRCODE_DATATYPE_MISMATCH),
> ! errmsg("\"%s\" is not a valid base type for a distinct type",
> ! TypeNameToString(stmt->typename))));
> ! else
> ! ereport(ERROR,
> ! (errcode(ERRCODE_DATATYPE_MISMATCH),
> ! errmsg("\"%s\" is not a valid base type for a domain",
> ! TypeNameToString(stmt->typename))));
> ! }
>
> /* passed by value */
> byValue = baseType->typbyval;
> *************** DefineDomain(CreateDomainStmt *stmt)
> *** 938,944 ****
> InvalidOid, /* relation oid (n/a here) */
> 0, /* relation kind (ditto) */
> internalLength, /* internal size */
> ! TYPTYPE_DOMAIN, /* type-type (domain type) */
> category, /* type-category */
> false, /* domain types are never preferred */
> delimiter, /* array element delimiter */
> --- 947,953 ----
> InvalidOid, /* relation oid (n/a here) */
> 0, /* relation kind (ditto) */
> internalLength, /* internal size */
> ! stmt->distinct_type ? TYPTYPE_DISTINCT : TYPTYPE_DOMAIN, /* type-type (distinct type or domain) */
> category, /* type-category */
> false, /* domain types are never preferred */
> delimiter, /* array element delimiter */
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/backend/executor/functions.c ./src/backend/executor/functions.c
> *** ../cvs-pgsql/src/backend/executor/functions.c 2008-08-26 01:42:32.000000000 +0300
> --- ./src/backend/executor/functions.c 2008-10-30 14:46:05.000000000 +0200
> *************** check_sql_fn_retval(Oid func_id, Oid ret
> *** 924,929 ****
> --- 924,930 ----
> fn_typtype = get_typtype(rettype);
>
> if (fn_typtype == TYPTYPE_BASE ||
> + fn_typtype == TYPTYPE_DISTINCT ||
> fn_typtype == TYPTYPE_DOMAIN ||
> fn_typtype == TYPTYPE_ENUM ||
> rettype == VOIDOID)
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/backend/nodes/copyfuncs.c ./src/backend/nodes/copyfuncs.c
> *** ../cvs-pgsql/src/backend/nodes/copyfuncs.c 2008-10-22 14:35:44.000000000 +0300
> --- ./src/backend/nodes/copyfuncs.c 2008-10-30 14:46:05.000000000 +0200
> *************** _copyCreateDomainStmt(CreateDomainStmt *
> *** 2657,2662 ****
> --- 2657,2663 ----
> COPY_NODE_FIELD(domainname);
> COPY_NODE_FIELD(typename);
> COPY_NODE_FIELD(constraints);
> + COPY_SCALAR_FIELD(distinct_type);
>
> return newnode;
> }
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/backend/nodes/equalfuncs.c ./src/backend/nodes/equalfuncs.c
> *** ../cvs-pgsql/src/backend/nodes/equalfuncs.c 2008-10-22 14:35:44.000000000 +0300
> --- ./src/backend/nodes/equalfuncs.c 2008-10-30 14:46:05.000000000 +0200
> *************** _equalCreateDomainStmt(CreateDomainStmt
> *** 1342,1347 ****
> --- 1342,1348 ----
> COMPARE_NODE_FIELD(domainname);
> COMPARE_NODE_FIELD(typename);
> COMPARE_NODE_FIELD(constraints);
> + COMPARE_SCALAR_FIELD(distinct_type);
>
> return true;
> }
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/backend/parser/gram.y ./src/backend/parser/gram.y
> *** ../cvs-pgsql/src/backend/parser/gram.y 2008-10-29 13:37:47.000000000 +0200
> --- ./src/backend/parser/gram.y 2008-10-30 14:46:05.000000000 +0200
> *************** CreateDomainStmt:
> *** 5608,5613 ****
> --- 5608,5623 ----
> n->domainname = $3;
> n->typename = $5;
> n->constraints = $6;
> + n->distinct_type = FALSE;
> + $$ = (Node *)n;
> + }
> + | CREATE TYPE_P any_name AS Typename
> + {
> + CreateDomainStmt *n = makeNode(CreateDomainStmt);
> + n->domainname = $3;
> + n->typename = $5;
> + n->constraints = NIL;
> + n->distinct_type = TRUE;
> $$ = (Node *)n;
> }
> ;
> *************** unreserved_keyword:
> *** 9439,9445 ****
> | ENABLE_P
> | ENCODING
> | ENCRYPTED
> - | ENUM_P
> | ESCAPE
> | EXCLUDING
> | EXCLUSIVE
> --- 9449,9454 ----
> *************** col_name_keyword:
> *** 9626,9631 ****
> --- 9635,9641 ----
> | COALESCE
> | DEC
> | DECIMAL_P
> + | ENUM_P
> | EXISTS
> | EXTRACT
> | FLOAT_P
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/backend/parser/keywords.c ./src/backend/parser/keywords.c
> *** ../cvs-pgsql/src/backend/parser/keywords.c 2008-10-28 14:31:25.000000000 +0200
> --- ./src/backend/parser/keywords.c 2008-10-30 14:46:05.000000000 +0200
> *************** const ScanKeyword ScanKeywords[] = {
> *** 157,163 ****
> {"encoding", ENCODING, UNRESERVED_KEYWORD},
> {"encrypted", ENCRYPTED, UNRESERVED_KEYWORD},
> {"end", END_P, RESERVED_KEYWORD},
> ! {"enum", ENUM_P, UNRESERVED_KEYWORD},
> {"escape", ESCAPE, UNRESERVED_KEYWORD},
> {"except", EXCEPT, RESERVED_KEYWORD},
> {"excluding", EXCLUDING, UNRESERVED_KEYWORD},
> --- 157,163 ----
> {"encoding", ENCODING, UNRESERVED_KEYWORD},
> {"encrypted", ENCRYPTED, UNRESERVED_KEYWORD},
> {"end", END_P, RESERVED_KEYWORD},
> ! {"enum", ENUM_P, COL_NAME_KEYWORD},
> {"escape", ESCAPE, UNRESERVED_KEYWORD},
> {"except", EXCEPT, RESERVED_KEYWORD},
> {"excluding", EXCLUDING, UNRESERVED_KEYWORD},
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/backend/parser/parse_coerce.c ./src/backend/parser/parse_coerce.c
> *** ../cvs-pgsql/src/backend/parser/parse_coerce.c 2008-10-27 10:14:16.000000000 +0200
> --- ./src/backend/parser/parse_coerce.c 2008-10-31 13:52:30.000000000 +0200
> *************** find_coercion_pathway(Oid targetTypeId,
> *** 1867,1881 ****
> *funcid = InvalidOid;
>
> /* Perhaps the types are domains; if so, look at their base types */
> ! if (OidIsValid(sourceTypeId))
> sourceTypeId = getBaseType(sourceTypeId);
> ! if (OidIsValid(targetTypeId))
> targetTypeId = getBaseType(targetTypeId);
>
> /* Domains are always coercible to and from their base type */
> if (sourceTypeId == targetTypeId)
> return COERCION_PATH_RELABELTYPE;
>
> /* Look in pg_cast */
> tuple = SearchSysCache(CASTSOURCETARGET,
> ObjectIdGetDatum(sourceTypeId),
> --- 1867,1891 ----
> *funcid = InvalidOid;
>
> /* Perhaps the types are domains; if so, look at their base types */
> ! if (OidIsValid(sourceTypeId) && get_typtype(sourceTypeId) == TYPTYPE_DOMAIN)
> sourceTypeId = getBaseType(sourceTypeId);
> ! if (OidIsValid(targetTypeId) && get_typtype(targetTypeId) == TYPTYPE_DOMAIN)
> targetTypeId = getBaseType(targetTypeId);
>
> /* Domains are always coercible to and from their base type */
> if (sourceTypeId == targetTypeId)
> return COERCION_PATH_RELABELTYPE;
>
> + /* Distinct types are castable AS ASSIGNMENT to and from their base types */
> + if (ccontext >= COERCION_ASSIGNMENT
> + && ((OidIsValid(sourceTypeId)
> + && get_typtype(sourceTypeId) == TYPTYPE_DISTINCT
> + && getDirectBaseType(sourceTypeId) == targetTypeId)
> + || (OidIsValid(targetTypeId)
> + && get_typtype(targetTypeId) == TYPTYPE_DISTINCT
> + && getDirectBaseType(targetTypeId) == sourceTypeId)))
> + return COERCION_PATH_RELABELTYPE;
> +
> /* Look in pg_cast */
> tuple = SearchSysCache(CASTSOURCETARGET,
> ObjectIdGetDatum(sourceTypeId),
> *************** find_typmod_coercion_function(Oid typeId
> *** 2021,2026 ****
> --- 2031,2037 ----
> /* Check for a varlena array type (and not a domain) */
> if (typeForm->typelem != InvalidOid &&
> typeForm->typlen == -1 &&
> + typeForm->typtype != TYPTYPE_DISTINCT &&
> typeForm->typtype != TYPTYPE_DOMAIN)
> {
> /* Yes, switch our attention to the element type */
> Only in ./src/backend/parser: parse_coerce.c.~2.170.~
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/backend/utils/adt/format_type.c ./src/backend/utils/adt/format_type.c
> *** ../cvs-pgsql/src/backend/utils/adt/format_type.c 2008-03-26 00:42:44.000000000 +0200
> --- ./src/backend/utils/adt/format_type.c 2008-10-30 15:30:09.000000000 +0200
> *************** format_type_internal(Oid type_oid, int32
> *** 147,152 ****
> --- 147,153 ----
>
> if (array_base_type != InvalidOid &&
> typeform->typstorage != 'p' &&
> + typeform->typtype != TYPTYPE_DISTINCT &&
> typeform->typtype != TYPTYPE_DOMAIN)
> {
> /* Switch our attention to the array element type */
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/backend/utils/adt/xml.c ./src/backend/utils/adt/xml.c
> *** ../cvs-pgsql/src/backend/utils/adt/xml.c 2008-10-29 11:32:17.000000000 +0200
> --- ./src/backend/utils/adt/xml.c 2008-10-30 14:46:05.000000000 +0200
> *************** map_sql_typecoll_to_xmlschema_types(List
> *** 2861,2867 ****
> }
> }
>
> ! /* add base types of domains */
> foreach(cell0, uniquetypes)
> {
> Oid typid = lfirst_oid(cell0);
> --- 2861,2867 ----
> }
> }
>
> ! /* add base types of distinct types and domains */
> foreach(cell0, uniquetypes)
> {
> Oid typid = lfirst_oid(cell0);
> *************** map_sql_type_to_xmlschema_type(Oid typeo
> *** 3045,3051 ****
> break;
>
> default:
> ! if (get_typtype(typeoid) == TYPTYPE_DOMAIN)
> {
> Oid base_typeoid;
> int32 base_typmod = -1;
> --- 3045,3051 ----
> break;
>
> default:
> ! if (get_typtype(typeoid) == TYPTYPE_DISTINCT || get_typtype(typeoid) == TYPTYPE_DOMAIN)
> {
> Oid base_typeoid;
> int32 base_typmod = -1;
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/backend/utils/cache/lsyscache.c ./src/backend/utils/cache/lsyscache.c
> *** ../cvs-pgsql/src/backend/utils/cache/lsyscache.c 2008-10-02 10:50:16.000000000 +0300
> --- ./src/backend/utils/cache/lsyscache.c 2008-10-31 12:21:48.000000000 +0200
> *************** get_typdefault(Oid typid)
> *** 2032,2038 ****
>
> /*
> * getBaseType
> ! * If the given type is a domain, return its base type;
> * otherwise return the type's own OID.
> */
> Oid
> --- 2032,2038 ----
>
> /*
> * getBaseType
> ! * If the given type is a distinct type or domain, return its base type;
> * otherwise return the type's own OID.
> */
> Oid
> *************** getBaseType(Oid typid)
> *** 2045,2051 ****
>
> /*
> * getBaseTypeAndTypmod
> ! * If the given type is a domain, return its base type and typmod;
> * otherwise return the type's own OID, and leave *typmod unchanged.
> *
> * Note that the "applied typmod" should be -1 for every domain level
> --- 2045,2051 ----
>
> /*
> * getBaseTypeAndTypmod
> ! * If the given type is a distinct type or domain, return its base type and typmod;
> * otherwise return the type's own OID, and leave *typmod unchanged.
> *
> * Note that the "applied typmod" should be -1 for every domain level
> *************** getBaseTypeAndTypmod(Oid typid, int32 *t
> *** 2069,2077 ****
> if (!HeapTupleIsValid(tup))
> elog(ERROR, "cache lookup failed for type %u", typid);
> typTup = (Form_pg_type) GETSTRUCT(tup);
> ! if (typTup->typtype != TYPTYPE_DOMAIN)
> {
> ! /* Not a domain, so done */
> ReleaseSysCache(tup);
> break;
> }
> --- 2069,2077 ----
> if (!HeapTupleIsValid(tup))
> elog(ERROR, "cache lookup failed for type %u", typid);
> typTup = (Form_pg_type) GETSTRUCT(tup);
> ! if (typTup->typtype != TYPTYPE_DISTINCT && typTup->typtype != TYPTYPE_DOMAIN)
> {
> ! /* Not a distinct type or domain, so done */
> ReleaseSysCache(tup);
> break;
> }
> *************** getBaseTypeAndTypmod(Oid typid, int32 *t
> *** 2087,2092 ****
> --- 2087,2116 ----
> }
>
> /*
> + * getDirectBaseType
> + * If the given type is a distinct type or domain, return its direct base type;
> + * otherwise return the type's own OID.
> + */
> + Oid
> + getDirectBaseType(Oid typid)
> + {
> + HeapTuple tup;
> + Form_pg_type typTup;
> +
> + tup = SearchSysCache(TYPEOID,
> + ObjectIdGetDatum(typid),
> + 0, 0, 0);
> + if (!HeapTupleIsValid(tup))
> + elog(ERROR, "cache lookup failed for type %u", typid);
> + typTup = (Form_pg_type) GETSTRUCT(tup);
> + if (typTup->typtype == TYPTYPE_DISTINCT || typTup->typtype == TYPTYPE_DOMAIN)
> + typid = typTup->typbasetype;
> +
> + ReleaseSysCache(tup);
> + return typid;
> + }
> +
> + /*
> * get_typavgwidth
> *
> * Given a type OID and a typmod value (pass -1 if typmod is unknown),
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/backend/utils/fmgr/funcapi.c ./src/backend/utils/fmgr/funcapi.c
> *** ../cvs-pgsql/src/backend/utils/fmgr/funcapi.c 2008-08-26 01:42:34.000000000 +0300
> --- ./src/backend/utils/fmgr/funcapi.c 2008-10-30 15:28:47.000000000 +0200
> *************** get_type_func_class(Oid typid)
> *** 643,648 ****
> --- 643,649 ----
> case TYPTYPE_COMPOSITE:
> return TYPEFUNC_COMPOSITE;
> case TYPTYPE_BASE:
> + case TYPTYPE_DISTINCT:
> case TYPTYPE_DOMAIN:
> case TYPTYPE_ENUM:
> return TYPEFUNC_SCALAR;
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/bin/pg_dump/pg_dump.c ./src/bin/pg_dump/pg_dump.c
> *** ../cvs-pgsql/src/bin/pg_dump/pg_dump.c 2008-10-02 10:50:16.000000000 +0300
> --- ./src/bin/pg_dump/pg_dump.c 2008-10-30 17:01:25.000000000 +0200
> *************** static void dumpNamespace(Archive *fout,
> *** 133,138 ****
> --- 133,139 ----
> static void dumpType(Archive *fout, TypeInfo *tinfo);
> static void dumpBaseType(Archive *fout, TypeInfo *tinfo);
> static void dumpEnumType(Archive *fout, TypeInfo *tinfo);
> + static void dumpDistinctType(Archive *fout, TypeInfo *tinfo);
> static void dumpDomain(Archive *fout, TypeInfo *tinfo);
> static void dumpCompositeType(Archive *fout, TypeInfo *tinfo);
> static void dumpShellType(Archive *fout, ShellTypeInfo *stinfo);
> *************** dumpType(Archive *fout, TypeInfo *tinfo)
> *** 5719,5724 ****
> --- 5720,5727 ----
> /* Dump out in proper style */
> if (tinfo->typtype == TYPTYPE_BASE)
> dumpBaseType(fout, tinfo);
> + else if (tinfo->typtype == TYPTYPE_DISTINCT)
> + dumpDistinctType(fout, tinfo);
> else if (tinfo->typtype == TYPTYPE_DOMAIN)
> dumpDomain(fout, tinfo);
> else if (tinfo->typtype == TYPTYPE_COMPOSITE)
> *************** dumpBaseType(Archive *fout, TypeInfo *ti
> *** 6174,6179 ****
> --- 6177,6258 ----
> }
>
> /*
> + * dumpDistinctType
> + * writes out to fout the queries to recreate a user-defined distinct type
> + */
> + static void
> + dumpDistinctType(Archive *fout, TypeInfo *tinfo)
> + {
> + PQExpBuffer q = createPQExpBuffer();
> + PQExpBuffer delq = createPQExpBuffer();
> + PQExpBuffer query = createPQExpBuffer();
> + PGresult *res;
> + int ntups;
> + char *typdefn;
> +
> + /* Set proper schema search path so type references list correctly */
> + selectSourceSchema(tinfo->dobj.namespace->dobj.name);
> +
> + /* Fetch type specific details */
> + appendPQExpBuffer(query, "SELECT pg_catalog.format_type(typbasetype, typtypmod) as typdefn "
> + "FROM pg_catalog.pg_type "
> + "WHERE oid = '%u'::pg_catalog.oid",
> + tinfo->dobj.catId.oid);
> +
> + res = PQexec(g_conn, query->data);
> + check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
> +
> + /* Expecting a single result only */
> + ntups = PQntuples(res);
> + if (ntups != 1)
> + {
> + write_msg(NULL, "query returned %d rows instead of one: %s\n",
> + ntups, query->data);
> + exit_nicely();
> + }
> +
> + typdefn = PQgetvalue(res, 0, PQfnumber(res, "typdefn"));
> +
> + appendPQExpBuffer(q,
> + "CREATE TYPE %s AS %s",
> + fmtId(tinfo->dobj.name),
> + typdefn);
> +
> + PQclear(res);
> +
> + appendPQExpBuffer(q, ";\n");
> +
> + /*
> + * DROP must be fully qualified in case same name appears in pg_catalog
> + */
> + appendPQExpBuffer(delq, "DROP TYPE %s.",
> + fmtId(tinfo->dobj.namespace->dobj.name));
> + appendPQExpBuffer(delq, "%s;\n",
> + fmtId(tinfo->dobj.name));
> +
> + ArchiveEntry(fout, tinfo->dobj.catId, tinfo->dobj.dumpId,
> + tinfo->dobj.name,
> + tinfo->dobj.namespace->dobj.name,
> + NULL,
> + tinfo->rolname, false,
> + "TYPE", q->data, delq->data, NULL,
> + tinfo->dobj.dependencies, tinfo->dobj.nDeps,
> + NULL, NULL);
> +
> + /* Dump Type Comments */
> + resetPQExpBuffer(q);
> +
> + appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo->dobj.name));
> + dumpComment(fout, q->data,
> + tinfo->dobj.namespace->dobj.name, tinfo->rolname,
> + tinfo->dobj.catId, 0, tinfo->dobj.dumpId);
> +
> + destroyPQExpBuffer(q);
> + destroyPQExpBuffer(delq);
> + destroyPQExpBuffer(query);
> + }
> +
> + /*
> * dumpDomain
> * writes out to fout the queries to recreate a user-defined domain
> */
> Only in ./src/bin/pg_dump: pg_dump.c.~1.502.~
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/include/catalog/pg_type.h ./src/include/catalog/pg_type.h
> *** ../cvs-pgsql/src/include/catalog/pg_type.h 2008-10-15 14:19:43.000000000 +0300
> --- ./src/include/catalog/pg_type.h 2008-10-30 14:46:05.000000000 +0200
> *************** CATALOG(pg_type,1247) BKI_BOOTSTRAP
> *** 60,66 ****
>
> /*
> * typtype is 'b' for a base type, 'c' for a composite type (e.g., a
> ! * table's rowtype), 'd' for a domain type, 'e' for an enum type, or 'p'
> * for a pseudo-type. (Use the TYPTYPE macros below.)
> *
> * If typtype is 'c', typrelid is the OID of the class' entry in pg_class.
> --- 60,66 ----
>
> /*
> * typtype is 'b' for a base type, 'c' for a composite type (e.g., a
> ! * table's rowtype), 'd' for a domain type, 'D' for a distinct type, 'e' for an enum type, or 'p'
> * for a pseudo-type. (Use the TYPTYPE macros below.)
> *
> * If typtype is 'c', typrelid is the OID of the class' entry in pg_class.
> *************** DATA(insert OID = 3500 ( anyenum PGNSP
> *** 631,636 ****
> --- 631,637 ----
> #define TYPTYPE_BASE 'b' /* base type (ordinary scalar type) */
> #define TYPTYPE_COMPOSITE 'c' /* composite (e.g., table's rowtype) */
> #define TYPTYPE_DOMAIN 'd' /* domain over another type */
> + #define TYPTYPE_DISTINCT 'D' /* distinct type based on another type */
> #define TYPTYPE_ENUM 'e' /* enumerated type */
> #define TYPTYPE_PSEUDO 'p' /* pseudo-type */
>
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/include/nodes/parsenodes.h ./src/include/nodes/parsenodes.h
> *** ../cvs-pgsql/src/include/nodes/parsenodes.h 2008-10-15 14:19:43.000000000 +0300
> --- ./src/include/nodes/parsenodes.h 2008-10-30 14:46:05.000000000 +0200
> *************** typedef struct CreateDomainStmt
> *** 1452,1457 ****
> --- 1452,1458 ----
> List *domainname; /* qualified name (list of Value strings) */
> TypeName *typename; /* the base type */
> List *constraints; /* constraints (list of Constraint nodes) */
> + bool distinct_type; /* create distinct type rather than domain */
> } CreateDomainStmt;
>
> /* ----------------------
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/include/utils/lsyscache.h ./src/include/utils/lsyscache.h
> *** ../cvs-pgsql/src/include/utils/lsyscache.h 2008-10-02 10:50:17.000000000 +0300
> --- ./src/include/utils/lsyscache.h 2008-10-31 12:21:50.000000000 +0200
> *************** extern void getTypeBinaryOutputInfo(Oid
> *** 123,128 ****
> --- 123,129 ----
> extern Oid get_typmodin(Oid typid);
> extern Oid getBaseType(Oid typid);
> extern Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod);
> + extern Oid getDirectBaseType(Oid typid);
> extern int32 get_typavgwidth(Oid typid, int32 typmod);
> extern int32 get_attavgwidth(Oid relid, AttrNumber attnum);
> extern bool get_attstatsslot(HeapTuple statstuple,
> Only in ./src/include/utils: lsyscache.h.~1.126.~
> diff -x CVS -x TAGS -prc ../cvs-pgsql/src/pl/plpgsql/src/pl_comp.c ./src/pl/plpgsql/src/pl_comp.c
> *** ../cvs-pgsql/src/pl/plpgsql/src/pl_comp.c 2008-10-15 14:19:44.000000000 +0300
> --- ./src/pl/plpgsql/src/pl_comp.c 2008-10-30 15:19:33.000000000 +0200
> *************** build_datatype(HeapTuple typeTup, int32
> *** 1725,1730 ****
> --- 1725,1731 ----
> switch (typeStruct->typtype)
> {
> case TYPTYPE_BASE:
> + case TYPTYPE_DISTINCT:
> case TYPTYPE_DOMAIN:
> case TYPTYPE_ENUM:
> typ->ttype = PLPGSQL_TTYPE_SCALAR;

>
> --
> Sent via pgsql-hackers mailing list (pgsql-hackers(at)postgresql(dot)org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-hackers

--
Bruce Momjian <bruce(at)momjian(dot)us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Bruce Momjian 2009-01-08 20:48:59 Re: [WIP] Reduce alignment requirements on 64-bit systems.
Previous Message Heikki Linnakangas 2009-01-08 20:44:00 Re: Hot standby, slot ids and stuff