diff --git a/src/common/backend/parser/parse_clause.cpp b/src/common/backend/parser/parse_clause.cpp index 160882119a4630b4393325ecac195b11640b40ee..3b8ae8f9c50ef57e519866290516ecf232778c18 100644 --- a/src/common/backend/parser/parse_clause.cpp +++ b/src/common/backend/parser/parse_clause.cpp @@ -89,7 +89,6 @@ static Node* transformGroupingSet(List** flatresult, ParseState* pstate, Groupin static Index transformGroupClauseExpr(List** flatresult, Bitmapset* seen_local, ParseState* pstate, Node* gexpr, List** targetlist, List* sortClause, ParseExprKind exprKind, bool useSQL99, bool toplevel); static void CheckOrderbyColumns(ParseState* pstate, List* targetList, bool isAggregate); -static bool ColNameInFuncParasList(char *colName, List *funcParaList); /* * @Description: append from clause item to the left tree @@ -594,6 +593,40 @@ static RangeTblEntry* transformCTEReference(ParseState* pstate, RangeVar* r, Com return rte; } +bool PullColumnRefWalker(Node* node, PullColumnRefContext* context) +{ + if (node == NULL) { + return false; + } + if (IsA(node, ColumnRef)) { + context->columnRefs = lappend(context->columnRefs, node); + return false; + } + return raw_expression_tree_walker(node, (bool (*)())PullColumnRefWalker, (void*)context); +} + +List* PullColumnRefs(Node* node) +{ + PullColumnRefContext context; + context.columnRefs = NIL; + + PullColumnRefWalker(node, &context); + + return context.columnRefs; +} + +static bool ColNameInFuncParasList(char* colName, List* columnsInAggFunc) +{ + ListCell* cell; + + foreach (cell, columnsInAggFunc) { + ColumnRef* cr = (ColumnRef*)lfirst(cell); + if (strcmp(colName, strVal(lfirst(list_head(cr->fields)))) == 0) + return true; + } + return false; +} + /* * transformRangeSubselect --- transform a sub-SELECT appearing in FROM */ @@ -625,6 +658,7 @@ static RangeTblEntry* transformRangeSubselect(ParseState* pstate, RangeSubselect ColumnRef *cref; ResTarget *resT; List *filterlist; + List *columnsInAggFunc = NIL; subQueryStmt = (SelectStmt *)r->subquery; prev = NULL; if (1 == list_length(subQueryStmt->targetList)) { @@ -658,13 +692,14 @@ static RangeTblEntry* transformRangeSubselect(ParseState* pstate, RangeSubselect } /* remove target */ + columnsInAggFunc = PullColumnRefs((Node*)r->rotate->aggregateFuncCallList); for (targetCell = list_head(subQueryStmt->targetList); targetCell; targetCell = next) { ResTarget *resTarget = (ResTarget *)lfirst(targetCell); next = lnext(targetCell); if (IsA(resTarget->val, ColumnRef)) { char *colName = strVal(lfirst(list_head(((ColumnRef *)resTarget->val)->fields))); if (list_member(r->rotate->forColName, lfirst(list_head(((ColumnRef *)resTarget->val)->fields))) || - ColNameInFuncParasList(colName, r->rotate->aggregateFuncCallList)) + ColNameInFuncParasList(colName, columnsInAggFunc)) subQueryStmt->targetList = list_delete_cell(subQueryStmt->targetList, targetCell, prev); else prev = targetCell; @@ -796,21 +831,6 @@ static RangeTblEntry* transformRangeSubselect(ParseState* pstate, RangeSubselect return rte; } -static bool ColNameInFuncParasList(char *colName, List *funcParaList) -{ - ListCell *cell; - ListCell *paracell; - foreach (cell, funcParaList) { - FuncCall *aggregateFuncCall = (FuncCall *)lfirst(cell); - foreach (paracell, aggregateFuncCall->args) { - ColumnRef *cr = (ColumnRef *)lfirst(paracell); - if (strcmp(colName, strVal(lfirst(list_head(cr->fields)))) == 0) - return true; - } - } - return false; -} - /* * transformRangeFunction --- transform a function call appearing in FROM */ diff --git a/src/include/nodes/parsenodes_common.h b/src/include/nodes/parsenodes_common.h index e678644475fb6d5e7bc91d6b9858401ed5724d64..39fd8a96f09cae281b9f1f69d115ce22276b82c0 100644 --- a/src/include/nodes/parsenodes_common.h +++ b/src/include/nodes/parsenodes_common.h @@ -1568,6 +1568,10 @@ typedef struct ColumnRef { int location; /* token location, or -1 if unknown */ } ColumnRef; +typedef struct { + List* columnRefs; +}PullColumnRefContext; + /* * TimeCapsuleClause - TIMECAPSULE appearing in a transformed FROM clause * diff --git a/src/test/regress/expected/gb_ora_rotate_unrotate.out b/src/test/regress/expected/gb_ora_rotate_unrotate.out index a23d8ddd241a4595e037f9fe2a7df1a1f1ad5bbc..c67723ef651b81d2eecdbcacce76f4cf71bbaff4 100644 --- a/src/test/regress/expected/gb_ora_rotate_unrotate.out +++ b/src/test/regress/expected/gb_ora_rotate_unrotate.out @@ -31,6 +31,14 @@ select * from (select year, order_mode, order_total from original_orders) rotate 2022 | (3 rows) +select * from ( select year, order_mode, order_total from original_orders) rotate (sum(order_total + 100) for order_mode in ('direct' as store, 'online' as internet)) order by year; + year | store | internet +------+-------+---------- + 2020 | 5700 | 1100 + 2021 | 1100 | 1100 + 2022 | 5100 | +(3 rows) + create table rotate_orders as (select * from (select year, order_mode, order_total from original_orders) as t rotate (sum(order_total) for order_mode in ('direct' as store, 'online' as internet)) order by year); -- test not rotate (column transform to row) select * from rotate_orders not rotate ( yearly_total for order_mode in ( store as 'direct', internet as 'online')); diff --git a/src/test/regress/sql/gb_ora_rotate_unrotate.sql b/src/test/regress/sql/gb_ora_rotate_unrotate.sql index ea895c9b2acca83e7412ca965b61dccd37d2509a..8cb15d14c9fbf04ebb261c53a507f3de46319981 100644 --- a/src/test/regress/sql/gb_ora_rotate_unrotate.sql +++ b/src/test/regress/sql/gb_ora_rotate_unrotate.sql @@ -14,6 +14,8 @@ select * from tt rotate (sum(order_total) for order_mode in ('direct' as store, select * from (select year, order_mode, order_total from original_orders) rotate (sum(order_total) for order_mode in ('online' as internet )) order by year; +select * from ( select year, order_mode, order_total from original_orders) rotate (sum(order_total + 100) for order_mode in ('direct' as store, 'online' as internet)) order by year; + create table rotate_orders as (select * from (select year, order_mode, order_total from original_orders) as t rotate (sum(order_total) for order_mode in ('direct' as store, 'online' as internet)) order by year); -- test not rotate (column transform to row)