-
Notifications
You must be signed in to change notification settings - Fork 219
Expand file tree
/
Copy pathlimit_plan.go
More file actions
133 lines (114 loc) · 2.58 KB
/
limit_plan.go
File metadata and controls
133 lines (114 loc) · 2.58 KB
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
* Radon
*
* Copyright 2018 The Radon Authors.
* Code is licensed under the GPLv3.
*
*/
package planner
import (
"encoding/json"
"fmt"
"strconv"
"github.com/pkg/errors"
"github.com/xelabs/go-mysqlstack/sqlparser"
"github.com/xelabs/go-mysqlstack/sqlparser/depends/common"
"github.com/xelabs/go-mysqlstack/xlog"
)
var (
_ Plan = &LimitPlan{}
)
// LimitPlan represents order-by plan.
type LimitPlan struct {
log *xlog.Log
node *sqlparser.Limit
rewritten *sqlparser.Limit
Offset int
Limit int
// type
typ PlanType
}
// NewLimitPlan used to create LimitPlan.
func NewLimitPlan(log *xlog.Log, node *sqlparser.Limit) *LimitPlan {
return &LimitPlan{
log: log,
node: node,
typ: PlanTypeLimit,
}
}
// analyze used to analyze the 'order by' is at the support level.
func (p *LimitPlan) analyze() error {
ok := true
sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
switch node.(type) {
// Limit clause must be SQLVal type.
case *sqlparser.Limit:
return true, nil
case *sqlparser.SQLVal:
val := node.(*sqlparser.SQLVal)
if val.Type != sqlparser.IntVal {
ok = false
return false, nil
}
return true, nil
default:
ok = false
return false, nil
}
}, p.node)
if !ok {
return errors.New("unsupported: limit.offset.or.counts.must.be.IntVal")
}
return nil
}
// Build used to build distributed querys.
func (p *LimitPlan) Build() error {
if p.node == nil {
return nil
}
if err := p.analyze(); err != nil {
return err
}
if p.node.Offset != nil {
val := p.node.Offset.(*sqlparser.SQLVal)
out, err := strconv.ParseInt(common.BytesToString(val.Val), 10, 64)
if err != nil {
return err
}
p.Offset = int(out)
}
if p.node.Rowcount != nil {
val := p.node.Rowcount.(*sqlparser.SQLVal)
out, err := strconv.ParseInt(common.BytesToString(val.Val), 10, 64)
if err != nil {
return err
}
p.Limit = int(out)
}
p.rewritten = &sqlparser.Limit{Rowcount: sqlparser.NewIntVal([]byte(fmt.Sprintf("%d", p.Offset+p.Limit)))}
return nil
}
// Type returns the type of the plan.
func (p *LimitPlan) Type() PlanType {
return p.typ
}
// JSON returns the plan info.
func (p *LimitPlan) JSON() string {
bout, err := json.MarshalIndent(p, "", "\t")
if err != nil {
return err.Error()
}
return string(bout)
}
// Children returns the children of the plan.
func (p *LimitPlan) Children() *PlanTree {
return nil
}
// ReWritten used to re-write the limit clause.
func (p *LimitPlan) ReWritten() *sqlparser.Limit {
return p.rewritten
}
// Size returns the memory size.
func (p *LimitPlan) Size() int {
return 0
}