forked from gobuffalo/pop
-
Notifications
You must be signed in to change notification settings - Fork 0
/
columns.go
149 lines (130 loc) · 2.99 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
package columns
import (
"fmt"
"sort"
"strings"
"sync"
)
type Columns struct {
Cols map[string]*Column
lock *sync.RWMutex
TableName string
TableAlias string
}
// Add a column to the list.
func (c *Columns) Add(names ...string) []*Column {
ret := []*Column{}
c.lock.Lock()
tableAlias := c.TableAlias
if tableAlias == "" {
tableAlias = c.TableName
}
for _, name := range names {
var xs []string
var col *Column
ss := ""
//support for distinct xx, or distinct on (field) table.fields
if strings.HasSuffix(name, ",r") || strings.HasSuffix(name, ",w") {
xs = []string{name[0 : len(name)-2], name[len(name)-1 : len(name)]}
} else {
xs = []string{name}
}
xs[0] = strings.TrimSpace(xs[0])
//eg: id id2 - select id as id2
// also distinct columnname
// and distinct on (column1) column2
if strings.Contains(strings.ToUpper(xs[0]), " AS ") {
//eg: select id as id2
i := strings.LastIndex(strings.ToUpper(xs[0]), " AS ")
ss = xs[0]
xs[0] = xs[0][i+4 : len(xs[0])] //get id2
} else if strings.Contains(xs[0], " ") {
i := strings.LastIndex(name, " ")
ss = xs[0]
xs[0] = xs[0][i+1 : len(xs[0])] //get id2
}
col = c.Cols[xs[0]]
//fmt.Printf("column: %v, col: %v, xs: %v, ss: %v\n", xs[0], col, xs, ss)
if col == nil {
if ss == "" {
ss = xs[0]
if tableAlias != "" {
ss = fmt.Sprintf("%s.%s", tableAlias, ss)
}
}
col = &Column{
Name: xs[0],
SelectSQL: ss,
Readable: true,
Writeable: true,
}
if len(xs) > 1 {
if xs[1] == "r" {
col.Writeable = false
}
if xs[1] == "w" {
col.Readable = false
}
} else if col.Name == "id" {
col.Writeable = false
}
c.Cols[col.Name] = col
}
ret = append(ret, col)
}
c.lock.Unlock()
return ret
}
// Remove a column from the list.
func (c *Columns) Remove(names ...string) {
for _, name := range names {
xs := strings.Split(name, ",")
name = xs[0]
delete(c.Cols, name)
}
}
func (c Columns) Writeable() *WriteableColumns {
w := &WriteableColumns{NewColumnsWithAlias(c.TableName, c.TableAlias)}
for _, col := range c.Cols {
if col.Writeable {
w.Cols[col.Name] = col
}
}
return w
}
func (c Columns) Readable() *ReadableColumns {
w := &ReadableColumns{NewColumnsWithAlias(c.TableName, c.TableAlias)}
for _, col := range c.Cols {
if col.Readable {
w.Cols[col.Name] = col
}
}
return w
}
func (c Columns) String() string {
xs := []string{}
for _, t := range c.Cols {
xs = append(xs, t.Name)
}
sort.Strings(xs)
return strings.Join(xs, ", ")
}
func (c Columns) SymbolizedString() string {
xs := []string{}
for _, t := range c.Cols {
xs = append(xs, ":"+t.Name)
}
sort.Strings(xs)
return strings.Join(xs, ", ")
}
func NewColumns(tableName string) Columns {
return NewColumnsWithAlias(tableName, "")
}
func NewColumnsWithAlias(tableName string, tableAlias string) Columns {
return Columns{
lock: &sync.RWMutex{},
Cols: map[string]*Column{},
TableName: tableName,
TableAlias: tableAlias,
}
}