diff --git a/createas.c b/createas.c index b6649e5..d5aa664 100644 --- a/createas.c +++ b/createas.c @@ -289,6 +289,15 @@ rewriteQueryForIMMV(Query *query, List *colNames) ParseState *pstate = make_parsestate(NULL); FuncCall *fn; + /* + * Check the length of colunm name list not to override names of + * additional columns + */ + if (list_length(colNames) > list_length(query->targetList)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("too many column names were specified"))); + rewritten = copyObject(query); pstate->p_expr_kind = EXPR_KIND_SELECT_TARGET; @@ -321,10 +330,11 @@ rewriteQueryForIMMV(Query *query, List *colNames) foreach(lc, rewritten->targetList) { TargetEntry *tle = (TargetEntry *) lfirst(lc); - char *resname = (colNames == NIL ? tle->resname : strVal(list_nth(colNames, tle->resno - 1))); + char *resname = (colNames == NIL || foreach_current_index(lc) >= list_length(colNames) ? + tle->resname : strVal(list_nth(colNames, tle->resno - 1))); if (IsA(tle->expr, Aggref)) - makeIvmAggColumn(pstate, (Aggref *)tle->expr, resname, &next_resno, &aggs); + makeIvmAggColumn(pstate, (Aggref *) tle->expr, resname, &next_resno, &aggs); } rewritten->targetList = list_concat(rewritten->targetList, aggs); } diff --git a/expected/pg_ivm.out b/expected/pg_ivm.out index c329758..b203ad3 100644 --- a/expected/pg_ivm.out +++ b/expected/pg_ivm.out @@ -464,6 +464,55 @@ SELECT * FROM mv_ivm_min_max; | | 0 | 0 | 0 (1 row) +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +SELECT create_immv('mv_ivm_agg(a)', 'SELECT i, SUM(j) FROM mv_base_a GROUP BY i'); +NOTICE: created index "mv_ivm_agg_index" on immv "mv_ivm_agg" + create_immv +------------- + 5 +(1 row) + +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum | __ivm_count_sum__ | __ivm_count__ +---+------+-------------------+--------------- + 1 | 110 | 2 | 2 + 2 | 2200 | 2 | 2 + 3 | 300 | 1 | 1 + 4 | 40 | 1 | 1 + 5 | 50 | 1 | 1 +(5 rows) + +ROLLBACK; +BEGIN; +SELECT create_immv('mv_ivm_agg(a,b)', 'SELECT i, SUM(j) FROM mv_base_a GROUP BY i'); +NOTICE: created index "mv_ivm_agg_index" on immv "mv_ivm_agg" + create_immv +------------- + 5 +(1 row) + +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b | __ivm_count_b__ | __ivm_count__ +---+------+-----------------+--------------- + 1 | 110 | 2 | 2 + 2 | 2200 | 2 | 2 + 3 | 300 | 1 | 1 + 4 | 40 | 1 | 1 + 5 | 50 | 1 | 1 +(5 rows) + +ROLLBACK; +BEGIN; +SELECT create_immv('mv_ivm_agg(a,b,c)', 'SELECT i, SUM(j) FROM mv_base_a GROUP BY i'); +ERROR: too many column names were specified ROLLBACK; -- support self join view and multiple change on the same table BEGIN; diff --git a/pg_ivm.c b/pg_ivm.c index 02c96a6..885dab5 100644 --- a/pg_ivm.c +++ b/pg_ivm.c @@ -224,7 +224,7 @@ create_immv(PG_FUNCTION_ARGS) query = transformStmt(pstate, (Node *)ctas); Assert(query->commandType == CMD_UTILITY && IsA(query->utilityStmt, CreateTableAsStmt)); - ExecCreateImmv(pstate, (CreateTableAsStmt *)query->utilityStmt, NULL, NULL, &qc); + ExecCreateImmv(pstate, (CreateTableAsStmt *) query->utilityStmt, NULL, NULL, &qc); PG_RETURN_INT64(qc.nprocessed); } diff --git a/sql/pg_ivm.sql b/sql/pg_ivm.sql index 5d2dded..c775c85 100644 --- a/sql/pg_ivm.sql +++ b/sql/pg_ivm.sql @@ -150,6 +150,25 @@ DELETE FROM mv_base_a; SELECT * FROM mv_ivm_min_max; ROLLBACK; +-- aggregate views with column names specified +BEGIN; +SELECT create_immv('mv_ivm_agg(a)', 'SELECT i, SUM(j) FROM mv_base_a GROUP BY i'); +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +SELECT create_immv('mv_ivm_agg(a,b)', 'SELECT i, SUM(j) FROM mv_base_a GROUP BY i'); +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +SELECT create_immv('mv_ivm_agg(a,b,c)', 'SELECT i, SUM(j) FROM mv_base_a GROUP BY i'); +ROLLBACK; + -- support self join view and multiple change on the same table BEGIN; CREATE TABLE base_t (i int, v int);