github.com/artisanhe/tools@v1.0.1-0.20210607022958-19a8fef2eb04/sqlx/builder/obj_key.go (about) 1 package builder 2 3 import ( 4 "container/list" 5 "fmt" 6 ) 7 8 type keyType string 9 10 const ( 11 PRIMARY keyType = "PRIMARY" 12 INDEX keyType = "INDEX" 13 UNIQUE_INDEX keyType = "UNIQUE INDEX" 14 ) 15 16 func PrimaryKey() *Key { 17 return &Key{ 18 Name: string(PRIMARY), 19 Type: PRIMARY, 20 } 21 } 22 23 func Index(name string) *Key { 24 return &Key{ 25 Name: name, 26 Type: INDEX, 27 } 28 } 29 30 func UniqueIndex(name string) *Key { 31 return &Key{ 32 Name: name, 33 Type: UNIQUE_INDEX, 34 } 35 } 36 37 type Keys struct { 38 m map[string]*list.Element 39 l *list.List 40 } 41 42 func (keys *Keys) Clone() *Keys { 43 k := &Keys{} 44 keys.Range(func(key *Key, idx int) { 45 k.Add(key) 46 }) 47 return k 48 } 49 50 func (keys *Keys) Len() int { 51 if keys.l == nil { 52 return 0 53 } 54 return keys.l.Len() 55 } 56 57 func (keys *Keys) IsEmpty() bool { 58 return keys.l == nil || keys.l.Len() == 0 59 } 60 61 func (keys *Keys) Key(keyName string) (key *Key, exists bool) { 62 if keys.m != nil { 63 if c, ok := keys.m[keyName]; ok { 64 return c.Value.(*Key), true 65 } 66 } 67 return nil, false 68 } 69 70 func (keys *Keys) Add(nextKeys ...*Key) { 71 if keys.m == nil { 72 keys.m = map[string]*list.Element{} 73 keys.l = list.New() 74 } 75 for _, key := range nextKeys { 76 keys.m[key.Name] = keys.l.PushBack(key) 77 } 78 } 79 80 func (keys *Keys) Remove(name string) { 81 if keys.m != nil { 82 if e, exists := keys.m[name]; exists { 83 keys.l.Remove(e) 84 delete(keys.m, name) 85 } 86 } 87 } 88 89 func (keys *Keys) Range(cb func(key *Key, idx int)) { 90 if keys.l != nil { 91 i := 0 92 for e := keys.l.Front(); e != nil; e = e.Next() { 93 cb(e.Value.(*Key), i) 94 i++ 95 } 96 } 97 } 98 99 func (keys Keys) Diff(targetKeys Keys) keysDiffResult { 100 r := keysDiffResult{} 101 102 ks := keys.Clone() 103 104 targetKeys.Range(func(key *Key, idx int) { 105 if currentKey, exists := ks.Key(key.Name); exists { 106 if currentKey.Def().Query != key.Def().Query { 107 r.keysForUpdate.Add(key) 108 } 109 } else { 110 r.keysForAdd.Add(key) 111 } 112 ks.Remove(key.Name) 113 }) 114 115 ks.Range(func(key *Key, idx int) { 116 r.keysForDelete.Add(key) 117 }) 118 119 return r 120 } 121 122 type keysDiffResult struct { 123 keysForAdd Keys 124 keysForUpdate Keys 125 keysForDelete Keys 126 } 127 128 func (r keysDiffResult) IsChanged() bool { 129 return !r.keysForAdd.IsEmpty() || !r.keysForUpdate.IsEmpty() || !r.keysForDelete.IsEmpty() 130 } 131 132 type Key struct { 133 Name string 134 Columns 135 Type keyType 136 } 137 138 func (key *Key) WithCols(columns ...*Column) *Key { 139 key.Columns.Add(columns...) 140 return key 141 } 142 143 func (key *Key) String() string { 144 return quote(key.Name) 145 } 146 147 func (key *Key) Add() *Expression { 148 return Expr("ADD").ConcatBy(" ", key.Def()) 149 } 150 151 func (key *Key) Drop() *Expression { 152 if key.Type == PRIMARY { 153 return Expr(fmt.Sprintf("DROP %s KEY", key.Type)) 154 } 155 return Expr(fmt.Sprintf("DROP INDEX %s", key.String())) 156 } 157 158 func (key *Key) IsValidDef() bool { 159 return !key.Columns.IsEmpty() 160 } 161 162 func (key *Key) Def() *Expression { 163 if key.Type == PRIMARY { 164 return Expr(string(key.Type)+" KEY").ConcatBy(" ", key.Columns.Wrap()) 165 } 166 return Expr(string(key.Type)+" "+key.String()).ConcatBy(" ", key.Columns.Wrap()) 167 }