diff --git a/src/common/backend/parser/parse_clause.cpp b/src/common/backend/parser/parse_clause.cpp index d126b7329..81689f832 100644 --- a/src/common/backend/parser/parse_clause.cpp +++ b/src/common/backend/parser/parse_clause.cpp @@ -1908,6 +1908,12 @@ static Index transformGroupClauseExpr(List** flatresult, Bitmapset* seen_local, TargetEntry* tle = NULL; bool found = false; + if (DB_IS_CMPT(B_FORMAT) && gexpr && IsA(gexpr, UserSetElem)) { + pretransformAggWithUserSet(pstate, targetlist, gexpr, EXPR_KIND_GROUP_BY); + /* means nothing to deal in group by */ + return 0; + } + if (useSQL99) { tle = findTargetlistEntrySQL99(pstate, gexpr, targetlist, exprKind); } else { @@ -2952,3 +2958,30 @@ static Node* transformFrameOffset(ParseState* pstate, int frameOptions, Node* cl return node; } + +/* + * special handle for UserSetElement used in group clause + * it must set at top of targetList to get value before real + * targetList to ensure @var appeard in real List got right + * value. resjunk must be true, because we do not want this + * UserSetElement actually appeared + */ +void pretransformAggWithUserSet(ParseState* pstate, List** targetList, Node* groupClause, ParseExprKind exprKind) +{ + ListCell* tllc = NULL; + TargetEntry* target = NULL; + + Expr* expr = (Expr*)transformExpr(pstate, groupClause, exprKind); + + TargetEntry* entry = makeTargetEntry((Expr*)expr, 1, NULL, true); + + foreach (tllc, *targetList) { + target = (TargetEntry*)lfirst(tllc); + target->resno++; + } + pstate->p_next_resno++; + *targetList = list_concat(list_make1(entry), *targetList); + pstate->p_target_list = *targetList; + + return; +} \ No newline at end of file diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h index a77c96e0b..238dae399 100644 --- a/src/include/parser/parse_clause.h +++ b/src/include/parser/parse_clause.h @@ -55,5 +55,6 @@ extern ParseNamespaceItem *makeNamespaceItem(RangeTblEntry *rte, bool lateral_on */ extern void transformStartWith(ParseState *pstate, SelectStmt *stmt, Query *qry); extern void AddStartWithCTEPseudoReturnColumns(CommonTableExpr *cte, RangeTblEntry *rte, Index rte_index); +extern void pretransformAggWithUserSet(ParseState* pstate, List** targetList, Node* groupClause, ParseExprKind exprKind); #endif /* PARSE_CLAUSE_H */ diff --git a/src/test/regress/expected/mysql_compatibility.out b/src/test/regress/expected/mysql_compatibility.out index d9f749b7f..19b172d15 100644 --- a/src/test/regress/expected/mysql_compatibility.out +++ b/src/test/regress/expected/mysql_compatibility.out @@ -1725,6 +1725,33 @@ INFO: id+ is 4 (1 row) +--bugfix @var := expr in group by +drop table if exists tt_bug1 ; +NOTICE: table "tt_bug1" does not exist, skipping +create table tt_bug1(a int ); +insert into tt_bug1 values(1),(11),(111); +SELECT a, @a, a as xx FROM tt_bug1 GROUP BY @a:= 999,a order by a ; + a | @a | xx +-----+-----+----- + 1 | 999 | 1 + 11 | 999 | 11 + 111 | 999 | 111 +(3 rows) + +SELECT a, @a, count(a) as xx FROM tt_bug1 GROUP BY @a:= a+11 ,a order by a ; + a | @a | xx +-----+-----+---- + 1 | 12 | 1 + 11 | 22 | 1 + 111 | 122 | 1 +(3 rows) + +SELECT @a, avg(a) as xx FROM tt_bug1 GROUP BY @a:= 11; + @a | xx +----+--------------------- + 11 | 41.0000000000000000 +(1 row) + set enable_set_variable_b_format = 0; select @var_t_1 := 2; ERROR: syntax error at or near ":=" diff --git a/src/test/regress/sql/mysql_compatibility.sql b/src/test/regress/sql/mysql_compatibility.sql index b7f4bce00..23219cf94 100644 --- a/src/test/regress/sql/mysql_compatibility.sql +++ b/src/test/regress/sql/mysql_compatibility.sql @@ -581,6 +581,16 @@ END; / call load_tbtest_WITH_REPLACE(3); + +--bugfix @var := expr in group by +drop table if exists tt_bug1 ; +create table tt_bug1(a int ); +insert into tt_bug1 values(1),(11),(111); +SELECT a, @a, a as xx FROM tt_bug1 GROUP BY @a:= 999,a order by a ; +SELECT a, @a, count(a) as xx FROM tt_bug1 GROUP BY @a:= a+11 ,a order by a ; +SELECT @a, avg(a) as xx FROM tt_bug1 GROUP BY @a:= 11; + + set enable_set_variable_b_format = 0; select @var_t_1 := 2;