From a264a27c6af05fb7f7f03598eaa31a3a33274f3e Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Tue, 2 May 2023 19:04:14 +0530 Subject: [PATCH] [release-14.0] fix: union distinct between unsharded route and sharded join (#12968) (#12983) * fix: union distinct between unsharded route and sharded join Signed-off-by: Harshit Gangal * test: removed TablesUsed from the expected output Signed-off-by: Harshit Gangal --------- Signed-off-by: Harshit Gangal --- .gitignore | 3 + .../planbuilder/operator_transformers.go | 29 ++--- .../planbuilder/testdata/union_cases.json | 120 ++++++++++++++++++ 3 files changed, 136 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 60b397f1ec6..b84eb6958a2 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,6 @@ venv .scannerwork report + +# plan test output +/go/vt/vtgate/planbuilder/testdata/plan_test* diff --git a/go/vt/vtgate/planbuilder/operator_transformers.go b/go/vt/vtgate/planbuilder/operator_transformers.go index b6bac24d1c7..7ef72c79428 100644 --- a/go/vt/vtgate/planbuilder/operator_transformers.go +++ b/go/vt/vtgate/planbuilder/operator_transformers.go @@ -363,25 +363,22 @@ func pushWeightStringForDistinct(ctx *plancontext.PlanningContext, plan logicalP } node.noNeedToTypeCheck = append(node.noNeedToTypeCheck, newOffset) case *joinGen4: - lhsSolves := node.Left.ContainsTables() - rhsSolves := node.Right.ContainsTables() - expr := node.OutputColumns()[offset] - aliasedExpr, isAliased := expr.(*sqlparser.AliasedExpr) - if !isAliased { - return 0, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "cannot convert select expression to an aliased expression") - } - deps := ctx.SemTable.RecursiveDeps(aliasedExpr.Expr) + joinOffset := node.Cols[offset] switch { - case deps.IsSolvedBy(lhsSolves): - offset, err = pushWeightStringForDistinct(ctx, node.Left, offset) - node.Cols = append(node.Cols, -(offset + 1)) - case deps.IsSolvedBy(rhsSolves): - offset, err = pushWeightStringForDistinct(ctx, node.Right, offset) - node.Cols = append(node.Cols, offset+1) + case joinOffset < 0: + offset, err = pushWeightStringForDistinct(ctx, node.Left, -(joinOffset + 1)) + offset = -(offset + 1) + case joinOffset > 0: + offset, err = pushWeightStringForDistinct(ctx, node.Right, joinOffset-1) + offset = offset + 1 default: - return 0, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "cannot push distinct weight string to both sides of the join") + return 0, vterrors.New(vtrpcpb.Code_INTERNAL, "[BUG]: wrong column offset in join plan to push DISTINCT WEIGHT_STRING") } - newOffset = len(node.Cols) - 1 + if err != nil { + return 0, err + } + newOffset = len(node.Cols) + node.Cols = append(node.Cols, offset) default: return 0, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "bug: not supported pushWeightStringForDistinct on %T", plan) } diff --git a/go/vt/vtgate/planbuilder/testdata/union_cases.json b/go/vt/vtgate/planbuilder/testdata/union_cases.json index 572b97d284b..87581673c77 100644 --- a/go/vt/vtgate/planbuilder/testdata/union_cases.json +++ b/go/vt/vtgate/planbuilder/testdata/union_cases.json @@ -1935,5 +1935,125 @@ "Table": "unsharded" } } + }, + { + "comment": "union of unsharded route with sharded join with involvement of weight string", + "query": "select id, foo, bar from unsharded union select user.intcol, user.textcol2, authoritative.col2 from user join authoritative", + "v3-plan": { + "QueryType": "SELECT", + "Original": "select id, foo, bar from unsharded union select user.intcol, user.textcol2, authoritative.col2 from user join authoritative", + "Instructions": { + "OperatorType": "Distinct", + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select id, foo, bar from unsharded where 1 != 1", + "Query": "select id, foo, bar from unsharded", + "Table": "unsharded" + }, + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,L:1,R:0", + "TableName": "`user`_authoritative", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select `user`.intcol, `user`.textcol2 from `user` where 1 != 1", + "Query": "select `user`.intcol, `user`.textcol2 from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select authoritative.col2 from authoritative where 1 != 1", + "Query": "select authoritative.col2 from authoritative", + "Table": "authoritative" + } + ] + } + ] + } + ] + } + }, + "gen4-plan": { + "QueryType": "SELECT", + "Original": "select id, foo, bar from unsharded union select user.intcol, user.textcol2, authoritative.col2 from user join authoritative", + "Instructions": { + "OperatorType": "Distinct", + "Collations": [ + "(0:3)", + "(1:4)", + "(2:5)" + ], + "ResultColumns": 3, + "Inputs": [ + { + "OperatorType": "Concatenate", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Unsharded", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select id, foo, bar, weight_string(id), weight_string(foo), weight_string(bar) from unsharded where 1 != 1", + "Query": "select distinct id, foo, bar, weight_string(id), weight_string(foo), weight_string(bar) from unsharded", + "Table": "unsharded" + }, + { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "L:0,L:1,R:0,L:2,L:3,R:1", + "TableName": "`user`_authoritative", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select `user`.intcol, `user`.textcol2, weight_string(`user`.intcol), weight_string(`user`.textcol2) from `user` where 1 != 1", + "Query": "select `user`.intcol, `user`.textcol2, weight_string(`user`.intcol), weight_string(`user`.textcol2) from `user`", + "Table": "`user`" + }, + { + "OperatorType": "Route", + "Variant": "Scatter", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select authoritative.col2, weight_string(authoritative.col2) from authoritative where 1 != 1", + "Query": "select authoritative.col2, weight_string(authoritative.col2) from authoritative", + "Table": "authoritative" + } + ] + } + ] + } + ] + } + } } ]