-
Notifications
You must be signed in to change notification settings - Fork 2
/
columnset.go
190 lines (167 loc) · 4.85 KB
/
columnset.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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
package sol
import (
"fmt"
"strings"
"github.com/aodin/sol/dialect"
)
// ColumnSet maintains a []ColumnElem. It includes a variety of
// getters, setters, and filters.
type ColumnSet struct {
order []ColumnElem
}
func (set ColumnSet) Compile(d dialect.Dialect, ps *Parameters) (string, error) {
names := make([]string, len(set.order))
for i, col := range set.order {
compiled, err := col.Compile(d, ps)
if err != nil {
return "", err
}
if col.Alias() != "" {
compiled += fmt.Sprintf(` AS "%s"`, col.Alias())
}
names[i] = compiled
}
return strings.Join(names, ", "), nil
}
// Add adds any number of Columnar types to the set and returns the new set.
func (set ColumnSet) Add(columns ...Columnar) (ColumnSet, error) {
for _, column := range columns {
set.order = append(set.order, column.Column())
}
return set, nil
}
// All returns all columns in their default order
func (set ColumnSet) All() []ColumnElem {
return set.order
}
// Exists returns true if there is at least one column in the set
func (set ColumnSet) Exists() bool {
return len(set.order) > 0
}
// Filter returns a ColumnSet of columns from the original set that
// match the given names
func (set ColumnSet) Filter(names ...string) (out ColumnSet) {
for _, column := range set.order {
for _, name := range names {
if column.Name() == name {
out.order = append(out.order, column)
break
}
}
}
return
}
// FullNames returns the full names of the set's columns without alias
func (set ColumnSet) FullNames() []string {
names := make([]string, len(set.order))
for i, col := range set.order {
names[i] = col.FullName()
}
return names
}
// Get returns a ColumnElem - or an invalid ColumnElem if a column
// with the given name does not exist in the set
func (set ColumnSet) Get(name string) ColumnElem {
for _, column := range set.order {
if column.Name() == name {
return column
}
}
return InvalidColumn(name, nil)
}
// Has returns true if there is a column with the given name in the ColumnSet
func (set ColumnSet) Has(name string) bool {
return set.Get(name).IsValid()
}
// IsEmpty returns true if there are no columns in this set
func (set ColumnSet) IsEmpty() bool {
return len(set.order) == 0
}
// Names returns the names of the set's columns without alias
func (set ColumnSet) Names() []string {
names := make([]string, len(set.order))
for i, col := range set.order {
names[i] = col.Name()
}
return names
}
// Reject removes the given column names and returns a new ColumnSet
func (set ColumnSet) Reject(names ...string) (out ColumnSet) {
ColumnLoop:
for _, column := range set.order {
for _, name := range names {
if column.Name() == name {
continue ColumnLoop
}
}
out.order = append(out.order, column)
}
return
}
func (set ColumnSet) MakeUnique() (UniqueColumnSet, error) {
unique := UniqueColumns()
var err error
for _, column := range set.All() {
// If an alias exists, then replace the column name
if column.alias != "" {
column.name = column.alias
column.alias = ""
}
if unique, err = unique.Add(column); err != nil {
return unique, err
}
}
return unique, nil
}
// Columns creates a new ColumnSet
func Columns(columns ...ColumnElem) ColumnSet {
return ColumnSet{order: columns}
}
// UniqueColumnSet is a ColumnSet, but column names must be unique
type UniqueColumnSet struct{ ColumnSet }
// Add adds any number of Columnar types to the set and returns the new set.
// Adding a column with the same name as an existing column in the set
// will return an error.
func (set UniqueColumnSet) Add(columns ...Columnar) (UniqueColumnSet, error) {
for _, column := range columns {
for _, existing := range set.order {
if existing.Name() == column.Name() {
if existing.Table() == nil {
return set, fmt.Errorf(
"sol: this set already has a column named '%s'",
existing.Name(),
)
}
return set, fmt.Errorf(
"sol: table '%s' already has a column named '%s'",
existing.Table().Name(),
existing.Name(),
)
}
}
set.order = append(set.order, column.Column())
}
return set, nil
}
// EmptyValues creates an empty Values from the UniqueColumnSet
func (set UniqueColumnSet) EmptyValues() Values {
values := Values{}
for _, column := range set.order {
values[column.Name()] = nil
}
return values
}
// Filter returns a UniqueColumnSet of columns from the original
// set that match the given names
func (set UniqueColumnSet) Filter(names ...string) (out UniqueColumnSet) {
return UniqueColumnSet{ColumnSet: set.ColumnSet.Filter(names...)}
}
// Reject removes the given column names and returns a new ColumnSet
func (set UniqueColumnSet) Reject(names ...string) (out UniqueColumnSet) {
return UniqueColumnSet{ColumnSet: set.ColumnSet.Reject(names...)}
}
// UniqueColumns creates a new ColumnSet that can only hold columns
// with unique names
func UniqueColumns() (set UniqueColumnSet) {
return
}