Index: doc/src/sgml/ref/create_domain.sgml =================================================================== RCS file: /cvsroot/pgsql/doc/src/sgml/ref/create_domain.sgml,v retrieving revision 1.32 diff -u -3 -p -r1.32 create_domain.sgml --- doc/src/sgml/ref/create_domain.sgml 14 Nov 2008 10:22:46 -0000 1.32 +++ doc/src/sgml/ref/create_domain.sgml 25 Nov 2008 10:13:18 -0000 @@ -58,6 +58,12 @@ where con Define a domain rather than setting up each table's constraint individually. + + + Domains are similar to distinct types, described in , except that you can specify defaults or + constraints, and a domain can be implicitly cast to its base type. + Index: doc/src/sgml/ref/create_type.sgml =================================================================== RCS file: /cvsroot/pgsql/doc/src/sgml/ref/create_type.sgml,v retrieving revision 1.78 diff -u -3 -p -r1.78 create_type.sgml --- doc/src/sgml/ref/create_type.sgml 14 Nov 2008 10:22:46 -0000 1.78 +++ doc/src/sgml/ref/create_type.sgml 25 Nov 2008 10:13:18 -0000 @@ -27,6 +27,8 @@ CREATE TYPE name AS ENUM ( 'label' [, ... ] ) +CREATE TYPE name AS data_type + CREATE TYPE name ( INPUT = input_function, OUTPUT = output_function @@ -96,10 +98,25 @@ CREATE TYPE , except that they do not have + defaults or constraints, and they cannot be implicitly cast to + their base type. Distinct types are useful to avoid making + mistakes by comparing two unrelated values that happen to be the + same type, such as two integers representing supplier number and + part number. + + + + Base Types - The third form of CREATE TYPE creates a new base type + The fourth form of CREATE TYPE creates a new base type (scalar type). To create a new base type, you must be a superuser. (This restriction is made because an erroneous type definition could confuse or even crash the server.) Index: src/backend/commands/typecmds.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/commands/typecmds.c,v retrieving revision 1.126 diff -u -3 -p -r1.126 typecmds.c --- src/backend/commands/typecmds.c 2 Nov 2008 01:45:28 -0000 1.126 +++ src/backend/commands/typecmds.c 25 Nov 2008 10:13:18 -0000 @@ -648,7 +648,7 @@ RemoveTypeById(Oid typeOid) /* * DefineDomain - * Registers a new domain. + * Registers a new domain or distinct type. */ void DefineDomain(CreateDomainStmt *stmt) @@ -721,18 +721,27 @@ DefineDomain(CreateDomainStmt *stmt) basetypeoid = HeapTupleGetOid(typeTup); /* - * Base type must be a plain base type, another domain or an enum. Domains + * 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) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("\"%s\" is not a valid base type for a domain", - TypeNameToString(stmt->typename)))); + { + 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; @@ -938,7 +947,7 @@ DefineDomain(CreateDomainStmt *stmt) InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ internalLength, /* internal size */ - TYPTYPE_DOMAIN, /* type-type (domain type) */ + 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 */ Index: src/backend/executor/functions.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/executor/functions.c,v retrieving revision 1.128 diff -u -3 -p -r1.128 functions.c --- src/backend/executor/functions.c 31 Oct 2008 21:07:55 -0000 1.128 +++ src/backend/executor/functions.c 25 Nov 2008 10:13:18 -0000 @@ -1092,6 +1092,7 @@ check_sql_fn_retval(Oid func_id, Oid ret fn_typtype = get_typtype(rettype); if (fn_typtype == TYPTYPE_BASE || + fn_typtype == TYPTYPE_DISTINCT || fn_typtype == TYPTYPE_DOMAIN || fn_typtype == TYPTYPE_ENUM || rettype == VOIDOID) Index: src/backend/nodes/copyfuncs.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v retrieving revision 1.413 diff -u -3 -p -r1.413 copyfuncs.c --- src/backend/nodes/copyfuncs.c 24 Nov 2008 08:46:03 -0000 1.413 +++ src/backend/nodes/copyfuncs.c 25 Nov 2008 10:13:18 -0000 @@ -2659,6 +2659,7 @@ _copyCreateDomainStmt(CreateDomainStmt * COPY_NODE_FIELD(domainname); COPY_NODE_FIELD(typename); COPY_NODE_FIELD(constraints); + COPY_SCALAR_FIELD(distinct_type); return newnode; } Index: src/backend/nodes/equalfuncs.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v retrieving revision 1.338 diff -u -3 -p -r1.338 equalfuncs.c --- src/backend/nodes/equalfuncs.c 24 Nov 2008 08:46:03 -0000 1.338 +++ src/backend/nodes/equalfuncs.c 25 Nov 2008 10:13:18 -0000 @@ -1342,6 +1342,7 @@ _equalCreateDomainStmt(CreateDomainStmt COMPARE_NODE_FIELD(domainname); COMPARE_NODE_FIELD(typename); COMPARE_NODE_FIELD(constraints); + COMPARE_SCALAR_FIELD(distinct_type); return true; } Index: src/backend/parser/gram.y =================================================================== RCS file: /cvsroot/pgsql/src/backend/parser/gram.y,v retrieving revision 2.640 diff -u -3 -p -r2.640 gram.y --- src/backend/parser/gram.y 24 Nov 2008 08:46:03 -0000 2.640 +++ src/backend/parser/gram.y 25 Nov 2008 10:13:18 -0000 @@ -5623,6 +5623,16 @@ CreateDomainStmt: 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; } ; @@ -9477,7 +9487,6 @@ unreserved_keyword: | ENABLE_P | ENCODING | ENCRYPTED - | ENUM_P | ESCAPE | EXCLUDING | EXCLUSIVE @@ -9664,6 +9673,7 @@ col_name_keyword: | COALESCE | DEC | DECIMAL_P + | ENUM_P | EXISTS | EXTRACT | FLOAT_P Index: src/backend/parser/keywords.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/parser/keywords.c,v retrieving revision 1.205 diff -u -3 -p -r1.205 keywords.c --- src/backend/parser/keywords.c 27 Oct 2008 09:37:47 -0000 1.205 +++ src/backend/parser/keywords.c 25 Nov 2008 10:13:18 -0000 @@ -157,7 +157,7 @@ const ScanKeyword ScanKeywords[] = { {"encoding", ENCODING, UNRESERVED_KEYWORD}, {"encrypted", ENCRYPTED, UNRESERVED_KEYWORD}, {"end", END_P, RESERVED_KEYWORD}, - {"enum", ENUM_P, UNRESERVED_KEYWORD}, + {"enum", ENUM_P, COL_NAME_KEYWORD}, {"escape", ESCAPE, UNRESERVED_KEYWORD}, {"except", EXCEPT, RESERVED_KEYWORD}, {"excluding", EXCLUDING, UNRESERVED_KEYWORD}, Index: src/backend/parser/parse_coerce.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v retrieving revision 2.171 diff -u -3 -p -r2.171 parse_coerce.c --- src/backend/parser/parse_coerce.c 31 Oct 2008 08:39:21 -0000 2.171 +++ src/backend/parser/parse_coerce.c 25 Nov 2008 10:13:18 -0000 @@ -1867,15 +1867,25 @@ find_coercion_pathway(Oid targetTypeId, *funcid = InvalidOid; /* Perhaps the types are domains; if so, look at their base types */ - if (OidIsValid(sourceTypeId)) + if (OidIsValid(sourceTypeId) && get_typtype(sourceTypeId) == TYPTYPE_DOMAIN) sourceTypeId = getBaseType(sourceTypeId); - if (OidIsValid(targetTypeId)) + 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), @@ -2033,6 +2043,7 @@ find_typmod_coercion_function(Oid typeId /* 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 */ Index: src/backend/tcop/utility.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/tcop/utility.c,v retrieving revision 1.301 diff -u -3 -p -r1.301 utility.c --- src/backend/tcop/utility.c 7 Nov 2008 18:25:06 -0000 1.301 +++ src/backend/tcop/utility.c 25 Nov 2008 10:13:18 -0000 @@ -1291,7 +1291,11 @@ CreateCommandTag(Node *parsetree) break; case T_CreateDomainStmt: - tag = "CREATE DOMAIN"; + { + CreateDomainStmt *stmt = (CreateDomainStmt *) parsetree; + + tag = (stmt->distinct_type) ? "CREATE TYPE" : "CREATE DOMAIN"; + } break; case T_CreateSchemaStmt: Index: src/backend/utils/adt/format_type.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v retrieving revision 1.50 diff -u -3 -p -r1.50 format_type.c --- src/backend/utils/adt/format_type.c 25 Mar 2008 22:42:44 -0000 1.50 +++ src/backend/utils/adt/format_type.c 25 Nov 2008 10:13:18 -0000 @@ -147,6 +147,7 @@ format_type_internal(Oid type_oid, int32 if (array_base_type != InvalidOid && typeform->typstorage != 'p' && + typeform->typtype != TYPTYPE_DISTINCT && typeform->typtype != TYPTYPE_DOMAIN) { /* Switch our attention to the array element type */ Index: src/backend/utils/adt/xml.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/utils/adt/xml.c,v retrieving revision 1.81 diff -u -3 -p -r1.81 xml.c --- src/backend/utils/adt/xml.c 10 Nov 2008 18:02:20 -0000 1.81 +++ src/backend/utils/adt/xml.c 25 Nov 2008 10:13:18 -0000 @@ -2872,7 +2872,7 @@ map_sql_typecoll_to_xmlschema_types(List } } - /* add base types of domains */ + /* add base types of distinct types and domains */ foreach(cell0, uniquetypes) { Oid typid = lfirst_oid(cell0); @@ -3056,7 +3056,7 @@ map_sql_type_to_xmlschema_type(Oid typeo break; default: - if (get_typtype(typeoid) == TYPTYPE_DOMAIN) + if (get_typtype(typeoid) == TYPTYPE_DISTINCT || get_typtype(typeoid) == TYPTYPE_DOMAIN) { Oid base_typeoid; int32 base_typmod = -1; Index: src/backend/utils/cache/lsyscache.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v retrieving revision 1.160 diff -u -3 -p -r1.160 lsyscache.c --- src/backend/utils/cache/lsyscache.c 28 Sep 2008 19:51:40 -0000 1.160 +++ src/backend/utils/cache/lsyscache.c 25 Nov 2008 10:13:18 -0000 @@ -2032,7 +2032,7 @@ get_typdefault(Oid typid) /* * getBaseType - * If the given type is a domain, return its base type; + * If the given type is a distinct type or domain, return its base type; * otherwise return the type's own OID. */ Oid @@ -2045,7 +2045,7 @@ getBaseType(Oid typid) /* * getBaseTypeAndTypmod - * If the given type is a domain, return its base type and typmod; + * 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 @@ -2069,9 +2069,9 @@ getBaseTypeAndTypmod(Oid typid, int32 *t if (!HeapTupleIsValid(tup)) elog(ERROR, "cache lookup failed for type %u", typid); typTup = (Form_pg_type) GETSTRUCT(tup); - if (typTup->typtype != TYPTYPE_DOMAIN) + if (typTup->typtype != TYPTYPE_DISTINCT && typTup->typtype != TYPTYPE_DOMAIN) { - /* Not a domain, so done */ + /* Not a distinct type or domain, so done */ ReleaseSysCache(tup); break; } @@ -2087,6 +2087,30 @@ getBaseTypeAndTypmod(Oid typid, int32 *t } /* + * 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), Index: src/backend/utils/fmgr/funcapi.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/utils/fmgr/funcapi.c,v retrieving revision 1.42 diff -u -3 -p -r1.42 funcapi.c --- src/backend/utils/fmgr/funcapi.c 25 Aug 2008 22:42:34 -0000 1.42 +++ src/backend/utils/fmgr/funcapi.c 25 Nov 2008 10:13:18 -0000 @@ -643,6 +643,7 @@ get_type_func_class(Oid typid) case TYPTYPE_COMPOSITE: return TYPEFUNC_COMPOSITE; case TYPTYPE_BASE: + case TYPTYPE_DISTINCT: case TYPTYPE_DOMAIN: case TYPTYPE_ENUM: return TYPEFUNC_SCALAR; Index: src/bin/pg_dump/pg_dump.c =================================================================== RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v retrieving revision 1.505 diff -u -3 -p -r1.505 pg_dump.c --- src/bin/pg_dump/pg_dump.c 9 Nov 2008 21:24:32 -0000 1.505 +++ src/bin/pg_dump/pg_dump.c 25 Nov 2008 10:13:18 -0000 @@ -134,6 +134,7 @@ static void dumpNamespace(Archive *fout, 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); @@ -5755,6 +5756,8 @@ dumpType(Archive *fout, TypeInfo *tinfo) /* 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) @@ -6210,6 +6213,82 @@ dumpBaseType(Archive *fout, TypeInfo *ti } /* + * 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 */ Index: src/include/catalog/pg_type.h =================================================================== RCS file: /cvsroot/pgsql/src/include/catalog/pg_type.h,v retrieving revision 1.203 diff -u -3 -p -r1.203 pg_type.h --- src/include/catalog/pg_type.h 21 Nov 2008 18:49:24 -0000 1.203 +++ src/include/catalog/pg_type.h 25 Nov 2008 10:13:18 -0000 @@ -60,7 +60,7 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP /* * 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' + * 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. @@ -632,6 +632,7 @@ DATA(insert OID = 3500 ( anyenum PGNSP #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 */ Index: src/include/nodes/parsenodes.h =================================================================== RCS file: /cvsroot/pgsql/src/include/nodes/parsenodes.h,v retrieving revision 1.379 diff -u -3 -p -r1.379 parsenodes.h --- src/include/nodes/parsenodes.h 24 Nov 2008 08:46:04 -0000 1.379 +++ src/include/nodes/parsenodes.h 25 Nov 2008 10:13:18 -0000 @@ -1461,6 +1461,7 @@ typedef struct CreateDomainStmt 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; /* ---------------------- Index: src/include/utils/lsyscache.h =================================================================== RCS file: /cvsroot/pgsql/src/include/utils/lsyscache.h,v retrieving revision 1.126 diff -u -3 -p -r1.126 lsyscache.h --- src/include/utils/lsyscache.h 28 Sep 2008 19:51:40 -0000 1.126 +++ src/include/utils/lsyscache.h 25 Nov 2008 10:13:18 -0000 @@ -123,6 +123,7 @@ extern void getTypeBinaryOutputInfo(Oid 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, Index: src/interfaces/ecpg/preproc/parse.pl =================================================================== RCS file: /cvsroot/pgsql/src/interfaces/ecpg/preproc/parse.pl,v retrieving revision 1.1 diff -u -3 -p -r1.1 parse.pl --- src/interfaces/ecpg/preproc/parse.pl 14 Nov 2008 10:01:04 -0000 1.1 +++ src/interfaces/ecpg/preproc/parse.pl 25 Nov 2008 10:13:18 -0000 @@ -60,6 +60,7 @@ $replace_types{'Sconst'} = 'ignore'; $replace_line{'fetch_direction'} = 'ignore'; $replace_line{"opt_array_boundsopt_array_bounds'['Iconst']'"} = 'ignore'; $replace_line{'col_name_keywordCHAR_P'} = 'ignore'; +$replace_line{'col_name_keywordENUM_P'} = 'ignore'; $replace_line{'col_name_keywordINT_P'} = 'ignore'; $replace_line{'col_name_keywordVALUES'} = 'ignore'; $replace_line{'reserved_keywordTO'} = 'ignore'; Index: src/pl/plpgsql/src/pl_comp.c =================================================================== RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v retrieving revision 1.132 diff -u -3 -p -r1.132 pl_comp.c --- src/pl/plpgsql/src/pl_comp.c 5 Nov 2008 00:07:53 -0000 1.132 +++ src/pl/plpgsql/src/pl_comp.c 25 Nov 2008 10:13:19 -0000 @@ -1725,6 +1725,7 @@ build_datatype(HeapTuple typeTup, int32 switch (typeStruct->typtype) { case TYPTYPE_BASE: + case TYPTYPE_DISTINCT: case TYPTYPE_DOMAIN: case TYPTYPE_ENUM: typ->ttype = PLPGSQL_TTYPE_SCALAR;