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

Move UNION planning to the operators #13450

Merged
merged 46 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
ad06b80
start moving UNION planning over to the operators
systay Jul 6, 2023
7e89fdd
rename the slices2 package to slice
systay Jul 6, 2023
5b6b159
rename Merge to MergeJoin to make place for MergeUnion
systay Jul 6, 2023
5951c26
rewrite the compact rules for UNION
systay Jul 6, 2023
2179342
Make UNION compact more efficient
systay Jul 7, 2023
6ea5eda
another attempt at offset planning for UNION
systay Jul 7, 2023
e0b79bb
wip - start of merging UNION
systay Jul 8, 2023
78c7422
wip - continue with merging of UNION
systay Jul 12, 2023
6a3eeb6
wip - logic around turning UNION operators to SQL
systay Jul 12, 2023
616bfbe
logic around DISTINCT pushing
systay Jul 12, 2023
22d7f35
improved logic in Union.AddColumn
systay Jul 12, 2023
897089e
missing license header
systay Jul 12, 2023
efde977
don't remove operators by mistake
systay Jul 13, 2023
bce1ff8
merge UNION ALL as well
systay Jul 13, 2023
e478eaf
add FindCol to the Operator interface
systay Jul 13, 2023
5111b7f
create derived projection on top of union on horizon expansion
harshit-gangal Jul 14, 2023
613ff29
handle union columns in the semtable so dependencies are handled corr…
systay Jul 19, 2023
6eb1e87
make sure that UNION reports enough columns so column truncation can …
systay Jul 19, 2023
fed1124
handle types and dependencies better for UNIONs not in derived tables
systay Jul 19, 2023
07cf4f8
clean up Disinct operator handling
systay Jul 21, 2023
e284b57
instead of failing, we can use a Filter op instead
systay Jul 21, 2023
e9eac98
move from AddColumn to AddColumns
systay Jul 26, 2023
f939787
clean up projections around aggregation and derived tables
systay Jul 27, 2023
55c3738
distinct to send columns at once to source for AddColumns, route to a…
harshit-gangal Aug 2, 2023
054f78f
add truncation logic to filter
harshit-gangal Aug 2, 2023
b9278d2
fix the test expectation
harshit-gangal Aug 2, 2023
f5dd14b
update sizegen
harshit-gangal Aug 2, 2023
b173f8c
improve distinct planning to only reject when columns do not align
harshit-gangal Aug 2, 2023
d37cc71
update executor union query test expectation
harshit-gangal Aug 2, 2023
edcbc4f
fix compact and truncation order by reversing it and adding one more …
harshit-gangal Aug 2, 2023
ddc049e
merge sharded route on union only when both are scatter or both are e…
harshit-gangal Aug 3, 2023
364d3ad
fix unit test
harshit-gangal Aug 3, 2023
357d349
addressed review comments
harshit-gangal Aug 4, 2023
e5ee6bb
moved unsupported cases to unsupported_cases file
harshit-gangal Aug 6, 2023
b455e75
Merge remote-tracking branch 'upstream/main' into new-union-planning
harshit-gangal Aug 6, 2023
52299b3
remove optimization that lead to issues
systay Aug 7, 2023
885a94e
clean up distinct ws handling
systay Aug 7, 2023
6878101
no need to ask for the weightstring of a weightstring
systay Aug 7, 2023
41bdbf0
fix test in executor
harshit-gangal Aug 7, 2023
c10e4f5
no compact after truncation call
harshit-gangal Aug 7, 2023
9b19a24
calculate the dependencies more fine grained
systay Aug 7, 2023
6b4a544
remove unneeded projections
systay Aug 7, 2023
5abffd6
remove weightstring for literal values
systay Aug 7, 2023
2021206
remove any DISTINCTs we still have not pushed down
systay Aug 7, 2023
125145f
Merge remote-tracking branch 'upstream/main' into new-union-planning
harshit-gangal Aug 8, 2023
ff8d3f1
fix test query
harshit-gangal Aug 8, 2023
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
18 changes: 16 additions & 2 deletions go/slices2/slices.go → go/slice/slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

// Package slices2 contains generic Slice helpers;
// Package slice contains generic Slice helpers;
// Some of this code is sourced from https://github.com/luraim/fun (Apache v2)
package slices2
package slice

// All returns true if all elements return true for given predicate
func All[T any](s []T, fn func(T) bool) bool {
Expand Down Expand Up @@ -48,3 +48,17 @@ func Map[From, To any](in []From, f func(From) To) []To {
}
return result
}

func MapWithError[From, To any](in []From, f func(From) (To, error)) (result []To, err error) {
if in == nil {
return nil, nil
}
result = make([]To, len(in))
for i, col := range in {
result[i], err = f(col)
if err != nil {
return nil, err
}
}
return
}
2 changes: 1 addition & 1 deletion go/test/endtoend/vtgate/gen4/gen4_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func TestDistinct(t *testing.T) {
utils.Exec(t, mcmp.VtConn, `insert into t2(id, tcol1, tcol2) values (1, 'A', 'A'),(2, 'B', 'C'),(3, 'A', 'C'),(4, 'C', 'A'),(5, 'A', 'A'),(6, 'B', 'C'),(7, 'B', 'A'),(8, 'C', 'A')`)

// multi distinct
utils.AssertMatches(t, mcmp.VtConn, `select distinct tcol1, tcol2 from t2`,
utils.AssertMatchesNoOrder(t, mcmp.VtConn, `select distinct tcol1, tcol2 from t2`,
`[[VARCHAR("A") VARCHAR("A")] [VARCHAR("A") VARCHAR("C")] [VARCHAR("B") VARCHAR("A")] [VARCHAR("B") VARCHAR("C")] [VARCHAR("C") VARCHAR("A")]]`)
}

Expand Down
5 changes: 3 additions & 2 deletions go/test/endtoend/vtgate/queries/random/query_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import (
"math/rand"
"time"

"vitess.io/vitess/go/slice"

"golang.org/x/exp/slices"

"vitess.io/vitess/go/slices2"
"vitess.io/vitess/go/vt/log"
"vitess.io/vitess/go/vt/sqlparser"
)
Expand Down Expand Up @@ -459,7 +460,7 @@ func createLimit() *sqlparser.Limit {
// returns a random expression and its type
func getRandomExpr(tables []tableT) sqlparser.Expr {
seed := time.Now().UnixNano()
g := sqlparser.NewGenerator(seed, 2, slices2.Map(tables, func(t tableT) sqlparser.ExprGenerator { return &t })...)
g := sqlparser.NewGenerator(seed, 2, slice.Map(tables, func(t tableT) sqlparser.ExprGenerator { return &t })...)
return g.Expression()
}

Expand Down
5 changes: 3 additions & 2 deletions go/test/endtoend/vtgate/queries/random/random_expr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import (
"testing"
"time"

"vitess.io/vitess/go/slices2"
"vitess.io/vitess/go/slice"

"vitess.io/vitess/go/vt/sqlparser"
)

Expand All @@ -47,6 +48,6 @@ func TestRandomExprWithTables(t *testing.T) {
}...)

seed := time.Now().UnixNano()
g := sqlparser.NewGenerator(seed, 3, slices2.Map(schemaTables, func(t tableT) sqlparser.ExprGenerator { return &t })...)
g := sqlparser.NewGenerator(seed, 3, slice.Map(schemaTables, func(t tableT) sqlparser.ExprGenerator { return &t })...)
g.Expression()
}
4 changes: 2 additions & 2 deletions go/viperutil/debug/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
"github.com/spf13/viper"

"vitess.io/vitess/go/acl"
"vitess.io/vitess/go/slices2"
"vitess.io/vitess/go/slice"
"vitess.io/vitess/go/viperutil/internal/registry"
)

Expand All @@ -53,7 +53,7 @@ func HandlerFunc(w http.ResponseWriter, r *http.Request) {
switch {
case format == "":
v.DebugTo(w)
case slices2.Any(viper.SupportedExts, func(ext string) bool { return ext == format }):
case slice.Any(viper.SupportedExts, func(ext string) bool { return ext == format }):
// Got a supported format; write the config to a tempfile in that format,
// then copy it to the response.
//
Expand Down
1 change: 1 addition & 0 deletions go/vt/sqlparser/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ type (
GetColumnCount() int
GetColumns() SelectExprs
Commented
IsDistinct() bool
}

// DDLStatement represents any DDL Statement
Expand Down
35 changes: 35 additions & 0 deletions go/vt/sqlparser/ast_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,11 @@ func (node *Select) MakeDistinct() {
node.Distinct = true
}

// IsDistinct implements the SelectStatement interface
func (node *Select) IsDistinct() bool {
return node.Distinct
}

// GetColumnCount return SelectExprs count.
func (node *Select) GetColumnCount() int {
return len(node.SelectExprs)
Expand Down Expand Up @@ -1192,6 +1197,11 @@ func (node *Union) MakeDistinct() {
node.Distinct = true
}

// IsDistinct implements the SelectStatement interface
func (node *Union) IsDistinct() bool {
return node.Distinct
}

// GetColumnCount implements the SelectStatement interface
func (node *Union) GetColumnCount() int {
return node.Left.GetColumnCount()
Expand Down Expand Up @@ -2494,3 +2504,28 @@ func (ty KillType) ToString() string {
return ConnectionStr
}
}

func VisitAllSelects(in SelectStatement, f func(p *Select, idx int) error) error {
v := visitor{}
return v.visitAllSelects(in, f)
}

type visitor struct {
idx int
}

func (v *visitor) visitAllSelects(in SelectStatement, f func(p *Select, idx int) error) error {
switch sel := in.(type) {
case *Select:
err := f(sel, v.idx)
v.idx++
return err
case *Union:
err := v.visitAllSelects(sel.Left, f)
if err != nil {
return err
}
return v.visitAllSelects(sel.Right, f)
}
panic("switch should be exhaustive")
}
5 changes: 3 additions & 2 deletions go/vt/vtgate/engine/aggregations.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ import (
"fmt"
"strconv"

"vitess.io/vitess/go/slice"

"vitess.io/vitess/go/vt/vterrors"

"google.golang.org/protobuf/proto"

"vitess.io/vitess/go/mysql/collations"
"vitess.io/vitess/go/slices2"
"vitess.io/vitess/go/sqltypes"
binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata"
querypb "vitess.io/vitess/go/vt/proto/query"
Expand Down Expand Up @@ -279,7 +280,7 @@ func convertFinal(current []sqltypes.Value, aggregates []*AggregateParams) ([]sq
}

func convertFields(fields []*querypb.Field, aggrs []*AggregateParams) []*querypb.Field {
fields = slices2.Map(fields, func(from *querypb.Field) *querypb.Field {
fields = slice.Map(fields, func(from *querypb.Field) *querypb.Field {
return proto.Clone(from).(*querypb.Field)
})
for _, aggr := range aggrs {
Expand Down
2 changes: 1 addition & 1 deletion go/vt/vtgate/engine/cached_size.go

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

15 changes: 8 additions & 7 deletions go/vt/vtgate/engine/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,10 @@ package engine
import (
"context"

"vitess.io/vitess/go/vt/sqlparser"
"vitess.io/vitess/go/vt/vtgate/evalengine"

"vitess.io/vitess/go/sqltypes"

querypb "vitess.io/vitess/go/vt/proto/query"
"vitess.io/vitess/go/vt/sqlparser"
"vitess.io/vitess/go/vt/vtgate/evalengine"
)

var _ Primitive = (*Filter)(nil)
Expand All @@ -35,6 +33,8 @@ type Filter struct {
ASTPredicate sqlparser.Expr
Input Primitive

Truncate int

noTxNeeded
}

Expand Down Expand Up @@ -73,7 +73,7 @@ func (f *Filter) TryExecute(ctx context.Context, vcursor VCursor, bindVars map[s
}
}
result.Rows = rows
return result, nil
return result.Truncate(f.Truncate), nil
}

// TryStreamExecute satisfies the Primitive interface.
Expand All @@ -96,7 +96,7 @@ func (f *Filter) TryStreamExecute(ctx context.Context, vcursor VCursor, bindVars
}
}
results.Rows = rows
return callback(results)
return callback(results.Truncate(f.Truncate))
}

return vcursor.StreamExecutePrimitive(ctx, f.Input, bindVars, wantfields, filter)
Expand All @@ -114,7 +114,8 @@ func (f *Filter) Inputs() []Primitive {

func (f *Filter) description() PrimitiveDescription {
other := map[string]any{
"Predicate": sqlparser.String(f.ASTPredicate),
"Predicate": sqlparser.String(f.ASTPredicate),
"ResultColumns": f.Truncate,
}

return PrimitiveDescription{
Expand Down
5 changes: 3 additions & 2 deletions go/vt/vtgate/evalengine/compiler_asm.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import (
"strconv"
"time"

"vitess.io/vitess/go/slice"

"github.com/google/uuid"

"vitess.io/vitess/go/mysql/hex"
Expand All @@ -46,7 +48,6 @@ import (
"vitess.io/vitess/go/mysql/decimal"
"vitess.io/vitess/go/mysql/fastparse"
"vitess.io/vitess/go/mysql/json"
"vitess.io/vitess/go/slices2"
"vitess.io/vitess/go/sqltypes"
querypb "vitess.io/vitess/go/vt/proto/query"
"vitess.io/vitess/go/vt/proto/vtrpc"
Expand Down Expand Up @@ -2172,7 +2173,7 @@ func (asm *assembler) Fn_JSON_CONTAINS_PATH(match jsonMatch, paths []*json.Path)
}

func (asm *assembler) Fn_JSON_EXTRACT0(jp []*json.Path) {
multi := len(jp) > 1 || slices2.Any(jp, func(path *json.Path) bool { return path.ContainsWildcards() })
multi := len(jp) > 1 || slice.Any(jp, func(path *json.Path) bool { return path.ContainsWildcards() })

if multi {
asm.emit(func(env *ExpressionEnv) int {
Expand Down
6 changes: 3 additions & 3 deletions go/vt/vtgate/evalengine/fn_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package evalengine
import (
"vitess.io/vitess/go/mysql/collations"
"vitess.io/vitess/go/mysql/json"
"vitess.io/vitess/go/slices2"
"vitess.io/vitess/go/slice"
"vitess.io/vitess/go/sqltypes"
querypb "vitess.io/vitess/go/vt/proto/query"
vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
Expand Down Expand Up @@ -131,7 +131,7 @@ func (call *builtinJSONExtract) compile(c *compiler) (ctype, error) {
return ctype{}, err
}

if slices2.All(call.Arguments[1:], func(expr Expr) bool { return expr.constant() }) {
if slice.All(call.Arguments[1:], func(expr Expr) bool { return expr.constant() }) {
paths := make([]*json.Path, 0, len(call.Arguments[1:]))

for _, arg := range call.Arguments[1:] {
Expand Down Expand Up @@ -406,7 +406,7 @@ func (call *builtinJSONContainsPath) compile(c *compiler) (ctype, error) {
return ctype{}, c.unsupported(call)
}

if !slices2.All(call.Arguments[2:], func(expr Expr) bool { return expr.constant() }) {
if !slice.All(call.Arguments[2:], func(expr Expr) bool { return expr.constant() }) {
return ctype{}, c.unsupported(call)
}

Expand Down
2 changes: 1 addition & 1 deletion go/vt/vtgate/evalengine/translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ func (ast *astCompiler) translateColOffset(col *sqlparser.Offset) (Expr, error)

func (ast *astCompiler) translateColName(colname *sqlparser.ColName) (Expr, error) {
if ast.cfg.ResolveColumn == nil {
return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "cannot lookup column (column access not supported here)")
return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "cannot lookup column '%s' (column access not supported here)", sqlparser.String(colname))
}
idx, err := ast.cfg.ResolveColumn(colname)
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions go/vt/vtgate/planbuilder/collations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ func TestOrderedAggregateCollations(t *testing.T) {
collations: []collationInTable{{ks: "user", table: "user", collationName: "utf8mb4_bin", colName: "textcol1"}},
query: "select distinct textcol1 from user",
check: func(t *testing.T, colls []collationInTable, primitive engine.Primitive) {
oa, isOA := primitive.(*engine.OrderedAggregate)
require.True(t, isOA, "should be an OrderedAggregate")
require.Equal(t, collid(colls[0].collationName), oa.GroupByKeys[0].CollationID)
distinct, isDistinct := primitive.(*engine.Distinct)
require.True(t, isDistinct, "should be a distinct")
require.Equal(t, collid(colls[0].collationName), distinct.CheckCols[0].Collation)
},
},
{
Expand Down
Loading
Loading