aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-01-24 23:22:13 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-01-24 23:22:13 +0000
commit56915ea29622e85b296b65e2fd6fd164c5bfd5d6 (patch)
treea1809626e9e928b4292e3d3b511226a41a37c1b3
parent49b35eb14b7b3df8c550bc4638856a4f79769d9c (diff)
downloadpostgresql-56915ea29622e85b296b65e2fd6fd164c5bfd5d6.tar.gz
postgresql-56915ea29622e85b296b65e2fd6fd164c5bfd5d6.zip
Fix ALTER TABLE ADD COLUMN so that constraints of domain types are
enforced properly when there is no explicit default value for the new column. Per report from Craig Perras.
-rw-r--r--src/backend/commands/tablecmds.c35
-rw-r--r--src/backend/commands/typecmds.c21
2 files changed, 44 insertions, 12 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index b788db35cbb..74df2b23e36 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.142 2005/01/10 20:02:20 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.142.4.1 2005/01/24 23:22:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -35,6 +35,7 @@
#include "commands/tablecmds.h"
#include "commands/tablespace.h"
#include "commands/trigger.h"
+#include "commands/typecmds.h"
#include "executor/executor.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"
@@ -2853,6 +2854,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
int minattnum,
maxatts;
HeapTuple typeTuple;
+ Oid typeOid;
Form_pg_type tform;
Expr *defval;
@@ -2930,9 +2932,10 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
typeTuple = typenameType(colDef->typename);
tform = (Form_pg_type) GETSTRUCT(typeTuple);
+ typeOid = HeapTupleGetOid(typeTuple);
/* make sure datatype is legal for a column */
- CheckAttributeType(colDef->colname, HeapTupleGetOid(typeTuple));
+ CheckAttributeType(colDef->colname, typeOid);
attributeTuple = heap_addheader(Natts_pg_attribute,
false,
@@ -2943,7 +2946,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
attribute->attrelid = myrelid;
namestrcpy(&(attribute->attname), colDef->colname);
- attribute->atttypid = HeapTupleGetOid(typeTuple);
+ attribute->atttypid = typeOid;
attribute->attstattarget = -1;
attribute->attlen = tform->typlen;
attribute->attcacheoff = -1;
@@ -3015,11 +3018,37 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
* and return NULL if so, so without any modification of the tuple
* data we will get the effect of NULL values in the new column.
*
+ * An exception occurs when the new column is of a domain type: the
+ * domain might have a NOT NULL constraint, or a check constraint that
+ * indirectly rejects nulls. If there are any domain constraints then
+ * we construct an explicit NULL default value that will be passed through
+ * CoerceToDomain processing. (This is a tad inefficient, since it
+ * causes rewriting the table which we really don't have to do, but
+ * the present design of domain processing doesn't offer any simple way
+ * of checking the constraints more directly.)
+ *
* Note: we use build_column_default, and not just the cooked default
* returned by AddRelationRawConstraints, so that the right thing
* happens when a datatype's default applies.
*/
defval = (Expr *) build_column_default(rel, attribute->attnum);
+
+ if (!defval && GetDomainConstraints(typeOid) != NIL)
+ {
+ Oid basetype = getBaseType(typeOid);
+
+ defval = (Expr *) makeNullConst(basetype);
+ defval = (Expr *) coerce_to_target_type(NULL,
+ (Node *) defval,
+ basetype,
+ typeOid,
+ colDef->typename->typmod,
+ COERCION_ASSIGNMENT,
+ COERCE_IMPLICIT_CAST);
+ if (defval == NULL) /* should not happen */
+ elog(ERROR, "failed to coerce base type to domain");
+ }
+
if (defval)
{
NewColumnValue *newval;
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index efeb3f3bab2..ef45d119868 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.65 2004/12/31 21:59:42 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.65.4.1 2005/01/24 23:22:13 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -1929,6 +1929,9 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
* This is called by the executor during plan startup for a CoerceToDomain
* expression node. The given constraints will be checked for each value
* passed through the node.
+ *
+ * We allow this to be called for non-domain types, in which case the result
+ * is always NIL.
*/
List *
GetDomainConstraints(Oid typeOid)
@@ -1954,6 +1957,13 @@ GetDomainConstraints(Oid typeOid)
elog(ERROR, "cache lookup failed for type %u", typeOid);
typTup = (Form_pg_type) GETSTRUCT(tup);
+ if (typTup->typtype != 'd')
+ {
+ /* Not a domain, so done */
+ ReleaseSysCache(tup);
+ break;
+ }
+
/* Test for NOT NULL Constraint */
if (typTup->typnotnull)
notNull = true;
@@ -2010,14 +2020,7 @@ GetDomainConstraints(Oid typeOid)
systable_endscan(scan);
- if (typTup->typtype != 'd')
- {
- /* Not a domain, so done */
- ReleaseSysCache(tup);
- break;
- }
-
- /* else loop to next domain in stack */
+ /* loop to next domain in stack */
typeOid = typTup->typbasetype;
ReleaseSysCache(tup);
}