alter_add.patch
application/octet-stream
Filename: alter_add.patch
Type: application/octet-stream
Part: 0
Message:
Re: cataloguing NOT NULL constraints
*** a/src/backend/commands/tablecmds.c
--- b/src/backend/commands/tablecmds.c
***************
*** 2655,2660 **** AlterTableGetLockLevel(List *cmds)
--- 2655,2661 ----
* These subcommands affect write operations only.
*/
case AT_ColumnDefault:
+ case AT_ColumnConstraint:
case AT_ProcessedConstraint: /* becomes AT_AddConstraint */
case AT_AddConstraintRecurse: /* becomes AT_AddConstraint */
case AT_EnableTrig:
***************
*** 2853,2858 **** ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
--- 2854,2865 ----
/* No command-specific prep needed */
pass = cmd->def ? AT_PASS_ADD_CONSTR : AT_PASS_DROP;
break;
+ case AT_ColumnConstraint: /* ALTER COLUMN ADD CONSTRAINT */
+ /* should have been discarded by transformAlterTableStmt */
+ pass = AT_PASS_ADD_CONSTR; /* keep compiler quiet */
+ elog(ERROR, "unrecognized alter table type: %d",
+ (int) cmd->subtype);
+ break;
case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */
ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
***************
*** 3106,3111 **** ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
--- 3113,3123 ----
case AT_ColumnDefault: /* ALTER COLUMN DEFAULT */
ATExecColumnDefault(rel, cmd->name, cmd->def, lockmode);
break;
+ case AT_ColumnConstraint: /* ALTER COLUMN ADD CONSTRAINT */
+ /* should have been discarded by transformAlterTableStmt */
+ elog(ERROR, "unrecognized alter table type: %d",
+ (int) cmd->subtype);
+ break;
case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */
ATExecDropNotNull(rel, cmd->name, lockmode);
break;
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 1680,1685 **** alter_table_cmd:
--- 1680,1699 ----
n->def = $4;
$$ = (Node *)n;
}
+ /* ALTER TABLE <name> ALTER [COLUMN] <colname> ADD CONSTRAINT ... */
+ | ALTER opt_column ColId ADD_P ColQualList
+ {
+ AlterTableCmd *n = makeNode(AlterTableCmd);
+ CollateClause *collate;
+ n->subtype = AT_ColumnConstraint;
+ n->name = $3;
+ SplitColQualList($5, (List **) &n->def, &collate, yyscanner);
+ if (collate != NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("COLLATE clause not allowed in ALTER TABLE / ALTER COLUMN")));
+ $$ = (Node *)n;
+ }
/* ALTER TABLE <name> ALTER [COLUMN] <colname> DROP NOT NULL */
| ALTER opt_column ColId DROP NOT NULL_P
{
*** a/src/backend/parser/parse_utilcmd.c
--- b/src/backend/parser/parse_utilcmd.c
***************
*** 78,83 **** typedef struct
--- 78,84 ----
List *ckconstraints; /* CHECK constraints */
List *fkconstraints; /* FOREIGN KEY constraints */
List *ixconstraints; /* index-creating constraints */
+ List *nnconstraints; /* NOT NULL constraints */
List *inh_indexes; /* cloned indexes from INCLUDING INDEXES */
List *blist; /* "before list" of things to do before
* creating the table */
***************
*** 120,125 **** static IndexStmt *transformIndexConstraint(Constraint *constraint,
--- 121,128 ----
static void transformFKConstraints(CreateStmtContext *cxt,
bool skipValidation,
bool isAddConstraint);
+ static void transformConstraintItems(CreateStmtContext *cxt,
+ ColumnDef *column);
static void transformConstraintAttrs(CreateStmtContext *cxt,
List *constraintList);
static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
***************
*** 293,302 **** static void
transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
{
bool is_serial;
- bool saw_nullable;
- bool saw_default;
- Constraint *constraint;
- ListCell *clist;
cxt->columns = lappend(cxt->columns, column);
--- 296,301 ----
***************
*** 360,365 **** transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
--- 359,365 ----
CreateSeqStmt *seqstmt;
AlterSeqStmt *altseqstmt;
List *attnamelist;
+ Constraint *constraint;
/*
* Determine namespace and name to use for the sequence.
***************
*** 471,476 **** transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
--- 471,493 ----
}
/* Process column constraints, if any... */
+ transformConstraintItems(cxt, column);
+ }
+
+ /*
+ * transformConstraintItems -
+ * Transform constraints as found on a column definition.
+ *
+ * in addition to transformColumnDefinition, this is used by ALTER TABLE
+ * ADD CONSTRAINT.
+ */
+ static void
+ transformConstraintItems(CreateStmtContext *cxt, ColumnDef *column)
+ {
+ bool saw_nullable;
+ bool saw_default;
+ ListCell *clist;
+
transformConstraintAttrs(cxt, column->constraints);
saw_nullable = false;
***************
*** 478,484 **** transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
foreach(clist, column->constraints)
{
! constraint = lfirst(clist);
Assert(IsA(constraint, Constraint));
switch (constraint->contype)
--- 495,501 ----
foreach(clist, column->constraints)
{
! Constraint *constraint = lfirst(clist);
Assert(IsA(constraint, Constraint));
switch (constraint->contype)
***************
*** 491,497 **** transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
column->colname, cxt->relation->relname),
parser_errposition(cxt->pstate,
constraint->location)));
! column->is_not_null = FALSE;
saw_nullable = true;
break;
--- 508,514 ----
column->colname, cxt->relation->relname),
parser_errposition(cxt->pstate,
constraint->location)));
! column->is_not_null = false;
saw_nullable = true;
break;
***************
*** 503,509 **** transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
column->colname, cxt->relation->relname),
parser_errposition(cxt->pstate,
constraint->location)));
! column->is_not_null = TRUE;
saw_nullable = true;
break;
--- 520,528 ----
column->colname, cxt->relation->relname),
parser_errposition(cxt->pstate,
constraint->location)));
! constraint->colname = column->colname;
! cxt->nnconstraints = lappend(cxt->nnconstraints, constraint);
! column->is_not_null = true;
saw_nullable = true;
break;
***************
*** 2287,2294 **** transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
/*
* The only subtypes that currently require parse transformation handling
! * are ADD COLUMN and ADD CONSTRAINT. These largely re-use code from
! * CREATE TABLE.
*/
foreach(lcmd, stmt->cmds)
{
--- 2306,2313 ----
/*
* The only subtypes that currently require parse transformation handling
! * are ADD COLUMN, ADD CONSTRAINT and ALTER COLUMN ADD CONSTRAINT. These
! * largely re-use code from CREATE TABLE.
*/
foreach(lcmd, stmt->cmds)
{
***************
*** 2346,2351 **** transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
--- 2365,2384 ----
newcmds = lappend(newcmds, cmd);
break;
+ case AT_ColumnConstraint:
+ /*
+ * The original ColumnConstraint node doesn't go to newcmds
+ */
+ {
+ ColumnDef *phony = makeNode(ColumnDef);
+ phony->colname = cmd->name;
+ phony->constraints = (List *) cmd->def;
+ transformConstraintItems(&cxt, phony);
+ if (phony->raw_default)
+ ereport(ERROR,
+ (errmsg("DEFAULT clause not supported in ALTER TABLE / ALTER COLUMN")));
+ }
+ break;
default:
newcmds = lappend(newcmds, cmd);
break;
***************
*** 2384,2390 **** transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
}
cxt.alist = NIL;
! /* Append any CHECK or FK constraints to the commands list */
foreach(l, cxt.ckconstraints)
{
newcmd = makeNode(AlterTableCmd);
--- 2417,2423 ----
}
cxt.alist = NIL;
! /* Append any CHECK, NOT NULL or FK constraints to the commands list */
foreach(l, cxt.ckconstraints)
{
newcmd = makeNode(AlterTableCmd);
***************
*** 2399,2404 **** transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
--- 2432,2444 ----
newcmd->def = (Node *) lfirst(l);
newcmds = lappend(newcmds, newcmd);
}
+ foreach(l, cxt.nnconstraints)
+ {
+ newcmd = makeNode(AlterTableCmd);
+ newcmd->subtype = AT_SetNotNull;
+ newcmd->name = ((Constraint *) lfirst(l))->colname;
+ newcmds = lappend(newcmds, newcmd);
+ }
/* Close rel but keep lock */
relation_close(rel, NoLock);
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
***************
*** 1177,1182 **** typedef enum AlterTableType
--- 1177,1183 ----
AT_AddColumnRecurse, /* internal to commands/tablecmds.c */
AT_AddColumnToView, /* implicitly via CREATE OR REPLACE VIEW */
AT_ColumnDefault, /* alter column default */
+ AT_ColumnConstraint, /* alter column add constraint */
AT_DropNotNull, /* alter column drop not null */
AT_SetNotNull, /* alter column set not null */
AT_SetStatistics, /* alter column set statistics */
***************
*** 1545,1550 **** typedef struct Constraint
--- 1546,1554 ----
char fk_upd_action; /* ON UPDATE action */
char fk_del_action; /* ON DELETE action */
+ /* Fields used for a NOT NULL constraints: */
+ char *colname; /* column name */
+
/* Fields used for constraints that allow a NOT VALID specification */
bool skip_validation; /* skip validation of existing rows? */
bool initially_valid; /* mark the new constraint as valid? */