-
Notifications
You must be signed in to change notification settings - Fork 84
/
optimizer.go
102 lines (89 loc) · 2.64 KB
/
optimizer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and Limitations
// under the License.
package logical
import (
modelv1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v1"
)
// OptimizeRule allows optimizing a Plan based on a rule.
type OptimizeRule interface {
Optimize(Plan) (Plan, error)
}
// ApplyRules apply OptimizeRules to a Plan.
func ApplyRules(plan Plan, rules ...OptimizeRule) error {
p := plan
for _, r := range rules {
var err error
if p, err = r.Optimize(p); err != nil {
return err
}
}
cc := plan.Children()
if len(cc) < 1 {
return nil
}
for _, c := range cc {
if err := ApplyRules(c, rules...); err != nil {
return err
}
}
return nil
}
// VolumeLimiter controls the volume of a Plan's output.
type VolumeLimiter interface {
Plan
Limit(max int)
}
// Sorter sorts a Plan's output.
type Sorter interface {
Plan
Sort(order *OrderBy)
}
var _ OptimizeRule = (*PushDownOrder)(nil)
// PushDownOrder pushes down the order to a Plan.
type PushDownOrder struct {
order *modelv1.QueryOrder
}
// NewPushDownOrder returns a new PushDownOrder.
func NewPushDownOrder(order *modelv1.QueryOrder) PushDownOrder {
return PushDownOrder{order: order}
}
// Optimize a Plan by pushing down the query order.
func (pdo PushDownOrder) Optimize(plan Plan) (Plan, error) {
if v, ok := plan.(Sorter); ok {
if order, err := ParseOrderBy(v.Schema(), pdo.order.GetIndexRuleName(), pdo.order.GetSort()); err == nil {
v.Sort(order)
} else {
return nil, err
}
}
return plan, nil
}
// PushDownMaxSize pushes down the max volume to a Plan.
type PushDownMaxSize struct {
max int
}
// NewPushDownMaxSize returns a new PushDownMaxSize.
func NewPushDownMaxSize(max int) PushDownMaxSize {
return PushDownMaxSize{max: max}
}
// Optimize a Plan by pushing down the max volume.
func (pde PushDownMaxSize) Optimize(plan Plan) (Plan, error) {
if v, ok := plan.(VolumeLimiter); ok {
v.Limit(pde.max)
}
return plan, nil
}