diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 002319e8a02f1f79494713f3707adfa70c085741..eecc30f783f8856c00bba83db7fd5a66ea525eac 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -7776,7 +7776,7 @@ ATPrepAlterColumnType(List **wqueue, char *colName = cmd->name; ColumnDef *def = (ColumnDef *) cmd->def; TypeName *typeName = def->typeName; - Node *transform = def->raw_default; + Node *transform = def->cooked_default; HeapTuple tuple; Form_pg_attribute attTup; AttrNumber attnum; @@ -7835,34 +7835,13 @@ ATPrepAlterColumnType(List **wqueue, { /* * Set up an expression to transform the old data value to the new - * type. If a USING option was given, transform and use that - * expression, else just take the old value and try to coerce it. We - * do this first so that type incompatibility can be detected before - * we waste effort, and because we need the expression to be parsed - * against the original table row type. + * type. If a USING option was given, use the expression as transformed + * by transformAlterTableStmt, else just take the old value and try to + * coerce it. We do this first so that type incompatibility can be + * detected before we waste effort, and because we need the expression + * to be parsed against the original table row type. */ - if (transform) - { - RangeTblEntry *rte; - - /* Expression must be able to access vars of old table */ - rte = addRangeTableEntryForRelation(pstate, - rel, - NULL, - false, - true); - addRTEtoQuery(pstate, rte, false, true, true); - - transform = transformExpr(pstate, transform, - EXPR_KIND_ALTER_COL_TRANSFORM); - - /* It can't return a set */ - if (expression_returns_set(transform)) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("transform expression must not return a set"))); - } - else + if (!transform) { transform = (Node *) makeVar(1, attnum, attTup->atttypid, attTup->atttypmod, diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 1bbed9582c988e97692d9600f4822f3187725072..1fc8c2cbe1eac77eb05094784867f1a4272a67a0 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -2372,6 +2372,7 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, List *newcmds = NIL; bool skipValidation = true; AlterTableCmd *newcmd; + RangeTblEntry *rte; /* * We must not scribble on the passed-in AlterTableStmt, so copy it. (This @@ -2382,10 +2383,17 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, /* Caller is responsible for locking the relation */ rel = relation_open(relid, NoLock); - /* Set up pstate and CreateStmtContext */ + /* Set up pstate */ pstate = make_parsestate(NULL); pstate->p_sourcetext = queryString; + rte = addRangeTableEntryForRelation(pstate, + rel, + NULL, + false, + true); + addRTEtoQuery(pstate, rte, false, true, true); + /* Set up CreateStmtContext */ cxt.pstate = pstate; if (stmt->relkind == OBJECT_FOREIGN_TABLE) { @@ -2413,8 +2421,8 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, /* * The only subtypes that currently require parse transformation handling - * are ADD COLUMN and ADD CONSTRAINT. These largely re-use code from - * CREATE TABLE. + * are ADD COLUMN, ADD CONSTRAINT and SET DATA TYPE. These largely re-use + * code from CREATE TABLE. */ foreach(lcmd, stmt->cmds) { @@ -2446,6 +2454,7 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, newcmds = lappend(newcmds, cmd); break; } + case AT_AddConstraint: /* @@ -2472,6 +2481,31 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, newcmds = lappend(newcmds, cmd); break; + case AT_AlterColumnType: + { + ColumnDef *def = (ColumnDef *) cmd->def; + + /* + * For ALTER COLUMN TYPE, transform the USING clause if + * one was specified. + */ + if (def->raw_default) + { + def->cooked_default = + transformExpr(pstate, def->raw_default, + EXPR_KIND_ALTER_COL_TRANSFORM); + + /* it can't return a set */ + if (expression_returns_set(def->cooked_default)) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("transform expression must not return a set"))); + } + + newcmds = lappend(newcmds, cmd); + break; + } + default: newcmds = lappend(newcmds, cmd); break;