diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index e587abd999..b6e96008ee 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -166,6 +166,15 @@ static relopt_bool boolRelOpts[] = }, true }, + { + { + "on_update_set_default", + "Automatically set the column to its default value if the column has a default value in an UPDATE statement", + RELOPT_KIND_ATTRIBUTE, + ShareUpdateExclusiveLock + }, + false + }, /* list terminator */ {{NULL}} }; @@ -2070,7 +2079,8 @@ attribute_reloptions(Datum reloptions, bool validate) { static const relopt_parse_elt tab[] = { {"n_distinct", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct)}, - {"n_distinct_inherited", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct_inherited)} + {"n_distinct_inherited", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct_inherited)}, + {"on_update_set_default", RELOPT_TYPE_BOOL, offsetof(AttributeOpts, on_update_set_default)} }; return (bytea *) build_reloptions(reloptions, validate, diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 1a5dfd0aa4..09ee1a29e8 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -41,6 +41,7 @@ #include "rewrite/rewriteSearchCycle.h" #include "rewrite/rowsecurity.h" #include "tcop/tcopprot.h" +#include "utils/attoptcache.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/rel.h" @@ -840,6 +841,7 @@ rewriteTargetListIU(List *targetList, { TargetEntry *new_tle = new_tles[attrno - 1]; bool apply_default; + bool on_update_set_default = false; att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1); @@ -975,6 +977,17 @@ rewriteTargetListIU(List *targetList, NameStr(att_tup->attname)), errdetail("Column \"%s\" is a generated column.", NameStr(att_tup->attname)))); + + if (!new_tle) + { + AttributeOpts *aopt; + + Assert(!apply_default); + + aopt = get_attribute_options(target_relation->rd_id, attrno); + if (aopt != NULL && aopt->on_update_set_default) + on_update_set_default = true; + } } if (att_tup->attgenerated) @@ -1027,6 +1040,24 @@ rewriteTargetListIU(List *targetList, pstrdup(NameStr(att_tup->attname)), false); } + else if(on_update_set_default) + { + Node *new_expr; + + Assert(!new_tle); + + new_expr = build_column_default(target_relation, attrno); + /* + * If there is a default value, it should be automatically updated + * to the default value; otherwise, we should not modify the value + * of that column. + */ + if (new_expr) + new_tle = makeTargetEntry((Expr *) new_expr, + attrno, + pstrdup(NameStr(att_tup->attname)), + false); + } if (new_tle) new_tlist = lappend(new_tlist, new_tle); diff --git a/src/include/utils/attoptcache.h b/src/include/utils/attoptcache.h index f684a772af..1fce8bedb5 100644 --- a/src/include/utils/attoptcache.h +++ b/src/include/utils/attoptcache.h @@ -21,6 +21,7 @@ typedef struct AttributeOpts int32 vl_len_; /* varlena header (do not touch directly!) */ float8 n_distinct; float8 n_distinct_inherited; + bool on_update_set_default; } AttributeOpts; extern AttributeOpts *get_attribute_options(Oid attrelid, int attnum);