Re: Distinct types - Mailing list pgsql-hackers
From | Bruce Momjian |
---|---|
Subject | Re: Distinct types |
Date | |
Msg-id | 200901082048.n08KmPd26951@momjian.us Whole thread Raw |
In response to | Distinct types (Peter Eisentraut <Peter.Eisentraut@Sun.COM>) |
List | 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@postgresql.org) > To make changes to your subscription: > http://www.postgresql.org/mailpref/pgsql-hackers -- Bruce Momjian <bruce@momjian.us> http://momjian.us EnterpriseDB http://enterprisedb.com + If your life is a hard drive, Christ can be your backup. +
pgsql-hackers by date: