From 53c4f1233fa950c0c6c0e0bbaa7a177278e14b04 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Wed, 25 Jun 2003 04:19:24 +0000 Subject: [PATCH] UPDATE ... SET = DEFAULT Rod Taylor --- doc/src/sgml/ref/update.sgml | 13 ++++++++-- src/backend/nodes/copyfuncs.c | 12 ++++----- src/backend/nodes/equalfuncs.c | 8 +++--- src/backend/parser/analyze.c | 24 +++++------------- src/backend/parser/gram.y | 13 ++++++++-- src/backend/parser/parse_target.c | 37 ++++++++++++++++++++-------- src/backend/rewrite/rewriteHandler.c | 22 +++++++++++++++-- src/include/nodes/nodes.h | 4 +-- src/include/nodes/parsenodes.h | 6 ++--- 9 files changed, 90 insertions(+), 49 deletions(-) diff --git a/doc/src/sgml/ref/update.sgml b/doc/src/sgml/ref/update.sgml index af7d8cce301..02cc07b0bd4 100644 --- a/doc/src/sgml/ref/update.sgml +++ b/doc/src/sgml/ref/update.sgml @@ -1,5 +1,5 @@ @@ -16,7 +16,7 @@ PostgreSQL documentation -UPDATE [ ONLY ] table SET column = expression [, ...] +UPDATE [ ONLY ] table SET column = { expression | DEFAULT } [, ...] [ FROM fromlist ] [ WHERE condition ] @@ -77,6 +77,15 @@ UPDATE [ ONLY ] table SET + + DEFAULT + + + This column will be filled with its default value. + + + + fromlist diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index ecc9703b7c5..0cd199656c0 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.254 2003/06/25 03:40:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.255 2003/06/25 04:19:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1661,10 +1661,10 @@ _copyFuncWithArgs(FuncWithArgs *from) return newnode; } -static InsertDefault * -_copyInsertDefault(InsertDefault *from) +static SetToDefault * +_copySetToDefault(SetToDefault *from) { - InsertDefault *newnode = makeNode(InsertDefault); + SetToDefault *newnode = makeNode(SetToDefault); return newnode; } @@ -2942,8 +2942,8 @@ copyObject(void *from) case T_FuncWithArgs: retval = _copyFuncWithArgs(from); break; - case T_InsertDefault: - retval = _copyInsertDefault(from); + case T_SetToDefault: + retval = _copySetToDefault(from); break; default: diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 0e46d46ea1b..93f63c586c6 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.197 2003/06/25 03:40:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.198 2003/06/25 04:19:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -728,7 +728,7 @@ _equalFuncWithArgs(FuncWithArgs *a, FuncWithArgs *b) } static bool -_equalInsertDefault(InsertDefault *a, InsertDefault *b) +_equalSetToDefault(SetToDefault *a, SetToDefault *b) { return true; } @@ -2055,8 +2055,8 @@ equal(void *a, void *b) case T_FuncWithArgs: retval = _equalFuncWithArgs(a, b); break; - case T_InsertDefault: - retval = _equalInsertDefault(a, b); + case T_SetToDefault: + retval = _equalSetToDefault(a, b); break; default: diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 6476b09f99b..99efae80721 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.276 2003/06/25 03:40:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.277 2003/06/25 04:19:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -660,23 +660,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt, col = (ResTarget *) lfirst(icolumns); Assert(IsA(col, ResTarget)); - /* - * When the value is to be set to the column default we can simply - * drop the TLE now and handle it later on using methods for missing - * columns. - */ - if (IsA(tle, InsertDefault)) - { - qry->targetList = lremove(tle, qry->targetList); - /* Note: the stmt->cols list is not adjusted to match */ - } - else - { - /* Normal case */ - Assert(!tle->resdom->resjunk); - updateTargetListEntry(pstate, tle, col->name, lfirsti(attnos), - col->indirection); - } + Assert(!tle->resdom->resjunk); + updateTargetListEntry(pstate, tle, col->name, lfirsti(attnos), + col->indirection); icolumns = lnext(icolumns); attnos = lnext(attnos); @@ -2431,10 +2417,12 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt) if (origTargetList == NIL) elog(ERROR, "UPDATE target count mismatch --- internal error"); origTarget = (ResTarget *) lfirst(origTargetList); + updateTargetListEntry(pstate, tle, origTarget->name, attnameAttNum(pstate->p_target_relation, origTarget->name, true), origTarget->indirection); + origTargetList = lnext(origTargetList); } if (origTargetList != NIL) diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 9806d658889..ed409c91715 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.419 2003/06/25 03:40:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.420 2003/06/25 04:19:24 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -6945,6 +6945,15 @@ update_target_el: $$->indirection = $2; $$->val = (Node *)$4; } + | ColId opt_indirection '=' DEFAULT + { + SetToDefault *def = makeNode(SetToDefault); + $$ = makeNode(ResTarget); + $$->name = $1; + $$->indirection = NULL; + $$->val = (Node *)def; + } + ; insert_target_list: @@ -6956,7 +6965,7 @@ insert_target_el: target_el { $$ = $1; } | DEFAULT { - InsertDefault *def = makeNode(InsertDefault); + SetToDefault *def = makeNode(SetToDefault); $$ = makeNode(ResTarget); $$->name = NULL; $$->indirection = NULL; diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 0b36e6b5e58..91726df7aa2 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.102 2003/05/31 19:03:34 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.103 2003/06/25 04:19:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -177,19 +177,24 @@ transformTargetList(ParseState *pstate, List *targetlist) false)); } } - else if (IsA(res->val, InsertDefault)) + else if (IsA(res->val, SetToDefault)) { - InsertDefault *newnode = makeNode(InsertDefault); - /* - * If this is a DEFAULT element, we make a junk entry which - * will get dropped on return to transformInsertStmt(). + * If this is a DEFAULT element, we make a standard entry using + * the default for the target expression. rewriteTargetList will + * substitute the columns default for this expression. */ - p_target = lappend(p_target, newnode); + p_target = lappend(p_target, + makeTargetEntry(makeResdom((AttrNumber) pstate->p_next_resno++, + UNKNOWNOID, + -1, + res->name, + false), + (Expr *) res->val)); } else { - /* Everything else but ColumnRef and InsertDefault */ + /* Everything else but ColumnRef and SetToDefault */ p_target = lappend(p_target, transformTargetEntry(pstate, res->val, @@ -321,9 +326,10 @@ updateTargetListEntry(ParseState *pstate, int attrno, List *indirection) { - Oid type_id = exprType((Node *) tle->expr); /* type of value provided */ + Oid type_id; /* type of value provided */ Oid attrtype; /* type of target column */ int32 attrtypmod; + bool isDefault = false; Resdom *resnode = tle->resdom; Relation rd = pstate->p_target_relation; @@ -333,6 +339,17 @@ updateTargetListEntry(ParseState *pstate, attrtype = attnumTypeId(rd, attrno); attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod; + /* The type of the default column is equivalent to that of the column */ + if (tle->expr != NULL && IsA(tle->expr, SetToDefault)) + { + type_id = attrtype; + isDefault = true; + } + + /* Otherwise the expression holds the type */ + else + type_id = exprType((Node *) tle->expr); + /* * If there are subscripts on the target column, prepare an array * assignment expression. This will generate an array value that the @@ -383,7 +400,7 @@ updateTargetListEntry(ParseState *pstate, * coercion. But accept InvalidOid, which indicates the source is * a NULL constant. (XXX is that still true?) */ - if (type_id != InvalidOid) + if (!isDefault && type_id != InvalidOid) { tle->expr = (Expr *) coerce_to_target_type(pstate, diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 5d481a3f0a5..4c1e1247b2c 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.120 2003/05/02 20:54:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.121 2003/06/25 04:19:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -307,7 +307,25 @@ rewriteTargetList(Query *parsetree, Relation target_relation) { Assert(strcmp(resdom->resname, NameStr(att_tup->attname)) == 0); - new_tle = process_matched_tle(old_tle, new_tle); + + if (old_tle->expr != NULL && IsA(old_tle->expr, SetToDefault)) + { + /* Set to the default value of the column, as requested */ + Node *new_expr; + + new_expr = build_column_default(target_relation, attrno); + + new_tle = makeTargetEntry(makeResdom(attrno, + att_tup->atttypid, + att_tup->atttypmod, + pstrdup(NameStr(att_tup->attname)), + false), + (Expr *) new_expr); + } + else + /* Normal Case */ + new_tle = process_matched_tle(old_tle, new_tle); + /* keep scanning to detect multiple assignments to attr */ } } diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index a6c2c022141..af87482e42a 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.141 2003/06/25 03:40:19 momjian Exp $ + * $Id: nodes.h,v 1.142 2003/06/25 04:19:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -277,7 +277,7 @@ typedef enum NodeTag T_PrivGrantee, T_FuncWithArgs, T_PrivTarget, - T_InsertDefault, + T_SetToDefault, T_CreateOpClassItem, T_CompositeTypeStmt, T_InhRelation, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 772e4341721..2e6e1559fa0 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.239 2003/06/25 03:40:19 momjian Exp $ + * $Id: parsenodes.h,v 1.240 2003/06/25 04:19:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -279,10 +279,10 @@ typedef struct ResTarget /* * Empty node used as a marker for Default Columns */ -typedef struct InsertDefault +typedef struct SetToDefault { NodeTag type; -} InsertDefault; +} SetToDefault; /* * SortGroupBy - for ORDER BY clause -- 2.30.2