forked from volatiletech/sqlboiler
/
columns.go
174 lines (158 loc) · 5.64 KB
/
columns.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
package boil
import (
"github.com/volatiletech/sqlboiler/strmangle"
)
// Columns kinds
// Note: These are not exported because they should only be used
// internally. To hide the clutter from the public API so boil
// continues to be a package aimed towards users, we add a method
// to query for each kind on the column type itself, see IsInfer
// as example.
const (
columnsInfer int = iota
columnsWhitelist
columnsGreylist
columnsBlacklist
)
// Columns is a list of columns and a kind of list.
// Each kind interacts differently with non-zero and default column
// inference to produce a final list of columns for a given query.
// (Typically insert/updates).
type Columns struct {
Kind int
Cols []string
}
// Infer is a placeholder that means there is no other list, simply
// infer the final list of columns for insert/update etc.
func Infer() Columns {
return Columns{
Kind: columnsInfer,
}
}
// IsInfer checks to see if these columns should be inferred.
// This method is here simply to not have to export the columns types.
func (c Columns) IsInfer() bool {
return c.Kind == columnsInfer
}
// Whitelist creates a list that completely overrides column inference.
// It becomes the final list for the insert/update etc.
func Whitelist(columns ...string) Columns {
return Columns{
Kind: columnsWhitelist,
Cols: columns,
}
}
// IsWhitelist checks to see if these columns should be inferred.
// This method is here simply to not have to export the columns types.
func (c Columns) IsWhitelist() bool {
return c.Kind == columnsWhitelist
}
// Blacklist creates a list that overrides column inference choices
// by excluding a column from the inferred list. In essence, inference
// creates the list of columns, and blacklisted columns are removed from
// that list to produce the final list.
func Blacklist(columns ...string) Columns {
return Columns{
Kind: columnsBlacklist,
Cols: columns,
}
}
// IsBlacklist checks to see if these columns should be inferred.
// This method is here simply to not have to export the columns types.
func (c Columns) IsBlacklist() bool {
return c.Kind == columnsBlacklist
}
// Greylist creates a list that adds to the inferred column choices.
// The final list is composed of both inferred columns and greylisted columns.
func Greylist(columns ...string) Columns {
return Columns{
Kind: columnsGreylist,
Cols: columns,
}
}
// IsGreylist checks to see if these columns should be inferred.
// This method is here simply to not have to export the columns types.
func (c Columns) IsGreylist() bool {
return c.Kind == columnsGreylist
}
// InsertColumnSet generates the set of columns to insert and return for an
// insert statement. The return columns are used to get values that are
// assigned within the database during the insert to keep the struct in sync
// with what's in the db. The various interactions with the different
// types of Columns list are outlined below.
//
// Note that a default column's zero value is based on the Go type and does
// not take into account the default value in the database.
//
// Infer:
// insert: columns-without-default + non-zero-default-columns
// return: columns-with-defaults - insert
//
// Whitelist:
// insert: whitelist
// return: columns-with-defaults - whitelist
//
// Blacklist:
// insert: columns-without-default + non-zero-default-columns - blacklist
// return: columns-with-defaults - insert
//
// Greylist:
// insert: columns-without-default + non-zero-default-columns + greylist
// return: columns-with-defaults - insert
func (c Columns) InsertColumnSet(cols, defaults, noDefaults, nonZeroDefaults []string) ([]string, []string) {
switch c.Kind {
case columnsInfer:
insert := make([]string, len(noDefaults))
copy(insert, noDefaults)
insert = append(insert, nonZeroDefaults...)
insert = strmangle.SortByKeys(cols, insert)
ret := strmangle.SetComplement(defaults, insert)
return insert, ret
case columnsWhitelist:
return c.Cols, strmangle.SetComplement(defaults, c.Cols)
case columnsBlacklist:
insert := make([]string, len(noDefaults))
copy(insert, noDefaults)
insert = append(insert, nonZeroDefaults...)
insert = strmangle.SetComplement(insert, c.Cols)
insert = strmangle.SortByKeys(cols, insert)
ret := strmangle.SetComplement(defaults, insert)
return insert, ret
case columnsGreylist:
insert := make([]string, len(noDefaults))
copy(insert, noDefaults)
insert = append(insert, nonZeroDefaults...)
insert = strmangle.SetMerge(insert, c.Cols)
insert = strmangle.SortByKeys(cols, insert)
ret := strmangle.SetComplement(defaults, insert)
return insert, ret
default:
panic("not a real column list kind")
}
}
// UpdateColumnSet generates the set of columns to update for an update
// statement. The various interactions with the different types of Columns
// list are outlined below. In the case of greylist you can only add pkeys,
// which isn't useful in an update since then you can't find the original
// record you were trying to update.
//
// Infer: all - pkey-columns
// whitelist: whitelist
// blacklist: all - pkeys - blacklist
// greylist: all - pkeys + greylist
func (c Columns) UpdateColumnSet(allColumns, pkeyCols []string) []string {
switch c.Kind {
case columnsInfer:
return strmangle.SetComplement(allColumns, pkeyCols)
case columnsWhitelist:
return c.Cols
case columnsBlacklist:
return strmangle.SetComplement(strmangle.SetComplement(allColumns, pkeyCols), c.Cols)
case columnsGreylist:
// okay to modify return of SetComplement since it's a new slice
update := append(strmangle.SetComplement(allColumns, pkeyCols), c.Cols...)
return strmangle.SortByKeys(allColumns, update)
default:
panic("not a real column list kind")
}
}