/
key.go
148 lines (133 loc) · 2.94 KB
/
key.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
package psql
import (
"fmt"
"log/slog"
"reflect"
"strings"
)
var keyType = reflect.TypeOf(Key{})
// Name allows specifying the table name when associating a table with a struct
//
// For example:
// type X struct {
// KeyName psql.Key `sql:",type=UNIQUE,fields='A,B'"`
// ...
// }
type Key struct {
st *rowState
}
func (k *Key) state() *rowState {
if k.st == nil {
k.st = &rowState{}
}
return k.st
}
const (
keyPrimary = iota + 1
keyUnique
keyIndex
keyFulltext
keySpatial
)
type structKey struct {
index int
name string
key string // key name, can be != name
typ int
attrs map[string]string
fields []string
}
func (k *structKey) loadAttrs(attrs map[string]string) {
k.typ = keyIndex // default value
if t, ok := attrs["type"]; ok {
switch strings.ToUpper(t) {
case "PRIMARY":
k.typ = keyPrimary
case "UNIQUE":
k.typ = keyUnique
case "INDEX":
k.typ = keyIndex
case "FULLTEXT":
k.typ = keyFulltext
case "SPATIAL":
k.typ = keySpatial
default:
slog.Warn(fmt.Sprintf("[psql] Unsupported index key type %s assumed as INDEX", t), "event", "psql:key:badkey", "psql.index", k.name)
}
} else if k.key == "PRIMARY" {
k.typ = keyPrimary
}
k.attrs = attrs
k.fields = strings.Split(attrs["fields"], ",")
}
func (k *structKey) loadKeyName(kn string) {
switch {
case kn == "PRIMARY":
k.typ = keyPrimary
case strings.HasPrefix(kn, "UNIQUE:"):
kn = strings.TrimPrefix(kn, "UNIQUE:")
k.typ = keyUnique
}
k.name = kn
k.key = kn
}
func (k *structKey) keyname() string {
if k.typ == keyPrimary {
return "PRIMARY"
}
return k.key
}
func (k *structKey) sqlKeyName() string {
if k.typ == keyPrimary {
return "PRIMARY KEY"
}
return "INDEX " + QuoteName(k.key)
}
func (k *structKey) defString() string {
s := &strings.Builder{}
switch k.typ {
case keyPrimary:
// PRIMARY KEY [index_type] (key_part,...) [index_option] ...
// Primary keys don't have names
s.WriteString("PRIMARY KEY ")
case keyUnique:
// UNIQUE [INDEX | KEY] [index_name] [index_type] (key_part,...) [index_option] ...
s.WriteString("UNIQUE INDEX ")
s.WriteString(QuoteName(k.key))
case keyIndex:
// {INDEX | KEY} [index_name] [index_type] (key_part,...) [index_option] ...
s.WriteString("INDEX ")
s.WriteString(QuoteName(k.key))
case keyFulltext:
// {FULLTEXT | SPATIAL} [INDEX | KEY] [index_name] (key_part,...) [index_option] ...
s.WriteString("FULLTEXT INDEX ")
s.WriteString(QuoteName(k.key))
case keySpatial:
s.WriteString("SPATIAL INDEX ")
s.WriteString(QuoteName(k.key))
default:
return "" // ??
}
s.WriteByte('(')
for n, f := range k.fields {
if n > 0 {
s.WriteString(", ")
}
s.WriteString(QuoteName(f))
}
s.WriteByte(')')
return s.String()
}
func (k *structKey) isUnique() bool {
switch k.typ {
case keyPrimary, keyUnique:
return true
default:
return false
}
}
func (k *structKey) matches(otherK *ShowIndexResult) (bool, error) {
// check if this key matches
// ColumnName?
return true, nil
}