diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml index 9a06b19d4e..9a873a5616 100644 --- a/doc/src/sgml/ref/allfiles.sgml +++ b/doc/src/sgml/ref/allfiles.sgml @@ -1,5 +1,5 @@ @@ -38,7 +38,6 @@ Complete list of usable sgml source files in this directory. - diff --git a/doc/src/sgml/ref/alter_domain.sgml b/doc/src/sgml/ref/alter_domain.sgml deleted file mode 100644 index 8c26e01706..0000000000 --- a/doc/src/sgml/ref/alter_domain.sgml +++ /dev/null @@ -1,237 +0,0 @@ - - - - - ALTER DOMAIN - SQL - Language Statements - - - - ALTER DOMAIN - - - change the definition of a table - - - - - 2002-11-27 - - -ALTER DOMAIN domain - { SET DEFAULT value | DROP DEFAULT } -ALTER DOMAIN domain - { SET | DROP } NOT NULL -ALTER DOMAIN domain - ADD domain_constraint -ALTER DOMAIN domain - DROP CONSTRAINT constraint_name [ RESTRICT | CASCADE ] - - - - - 2002-11-27 - - - Inputs - - - - - - domain - - - The name (possibly schema-qualified) of an existing domain to - alter. - - - - - - domain_constraint - - - New domain constraint for the domain. - - - - - - constraint_name - - - Name of an existing constraint to drop. - - - - - - CASCADE - - - Automatically drop objects that depend constraint. - - - - - - RESTRICT - - - Refuse to drop the constraint if there are any dependent - objects. This is the default behavior. - - - - - - - - - - - 1998-04-15 - - - Outputs - - - - - - ALTER DOMAIN - - - Message returned from domain alteration. - - - - - - ERROR - - - Message returned if domain is not available. - - - - - - - - - - - 2002-11-27 - - - Description - - - ALTER DOMAIN changes the definition of an existing domain. - There are several sub-forms: - - - - - SET/DROP DEFAULT - - - These forms set or remove the default value for a column. Note - that defaults only apply to subsequent INSERT - commands; they do not cause rows already in a table using the domain. - - - - - - SET/DROP NOT NULL - - - These forms change whether a domain is marked to allow NULL - values or to reject NULL values. You may only SET NOT NULL - when the tables using the domain contain no null values in the domain - based column. - - - - - - ADD domain_constraint - - - This form adds a new constraint to a table using the same syntax as - . - - - - - - DROP CONSTRAINT - - - This form drops constraints on a domain. - - - - - - - - You must own the domain to use ALTER DOMAIN; except for - ALTER TABLE OWNER, which may only be executed by a superuser. - - - - - - Usage - - - To add a NOT NULL constraint to a column: - -ALTER DOMAIN zipcode SET NOT NULL; - - To remove a NOT NULL constraint from a column: - -ALTER DOMAIN zipcode DROP NOT NULL; - - - - - To add a check constraint to a table: - -ALTER DOMAIN zipcode ADD CONSTRAINT zipchk CHECK (char_length(VALUE) = 5); - - - - - To remove a check constraint from a table and all its children: - -ALTER DOMAIN zipcode DROP CONSTRAINT zipchk; - - - - - - - diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml index 8709343c3c..a4e7ca7260 100644 --- a/doc/src/sgml/reference.sgml +++ b/doc/src/sgml/reference.sgml @@ -1,5 +1,5 @@ @@ -47,7 +47,6 @@ PostgreSQL Reference Manual &abort; &alterDatabase; - &alterDomain; &alterGroup; &alterTable; &alterTrigger; diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index 3fb609b3f1..d3529aea48 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.15 2002/12/06 03:28:27 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.16 2002/12/06 03:42:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -36,7 +36,6 @@ #include "commands/proclang.h" #include "commands/schemacmds.h" #include "commands/trigger.h" -#include "commands/typecmds.h" #include "lib/stringinfo.h" #include "miscadmin.h" #include "optimizer/clauses.h" diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index d4e06a17e0..54e978569b 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.9 2002/12/06 03:28:27 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.10 2002/12/06 03:42:57 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -199,7 +199,6 @@ CreateConstraintEntry(const char *constraintName, domobject.classId = RelOid_pg_type; domobject.objectId = domainId; - domobject.objectSubId = 0; recordDependencyOn(&conobject, &domobject, DEPENDENCY_AUTO); } @@ -497,16 +496,15 @@ RemoveConstraintById(Oid conId) HeapTuple typTup; ScanKeyData typKey[1]; SysScanDesc typScan; - int nkeys = 0; typRel = heap_openr(TypeRelationName, RowExclusiveLock); - ScanKeyEntryInitialize(&typKey[nkeys++], 0x0, - ObjectIdAttributeNumber, F_OIDEQ, + ScanKeyEntryInitialize(&typKey[0], 0x0, + Anum_pg_constraint_contypid, F_OIDEQ, ObjectIdGetDatum(con->contypid)); typScan = systable_beginscan(typRel, TypeOidIndex, true, - SnapshotNow, nkeys, typKey); + SnapshotNow, 1, typKey); typTup = systable_getnext(typScan); @@ -519,11 +517,6 @@ RemoveConstraintById(Oid conId) /* Keep lock on domain type until end of xact */ heap_close(typRel, NoLock); } - else - { - elog(ERROR, "RemoveConstraintById: Constraint %u is not a known type", - conId); - } /* Fry the constraint itself */ simple_heap_delete(conDesc, &tup->t_self); diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 25721ebd42..bdddc1704a 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.83 2002/12/06 03:28:27 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.84 2002/12/06 03:42:57 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -139,7 +139,7 @@ TypeCreate(const char *typeName, Oid elementType, Oid baseType, const char *defaultTypeValue, /* human readable rep */ - char *defaultTypeBin, /* cooked rep */ + const char *defaultTypeBin, /* cooked rep */ bool passedByValue, char alignment, char storage, @@ -291,16 +291,79 @@ TypeCreate(const char *typeName, */ if (!IsBootstrapProcessingMode()) { - GenerateTypeDependencies(typeNamespace, - typeObjectId, - relationOid, - relationKind, - inputProcedure, - outputProcedure, - elementType, - baseType, - defaultTypeBin, - false); + ObjectAddress myself, + referenced; + + myself.classId = RelOid_pg_type; + myself.objectId = typeObjectId; + myself.objectSubId = 0; + + /* dependency on namespace */ + /* skip for relation rowtype, since we have indirect dependency */ + if (!OidIsValid(relationOid)) + { + referenced.classId = get_system_catalog_relid(NamespaceRelationName); + referenced.objectId = typeNamespace; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + + /* Normal dependencies on the I/O functions */ + referenced.classId = RelOid_pg_proc; + referenced.objectId = inputProcedure; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + + referenced.classId = RelOid_pg_proc; + referenced.objectId = outputProcedure; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + + /* + * If the type is a rowtype for a relation, mark it as internally + * dependent on the relation, *unless* it is a stand-alone + * composite type relation. For the latter case, we have to + * reverse the dependency. + * + * In the former case, this allows the type to be auto-dropped when + * the relation is, and not otherwise. And in the latter, of + * course we get the opposite effect. + */ + if (OidIsValid(relationOid)) + { + referenced.classId = RelOid_pg_class; + referenced.objectId = relationOid; + referenced.objectSubId = 0; + + if (relationKind != RELKIND_COMPOSITE_TYPE) + recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL); + else + recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL); + } + + /* + * If the type is an array type, mark it auto-dependent on the + * base type. (This is a compromise between the typical case + * where the array type is automatically generated and the case + * where it is manually created: we'd prefer INTERNAL for the + * former case and NORMAL for the latter.) + */ + if (OidIsValid(elementType)) + { + referenced.classId = RelOid_pg_type; + referenced.objectId = elementType; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO); + } + + /* Normal dependency from a domain to its base type. */ + if (OidIsValid(baseType)) + { + referenced.classId = RelOid_pg_type; + referenced.objectId = baseType; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } } /* @@ -311,107 +374,6 @@ TypeCreate(const char *typeName, return typeObjectId; } -void -GenerateTypeDependencies(Oid typeNamespace, - Oid typeObjectId, - Oid relationOid, /* only for 'c'atalog typeType */ - char relationKind, - Oid inputProcedure, - Oid outputProcedure, - Oid elementType, - Oid baseType, - char *defaultTypeBin, /* cooked rep */ - bool rebuild) -{ - ObjectAddress myself, - referenced; - - /* - * If true, we need to remove all current dependencies that the type - * holds, and rebuild them from scratch. This allows us to easily - * implement alter type, and alter domain statements. - */ - if (rebuild) - deleteDependencyRecordsFor(RelOid_pg_type, - typeObjectId); - - myself.classId = RelOid_pg_type; - myself.objectId = typeObjectId; - myself.objectSubId = 0; - - /* dependency on namespace */ - /* skip for relation rowtype, since we have indirect dependency */ - if (!OidIsValid(relationOid)) - { - referenced.classId = get_system_catalog_relid(NamespaceRelationName); - referenced.objectId = typeNamespace; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - } - - /* Normal dependencies on the I/O functions */ - referenced.classId = RelOid_pg_proc; - referenced.objectId = inputProcedure; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - - referenced.classId = RelOid_pg_proc; - referenced.objectId = outputProcedure; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - - /* - * If the type is a rowtype for a relation, mark it as internally - * dependent on the relation, *unless* it is a stand-alone - * composite type relation. For the latter case, we have to - * reverse the dependency. - * - * In the former case, this allows the type to be auto-dropped when - * the relation is, and not otherwise. And in the latter, of - * course we get the opposite effect. - */ - if (OidIsValid(relationOid)) - { - referenced.classId = RelOid_pg_class; - referenced.objectId = relationOid; - referenced.objectSubId = 0; - - if (relationKind != RELKIND_COMPOSITE_TYPE) - recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL); - else - recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL); - } - - /* - * If the type is an array type, mark it auto-dependent on the - * base type. (This is a compromise between the typical case - * where the array type is automatically generated and the case - * where it is manually created: we'd prefer INTERNAL for the - * former case and NORMAL for the latter.) - */ - if (OidIsValid(elementType)) - { - referenced.classId = RelOid_pg_type; - referenced.objectId = elementType; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO); - } - - /* Normal dependency from a domain to its base type. */ - if (OidIsValid(baseType)) - { - referenced.classId = RelOid_pg_type; - referenced.objectId = baseType; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - } - - /* Dependency on the default expression */ - if (defaultTypeBin) - recordDependencyOnExpr(&myself, stringToNode(defaultTypeBin), - NIL, DEPENDENCY_NORMAL); -} - /* * TypeRename * This renames a type diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 4822ae4160..0b211ded47 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.100 2002/12/06 03:28:27 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.101 2002/12/06 03:42:57 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -667,7 +667,7 @@ cluster(ClusterStmt *stmt) tableOid = RangeVarGetRelid(stmt->relation, false); if (!check_cluster_ownership(tableOid)) elog(ERROR, "CLUSTER: You do not own relation %s", - stmt->relation->relname); + stmt->relation->relname); tuple = SearchSysCache(RELOID, ObjectIdGetDatum(tableOid), @@ -706,7 +706,7 @@ cluster(ClusterStmt *stmt) } if (indexOid == InvalidOid) elog(ERROR, "CLUSTER: No previously clustered index found on table %s", - stmt->relation->relname); + stmt->relation->relname); RelationClose(rel); ReleaseSysCache(ituple); ReleaseSysCache(idxtuple); @@ -721,7 +721,7 @@ cluster(ClusterStmt *stmt) /* XXX Maybe the namespace should be reported as well */ if (!OidIsValid(indexOid)) elog(ERROR, "CLUSTER: cannot find index \"%s\" for table \"%s\"", - stmt->indexname, stmt->relation->relname); + stmt->indexname, stmt->relation->relname); rvtc.tableOid = tableOid; rvtc.indexOid = indexOid; rvtc.isPrevious = false; @@ -819,7 +819,7 @@ get_tables_to_cluster(AclId owner) List *rvs = NIL; /* - * Get all indexes that have indisclustered set. System + * Get all indexes that have indisclustered set. System * relations or nailed-in relations cannot ever have * indisclustered set, because CLUSTER will refuse to * set it when called with one of them as argument. diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index ebae0e272d..9bad570abf 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.18 2002/12/06 03:28:27 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.19 2002/12/06 03:42:57 momjian Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -32,18 +32,14 @@ #include "postgres.h" #include "access/heapam.h" -#include "access/genam.h" #include "catalog/catname.h" #include "catalog/dependency.h" #include "catalog/heap.h" -#include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_constraint.h" #include "catalog/pg_type.h" #include "commands/defrem.h" #include "commands/tablecmds.h" -#include "commands/typecmds.h" -#include "executor/executor.h" #include "miscadmin.h" #include "nodes/nodes.h" #include "optimizer/clauses.h" @@ -52,7 +48,6 @@ #include "parser/parse_coerce.h" #include "parser/parse_expr.h" #include "parser/parse_func.h" -#include "parser/parse_relation.h" #include "parser/parse_type.h" #include "utils/acl.h" #include "utils/builtins.h" @@ -60,21 +55,8 @@ #include "utils/lsyscache.h" #include "utils/syscache.h" -static Oid findTypeIOFunction(List *procname, Oid typeOid, bool isOutput); -static List *get_rels_with_domain(Oid domainOid); -static void domainPermissionCheck(HeapTuple tup, TypeName *typename); -static void domainCheckForUnsupportedConstraints(Node *newConstraint); -static char *domainAddConstraint(Oid domainOid, Oid domainNamespace, - Oid baseTypeOid, - int typMod, Constraint *constr, - int *counter, char *domainName); -typedef struct -{ - Oid relOid; - int natts; - int *atts; -} relToCheck; +static Oid findTypeIOFunction(List *procname, Oid typeOid, bool isOutput); /* * DefineType @@ -519,14 +501,12 @@ DefineDomain(CreateDomainStmt *stmt) Constraint *colDef; ParseState *pstate; - /* - * Check for constraint types which are not supported by - * domains. Throws an error if it finds one. - */ - domainCheckForUnsupportedConstraints(newConstraint); + /* Prior to processing, confirm that it is not a foreign key constraint */ + if (nodeTag(newConstraint) == T_FkConstraint) + elog(ERROR, "CREATE DOMAIN / FOREIGN KEY constraints not supported"); - /* Assume its a CHECK, DEFAULT, NULL or NOT NULL constraint */ colDef = (Constraint *) newConstraint; + switch (colDef->contype) { /* @@ -580,17 +560,25 @@ DefineDomain(CreateDomainStmt *stmt) nullDefined = true; break; - /* - * Check constraints are handled after domain creation, as they require - * the Oid of the domain - */ + case CONSTR_UNIQUE: + elog(ERROR, "CREATE DOMAIN / UNIQUE indexes not supported"); + break; + + case CONSTR_PRIMARY: + elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indexes not supported"); + break; + + /* Check constraints are handled after domain creation */ case CONSTR_CHECK: break; - /* - * If we reach this, then domainCheckForUnsupportedConstraints() - * doesn't have a complete list of unsupported domain constraints - */ + case CONSTR_ATTR_DEFERRABLE: + case CONSTR_ATTR_NOT_DEFERRABLE: + case CONSTR_ATTR_DEFERRED: + case CONSTR_ATTR_IMMEDIATE: + elog(ERROR, "DefineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported"); + break; + default: elog(ERROR, "DefineDomain: unrecognized constraint node type"); break; @@ -628,26 +616,142 @@ DefineDomain(CreateDomainStmt *stmt) foreach(listptr, schema) { Constraint *constr = lfirst(listptr); + ParseState *pstate; switch (constr->contype) { case CONSTR_CHECK: { - char *junk; + Node *expr; + char *ccsrc; + char *ccbin; + ConstraintTestValue *domVal; - /* Returns the cooked constraint which is not needed during creation */ - junk = domainAddConstraint(domainoid, domainNamespace, - basetypeoid, stmt->typename->typmod, - constr, &counter, domainName); + /* + * Assign or validate constraint name + */ + if (constr->name) + { + if (ConstraintNameIsUsed(CONSTRAINT_DOMAIN, + domainoid, + domainNamespace, + constr->name)) + elog(ERROR, "constraint \"%s\" already exists for domain \"%s\"", + constr->name, + domainName); + } + else + constr->name = GenerateConstraintName(CONSTRAINT_DOMAIN, + domainoid, + domainNamespace, + &counter); + + /* + * Convert the A_EXPR in raw_expr into an + * EXPR + */ + pstate = make_parsestate(NULL); + + /* + * We want to have the domain VALUE node type filled in so + * that proper casting can occur. + */ + domVal = makeNode(ConstraintTestValue); + domVal->typeId = basetypeoid; + domVal->typeMod = stmt->typename->typmod; + + expr = transformExpr(pstate, constr->raw_expr, domVal); + + /* + * Domains don't allow var clauses + */ + if (contain_var_clause(expr)) + elog(ERROR, "cannot use column references in domain CHECK clause"); + + /* + * Make sure it yields a boolean result. + */ + expr = coerce_to_boolean(expr, "CHECK"); + + /* + * Make sure no outside relations are + * referred to. + */ + if (length(pstate->p_rtable) != 0) + elog(ERROR, "Relations cannot be referenced in domain CHECK constraint"); + + /* + * No subplans or aggregates, either... + */ + if (contain_subplans(expr)) + elog(ERROR, "cannot use subselect in CHECK constraint expression"); + if (contain_agg_clause(expr)) + elog(ERROR, "cannot use aggregate function in CHECK constraint expression"); + + /* + * Might as well try to reduce any constant expressions. + */ + expr = eval_const_expressions(expr); + + /* + * Must fix opids in operator clauses. + */ + fix_opids(expr); + + ccbin = nodeToString(expr); + + /* + * Deparse it. Since VARNOs aren't allowed in domain + * constraints, relation context isn't required as anything + * other than a shell. + */ + ccsrc = deparse_expression(expr, + deparse_context_for(domainName, + InvalidOid), + false, false); + + /* Write the constraint */ + CreateConstraintEntry(constr->name, /* Constraint Name */ + domainNamespace, /* namespace */ + CONSTRAINT_CHECK, /* Constraint Type */ + false, /* Is Deferrable */ + false, /* Is Deferred */ + InvalidOid, /* not a relation constraint */ + NULL, + 0, + domainoid, /* domain constraint */ + InvalidOid, /* Foreign key fields */ + NULL, + 0, + ' ', + ' ', + ' ', + InvalidOid, + expr, /* Tree form check constraint */ + ccbin, /* Binary form check constraint */ + ccsrc); /* Source form check constraint */ } break; - - /* Errors for other constraints are taken care of prior to domain creation */ default: break; } } + /* + * Add any dependencies needed for the default expression. + */ + if (defaultExpr) + { + ObjectAddress domobject; + + domobject.classId = RelOid_pg_type; + domobject.objectId = domainoid; + domobject.objectSubId = 0; + + recordDependencyOnExpr(&domobject, defaultExpr, NIL, + DEPENDENCY_NORMAL); + } + /* * Now we can clean up. */ @@ -827,8 +931,7 @@ findTypeIOFunction(List *procname, Oid typeOid, bool isOutput) if (OidIsValid(procOid)) { /* Found, but must complain and fix the pg_proc entry */ - elog(NOTICE, "TypeCreate: changing argument type of function %s " - "from OPAQUE to CSTRING", + elog(NOTICE, "TypeCreate: changing argument type of function %s from OPAQUE to CSTRING", NameListToString(procname)); SetFunctionArgType(procOid, 0, CSTRINGOID); /* @@ -889,778 +992,3 @@ DefineCompositeType(const RangeVar *typevar, List *coldeflist) */ return DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE); } - -/* - * AlterDomainDefault - * - * Routine implementing ALTER DOMAIN SET/DROP DEFAULT statements. - */ -void -AlterDomainDefault(List *names, Node *defaultRaw) -{ - TypeName *typename; - Oid domainoid; - HeapTuple tup; - ParseState *pstate; - Relation rel; - char *defaultValue; - Node *defaultExpr = NULL; /* NULL if no default specified */ - Datum new_record[Natts_pg_type]; - char new_record_nulls[Natts_pg_type]; - char new_record_repl[Natts_pg_type]; - HeapTuple newtuple; - Form_pg_type typTup; - - /* Make a TypeName so we can use standard type lookup machinery */ - typename = makeNode(TypeName); - typename->names = names; - typename->typmod = -1; - typename->arrayBounds = NIL; - - /* Lock the domain in the type table */ - rel = heap_openr(TypeRelationName, RowExclusiveLock); - - /* Use LookupTypeName here so that shell types can be removed. */ - domainoid = LookupTypeName(typename); - if (!OidIsValid(domainoid)) - elog(ERROR, "Type \"%s\" does not exist", - TypeNameToString(typename)); - - tup = SearchSysCacheCopy(TYPEOID, - ObjectIdGetDatum(domainoid), - 0, 0, 0); - - if (!HeapTupleIsValid(tup)) - elog(ERROR, "AlterDomain: type \"%s\" does not exist", - TypeNameToString(typename)); - - /* Doesn't return if user isn't allowed to alter the domain */ - domainPermissionCheck(tup, typename); - - /* Setup new tuple */ - MemSet(new_record, (Datum) 0, sizeof(new_record)); - MemSet(new_record_nulls, ' ', sizeof(new_record_nulls)); - MemSet(new_record_repl, ' ', sizeof(new_record_repl)); - - /* Useful later */ - typTup = (Form_pg_type) GETSTRUCT(tup); - - /* Store the new default, if null then skip this step */ - if (defaultRaw) - { - /* Create a dummy ParseState for transformExpr */ - pstate = make_parsestate(NULL); - /* - * Cook the colDef->raw_expr into an expression. Note: - * Name is strictly for error message - */ - defaultExpr = cookDefault(pstate, defaultRaw, - typTup->typbasetype, - typTup->typtypmod, - NameStr(typTup->typname)); - - /* - * Expression must be stored as a nodeToString result, but - * we also require a valid textual representation (mainly - * to make life easier for pg_dump). - */ - defaultValue = deparse_expression(defaultExpr, - deparse_context_for(NameStr(typTup->typname), - InvalidOid), - false, false); - /* - * Form an updated tuple with the new default and write it back. - */ - new_record[Anum_pg_type_typdefaultbin - 1] = DirectFunctionCall1(textin, - CStringGetDatum( - nodeToString(defaultExpr))); - - new_record_repl[Anum_pg_type_typdefaultbin - 1] = 'r'; - new_record[Anum_pg_type_typdefault - 1] = DirectFunctionCall1(textin, - CStringGetDatum(defaultValue)); - new_record_repl[Anum_pg_type_typdefault - 1] = 'r'; - } - else /* Default is NULL, drop it */ - { - new_record_nulls[Anum_pg_type_typdefaultbin - 1] = 'n'; - new_record_repl[Anum_pg_type_typdefaultbin - 1] = 'r'; - new_record_nulls[Anum_pg_type_typdefault - 1] = 'n'; - new_record_repl[Anum_pg_type_typdefault - 1] = 'r'; - } - - newtuple = heap_modifytuple(tup, rel, - new_record, new_record_nulls, new_record_repl); - - simple_heap_update(rel, &tup->t_self, newtuple); - - CatalogUpdateIndexes(rel, newtuple); - - /* Rebuild dependencies */ - GenerateTypeDependencies(typTup->typnamespace, - domainoid, - typTup->typrelid, - InvalidOid, - typTup->typinput, - typTup->typoutput, - typTup->typelem, - typTup->typbasetype, - nodeToString(defaultExpr), - true); /* Rebuild is true */ - - /* Clean up */ - heap_close(rel, NoLock); - heap_freetuple(newtuple); -}; - -/* - * AlterDomainNotNull - * - * Routine implementing ALTER DOMAIN SET/DROP NOT NULL statements. - */ -void -AlterDomainNotNull(List *names, bool notNull) -{ - TypeName *typename; - Oid domainoid; - HeapTuple tup; - Relation rel; - Datum new_record[Natts_pg_type]; - char new_record_nulls[Natts_pg_type]; - char new_record_repl[Natts_pg_type]; - HeapTuple newtuple; - Form_pg_type typTup; - - /* Make a TypeName so we can use standard type lookup machinery */ - typename = makeNode(TypeName); - typename->names = names; - typename->typmod = -1; - typename->arrayBounds = NIL; - - /* Lock the type table */ - rel = heap_openr(TypeRelationName, RowExclusiveLock); - - /* Use LookupTypeName here so that shell types can be removed. */ - domainoid = LookupTypeName(typename); - if (!OidIsValid(domainoid)) - elog(ERROR, "Type \"%s\" does not exist", - TypeNameToString(typename)); - - tup = SearchSysCacheCopy(TYPEOID, - ObjectIdGetDatum(domainoid), - 0, 0, 0); - - if (!HeapTupleIsValid(tup)) - elog(ERROR, "AlterDomain: type \"%s\" does not exist", - TypeNameToString(typename)); - - /* Doesn't return if user isn't allowed to alter the domain */ - domainPermissionCheck(tup, typename); - - typTup = (Form_pg_type) GETSTRUCT(tup); - - /* Is the domain already set to the destination constraint? */ - if (typTup->typnotnull == notNull) - elog(ERROR, "AlterDomain: %s is already set to %s", - TypeNameToString(typename), - notNull ? "NOT NULL" : "NULL"); - - /* Adding a NOT NULL constraint requires checking current domains */ - if (notNull) - { - List *rels; - List *rt; - - /* Fetch relation list with attributes based on this domain */ - rels = get_rels_with_domain(domainoid); - - foreach (rt, rels) - { - Relation typrel; - HeapTuple tuple; - HeapScanDesc scan; - TupleDesc tupdesc; - relToCheck *rtc = (relToCheck *) lfirst(rt); - - /* Lock relation */ - typrel = heap_open(rtc->relOid, ExclusiveLock); - - tupdesc = RelationGetDescr(typrel); - - /* Fetch tuples sequentially */ - scan = heap_beginscan(typrel, SnapshotNow, 0, NULL); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) - { - int i; - - /* Test attributes */ - for (i = 0; i < rtc->natts; i++) - { - Datum d; - bool isNull; - - d = heap_getattr(tuple, rtc->atts[i], tupdesc, &isNull); - - if (isNull) - elog(ERROR, "ALTER DOMAIN: Relation \"%s\" Attribute \"%s\" " - "contains NULL values", - RelationGetRelationName(typrel), - NameStr(*attnumAttName(typrel, rtc->atts[i]))); - } - } - - heap_endscan(scan); - - /* Release lock */ - heap_close(typrel, NoLock); - } - } - - - /* Setup new tuple */ - MemSet(new_record, (Datum) 0, sizeof(new_record)); - MemSet(new_record_nulls, ' ', sizeof(new_record_nulls)); - MemSet(new_record_repl, ' ', sizeof(new_record_repl)); - - new_record[Anum_pg_type_typnotnull - 1] = BoolGetDatum(notNull); - new_record_repl[Anum_pg_type_typnotnull - 1] = 'r'; - - /* Build the new tuple */ - newtuple = heap_modifytuple(tup, rel, - new_record, new_record_nulls, new_record_repl); - - simple_heap_update(rel, &tup->t_self, newtuple); - - CatalogUpdateIndexes(rel, newtuple); - - /* Clean up */ - heap_close(rel, NoLock); - heap_freetuple(newtuple); -} - -/* - * AlterDomainDropConstraint - * - * Implements the ALTER DOMAIN DROP CONSTRAINT statement - */ -void -AlterDomainDropConstraint(List *names, const char *constrName, DropBehavior behavior) -{ - TypeName *typename; - Oid domainoid; - HeapTuple tup; - Relation rel; - Form_pg_type typTup; - Relation conrel; - SysScanDesc conscan; - ScanKeyData key[1]; - HeapTuple contup; - - /* Make a TypeName so we can use standard type lookup machinery */ - typename = makeNode(TypeName); - typename->names = names; - typename->typmod = -1; - typename->arrayBounds = NIL; - - /* Lock the type table */ - rel = heap_openr(TypeRelationName, RowExclusiveLock); - - /* Use LookupTypeName here so that shell types can be removed. */ - domainoid = LookupTypeName(typename); - if (!OidIsValid(domainoid)) - elog(ERROR, "Type \"%s\" does not exist", - TypeNameToString(typename)); - - tup = SearchSysCacheCopy(TYPEOID, - ObjectIdGetDatum(domainoid), - 0, 0, 0); - - if (!HeapTupleIsValid(tup)) - elog(ERROR, "AlterDomain: type \"%s\" does not exist", - TypeNameToString(typename)); - - /* Doesn't return if user isn't allowed to alter the domain */ - domainPermissionCheck(tup, typename); - - /* Grab an appropriate lock on the pg_constraint relation */ - conrel = heap_openr(ConstraintRelationName, RowExclusiveLock); - - /* Use the index to scan only constraints of the target relation */ - ScanKeyEntryInitialize(&key[0], 0x0, - Anum_pg_constraint_contypid, F_OIDEQ, - ObjectIdGetDatum(HeapTupleGetOid(tup))); - - conscan = systable_beginscan(conrel, ConstraintTypidIndex, true, - SnapshotNow, 1, key); - - typTup = (Form_pg_type) GETSTRUCT(tup); - - /* - * Scan over the result set, removing any matching entries. - */ - while ((contup = systable_getnext(conscan)) != NULL) - { - Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(contup); - - if (strcmp(NameStr(con->conname), constrName) == 0) - { - ObjectAddress conobj; - - conobj.classId = RelationGetRelid(conrel); - conobj.objectId = HeapTupleGetOid(contup); - conobj.objectSubId = 0; - - performDeletion(&conobj, behavior); - } - } - /* Clean up after the scan */ - systable_endscan(conscan); - heap_close(conrel, RowExclusiveLock); - - heap_close(rel, NoLock); -}; - -/* - * AlterDomainAddConstraint - * - * Implements the ALTER DOMAIN .. ADD CONSTRAINT statement. - */ -void -AlterDomainAddConstraint(List *names, Node *newConstraint) -{ - TypeName *typename; - Oid domainoid; - HeapTuple tup; - Relation rel; - List *rels; - List *rt; - Form_pg_type typTup; - char *ccbin; - Node *expr; - int counter = 0; - Constraint *constr; - - /* Make a TypeName so we can use standard type lookup machinery */ - typename = makeNode(TypeName); - typename->names = names; - typename->typmod = -1; - typename->arrayBounds = NIL; - - /* Lock the type table */ - rel = heap_openr(TypeRelationName, RowExclusiveLock); - - /* Use LookupTypeName here so that shell types can be removed. */ - domainoid = LookupTypeName(typename); - if (!OidIsValid(domainoid)) - elog(ERROR, "Type \"%s\" does not exist", - TypeNameToString(typename)); - - tup = SearchSysCacheCopy(TYPEOID, - ObjectIdGetDatum(domainoid), - 0, 0, 0); - - if (!HeapTupleIsValid(tup)) - elog(ERROR, "AlterDomain: type \"%s\" does not exist", - TypeNameToString(typename)); - - - /* Doesn't return if user isn't allowed to alter the domain */ - domainPermissionCheck(tup, typename); - - typTup = (Form_pg_type) GETSTRUCT(tup); - - - /* - * Check for constraint types which are not supported by - * domains. Throws an error if it finds one. - */ - domainCheckForUnsupportedConstraints(newConstraint); - - /* Assume its a CHECK, DEFAULT, NULL or NOT NULL constraint */ - constr = (Constraint *) newConstraint; - switch (constr->contype) - { - case CONSTR_DEFAULT: - elog(ERROR, "Use ALTER DOMAIN .. SET DEFAULT instead"); - break; - - case CONSTR_NOTNULL: - case CONSTR_NULL: - elog(ERROR, "Use ALTER DOMAIN .. [ SET | DROP ] NOT NULL instead"); - break; - - /* - * Check constraints are handled after domain creation, as they require - * the Oid of the domain - */ - case CONSTR_CHECK: - { - /* Returns the cooked constraint which is not needed during creation */ - ccbin = domainAddConstraint(HeapTupleGetOid(tup), typTup->typnamespace, - typTup->typbasetype, typTup->typtypmod, - constr, &counter, NameStr(typTup->typname)); - } - break; - - /* - * If we reach this, then domainCheckForUnsupportedConstraints() - * doesn't have a complete list of unsupported domain constraints - */ - default: - elog(ERROR, "DefineDomain: unrecognized constraint node type"); - break; - } - - /* - * Since all other constraint types throw errors, this must be - * a check constraint, and ccbin must be set. - * - * Test all values stored in the attributes based on the domain - * the constraint is being added to. - */ - expr = stringToNode(ccbin); - rels = get_rels_with_domain(domainoid); - foreach (rt, rels) - { - Relation typrel; - HeapTuple tuple; - HeapScanDesc scan; - TupleDesc tupdesc; - ExprContext *econtext; - TupleTableSlot *slot; - relToCheck *rtc = (relToCheck *) lfirst(rt); - - /* Lock relation */ - typrel = heap_open(rtc->relOid, ExclusiveLock); - - /* Test attributes */ - tupdesc = RelationGetDescr(typrel); - - /* Make tuple slot to hold tuples */ - slot = MakeTupleTableSlot(); - ExecSetSlotDescriptor(slot, RelationGetDescr(typrel), false); - - /* Make an expression context for ExecQual */ - econtext = MakeExprContext(slot, CurrentMemoryContext); - - /* Scan through table */ - scan = heap_beginscan(typrel, SnapshotNow, 0, NULL); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) - { - int i; - - ExecStoreTuple(tuple, slot, InvalidBuffer, false); - - /* Loop through each attribute of the tuple with a domain */ - for (i = 0; i < rtc->natts; i++) - { - Datum d; - bool isNull; - Datum conResult; - ExprDoneCond isDone; - - d = heap_getattr(tuple, rtc->atts[i], tupdesc, &isNull); - - if (isNull) - elog(ERROR, "ALTER DOMAIN: Relation \"%s\" Attribute \"%s\" " - "contains NULL values", - RelationGetRelationName(typrel), - NameStr(*attnumAttName(typrel, rtc->atts[i]))); - - econtext->domainValue_datum = d; - econtext->domainValue_isNull = isNull; - - conResult = ExecEvalExpr(expr, econtext, &isNull, &isDone); - - if (!DatumGetBool(conResult)) - elog(ERROR, "AlterDomainAddConstraint: Domain %s constraint %s failed", - NameStr(typTup->typname), constr->name); - } - - ResetExprContext(econtext); - } - - heap_endscan(scan); - - FreeExprContext(econtext); - pfree(slot); - - /* Hold type lock */ - heap_close(typrel, NoLock); - } - - /* Clean up */ - heap_close(rel, NoLock); -} - -/* - * get_rels_with_domain - * - * Fetch all relations / attributes which are using the domain - * while maintaining a RowExclusiveLock on the pg_attribute - * entries. - * - * Generally used for retrieving a list of tests when adding - * new constraints to a domain. - */ -List * -get_rels_with_domain(Oid domainOid) -{ - Relation classRel; - HeapTuple classTup; - Relation attRel; - HeapScanDesc classScan; - List *rels = NIL; - - /* - * We need to lock the domain rows for the length of the transaction, - * but once all of the tables and the appropriate attributes are - * found we can relese the relation lock. - */ - classRel = relation_openr(RelationRelationName, ExclusiveLock); - attRel = relation_openr(AttributeRelationName, RowExclusiveLock); - - classScan = heap_beginscan(classRel, SnapshotNow, 0, NULL); - - /* Scan through pg_class for tables */ - while ((classTup = heap_getnext(classScan, ForwardScanDirection)) != NULL) - { - bool addToList = true; - int nkeys = 0; - HeapTuple attTup; - HeapScanDesc attScan; - ScanKeyData attKey[2]; - Form_pg_class pg_class; - - /* Get our pg_class struct */ - pg_class = (Form_pg_class) GETSTRUCT(classTup); - - /* Fetch attributes from pg_attribute for the relation of the type domainOid */ - ScanKeyEntryInitialize(&attKey[nkeys++], 0, Anum_pg_attribute_attrelid, - F_OIDEQ, ObjectIdGetDatum(HeapTupleGetOid(classTup))); - - ScanKeyEntryInitialize(&attKey[nkeys++], 0, Anum_pg_attribute_atttypid, - F_OIDEQ, ObjectIdGetDatum(domainOid)); - - /* Setup to scan pg_attribute */ - attScan = heap_beginscan(attRel, SnapshotNow, nkeys, attKey); - - /* Scan through pg_attribute for attributes based on the domain */ - while ((attTup = heap_getnext(attScan, ForwardScanDirection)) != NULL) - { - relToCheck *rtc; - - /* Make the list entries for the relation */ - if (addToList) - { - addToList = false; - - rtc = (relToCheck *)palloc(sizeof(relToCheck)); - rtc->atts = (int *)palloc(sizeof(int) * pg_class->relnatts); - rtc->relOid = HeapTupleGetOid(classTup); - rtc->natts = 0; - rels = lcons((void *)rtc, rels); - } - - /* Now add the attribute */ - rtc->atts[rtc->natts++] = ((Form_pg_attribute) GETSTRUCT(attTup))->attnum; - } - - heap_endscan(attScan); - } - - heap_endscan(classScan); - - /* Release pg_class, hold pg_attribute for further processing */ - relation_close(classRel, ExclusiveLock); - relation_close(attRel, NoLock); - - return rels; -} - -/* - * domainPermissionCheck - * - * Throw an error if the current user doesn't have permission to modify - * the domain in an ALTER DOMAIN statement, or if the type isn't actually - * a domain. - */ -void -domainPermissionCheck(HeapTuple tup, TypeName *typename) -{ - Form_pg_type typTup = (Form_pg_type) GETSTRUCT(tup); - - /* Permission check: must own type or its namespace */ - if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId()) && - !pg_namespace_ownercheck(typTup->typnamespace, - GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, TypeNameToString(typename)); - - /* Check that this is actually a domain */ - if (typTup->typtype != 'd') - elog(ERROR, "%s is not a domain", - TypeNameToString(typename)); -} - - -/* - * - */ -char * -domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, - int typMod, Constraint *constr, int *counter, char *domainName) -{ - Node *expr; - char *ccsrc; - char *ccbin; - ParseState *pstate; - ConstraintTestValue *domVal; - - /* - * Assign or validate constraint name - */ - if (constr->name) - { - if (ConstraintNameIsUsed(CONSTRAINT_DOMAIN, - domainOid, - domainNamespace, - constr->name)) - elog(ERROR, "constraint \"%s\" already exists for domain \"%s\"", - constr->name, - domainName); - } - else - constr->name = GenerateConstraintName(CONSTRAINT_DOMAIN, - domainOid, - domainNamespace, - counter); - - /* - * Convert the A_EXPR in raw_expr into an - * EXPR - */ - pstate = make_parsestate(NULL); - - /* - * We want to have the domain VALUE node type filled in so - * that proper casting can occur. - */ - domVal = makeNode(ConstraintTestValue); - domVal->typeId = baseTypeOid; - domVal->typeMod = typMod; - - expr = transformExpr(pstate, constr->raw_expr, domVal); - - /* - * Domains don't allow var clauses - */ - if (contain_var_clause(expr)) - elog(ERROR, "cannot use column references in domain CHECK clause"); - - /* - * Make sure it yields a boolean result. - */ - expr = coerce_to_boolean(expr, "CHECK"); - - /* - * Make sure no outside relations are - * referred to. - */ - if (length(pstate->p_rtable) != 0) - elog(ERROR, "Relations cannot be referenced in domain CHECK constraint"); - - /* - * No subplans or aggregates, either... - */ - if (contain_subplans(expr)) - elog(ERROR, "cannot use subselect in CHECK constraint expression"); - if (contain_agg_clause(expr)) - elog(ERROR, "cannot use aggregate function in CHECK constraint expression"); - - /* - * Might as well try to reduce any constant expressions. - */ - expr = eval_const_expressions(expr); - - /* - * Must fix opids in operator clauses. - */ - fix_opids(expr); - - ccbin = nodeToString(expr); - - /* - * Deparse it. Since VARNOs aren't allowed in domain - * constraints, relation context isn't required as anything - * other than a shell. - */ - ccsrc = deparse_expression(expr, - deparse_context_for(domainName, - InvalidOid), - false, false); - - /* Write the constraint */ - CreateConstraintEntry(constr->name, /* Constraint Name */ - domainNamespace, /* namespace */ - CONSTRAINT_CHECK, /* Constraint Type */ - false, /* Is Deferrable */ - false, /* Is Deferred */ - InvalidOid, /* not a relation constraint */ - NULL, - 0, - domainOid, /* domain constraint */ - InvalidOid, /* Foreign key fields */ - NULL, - 0, - ' ', - ' ', - ' ', - InvalidOid, - expr, /* Tree form check constraint */ - ccbin, /* Binary form check constraint */ - ccsrc); /* Source form check constraint */ - - /* - * Return the constraint so the calling routine can perform any additional - * required tests. - */ - return ccbin; -} - -/* - * domainCheckForUnsupportedConstraints - * - * Throws an error on constraints that are unsupported by the - * domains. - */ -void -domainCheckForUnsupportedConstraints(Node *newConstraint) -{ - Constraint *colDef; - - if (nodeTag(newConstraint) == T_FkConstraint) - elog(ERROR, "CREATE DOMAIN / FOREIGN KEY constraints not supported"); - - colDef = (Constraint *) newConstraint; - - switch (colDef->contype) - { - case CONSTR_UNIQUE: - elog(ERROR, "CREATE DOMAIN / UNIQUE indexes not supported"); - break; - - case CONSTR_PRIMARY: - elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indexes not supported"); - break; - - case CONSTR_ATTR_DEFERRABLE: - case CONSTR_ATTR_NOT_DEFERRABLE: - case CONSTR_ATTR_DEFERRED: - case CONSTR_ATTR_IMMEDIATE: - elog(ERROR, "DefineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED" - " and IMMEDIATE not supported"); - break; - - default: - break; - } -} diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index fd531aaa73..8b3747cc96 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.114 2002/12/06 03:28:27 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.115 2002/12/06 03:42:57 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1610,8 +1610,8 @@ ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext, conResult = ExecEvalExpr(constraint->check_expr, econtext, isNull, isDone); if (!DatumGetBool(conResult)) - elog(ERROR, "ExecEvalConstraintTest: Domain %s constraint %s failed", - constraint->domname, constraint->name); + elog(ERROR, "Domain %s constraint %s failed", + constraint->name, constraint->domname); } break; default: diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 01abacfa02..282f9eae5d 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.227 2002/12/06 03:28:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.228 2002/12/06 03:42:59 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1479,20 +1479,6 @@ _copyAlterTableStmt(AlterTableStmt *from) return newnode; } -static AlterDomainStmt * -_copyAlterDomainStmt(AlterDomainStmt *from) -{ - AlterDomainStmt *newnode = makeNode(AlterDomainStmt); - - COPY_SCALAR_FIELD(subtype); - COPY_NODE_FIELD(typename); - COPY_STRING_FIELD(name); - COPY_NODE_FIELD(def); - COPY_SCALAR_FIELD(behavior); - - return newnode; -} - static GrantStmt * _copyGrantStmt(GrantStmt *from) { @@ -2478,9 +2464,6 @@ copyObject(void *from) case T_AlterTableStmt: retval = _copyAlterTableStmt(from); break; - case T_AlterDomainStmt: - retval = _copyAlterDomainStmt(from); - break; case T_GrantStmt: retval = _copyGrantStmt(from); break; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 3c5dc6c03f..262f916d79 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -18,7 +18,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.172 2002/12/06 03:28:32 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.173 2002/12/06 03:43:08 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -525,18 +525,6 @@ _equalAlterTableStmt(AlterTableStmt *a, AlterTableStmt *b) return true; } -static bool -_equalAlterDomainStmt(AlterDomainStmt *a, AlterDomainStmt *b) -{ - COMPARE_SCALAR_FIELD(subtype); - COMPARE_NODE_FIELD(typename); - COMPARE_STRING_FIELD(name); - COMPARE_NODE_FIELD(def); - COMPARE_SCALAR_FIELD(behavior); - - return true; -} - static bool _equalGrantStmt(GrantStmt *a, GrantStmt *b) { @@ -1633,9 +1621,6 @@ equal(void *a, void *b) case T_AlterTableStmt: retval = _equalAlterTableStmt(a, b); break; - case T_AlterDomainStmt: - retval = _equalAlterDomainStmt(a, b); - break; case T_GrantStmt: retval = _equalGrantStmt(a, b); break; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index e1fad41b0e..3e2b6ad4ea 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.384 2002/12/06 03:28:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.385 2002/12/06 03:43:08 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -128,7 +128,7 @@ static void doNegateFloat(Value *v); } %type stmt schema_stmt - AlterDatabaseSetStmt AlterDomainStmt AlterGroupStmt + AlterDatabaseSetStmt AlterGroupStmt AlterTableStmt AlterUserStmt AlterUserSetStmt AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt @@ -479,7 +479,6 @@ stmtmulti: stmtmulti ';' stmt stmt : AlterDatabaseSetStmt - | AlterDomainStmt | AlterGroupStmt | AlterTableStmt | AlterUserStmt @@ -3730,53 +3729,6 @@ CreateDomainStmt: } ; -AlterDomainStmt: - /* ALTER DOMAIN {SET DEFAULT |DROP DEFAULT} */ - ALTER DOMAIN_P any_name alter_column_default - { - AlterDomainStmt *n = makeNode(AlterDomainStmt); - n->subtype = 'T'; - n->typename = $3; - n->def = $4; - $$ = (Node *)n; - } - /* ALTER DOMAIN DROP NOT NULL */ - | ALTER DOMAIN_P any_name DROP NOT NULL_P - { - AlterDomainStmt *n = makeNode(AlterDomainStmt); - n->subtype = 'N'; - n->typename = $3; - $$ = (Node *)n; - } - /* ALTER DOMAIN SET NOT NULL */ - | ALTER DOMAIN_P any_name SET NOT NULL_P - { - AlterDomainStmt *n = makeNode(AlterDomainStmt); - n->subtype = 'O'; - n->typename = $3; - $$ = (Node *)n; - } - /* ALTER DOMAIN ADD CONSTRAINT ... */ - | ALTER DOMAIN_P any_name ADD TableConstraint - { - AlterDomainStmt *n = makeNode(AlterDomainStmt); - n->subtype = 'C'; - n->typename = $3; - n->def = $5; - $$ = (Node *)n; - } - /* ALTER DOMAIN DROP CONSTRAINT [RESTRICT|CASCADE] */ - | ALTER DOMAIN_P any_name DROP CONSTRAINT name opt_drop_behavior - { - AlterDomainStmt *n = makeNode(AlterDomainStmt); - n->subtype = 'X'; - n->typename = $3; - n->name = $6; - n->behavior = $7; - $$ = (Node *)n; - } - ; - opt_as: AS {} | /* EMPTY */ {} ; diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 834cc9c82d..b36b37a755 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.133 2002/12/06 03:28:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.134 2002/12/06 03:43:12 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -629,14 +629,6 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) case T_DomainConstraintValue: { - /* - * If domVal is NULL, we are not translating an expression that - * can use it - */ - if (domVal == NULL) - elog(ERROR, "VALUE is not allowed in expression for node %d", - nodeTag(expr)); - result = (Node *) copyObject(domVal); break; diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index ac51c0cf34..7bc800bd3c 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.311 2002/12/06 03:28:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.312 2002/12/06 03:43:13 momjian Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -1781,7 +1781,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.311 $ $Date: 2002/12/06 03:28:33 $\n"); + puts("$Revision: 1.312 $ $Date: 2002/12/06 03:43:13 $\n"); } /* @@ -2319,10 +2319,6 @@ CreateCommandTag(Node *parsetree) tag = "ALTER TABLE"; break; - case T_AlterDomainStmt: - tag = "ALTER DOMAIN"; - break; - case T_GrantStmt: { GrantStmt *stmt = (GrantStmt *) parsetree; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index a45c449535..d52ed258f3 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.183 2002/12/06 03:28:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.184 2002/12/06 03:43:16 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -36,7 +36,6 @@ #include "commands/sequence.h" #include "commands/tablecmds.h" #include "commands/trigger.h" -#include "commands/typecmds.h" #include "commands/user.h" #include "commands/vacuum.h" #include "commands/view.h" @@ -561,49 +560,6 @@ ProcessUtility(Node *parsetree, } break; - case T_AlterDomainStmt: - { - AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree; - - /* - * Some or all of these functions are recursive to cover - * inherited things, so permission checks are done there. - */ - switch (stmt->subtype) - { - case 'T': /* ALTER COLUMN DEFAULT */ - - /* - * Recursively alter column default for table and, - * if requested, for descendants - */ - AlterDomainDefault(stmt->typename, - stmt->def); - break; - case 'N': /* ALTER COLUMN DROP NOT NULL */ - AlterDomainNotNull(stmt->typename, - false); - break; - case 'O': /* ALTER COLUMN SET NOT NULL */ - AlterDomainNotNull(stmt->typename, - true); - break; - case 'C': /* ADD CONSTRAINT */ - AlterDomainAddConstraint(stmt->typename, - stmt->def); - break; - case 'X': /* DROP CONSTRAINT */ - AlterDomainDropConstraint(stmt->typename, - stmt->name, - stmt->behavior); - break; - default: /* oops */ - elog(ERROR, "T_AlterDomainStmt: unknown subtype"); - break; - } - } - break; - case T_GrantStmt: ExecuteGrantStmt((GrantStmt *) parsetree); diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 8804e5fe60..c702270fbe 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_type.h,v 1.135 2002/12/06 03:28:33 momjian Exp $ + * $Id: pg_type.h,v 1.136 2002/12/06 03:43:18 momjian Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -550,7 +550,7 @@ extern Oid TypeCreate(const char *typeName, Oid elementType, Oid baseType, const char *defaultTypeValue, - char *defaultTypeBin, + const char *defaultTypeBin, bool passedByValue, char alignment, char storage, @@ -558,18 +558,6 @@ extern Oid TypeCreate(const char *typeName, int32 typNDims, bool typeNotNull); -extern void -GenerateTypeDependencies(Oid typeNamespace, - Oid typeObjectId, - Oid relationOid, /* only for 'c'atalog typeType */ - char relationKind, - Oid inputProcedure, - Oid outputProcedure, - Oid elementType, - Oid baseType, - char *defaultTypeBin, /* cooked rep */ - bool rebuild); - extern void TypeRename(const char *oldTypeName, Oid typeNamespace, const char *newTypeName); diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index d098277e79..9f9dd63ab4 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: defrem.h,v 1.47 2002/12/06 03:28:33 momjian Exp $ + * $Id: defrem.h,v 1.48 2002/12/06 03:43:28 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -52,6 +52,14 @@ extern void RemoveOperatorById(Oid operOid); extern void DefineAggregate(List *names, List *parameters); extern void RemoveAggregate(RemoveAggrStmt *stmt); +/* commands/typecmds.c */ +extern void DefineType(List *names, List *parameters); +extern void RemoveType(List *names, DropBehavior behavior); +extern void RemoveTypeById(Oid typeOid); +extern void DefineDomain(CreateDomainStmt *stmt); +extern void RemoveDomain(List *names, DropBehavior behavior); +extern Oid DefineCompositeType(const RangeVar *typevar, List *coldeflist); + /* commands/opclasscmds.c */ extern void DefineOpClass(CreateOpClassStmt *stmt); extern void RemoveOpClass(RemoveOpClassStmt *stmt); diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index dc1290775d..895a77cbf4 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: nodes.h,v 1.127 2002/12/06 03:28:33 momjian Exp $ + * $Id: nodes.h,v 1.128 2002/12/06 03:43:28 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -157,7 +157,6 @@ typedef enum NodeTag T_UpdateStmt, T_SelectStmt, T_AlterTableStmt, - T_AlterDomainStmt, T_SetOperationStmt, T_GrantStmt, T_ClosePortalStmt, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index adcb6d9a55..38fe9fe3db 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.219 2002/12/06 03:28:33 momjian Exp $ + * $Id: parsenodes.h,v 1.220 2002/12/06 03:43:28 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -827,33 +827,6 @@ typedef struct AlterTableStmt DropBehavior behavior; /* RESTRICT or CASCADE for DROP cases */ } AlterTableStmt; -/* ---------------------- - * Alter Domain - * - * The fields are used in different ways by the different variants of - * this command. Subtypes should match AlterTable subtypes - * ---------------------- - */ -typedef struct AlterDomainStmt -{ - NodeTag type; - char subtype; /*------------ - * T = alter column default - * N = alter column drop not null - * O = alter column set not null - * C = add constraint - * X = drop constraint - * U = change owner - *------------ - */ - List *typename; /* table to work on */ - char *name; /* column or constraint name to act on, or - * new owner */ - Node *def; /* definition of default or constraint */ - DropBehavior behavior; /* RESTRICT or CASCADE for DROP cases */ -} AlterDomainStmt; - - /* ---------------------- * Grant|Revoke Statement * ---------------------- diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out index f91191bddb..92c9cc2cc0 100644 --- a/src/test/regress/expected/domain.out +++ b/src/test/regress/expected/domain.out @@ -115,7 +115,7 @@ INSERT INTO nulltest DEFAULT VALUES; ERROR: Domain dnotnull does not allow NULL values INSERT INTO nulltest values ('a', 'b', 'c', 'd', 'c'); -- Good insert into nulltest values ('a', 'b', 'c', 'd', NULL); -ERROR: ExecEvalConstraintTest: Domain dcheck constraint $1 failed +ERROR: Domain $1 constraint dcheck failed insert into nulltest values ('a', 'b', 'c', 'd', 'a'); ERROR: ExecInsert: rejected due to CHECK constraint "nulltest_col5" on "nulltest" INSERT INTO nulltest values (NULL, 'b', 'c', 'd', 'd'); @@ -127,7 +127,7 @@ ERROR: ExecInsert: Fail to add null value in not null attribute col3 INSERT INTO nulltest values ('a', 'b', 'c', NULL, 'd'); -- Good -- Test copy COPY nulltest FROM stdin; --fail -ERROR: copy: line 1, ExecEvalConstraintTest: Domain dcheck constraint $1 failed +ERROR: copy: line 1, Domain $1 constraint dcheck failed lost synchronization with server, resetting connection SET autocommit TO 'on'; -- Last row is bad @@ -158,7 +158,6 @@ ERROR: Domain dnotnull does not allow NULL values drop table nulltest; drop domain dnotnull restrict; drop domain dnull restrict; -drop domain dcheck restrict; create domain ddef1 int4 DEFAULT 3; create domain ddef2 oid DEFAULT '12'; -- Type mixing, function returns int8 @@ -192,80 +191,7 @@ select * from defaulttest; (4 rows) drop sequence ddef4_seq; -drop table defaulttest cascade; --- Test ALTER DOMAIN .. NOT NULL -create domain dnotnulltest integer; -create table domnotnull -( col1 dnotnulltest -, col2 dnotnulltest -); -insert into domnotnull default values; -alter domain dnotnulltest set not null; -- fails -ERROR: ALTER DOMAIN: Relation "domnotnull" Attribute "col1" contains NULL values -update domnotnull set col1 = 5; -alter domain dnotnulltest set not null; -- fails -ERROR: ALTER DOMAIN: Relation "domnotnull" Attribute "col2" contains NULL values -update domnotnull set col2 = 6; -alter domain dnotnulltest set not null; -alter domain dnotnulltest set not null; -- fails -ERROR: AlterDomain: dnotnulltest is already set to NOT NULL -update domnotnull set col1 = null; -- fails -ERROR: Domain dnotnulltest does not allow NULL values -alter domain dnotnulltest drop not null; -alter domain dnotnulltest drop not null; -- fails -ERROR: AlterDomain: dnotnulltest is already set to NULL -update domnotnull set col1 = null; -drop domain dnotnulltest cascade; -NOTICE: Drop cascades to table domnotnull column col2 -NOTICE: Drop cascades to table domnotnull column col1 --- Test ALTER DOMAIN .. DEFAULT .. -create table domdeftest (col1 ddef1); -insert into domdeftest default values; -select * from domdeftest; - col1 ------- - 3 -(1 row) - -alter domain ddef1 set default '42'; -insert into domdeftest default values; -select * from domdeftest; - col1 ------- - 3 - 42 -(2 rows) - -alter domain ddef1 drop default; -insert into domdeftest default values; -select * from domdeftest; - col1 ------- - 3 - 42 - -(3 rows) - -drop table domdeftest; --- Test ALTER DOMAIN .. CONSTRAINT .. -create domain con as integer; -create table domcontest (col1 con); -insert into domcontest values (1); -insert into domcontest values (2); -alter domain con add constraint t check (VALUE < 1); -- fails -ERROR: AlterDomainAddConstraint: Domain con constraint t failed -alter domain con add constraint t check (VALUE < 34); -alter domain con add check (VALUE > 0); -insert into domcontest values (-5); -- fails -ERROR: ExecEvalConstraintTest: Domain con constraint $1 failed -insert into domcontest values (42); -- fails -ERROR: ExecEvalConstraintTest: Domain con constraint t failed -insert into domcontest values (5); -alter domain con drop constraint t; -insert into domcontest values (-5); --fails -ERROR: ExecEvalConstraintTest: Domain con constraint $1 failed -insert into domcontest values (42); --- cleanup +drop table defaulttest; drop domain ddef1 restrict; drop domain ddef2 restrict; drop domain ddef3 restrict; diff --git a/src/test/regress/resultmap b/src/test/regress/resultmap index d4fe5af993..0ab2f0e2f7 100644 --- a/src/test/regress/resultmap +++ b/src/test/regress/resultmap @@ -14,8 +14,8 @@ float8/.*-qnx=float8-exp-three-digits float8/alpha.*-dec-osf.*:cc=float8-fp-exception float8/i.86-pc-cygwin=float8-small-is-zero geometry/.*-darwin=geometry-positive-zeros -geometry/i.86-.*-freebsd4.[0-7]=geometry-positive-zeros -geometry/alpha.*-freebsd4.[0-7]=geometry-positive-zeros +geometry/i.86-.*-freebsd4.[0-5]=geometry-positive-zeros +geometry/alpha.*-freebsd4.[0-5]=geometry-positive-zeros geometry/i.86-.*-openbsd=geometry-positive-zeros geometry/sparc-.*-openbsd=geometry-positive-zeros geometry/.*-netbsd1.[0-5]=geometry-positive-zeros diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql index 76060e99c8..65fba7466f 100644 --- a/src/test/regress/sql/domain.sql +++ b/src/test/regress/sql/domain.sql @@ -127,7 +127,6 @@ SELECT cast(col4 as dnotnull) from nulltest; -- fail drop table nulltest; drop domain dnotnull restrict; drop domain dnull restrict; -drop domain dcheck restrict; create domain ddef1 int4 DEFAULT 3; @@ -160,71 +159,7 @@ COPY defaulttest(col5) FROM stdin; select * from defaulttest; drop sequence ddef4_seq; -drop table defaulttest cascade; - --- Test ALTER DOMAIN .. NOT NULL -create domain dnotnulltest integer; -create table domnotnull -( col1 dnotnulltest -, col2 dnotnulltest -); - -insert into domnotnull default values; -alter domain dnotnulltest set not null; -- fails - -update domnotnull set col1 = 5; -alter domain dnotnulltest set not null; -- fails - -update domnotnull set col2 = 6; - -alter domain dnotnulltest set not null; -alter domain dnotnulltest set not null; -- fails - -update domnotnull set col1 = null; -- fails - -alter domain dnotnulltest drop not null; -alter domain dnotnulltest drop not null; -- fails - -update domnotnull set col1 = null; - -drop domain dnotnulltest cascade; - --- Test ALTER DOMAIN .. DEFAULT .. -create table domdeftest (col1 ddef1); - -insert into domdeftest default values; -select * from domdeftest; - -alter domain ddef1 set default '42'; -insert into domdeftest default values; -select * from domdeftest; - -alter domain ddef1 drop default; -insert into domdeftest default values; -select * from domdeftest; - -drop table domdeftest; - --- Test ALTER DOMAIN .. CONSTRAINT .. -create domain con as integer; -create table domcontest (col1 con); - -insert into domcontest values (1); -insert into domcontest values (2); -alter domain con add constraint t check (VALUE < 1); -- fails - -alter domain con add constraint t check (VALUE < 34); -alter domain con add check (VALUE > 0); - -insert into domcontest values (-5); -- fails -insert into domcontest values (42); -- fails -insert into domcontest values (5); - -alter domain con drop constraint t; -insert into domcontest values (-5); --fails -insert into domcontest values (42); - --- cleanup +drop table defaulttest; drop domain ddef1 restrict; drop domain ddef2 restrict; drop domain ddef3 restrict;