From 7a187f698d31638c65da10a71e97060793a29c7f Mon Sep 17 00:00:00 2001
From: Mikhail Titov <mlt@gmx.us>
Date: Wed, 12 Aug 2020 21:07:22 -0500
Subject: [PATCH 2/2] Allow DEFAULT in VALUES RTE for generated columns

---
 src/backend/parser/parse_relation.c  | 50 ++++++++++++++++++++++------
 src/backend/rewrite/rewriteHandler.c | 13 +++++++-
 2 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index b875a50646..da26863d22 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -2981,19 +2981,47 @@ expandNSItemVars(ParseNamespaceItem *nsitem,
 		if (colname[0])
 		{
 			Var		   *var;
+			ListCell   *c;
+			Node	   *std = NULL;
+			bool		all_default = true;

 			Assert(nscol->p_varno > 0);
-			var = makeVar(nscol->p_varno,
-						  nscol->p_varattno,
-						  nscol->p_vartype,
-						  nscol->p_vartypmod,
-						  nscol->p_varcollid,
-						  sublevels_up);
-			/* makeVar doesn't offer parameters for these, so set by hand: */
-			var->varnosyn = nscol->p_varnosyn;
-			var->varattnosyn = nscol->p_varattnosyn;
-			var->location = location;
-			result = lappend(result, var);
+			foreach(c, nsitem->p_rte->values_lists)
+			{
+				List *row = (List*) lfirst(c);
+				std = list_nth_node(Node, row, colindex);
+				if (!IsA(std, SetToDefault))
+				{
+					all_default = false;
+					break;
+				}
+			}
+
+			if (all_default && std)
+			{
+				/*
+				 * If all nodes for the column are SetToDefault, keep the marker
+				 * for later INSERT VALUES list rewriting where we remove
+				 * TLE and force NULL constant values node.
+				 * We cannot just remove values column
+				 * as attribute numbering will be off.
+				 */
+				result = lappend(result, std);
+			}
+			else
+			{
+				var = makeVar(nscol->p_varno,
+							  nscol->p_varattno,
+							  nscol->p_vartype,
+							  nscol->p_vartypmod,
+							  nscol->p_varcollid,
+							  sublevels_up);
+				/* makeVar doesn't offer parameters for these, so set by hand: */
+				var->varnosyn = nscol->p_varnosyn;
+				var->varattnosyn = nscol->p_varattnosyn;
+				var->location = location;
+				result = lappend(result, var);
+			}
 			if (colnames)
 				*colnames = lappend(*colnames, colnameval);
 		}
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index fe777c3103..f885fe7405 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -1373,8 +1373,19 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
 				Form_pg_attribute att_tup;
 				Node	   *new_expr;

+				/*
+				 * TLE was likely already removed for this generated column.
+				 * We do not have a good way to check it now,
+				 * but attrno should not be 0 anyway.
+				 */
 				if (attrno == 0)
-					elog(ERROR, "cannot set value in column %d to DEFAULT", i);
+				{
+					SetToDefault *std = (SetToDefault*) col;
+					new_expr = (Node*) makeNullConst(std->typeId, std->typeMod, std->collation);
+					newList = lappend(newList, new_expr);
+					continue;
+				}
+
 				att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1);

 				if (!force_nulls && !att_tup->attisdropped)
--
2.28.0.windows.1

