diff options
Diffstat (limited to 'src/backend/rewrite/rewriteHandler.c')
-rw-r--r-- | src/backend/rewrite/rewriteHandler.c | 65 |
1 files changed, 38 insertions, 27 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 4c1e1247b2c..a1d9122f828 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.121 2003/06/25 04:19:24 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.122 2003/07/03 16:34:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -250,7 +250,9 @@ adjustJoinTreeList(Query *parsetree, bool removert, int rt_index) * attributes that have defaults and are not assigned to in the given tlist. * (We do not insert anything for default-less attributes, however. The * planner will later insert NULLs for them, but there's no reason to slow - * down rewriter processing with extra tlist nodes.) + * down rewriter processing with extra tlist nodes.) Also, for both INSERT + * and UPDATE, replace explicit DEFAULT specifications with column default + * expressions. * * 2. Merge multiple entries for the same target attribute, or declare error * if we can't. Presently, multiple entries are only allowed for UPDATE of @@ -307,40 +309,49 @@ rewriteTargetList(Query *parsetree, Relation target_relation) { Assert(strcmp(resdom->resname, NameStr(att_tup->attname)) == 0); - - 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); - + new_tle = process_matched_tle(old_tle, new_tle); /* keep scanning to detect multiple assignments to attr */ } } - if (new_tle == NULL && commandType == CMD_INSERT) + /* + * Handle the two cases where we need to insert a default expression: + * it's an INSERT and there's no tlist entry for the column, or the + * tlist entry is a DEFAULT placeholder node. + */ + if ((new_tle == NULL && commandType == CMD_INSERT) || + (new_tle && new_tle->expr && IsA(new_tle->expr, SetToDefault))) { - /* - * Didn't find a matching tlist entry; if it's an INSERT, look - * for a default value, and add a tlist entry computing the - * default if we find one. - */ Node *new_expr; new_expr = build_column_default(target_relation, attrno); + /* + * If there is no default (ie, default is effectively NULL), + * we can omit the tlist entry in the INSERT case, since the + * planner can insert a NULL for itself, and there's no point + * in spending any more rewriter cycles on the entry. But in the + * UPDATE case we've got to explicitly set the column to NULL. + */ + if (!new_expr) + { + if (commandType == CMD_INSERT) + new_tle = NULL; + else + { + new_expr = (Node *) makeConst(att_tup->atttypid, + att_tup->attlen, + (Datum) 0, + true, /* isnull */ + att_tup->attbyval); + /* this is to catch a NOT NULL domain constraint */ + new_expr = coerce_to_domain(new_expr, + InvalidOid, + att_tup->atttypid, + COERCE_IMPLICIT_CAST); + } + } + if (new_expr) new_tle = makeTargetEntry(makeResdom(attrno, att_tup->atttypid, |