/
index_description.go
86 lines (73 loc) · 2.64 KB
/
index_description.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
package format
import (
"database/sql"
"fmt"
)
// IndexDescription contains all the data known about a specific index.
// Note that some indexes may be related (e.g. in cases of clustered indexes).
type IndexDescription struct {
Table string `db:"Table"`
NonUnique bool `db:"Non_unique"`
KeyName string `db:"Key_name"`
SeqInIndex int `db:"Seq_in_index"`
ColumnName sql.NullString `db:"Column_name"`
Comment sql.NullString `db:"Comment"`
Expression sql.NullString `db:"Expression"`
// Not used (yet)
Collation sql.NullString `db:"Collation"`
Cardinality sql.NullString `db:"Cardinality"`
SubPart sql.NullString `db:"Sub_part"`
Packed sql.NullString `db:"Packed"`
Null sql.NullString `db:"Null"`
IndexType sql.NullString `db:"Index_type"`
IndexComment sql.NullString `db:"Index_comment"`
Visible sql.NullString `db:"Visible"`
Clustered sql.NullString `db:"Clustered"`
}
// IndexDescriptions is a set of index descriptions
type IndexDescriptions []IndexDescription
// ConvertToLogicalIndexes converts raw index descriptions into a aggregated
// type.
func (descs IndexDescriptions) ConvertToLogicalIndexes() ([]LogicalIndex, error) {
indices := map[string]LogicalIndex{}
for _, description := range descs {
var li LogicalIndex
var ok bool
if li, ok = indices[description.KeyName]; !ok {
li = LogicalIndex{
Table: description.Table,
NonUnique: description.NonUnique,
KeyName: description.KeyName,
Comment: description.Comment.String,
Expression: description.Expression.String,
}
}
li.IndexedColumnNamesOrdered = append(li.IndexedColumnNamesOrdered, description.ColumnName.String)
if len(li.IndexedColumnNamesOrdered) != description.SeqInIndex {
return nil, fmt.Errorf("internal logic error: expecting for indexed columns to always be returned in sequence")
}
indices[description.KeyName] = li
}
// return things in the order they were received -- required for the out
// put to be deterministic.
result := []LogicalIndex{}
var addedKeys = map[string]struct{}{}
for _, description := range descs {
// only add keys once
if _, ok := addedKeys[description.KeyName]; !ok {
result = append(result, indices[description.KeyName])
addedKeys[description.KeyName] = struct{}{}
}
}
return result, nil
}
// LogicalIndex defines a "logical index -- e.g. what will make the most sense
// to humans"
type LogicalIndex struct {
Table string
NonUnique bool
KeyName string
IndexedColumnNamesOrdered []string
Comment string
Expression string
}