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;