hi
based on v29.
based on https://stackoverflow.com/a/4014981/1560347:
I added a new function  append_update_set_caluse, and deleted
functions: {append_set_clause_for_count, append_set_clause_for_sum,
append_set_clause_for_avg, append_set_clause_for_minmax}

I guess this way is more extensible/generic than yours.

replaced the following code with the generic function: append_update_set_caluse.
+ /* For views with aggregates, we need to build SET clause for
updating aggregate
+ * values. */
+ if (query->hasAggs && IsA(tle->expr, Aggref))
+ {
+ Aggref *aggref = (Aggref *) tle->expr;
+ const char *aggname = get_func_name(aggref->aggfnoid);
+
+ /*
+ * We can use function names here because it is already checked if these
+ * can be used in IMMV by its OID at the definition time.
+ */
+
+ /* count */
+ if (!strcmp(aggname, "count"))
+ append_set_clause_for_count(resname, aggs_set_old, aggs_set_new,
aggs_list_buf);
+
+ /* sum */
+ else if (!strcmp(aggname, "sum"))
+ append_set_clause_for_sum(resname, aggs_set_old, aggs_set_new, aggs_list_buf);
+
+ /* avg */
+ else if (!strcmp(aggname, "avg"))
+ append_set_clause_for_avg(resname, aggs_set_old, aggs_set_new, aggs_list_buf,
+   format_type_be(aggref->aggtype));
+
+ else
+ elog(ERROR, "unsupported aggregate function: %s", aggname);
+ }
----------------------<<<
attached is my refactor. there is some whitespace errors in the
patches, you need use
git apply --reject --whitespace=fix
basedon_v29_matview_c_refactor_update_set_clause.patch

Also you patch cannot use git apply, i finally found out bulk apply
using gnu patch from
https://serverfault.com/questions/102324/apply-multiple-patch-files.
previously I just did it manually one by one.

I think if you use { for i in  $PATCHES/v29*.patch; do patch -p1 < $i;
done } GNU patch, it will generate an .orig file for every modified
file?
-----------------<<<<<
src/backend/commands/matview.c
2268: /* For tuple deletion */
maybe "/* For tuple deletion and update*/" is more accurate?
-----------------<<<<<
currently at here: src/test/regress/sql/incremental_matview.sql
98: -- support SUM(), COUNT() and AVG() aggregate functions
99: BEGIN;
100: CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i,
SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i;
101: SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4;
102: INSERT INTO mv_base_a VALUES(2,100);

src/backend/commands/matview.c
2858: if (SPI_exec(querybuf.data, 0) != SPI_OK_INSERT)
2859: elog(ERROR, "SPI_exec failed: %s", querybuf.data);

then I debug, print out querybuf.data:
WITH updt AS (UPDATE public.mv_ivm_agg AS mv SET __ivm_count__ =
mv.__ivm_count__ OPERATOR(pg_catalog.+) diff.__ivm_count__ , sum =
(CASE WHEN mv.__ivm_count_sum__ OPERATOR(pg_catalog.=) 0 AND
diff.__ivm_count_sum__ OPERATOR(pg_catalog.=) 0 THEN NULL WHEN mv.sum
IS NULL THEN diff.sum WHEN diff.sum IS NULL THEN mv.sum ELSE (mv.sum
OPERATOR(pg_catalog.+) diff.sum) END), __ivm_count_sum__ =
(mv.__ivm_count_sum__ OPERATOR(pg_catalog.+) diff.__ivm_count_sum__),
count = (mv.count OPERATOR(pg_catalog.+) diff.count), avg = (CASE WHEN
mv.__ivm_count_avg__ OPERATOR(pg_catalog.=) 0 AND
diff.__ivm_count_avg__ OPERATOR(pg_catalog.=) 0 THEN NULL WHEN
mv.__ivm_sum_avg__ IS NULL THEN diff.__ivm_sum_avg__ WHEN
diff.__ivm_sum_avg__ IS NULL THEN mv.__ivm_sum_avg__ ELSE
(mv.__ivm_sum_avg__ OPERATOR(pg_catalog.+)
diff.__ivm_sum_avg__)::numeric END) OPERATOR(pg_catalog./)
(mv.__ivm_count_avg__ OPERATOR(pg_catalog.+) diff.__ivm_count_avg__),
__ivm_sum_avg__ = (CASE WHEN mv.__ivm_count_avg__
OPERATOR(pg_catalog.=) 0 AND diff.__ivm_count_avg__
OPERATOR(pg_catalog.=) 0 THEN NULL WHEN mv.__ivm_sum_avg__ IS NULL
THEN diff.__ivm_sum_avg__ WHEN diff.__ivm_sum_avg__ IS NULL THEN
mv.__ivm_sum_avg__ ELSE (mv.__ivm_sum_avg__ OPERATOR(pg_catalog.+)
diff.__ivm_sum_avg__) END), __ivm_count_avg__ = (mv.__ivm_count_avg__
OPERATOR(pg_catalog.+) diff.__ivm_count_avg__) FROM new_delta AS diff
WHERE (mv.i OPERATOR(pg_catalog.=) diff.i OR (mv.i IS NULL AND diff.i
IS NULL)) RETURNING mv.i) INSERT INTO public.mv_ivm_agg (i, sum,
count, avg, __ivm_count_sum__, __ivm_count_avg__, __ivm_sum_avg__,
__ivm_count__) SELECT i, sum, count, avg, __ivm_count_sum__,
__ivm_count_avg__, __ivm_sum_avg__, __ivm_count__ FROM new_delta AS
diff WHERE NOT EXISTS (SELECT 1 FROM updt AS mv WHERE (mv.i
OPERATOR(pg_catalog.=) diff.i OR (mv.i IS NULL AND diff.i IS NULL)));

At this final SPI_exec, we have a update statement with related
columns { __ivm_count_sum__, sum, __ivm_count__, count, avg,
__ivm_sum_avg__, __ivm_count_avg__}. At this time, my mind stops
working, querybuf.data is way too big, but I still feel like there is
some logic associated with these columns, maybe we can use it as an
assertion to prove that this query (querybuf.len = 1834) is indeed
correct.

Since the apply delta query is quite complex, I feel like adding some
"if debug then print out the final querybuf.data end if" would be a
good idea.

we add hidden columns somewhere, also to avoid corner cases, so maybe
somewhere we should assert total attribute number is sane.
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index eff512d4..33f385cb 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -149,12 +149,39 @@ typedef enum
 	IVM_SUB
 } IvmOp;
 
+typedef enum
+{
+    BAD_AGGFUNC,
+    IVM_COUNT,
+    IVM_SUM,
+    IVM_AVG,
+    IVM_MIN,
+    IVM_MAX
+} IvmAggType;
+
+typedef struct aggname_entry
+{
+    const char *agg_name;
+    int val;
+} aggname_entry;
+
+/* map aggregate name with enum */
+static aggname_entry ivm_agg_lookup[] =
+{
+    { "count",IVM_COUNT},
+    { "sum", IVM_SUM},
+    { "avg", IVM_AVG},
+    { "min",IVM_MIN},
+    { "max",IVM_MAX}
+};
+
 /* ENR name for materialized view delta */
 #define NEW_DELTA_ENRNAME "new_delta"
 #define OLD_DELTA_ENRNAME "old_delta"
 
 static int	matview_maintenance_depth = 0;
 
+static int get_ivm_aggfunc(const char *agg_name);
 static void transientrel_startup(DestReceiver *self, int operation, TupleDesc typeinfo);
 static bool transientrel_receive(TupleTableSlot *slot, DestReceiver *self);
 static void transientrel_shutdown(DestReceiver *self);
@@ -191,16 +218,7 @@ static Query *rewrite_query_for_postupdate_state(Query *query, MV_TriggerTable *
 static void apply_delta(Oid matviewOid, Tuplestorestate *old_tuplestores, Tuplestorestate *new_tuplestores,
 			TupleDesc tupdesc_old, TupleDesc tupdesc_new,
 			Query *query, bool use_count, char *count_colname);
-static void append_set_clause_for_count(const char *resname, StringInfo buf_old,
-							StringInfo buf_new,StringInfo aggs_list);
-static void append_set_clause_for_sum(const char *resname, StringInfo buf_old,
-						  StringInfo buf_new, StringInfo aggs_list);
-static void append_set_clause_for_avg(const char *resname, StringInfo buf_old,
-						  StringInfo buf_new, StringInfo aggs_list,
-						  const char *aggtype);
-static void append_set_clause_for_minmax(const char *resname, StringInfo buf_old,
-							 StringInfo buf_new, StringInfo aggs_list,
-							 bool is_min);
+
 static char *get_operation_string(IvmOp op, const char *col, const char *arg1, const char *arg2,
 					 const char* count_col, const char *castType);
 static char *get_null_condition_string(IvmOp op, const char *arg1, const char *arg2,
@@ -235,6 +253,25 @@ static void mv_HashPreparedPlan(MV_QueryKey *key, SPIPlanPtr plan);
 static void mv_BuildQueryKey(MV_QueryKey *key, Oid matview_id, int32 query_type);
 static void clean_up_IVM_hash_entry(MV_TriggerHashEntry *entry, bool is_abort);
 
+static void append_update_set_caluse(const char *aggname, char *resname, StringInfo buf_old,
+							StringInfo buf_new,StringInfo aggs_list,
+                            char *aggtype);
+
+int
+get_ivm_aggfunc(const char *agg_name)
+{
+#define NKEYS (sizeof(ivm_agg_lookup)/sizeof(aggname_entry))
+
+    int i;
+    for (i=0; i < NKEYS; i++)
+    {
+        aggname_entry *entry = &ivm_agg_lookup[i];
+        if (strcmp(entry->agg_name, agg_name) == 0)
+            return entry->val;
+    }
+    return BAD_AGGFUNC;
+}
+
 /*
  * SetMatViewPopulatedState
  *		Mark a materialized view as populated, or not.
@@ -2210,38 +2247,23 @@ apply_delta(Oid matviewOid, Tuplestorestate *old_tuplestores, Tuplestorestate *n
 		{
 			Aggref *aggref = (Aggref *) tle->expr;
 			const char *aggname = get_func_name(aggref->aggfnoid);
+			char *aggtype = format_type_be(aggref->aggtype);
 
 			/*
 			 * We can use function names here because it is already checked if these
 			 * can be used in IMMV by its OID at the definition time.
 			 */
-
-			/* count */
-			if (!strcmp(aggname, "count"))
-				append_set_clause_for_count(resname, aggs_set_old, aggs_set_new, aggs_list_buf);
-
-			/* sum */
-			else if (!strcmp(aggname, "sum"))
-				append_set_clause_for_sum(resname, aggs_set_old, aggs_set_new, aggs_list_buf);
-
-			/* avg */
-			else if (!strcmp(aggname, "avg"))
-				append_set_clause_for_avg(resname, aggs_set_old, aggs_set_new, aggs_list_buf,
-										  format_type_be(aggref->aggtype));
-
-			/* min/max */
-			else if (!strcmp(aggname, "min") || !strcmp(aggname, "max"))
+            (void) append_update_set_caluse(aggname, resname, aggs_set_old,
+							aggs_set_new, aggs_list_buf, aggtype);
+            
+			if (!strcmp(aggname, "min") || !strcmp(aggname, "max"))
 			{
 				bool	is_min = (!strcmp(aggname, "min"));
 
-				append_set_clause_for_minmax(resname, aggs_set_old, aggs_set_new, aggs_list_buf, is_min);
-
 				/* make a resname list of min and max aggregates */
 				minmax_list = lappend(minmax_list, resname);
 				is_min_list = lappend_int(is_min_list, is_min);
 			}
-			else
-				elog(ERROR, "unsupported aggregate function: %s", aggname);
 		}
 	}
 
@@ -2338,224 +2360,6 @@ apply_delta(Oid matviewOid, Tuplestorestate *old_tuplestores, Tuplestorestate *n
 		elog(ERROR, "SPI_finish failed");
 }
 
-/*
- * append_set_clause_for_count
- *
- * Append SET clause string for count aggregation to given buffers.
- * Also, append resnames required for calculating the aggregate value.
- */
-static void
-append_set_clause_for_count(const char *resname, StringInfo buf_old,
-							StringInfo buf_new,StringInfo aggs_list)
-{
-	/* For tuple deletion */
-	if (buf_old)
-	{
-		/* resname = mv.resname - t.resname */
-		appendStringInfo(buf_old,
-			", %s = %s",
-			quote_qualified_identifier(NULL, resname),
-			get_operation_string(IVM_SUB, resname, "mv", "t", NULL, NULL));
-	}
-	/* For tuple insertion */
-	if (buf_new)
-	{
-		/* resname = mv.resname + diff.resname */
-		appendStringInfo(buf_new,
-			", %s = %s",
-			quote_qualified_identifier(NULL, resname),
-			get_operation_string(IVM_ADD, resname, "mv", "diff", NULL, NULL));
-	}
-
-	appendStringInfo(aggs_list, ", %s",
-		quote_qualified_identifier("diff", resname)
-	);
-}
-
-/*
- * append_set_clause_for_sum
- *
- * Append SET clause string for sum aggregation to given buffers.
- * Also, append resnames required for calculating the aggregate value.
- */
-static void
-append_set_clause_for_sum(const char *resname, StringInfo buf_old,
-						  StringInfo buf_new, StringInfo aggs_list)
-{
-	char *count_col = IVM_colname("count", resname);
-
-	/* For tuple deletion */
-	if (buf_old)
-	{
-		/* sum = mv.sum - t.sum */
-		appendStringInfo(buf_old,
-			", %s = %s",
-			quote_qualified_identifier(NULL, resname),
-			get_operation_string(IVM_SUB, resname, "mv", "t", count_col, NULL)
-		);
-		/* count = mv.count - t.count */
-		appendStringInfo(buf_old,
-			", %s = %s",
-			quote_qualified_identifier(NULL, count_col),
-			get_operation_string(IVM_SUB, count_col, "mv", "t", NULL, NULL)
-		);
-	}
-	/* For tuple insertion */
-	if (buf_new)
-	{
-		/* sum = mv.sum + diff.sum */
-		appendStringInfo(buf_new,
-			", %s = %s",
-			quote_qualified_identifier(NULL, resname),
-			get_operation_string(IVM_ADD, resname, "mv", "diff", count_col, NULL)
-		);
-		/* count = mv.count + diff.count */
-		appendStringInfo(buf_new,
-			", %s = %s",
-			quote_qualified_identifier(NULL, count_col),
-			get_operation_string(IVM_ADD, count_col, "mv", "diff", NULL, NULL)
-		);
-	}
-
-	appendStringInfo(aggs_list, ", %s, %s",
-		quote_qualified_identifier("diff", resname),
-		quote_qualified_identifier("diff", IVM_colname("count", resname))
-	);
-}
-
-/*
- * append_set_clause_for_avg
- *
- * Append SET clause string for avg aggregation to given buffers.
- * Also, append resnames required for calculating the aggregate value.
- */
-static void
-append_set_clause_for_avg(const char *resname, StringInfo buf_old,
-						  StringInfo buf_new, StringInfo aggs_list,
-						  const char *aggtype)
-{
-	char *sum_col = IVM_colname("sum", resname);
-	char *count_col = IVM_colname("count", resname);
-
-	/* For tuple deletion */
-	if (buf_old)
-	{
-		/* avg = (mv.sum - t.sum)::aggtype / (mv.count - t.count) */
-		appendStringInfo(buf_old,
-			", %s = %s OPERATOR(pg_catalog./) %s",
-			quote_qualified_identifier(NULL, resname),
-			get_operation_string(IVM_SUB, sum_col, "mv", "t", count_col, aggtype),
-			get_operation_string(IVM_SUB, count_col, "mv", "t", NULL, NULL)
-		);
-		/* sum = mv.sum - t.sum */
-		appendStringInfo(buf_old,
-			", %s = %s",
-			quote_qualified_identifier(NULL, sum_col),
-			get_operation_string(IVM_SUB, sum_col, "mv", "t", count_col, NULL)
-		);
-		/* count = mv.count - t.count */
-		appendStringInfo(buf_old,
-			", %s = %s",
-			quote_qualified_identifier(NULL, count_col),
-			get_operation_string(IVM_SUB, count_col, "mv", "t", NULL, NULL)
-		);
-
-	}
-	/* For tuple insertion */
-	if (buf_new)
-	{
-		/* avg = (mv.sum + diff.sum)::aggtype / (mv.count + diff.count) */
-		appendStringInfo(buf_new,
-			", %s = %s OPERATOR(pg_catalog./) %s",
-			quote_qualified_identifier(NULL, resname),
-			get_operation_string(IVM_ADD, sum_col, "mv", "diff", count_col, aggtype),
-			get_operation_string(IVM_ADD, count_col, "mv", "diff", NULL, NULL)
-		);
-		/* sum = mv.sum + diff.sum */
-		appendStringInfo(buf_new,
-			", %s = %s",
-			quote_qualified_identifier(NULL, sum_col),
-			get_operation_string(IVM_ADD, sum_col, "mv", "diff", count_col, NULL)
-		);
-		/* count = mv.count + diff.count */
-		appendStringInfo(buf_new,
-			", %s = %s",
-			quote_qualified_identifier(NULL, count_col),
-			get_operation_string(IVM_ADD, count_col, "mv", "diff", NULL, NULL)
-		);
-	}
-
-	appendStringInfo(aggs_list, ", %s, %s, %s",
-		quote_qualified_identifier("diff", resname),
-		quote_qualified_identifier("diff", IVM_colname("sum", resname)),
-		quote_qualified_identifier("diff", IVM_colname("count", resname))
-	);
-}
-
-/*
- * append_set_clause_for_minmax
- *
- * Append SET clause string for min or max aggregation to given buffers.
- * Also, append resnames required for calculating the aggregate value.
- * is_min is true if this is min, false if not.
- */
-static void
-append_set_clause_for_minmax(const char *resname, StringInfo buf_old,
-							 StringInfo buf_new, StringInfo aggs_list,
-							 bool is_min)
-{
-	char *count_col = IVM_colname("count", resname);
-
-	/* For tuple deletion */
-	if (buf_old)
-	{
-		/*
-		 * If the new value doesn't became NULL then use the value remaining
-		 * in the view although this will be recomputated afterwords.
-		 */
-		appendStringInfo(buf_old,
-			", %s = CASE WHEN %s THEN NULL ELSE %s END",
-			quote_qualified_identifier(NULL, resname),
-			get_null_condition_string(IVM_SUB, "mv", "t", count_col),
-			quote_qualified_identifier("mv", resname)
-		);
-		/* count = mv.count - t.count */
-		appendStringInfo(buf_old,
-			", %s = %s",
-			quote_qualified_identifier(NULL, count_col),
-			get_operation_string(IVM_SUB, count_col, "mv", "t", NULL, NULL)
-		);
-	}
-	/* For tuple insertion */
-	if (buf_new)
-	{
-		/*
-		 * min = LEAST(mv.min, diff.min)
-		 * max = GREATEST(mv.max, diff.max)
-		 */
-		appendStringInfo(buf_new,
-			", %s = CASE WHEN %s THEN NULL ELSE %s(%s,%s) END",
-			quote_qualified_identifier(NULL, resname),
-			get_null_condition_string(IVM_ADD, "mv", "diff", count_col),
-
-			is_min ? "LEAST" : "GREATEST",
-			quote_qualified_identifier("mv", resname),
-			quote_qualified_identifier("diff", resname)
-		);
-		/* count = mv.count + diff.count */
-		appendStringInfo(buf_new,
-			", %s = %s",
-			quote_qualified_identifier(NULL, count_col),
-			get_operation_string(IVM_ADD, count_col, "mv", "diff", NULL, NULL)
-		);
-	}
-
-	appendStringInfo(aggs_list, ", %s, %s",
-		quote_qualified_identifier("diff", resname),
-		quote_qualified_identifier("diff", IVM_colname("count", resname))
-	);
-}
-
 /*
  * get_operation_string
  *
@@ -3482,3 +3286,228 @@ isIvmName(const char *s)
 		return (strncmp(s, "__ivm_", 6) == 0);
 	return false;
 }
+
+void
+append_update_set_caluse(const char *aggname, char *resname, StringInfo buf_old,
+							StringInfo buf_new, StringInfo aggs_list,
+                            char *aggtype)
+{    
+    char *count_col = IVM_colname("count", resname);
+	char *sum_col = IVM_colname("sum", resname);
+
+    switch (get_ivm_aggfunc(aggname))
+    {
+        case IVM_COUNT:
+            if (buf_old)
+                appendStringInfo(buf_old,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, resname),
+                    get_operation_string(IVM_SUB, resname, "mv", "t", NULL, NULL));
+
+            if (buf_new)
+                appendStringInfo(buf_new,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, resname),
+                    get_operation_string(IVM_ADD, resname, "mv", "diff", NULL, NULL));
+
+            appendStringInfo(aggs_list, ", %s",
+                quote_qualified_identifier("diff", resname));
+			break;
+
+        case IVM_SUM:
+            if (buf_old)
+            {
+				/* sum = mv.sum - t.sum */
+                appendStringInfo(buf_old,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, resname),
+                    get_operation_string(IVM_SUB, resname, "mv", "t", count_col, NULL)
+                );
+
+                /* count = mv.count - t.count */
+                appendStringInfo(buf_old,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, count_col),
+                    get_operation_string(IVM_SUB, count_col, "mv", "t", NULL, NULL)
+                );
+            }
+
+            if (buf_new)
+            {
+                /* sum = mv.sum + diff.sum */
+                appendStringInfo(buf_new,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, resname),
+                    get_operation_string(IVM_ADD, resname, "mv", "diff", count_col, NULL)
+                );
+                
+				/* count = mv.count + diff.count */
+                appendStringInfo(buf_new,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, count_col),
+                    get_operation_string(IVM_ADD, count_col, "mv", "diff", NULL, NULL)
+                );
+            }
+
+            appendStringInfo(aggs_list, ", %s, %s",
+                quote_qualified_identifier("diff", resname),
+                quote_qualified_identifier("diff", IVM_colname("count", resname)));
+            break;
+
+        case IVM_AVG:
+            if (buf_old)
+            {
+                /* avg = (mv.sum - t.sum)::aggtype / (mv.count - t.count) */
+                appendStringInfo(buf_old,
+                    ", %s = %s OPERATOR(pg_catalog./) %s",
+                    quote_qualified_identifier(NULL, resname),
+                    get_operation_string(IVM_SUB, sum_col, "mv", "t", count_col, aggtype),
+                    get_operation_string(IVM_SUB, count_col, "mv", "t", NULL, NULL)
+                );
+                
+				/* sum = mv.sum - t.sum */
+                appendStringInfo(buf_old,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, sum_col),
+                    get_operation_string(IVM_SUB, sum_col, "mv", "t", count_col, NULL)
+                );
+                
+				/* count = mv.count - t.count */
+                appendStringInfo(buf_old,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, count_col),
+                    get_operation_string(IVM_SUB, count_col, "mv", "t", NULL, NULL)
+                );
+            }
+            
+            if (buf_new)
+            {
+                /* avg = (mv.sum + diff.sum)::aggtype / (mv.count + diff.count) */
+                appendStringInfo(buf_new,
+                    ", %s = %s OPERATOR(pg_catalog./) %s",
+                    quote_qualified_identifier(NULL, resname),
+                    get_operation_string(IVM_ADD, sum_col, "mv", "diff", count_col, aggtype),
+                    get_operation_string(IVM_ADD, count_col, "mv", "diff", NULL, NULL)
+                );
+                /* sum = mv.sum + diff.sum */
+                appendStringInfo(buf_new,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, sum_col),
+                    get_operation_string(IVM_ADD, sum_col, "mv", "diff", count_col, NULL)
+                );
+                /* count = mv.count + diff.count */
+                appendStringInfo(buf_new,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, count_col),
+                    get_operation_string(IVM_ADD, count_col, "mv", "diff", NULL, NULL)
+                );
+            }
+
+			appendStringInfo(aggs_list, ", %s, %s, %s",
+				quote_qualified_identifier("diff", resname),
+				quote_qualified_identifier("diff", IVM_colname("sum", resname)),
+				quote_qualified_identifier("diff", IVM_colname("count", resname)));
+
+            break;
+
+        case IVM_MIN:
+            if (buf_old)
+            {
+                /*
+                * If the new value doesn't became NULL then use the value remaining
+                * in the view although this will be recomputated afterwords.
+                */
+                appendStringInfo(buf_old,
+                    ", %s = CASE WHEN %s THEN NULL ELSE %s END",
+                    quote_qualified_identifier(NULL, resname),
+                    get_null_condition_string(IVM_SUB, "mv", "t", count_col),
+                    quote_qualified_identifier("mv", resname)
+                );
+                /* count = mv.count - t.count */
+                appendStringInfo(buf_old,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, count_col),
+                    get_operation_string(IVM_SUB, count_col, "mv", "t", NULL, NULL)
+                );
+            }
+
+            if (buf_new)
+            {                
+                /* min = LEAST(mv.min, diff.min) */         
+                appendStringInfo(buf_new,
+                    ", %s = CASE WHEN %s THEN NULL ELSE %s(%s,%s) END",
+                    quote_qualified_identifier(NULL, resname),
+                    get_null_condition_string(IVM_ADD, "mv", "diff", count_col),
+                    "LEAST",
+                    quote_qualified_identifier("mv", resname),
+                    quote_qualified_identifier("diff", resname)
+                );
+
+                /* count = mv.count + diff.count */
+                appendStringInfo(buf_new,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, count_col),
+                    get_operation_string(IVM_ADD, count_col, "mv", "diff", NULL, NULL)
+                );
+            }
+        	appendStringInfo(aggs_list, ", %s, %s",
+                quote_qualified_identifier("diff", resname),
+                quote_qualified_identifier("diff", IVM_colname("count", resname)));
+            break;
+
+        case IVM_MAX:
+            if (buf_old)
+            {
+                /*
+                * If the new value doesn't became NULL then use the value remaining
+                * in the view although this will be recomputated afterwords.
+                */
+                appendStringInfo(buf_old,
+                    ", %s = CASE WHEN %s THEN NULL ELSE %s END",
+                    quote_qualified_identifier(NULL, resname),
+                    get_null_condition_string(IVM_SUB, "mv", "t", count_col),
+                    quote_qualified_identifier("mv", resname)
+                );
+                /* count = mv.count - t.count */
+                appendStringInfo(buf_old,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, count_col),
+                    get_operation_string(IVM_SUB, count_col, "mv", "t", NULL, NULL)
+                );
+            }
+
+            if (buf_new)
+            {
+                /* max = GREATEST(mv.max, diff.max) */
+                appendStringInfo(buf_new,
+                    ", %s = CASE WHEN %s THEN NULL ELSE %s(%s,%s) END",
+                    quote_qualified_identifier(NULL, resname),
+                    get_null_condition_string(IVM_ADD, "mv", "diff", count_col),
+                    "GREATEST",
+                    quote_qualified_identifier("mv", resname),
+                    quote_qualified_identifier("diff", resname)
+                );
+
+                /* count = mv.count + diff.count */
+                appendStringInfo(buf_new,
+                    ", %s = %s",
+                    quote_qualified_identifier(NULL, count_col),
+                    get_operation_string(IVM_ADD, count_col, "mv", "diff", NULL, NULL)
+                );
+            }
+
+        	appendStringInfo(aggs_list, ", %s, %s",
+                quote_qualified_identifier("diff", resname),
+                quote_qualified_identifier("diff", IVM_colname("count", resname)));
+			break;
+
+		case BAD_AGGFUNC:
+            elog(ERROR, "unsupported aggregate function: %s", aggname);
+            break;
+
+        default:
+            elog(ERROR, "unsupported aggregate function: %s", aggname);
+            break;
+    }
+	return;
+}
\ No newline at end of file

Reply via email to