-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathalias.go
152 lines (130 loc) · 3.36 KB
/
alias.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
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package ep
var _ = registerGob(&alias{})
var _ = registerGob(&scope{})
// UnnamedColumn used as default name for columns without an alias
const UnnamedColumn = "?column?"
// AliasSetter interface allows to set alias on returned column within the runner
type AliasSetter interface {
SetAlias(name string)
}
// Alias wraps given runner's single return type with given alias.
// Useful for planners that need to externally wrap a runner with alias
// see Aliasing and Scoping
func Alias(r Runner, label string) Runner {
if setter, ok := r.(AliasSetter); ok {
setter.SetAlias(label)
return r
}
return &alias{r, label}
}
type alias struct {
Runner
Label string
}
func (a *alias) Equals(other interface{}) bool {
r, ok := other.(*alias)
return ok && a.Runner.Equals(r.Runner)
}
// Returns implements ep.Runner
func (a *alias) Returns() []Type {
inpTypes := a.Runner.Returns()
if len(inpTypes) == 1 {
return []Type{SetAlias(inpTypes[0], a.Label)}
}
panic("Invalid usage of alias. Consider use scope")
}
// Filter implements ep.FilterRunner
func (a *alias) Filter(keep []bool) {
if f, isFilterable := a.Runner.(FilterRunner); isFilterable {
f.Filter(keep)
}
}
func (a *alias) Scopes() StringsSet {
if r, ok := a.Runner.(ScopesRunner); ok {
return r.Scopes()
}
return StringsSet{}
}
func (a *alias) Push(toPush ScopesRunner) bool {
if p, ok := a.Runner.(PushRunner); ok {
return p.Push(toPush)
}
return false
}
// SetAlias sets an alias for the given typed column.
// Useful for runner that need aliasing each column internally
func SetAlias(col Type, alias string) Type {
return Modify(col, "Alias", alias)
}
// GetAlias returns the alias of the given typed column
func GetAlias(col Type) string {
alias, ok := Modifier(col, "Alias").(string)
if ok {
return alias
}
return ""
}
// Scope wraps given runner with scope alias to allow runner aliasing.
// Useful to mark all returned columns with runner alias by planners that need
// to externally wrap a runner with scope
// see Aliasing and Scoping
func Scope(r Runner, label string) Runner {
if cmp, ok := r.(*compose); ok {
cmp.RetScope = label
return r
}
return &scope{r, label}
}
type scope struct {
Runner
Label string
}
func (s *scope) Equals(other interface{}) bool {
r, ok := other.(*scope)
return ok && s.Runner.Equals(r.Runner)
}
// Returns implements ep.Runner
func (s *scope) Returns() []Type {
inpTypes := s.Runner.Returns()
return SetScope(inpTypes, s.Label)
}
// Filter implements ep.FilterRunner
func (s *scope) Filter(keep []bool) {
if f, isFilterable := s.Runner.(FilterRunner); isFilterable {
f.Filter(keep)
}
}
func (s *scope) Scopes() StringsSet {
return StringsSet{s.Label: struct{}{}}
}
func (s *scope) Push(toPush ScopesRunner) bool {
if p, ok := s.Runner.(PushRunner); ok {
return p.Push(toPush)
}
return false
}
func (s *scope) ApproxSize() int {
if sizer, ok := s.Runner.(ApproxSizer); ok {
return sizer.ApproxSize()
}
return UnknownSize
}
// SetScope sets a scope for the given columns
func SetScope(cols []Type, scope string) []Type {
if scope == "" {
return cols
}
types := make([]Type, len(cols))
for i := 0; i < len(cols); i++ {
types[i] = Modify(cols[i], "Scope", scope)
}
return types
}
// GetScope returns the scope alias of the given typed column
func GetScope(col Type) string {
scope, ok := Modifier(col, "Scope").(string)
if ok {
return scope
}
return ""
}