? GNUmakefile ? config.cache ? config.log ? config.status ? src/GNUmakefile ? src/Makefile.global ? src/backend/postgres.def ? src/backend/catalog/postgres.bki ? src/backend/catalog/postgres.description ? src/backend/port/Makefile ? src/bin/initdb/initdb ? src/bin/initlocation/initlocation ? src/bin/ipcclean/ipcclean ? src/bin/pg_config/pg_config ? src/bin/pg_ctl/pg_ctl ? src/bin/pg_dump/pg_dumpall ? src/bin/scripts/createlang ? src/include/pg_config.h ? src/include/stamp-h ? src/interfaces/ecpg/lib/ecpg.def ? src/interfaces/ecpg/lib/ecpg.dll ? src/interfaces/libpgeasy/pgeasy.def ? src/interfaces/libpgeasy/pgeasy.dll ? src/interfaces/libpq/pq.def ? src/interfaces/libpq/pq.dll ? src/pl/plpgsql/src/plpgsql.def ? src/pl/plpgsql/src/plpgsql.dll Index: src/backend/commands/define.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/define.c,v retrieving revision 1.64 diff -u -r1.64 define.c --- src/backend/commands/define.c 2001/10/28 06:25:42 1.64 +++ src/backend/commands/define.c 2002/02/16 22:42:24 @@ -526,6 +526,150 @@ } /* + * DefineDomain + * Registers a new domain. + */ +void +DefineDomain(CreateDomainStmt *stmt) +{ + int16 internalLength = -1; /* int2 */ + int16 externalLength = -1; /* int2 */ + char *inputName = NULL; + char *outputName = NULL; + char *sendName = NULL; + char *receiveName = NULL; + char *defaultValue = NULL; + bool byValue = false; + char delimiter = DEFAULT_TYPDELIM; + char alignment = 'i'; /* default alignment */ + char storage = 'p'; /* default TOAST storage method */ + char typtype; + Datum datum; + + bool isnull; + Relation pg_type_rel; + TupleDesc pg_type_dsc; + HeapTuple typeTup; + + /* + * Domainnames, unlike typenames don't need to account for the '_' + * prefix. So they can be one character longer. + */ + if (strlen(stmt->domainname) > (NAMEDATALEN - 1)) + elog(ERROR, "CREATE DOMAIN: domain names must be %d characters or less", + NAMEDATALEN - 1); + + + /* Test for existing Domain (or type) of that name */ + typeTup = SearchSysCache( TYPENAME + , PointerGetDatum(stmt->domainname) + , 0, 0, 0 + ); + if (HeapTupleIsValid(typeTup)) + { + elog(ERROR, "CREATE DOMAIN: domain or type %s already exists", + stmt->domainname); + } + + + /* + * Get the information about old types + */ + pg_type_rel = heap_openr(TypeRelationName, RowExclusiveLock); + pg_type_dsc = RelationGetDescr(pg_type_rel); + + typeTup = SearchSysCache( TYPENAME + , PointerGetDatum(stmt->typename) + , 0, 0, 0 + ); + if (!HeapTupleIsValid(typeTup)) + { + elog(ERROR, "CREATE DOMAIN: type %s does not exist", + stmt->typename); + } + + /* Check that this is a basetype */ + typtype = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typtype, pg_type_dsc, &isnull)); + Assert(!isnull); + + if (typtype != 'b') { + elog(ERROR, "%s is not a basetype", stmt->typename); + } + + elog(DEBUG, "NOTE: Extracting information"); + /* Extract useful data */ + byValue = DatumGetBool(heap_getattr(typeTup, Anum_pg_type_typbyval, pg_type_dsc, &isnull)); + Assert(!isnull); + + alignment = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typalign, pg_type_dsc, &isnull)); + Assert(!isnull); + + internalLength = DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typlen, pg_type_dsc, &isnull)); + Assert(!isnull); + + externalLength = DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typprtlen, pg_type_dsc, &isnull)); + Assert(!isnull); + + delimiter = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typdelim, pg_type_dsc, &isnull)); + Assert(!isnull); + + + datum = heap_getattr(typeTup, Anum_pg_type_typinput, pg_type_dsc, &isnull); + Assert(!isnull); + + inputName = DatumGetCString(DirectFunctionCall1(regprocout, datum)); + + + datum = heap_getattr(typeTup, Anum_pg_type_typoutput, pg_type_dsc, &isnull); + Assert(!isnull); + + outputName = DatumGetCString(DirectFunctionCall1(regprocout, datum)); + + +/* Not used + receiveName = DatumGetPointer(heap_getattr(typeTup, Anum_pg_type_typreceive, pg_type_dsc, &isnull)); + Assert(!isnull); + + sendName = DatumGetPointer(heap_getattr(typeTup, Anum_pg_type_typsend, pg_type_dsc, &isnull)); + Assert(!isnull); +*/ + + storage = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typstorage, pg_type_dsc, &isnull)); + Assert(!isnull); + + + datum = heap_getattr(typeTup, Anum_pg_type_typdefault, pg_type_dsc, &isnull); + if (!isnull) { + defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum)); + } + + /* + * now have TypeCreate do all the real work. + */ + TypeCreate(stmt->domainname, /* type name */ + InvalidOid, /* preassigned type oid (not done here) */ + InvalidOid, /* relation oid (n/a here) */ + internalLength, /* internal size */ + externalLength, /* external size */ + 'd', /* type-type (domain type) */ + delimiter, /* array element delimiter */ + inputName, /* input procedure */ + outputName, /* output procedure */ + receiveName, /* receive procedure */ + sendName, /* send procedure */ + stmt->typename, /* element type name */ + defaultValue, /* default type value */ + byValue, /* passed by value */ + alignment, /* required alignment */ + storage); /* TOAST strategy */ + + /* + * Now we can clean up. + */ + heap_close(pg_type_rel, NoLock); +} + +/* * DefineType * Registers a new type. */ Index: src/backend/commands/remove.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/remove.c,v retrieving revision 1.65 diff -u -r1.65 remove.c --- src/backend/commands/remove.c 2001/11/05 17:46:24 1.65 +++ src/backend/commands/remove.c 2002/02/16 22:42:24 @@ -1,7 +1,7 @@ /*------------------------------------------------------------------------- * * remove.c - * POSTGRES remove (function | type | operator ) utilty code. + * POSTGRES remove (function | domain | type | operator ) utilty code. * * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California @@ -22,6 +22,7 @@ #include "commands/comment.h" #include "commands/defrem.h" #include "miscadmin.h" +#include "parser/parse.h" #include "parser/parse_agg.h" #include "parser/parse_expr.h" #include "parser/parse_func.h" @@ -274,6 +275,62 @@ heap_close(relation, RowExclusiveLock); } + + +/* + * RemoveDomain + * Removes the domain 'typeName' and all attributes and relations that + * use it. + */ +void +RemoveDomain(char *domainName, int behavior) /* domain name to be removed */ +{ + Relation relation; + HeapTuple tup; + TupleDesc description; + char typtype; + bool isnull; + + + /* Domains are stored as types. Check for permissions on the type */ + if (!pg_ownercheck(GetUserId(), domainName, TYPENAME)) + elog(ERROR, "RemoveDomain: type '%s': permission denied", + domainName); + + + relation = heap_openr(TypeRelationName, RowExclusiveLock); + description = RelationGetDescr(relation); + + tup = SearchSysCache(TYPENAME, + PointerGetDatum(domainName), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + elog(ERROR, "RemoveType: type '%s' does not exist", domainName); + + + /* Check that this is actually a domain */ + typtype = DatumGetChar(heap_getattr(tup, Anum_pg_type_typtype, description, &isnull)); + Assert(!isnull); + + if (typtype != 'd') { + elog(ERROR, "%s is not a domain", domainName); + } + + /* CASCADE unsupported */ + if (behavior == CASCADE) { + elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword"); + } + + /* Delete any comments associated with this type */ + DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation)); + + simple_heap_delete(relation, &tup->t_self); + + ReleaseSysCache(tup); + + heap_close(relation, RowExclusiveLock); +} + /* * RemoveFunction Index: src/backend/nodes/copyfuncs.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v retrieving revision 1.160 diff -u -r1.160 copyfuncs.c --- src/backend/nodes/copyfuncs.c 2001/11/05 05:00:14 1.160 +++ src/backend/nodes/copyfuncs.c 2002/02/16 22:42:25 @@ -2210,6 +2210,19 @@ return newnode; } +static CreateDomainStmt * +_copyCreateDomainStmt(CreateDomainStmt *from) +{ + CreateDomainStmt *newnode = makeNode(CreateDomainStmt); + + if (from->domainname) + newnode->domainname = pstrdup(from->domainname); + if (from->typename) + newnode->typename = pstrdup(from->typename); + + return newnode; +} + static CreatedbStmt * _copyCreatedbStmt(CreatedbStmt *from) { Index: src/backend/nodes/equalfuncs.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v retrieving revision 1.108 diff -u -r1.108 equalfuncs.c --- src/backend/nodes/equalfuncs.c 2001/11/05 05:00:14 1.108 +++ src/backend/nodes/equalfuncs.c 2002/02/16 22:42:27 @@ -1086,6 +1086,17 @@ } static bool +_equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b) +{ + if (!equalstr(a->domainname, b->domainname)) + return false; + if (!equalstr(a->typename, b->typename)) + return false; + + return true; +} + +static bool _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b) { if (!equalstr(a->dbname, b->dbname)) @@ -1973,6 +1984,12 @@ case T_LoadStmt: retval = _equalLoadStmt(a, b); break; + case T_CreateDomainStmt: + retval = _equalCreateDomainStmt(a, b); + break; +/* case T_DropDomainStmt: + retval = _equalDropdbStmt(a, b); + break;*/ case T_CreatedbStmt: retval = _equalCreatedbStmt(a, b); break; Index: src/backend/parser/gram.y =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v retrieving revision 2.276 diff -u -r2.276 gram.y --- src/backend/parser/gram.y 2001/12/09 04:39:39 2.276 +++ src/backend/parser/gram.y 2002/02/16 22:42:52 @@ -135,7 +135,8 @@ ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt, CopyStmt, CreateAsStmt, CreateGroupStmt, CreatePLangStmt, CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt, - CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt, + CreateUserStmt, CreateDomainStmt, CreatedbStmt, CursorStmt, + DefineStmt, DeleteStmt, DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt, DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt, GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt, @@ -284,6 +285,8 @@ %type constraints_set_namelist %type constraints_set_mode +%type opt_as + /* * If you make any token changes, remember to: * - use "yacc -d" and update parse.h @@ -338,7 +341,7 @@ WITHOUT /* Keywords (in SQL92 non-reserved words) */ -%token COMMITTED, SERIALIZABLE, TYPE_P +%token COMMITTED, SERIALIZABLE, TYPE_P, DOMAIN_P /* Keywords for Postgres support (not in SQL92 reserved words) * @@ -439,6 +442,7 @@ | CopyStmt | CreateStmt | CreateAsStmt + | CreateDomainStmt | CreateSchemaStmt | CreateGroupStmt | CreateSeqStmt @@ -748,8 +752,11 @@ n->dbname = $3; $$ = (Node *)n; } + ; + + /***************************************************************************** * * Set PG internal variable @@ -2039,6 +2046,15 @@ DropStmt *n = makeNode(DropStmt); n->removeType = $2; n->names = $3; + n->behavior = NULL; + $$ = (Node *)n; + } + | DROP DOMAIN_P name_list drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = DROP_DOMAIN_P; + n->names = $3; + n->behavior = $4; $$ = (Node *)n; } ; @@ -2071,7 +2087,7 @@ * The COMMENT ON statement can take different forms based upon the type of * the object associated with the comment. The form of the statement is: * - * COMMENT ON [ [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] + * COMMENT ON [ [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] * | AGGREGATE () | FUNCTION * (arg1, arg2, ...) | OPERATOR * (leftoperand_typ rightoperand_typ) | TRIGGER ON @@ -2157,6 +2173,7 @@ | RULE { $$ = RULE; } | SEQUENCE { $$ = SEQUENCE; } | TABLE { $$ = TABLE; } + | DOMAIN_P { $$ = TYPE_P; } | TYPE_P { $$ = TYPE_P; } | VIEW { $$ = VIEW; } ; @@ -3129,6 +3146,25 @@ } ; +/***************************************************************************** + * + * Manipulate a domain + * + * + *****************************************************************************/ + +CreateDomainStmt: CREATE DOMAIN_P opt_as name name + { + CreateDomainStmt *n = makeNode(CreateDomainStmt); + n->domainname = $4; + n->typename = $5; + $$ = (Node *)n; + } + ; + +opt_as: AS {$$ = TRUE; } + | /* EMPTY */ {$$ = FALSE; } + ; /***************************************************************************** * @@ -5772,6 +5808,7 @@ | DEFERRED { $$ = "deferred"; } | DELETE { $$ = "delete"; } | DELIMITERS { $$ = "delimiters"; } + | DOMAIN_P { $$ = "domain"; } | DOUBLE { $$ = "double"; } | DROP { $$ = "drop"; } | EACH { $$ = "each"; } Index: src/backend/parser/keywords.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/parser/keywords.c,v retrieving revision 1.99 diff -u -r1.99 keywords.c --- src/backend/parser/keywords.c 2001/10/10 00:02:42 1.99 +++ src/backend/parser/keywords.c 2002/02/16 22:42:52 @@ -97,6 +97,7 @@ {"desc", DESC}, {"distinct", DISTINCT}, {"do", DO}, + {"domain", DOMAIN_P}, {"double", DOUBLE}, {"drop", DROP}, {"each", EACH}, Index: src/backend/tcop/utility.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/tcop/utility.c,v retrieving revision 1.125 diff -u -r1.125 utility.c --- src/backend/tcop/utility.c 2002/02/07 00:27:30 1.125 +++ src/backend/tcop/utility.c 2002/02/16 22:42:53 @@ -280,6 +280,11 @@ /* RemoveType does its own permissions checks */ RemoveType(relname); break; + + case DROP_DOMAIN_P: + /* RemoveDomain does its own permissions checks */ + RemoveDomain(relname, stmt->behavior); + break; } /* @@ -796,6 +801,16 @@ set_ps_display(commandTag = "DROP"); DropProceduralLanguage((DropPLangStmt *) parsetree); + break; + + /* + * ******************************** DOMAIN statements **** + * + */ + case T_CreateDomainStmt: + set_ps_display(commandTag = "CREATE DOMAIN"); + + DefineDomain((CreateDomainStmt *) parsetree); break; /* Index: src/include/commands/defrem.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/commands/defrem.h,v retrieving revision 1.28 diff -u -r1.28 defrem.h --- src/include/commands/defrem.h 2001/11/05 17:46:33 1.28 +++ src/include/commands/defrem.h 2002/02/16 22:42:54 @@ -39,10 +39,12 @@ extern void DefineOperator(char *name, List *parameters); extern void DefineAggregate(char *name, List *parameters); extern void DefineType(char *name, List *parameters); +extern void DefineDomain(CreateDomainStmt *stmt); /* * prototypes in remove.c */ +extern void RemoveDomain(char *domainName, int behavior); extern void RemoveFunction(char *functionName, List *argTypes); extern void RemoveOperator(char *operatorName, char *typeName1, char *typeName2); Index: src/include/nodes/nodes.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/nodes/nodes.h,v retrieving revision 1.96 diff -u -r1.96 nodes.h --- src/include/nodes/nodes.h 2001/11/05 17:46:34 1.96 +++ src/include/nodes/nodes.h 2002/02/16 22:42:54 @@ -172,6 +172,7 @@ T_TransactionStmt, T_ViewStmt, T_LoadStmt, + T_CreateDomainStmt, T_CreatedbStmt, T_DropdbStmt, T_VacuumStmt, Index: src/include/nodes/parsenodes.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/nodes/parsenodes.h,v retrieving revision 1.151 diff -u -r1.151 parsenodes.h --- src/include/nodes/parsenodes.h 2001/11/05 17:46:34 1.151 +++ src/include/nodes/parsenodes.h 2002/02/16 22:43:11 @@ -439,12 +439,14 @@ #define DROP_INDEX 4 #define DROP_RULE 5 #define DROP_TYPE_P 6 +#define DROP_DOMAIN_P 7 typedef struct DropStmt { NodeTag type; List *names; int removeType; + int behavior; /* CASCADE or RESTRICT drop behavior */ } DropStmt; /* ---------------------- @@ -652,6 +654,17 @@ NodeTag type; char *filename; /* file to load */ } LoadStmt; + +/* ---------------------- + * CreateDomain Statement + * ---------------------- + */ +typedef struct CreateDomainStmt +{ + NodeTag type; + char *domainname; /* name of domain to create */ + char *typename; /* name of the type to base it off */ +} CreateDomainStmt; /* ---------------------- * Createdb Statement