Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group Concat function support for separator #16237

Merged
merged 7 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that we want to add vitess-tester tests, but there is a cost of adding new test files. For a single query testing should be not update the existing group_concat test in TestGroupConcatAggregation

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use vitess_tester for all new tests, because of how much easier it is. Currently, the workflow is running in 6m 24s seconds, even after adding this test.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather like to move all the older tests to vitess_tester

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
CREATE TABLE `t1`
(
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(191) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE InnoDB,
CHARSET utf8mb4,
COLLATE utf8mb4_unicode_ci;

CREATE TABLE `t2`
(
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`t1_id` int unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE InnoDB,
CHARSET utf8mb4,
COLLATE utf8mb4_unicode_ci;

CREATE TABLE `t3`
(
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(191) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE InnoDB,
CHARSET utf8mb4,
COLLATE utf8mb4_unicode_ci;

insert into t1 (id, name)
values (1, 'A'),
(2, 'B'),
(3, 'C'),
(4, 'D');

insert into t2 (id, t1_id)
values (1, 1),
(2, 2),
(3, 3);

insert into t3 (id, name)
values (1, 'A'),
(2, 'B');

-- wait_authoritative t1
-- wait_authoritative t2
-- wait_authoritative t3
select group_concat(t3.name SEPARATOR ', ') as "Group Name"
from t1
join t2 on t1.id = t2.t1_id
left join t3 on t1.id = t3.id
group by t1.id;
20 changes: 15 additions & 5 deletions go/vt/vtgate/engine/aggregations.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type AggregateParams struct {
Type evalengine.Type

Alias string `json:",omitempty"`
Expr sqlparser.Expr
Func sqlparser.AggrFunc
Original *sqlparser.AliasedExpr

// This is based on the function passed in the select expression and
Expand Down Expand Up @@ -255,8 +255,9 @@ func (a *aggregatorScalar) reset() {
}

type aggregatorGroupConcat struct {
from int
type_ sqltypes.Type
from int
type_ sqltypes.Type
separator []byte

concat []byte
n int
Expand All @@ -267,7 +268,7 @@ func (a *aggregatorGroupConcat) add(row []sqltypes.Value) error {
return nil
}
if a.n > 0 {
a.concat = append(a.concat, ',')
a.concat = append(a.concat, a.separator...)
}
a.concat = append(a.concat, row[a.from].Raw()...)
a.n++
Expand Down Expand Up @@ -434,7 +435,16 @@ func newAggregation(fields []*querypb.Field, aggregates []*AggregateParams) (agg
ag = &aggregatorScalar{from: aggr.Col}

case AggregateGroupConcat:
ag = &aggregatorGroupConcat{from: aggr.Col, type_: targetType}
separator := []byte{','}
gcFunc := aggr.Func.(*sqlparser.GroupConcatExpr)
if gcFunc.Separator != "" {
separator = []byte(gcFunc.Separator)
}
ag = &aggregatorGroupConcat{
from: aggr.Col,
type_: targetType,
separator: separator,
}

default:
panic("BUG: unexpected Aggregation opcode")
Expand Down
4 changes: 2 additions & 2 deletions go/vt/vtgate/engine/cached_size.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion go/vt/vtgate/planbuilder/operator_transformers.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ func transformAggregator(ctx *plancontext.PlanningContext, op *operators.Aggrega
return nil, vterrors.VT12001(fmt.Sprintf("in scatter query: aggregation function '%s'", sqlparser.String(aggr.Original)))
}
aggrParam := engine.NewAggregateParam(aggr.OpCode, aggr.ColOffset, aggr.Alias, ctx.VSchema.Environment().CollationEnv())
aggrParam.Expr = aggr.Func
aggrParam.Func = aggr.Func
GuptaManan100 marked this conversation as resolved.
Show resolved Hide resolved
aggrParam.Original = aggr.Original
aggrParam.OrigOpcode = aggr.OriginalOpCode
aggrParam.WCol = aggr.WSOffset
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ func (ab *aggBuilder) handleAggr(ctx *plancontext.PlanningContext, aggr Aggr) er
return ab.handlePushThroughAggregation(ctx, aggr)
case opcode.AggregateGroupConcat:
f := aggr.Func.(*sqlparser.GroupConcatExpr)
if f.Distinct || len(f.OrderBy) > 0 || f.Separator != "" {
panic("fail here")
GuptaManan100 marked this conversation as resolved.
Show resolved Hide resolved
if f.Distinct || len(f.OrderBy) > 0 {
panic(vterrors.VT12001("cannot evaluate group concat with distinct or order by"))
}
// this needs special handling, currently aborting the push of function
// and later will try pushing the column instead.
Expand Down
60 changes: 60 additions & 0 deletions go/vt/vtgate/planbuilder/testdata/aggr_cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,66 @@
]
}
},
{
"comment": "group concat with a separator needing evaluation on vtgate",
"query": "select group_concat(music.name SEPARATOR ', ') as `Group Name` from user join user_extra on user.id = user_extra.user_id left join music on user.id = music.id group by user.id;",
"plan": {
"QueryType": "SELECT",
"Original": "select group_concat(music.name SEPARATOR ', ') as `Group Name` from user join user_extra on user.id = user_extra.user_id left join music on user.id = music.id group by user.id;",
"Instructions": {
"OperatorType": "Aggregate",
"Variant": "Ordered",
"Aggregates": "group_concat(0) AS Group Name",
GuptaManan100 marked this conversation as resolved.
Show resolved Hide resolved
"GroupBy": "(1|2)",
"ResultColumns": 1,
"Inputs": [
{
"OperatorType": "Join",
"Variant": "LeftJoin",
"JoinColumnIndexes": "R:0,L:0,L:1",
"JoinVars": {
"user_id": 0
},
"TableName": "`user`, user_extra_music",
"Inputs": [
{
"OperatorType": "Route",
"Variant": "Scatter",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select `user`.id, weight_string(`user`.id) from `user`, user_extra where 1 != 1",
"OrderBy": "(0|1) ASC",
"Query": "select `user`.id, weight_string(`user`.id) from `user`, user_extra where `user`.id = user_extra.user_id order by `user`.id asc",
"Table": "`user`, user_extra"
},
{
"OperatorType": "Route",
"Variant": "EqualUnique",
"Keyspace": {
"Name": "user",
"Sharded": true
},
"FieldQuery": "select music.`name` from music where 1 != 1",
"Query": "select music.`name` from music where music.id = :user_id",
"Table": "music",
"Values": [
":user_id"
],
"Vindex": "music_user_map"
}
]
}
]
},
"TablesUsed": [
"user.music",
"user.user",
"user.user_extra"
]
}
},
{
"comment": "scatter aggregate group by column number",
"query": "select col from user group by 1",
Expand Down
5 changes: 5 additions & 0 deletions go/vt/vtgate/planbuilder/testdata/unsupported_cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@
"query": "select id2 from user uu where id in (select id from user where id = uu.id and user.col in (select col from (select id from user_extra where user_id = 5) uu where uu.user_id = uu.id))",
"plan": "VT12001: unsupported: correlated subquery is only supported for EXISTS"
},
{
"comment": "group concat with order by requiring evaluation at vtgate",
"query": "select group_concat(music.name ORDER BY 1 asc SEPARATOR ', ') as `Group Name` from user join user_extra on user.id = user_extra.user_id left join music on user.id = music.id group by user.id;",
"plan": "VT12001: unsupported: cannot evaluate group concat with distinct or order by"
},
{
"comment": "outer and inner subquery route reference the same \"uu.id\" name\n# but they refer to different things. The first reference is to the outermost query,\n# and the second reference is to the innermost 'from' subquery.\n# changed to project all the columns from the derived tables.",
"query": "select id2 from user uu where id in (select id from user where id = uu.id and user.col in (select col from (select col, id, user_id from user_extra where user_id = 5) uu where uu.user_id = uu.id))",
Expand Down
Loading