11package e2db
22
33import (
4+ "bytes"
5+ "crypto/sha1"
6+ "encoding/hex"
7+ "fmt"
48 "reflect"
9+ "sort"
510 "strings"
11+ "unicode"
612
713 "github.com/criticalstack/e2d/pkg/e2db/key"
814 "github.com/pkg/errors"
@@ -16,15 +22,50 @@ type Tag struct {
1622 Name , Value string
1723}
1824
25+ func (t * Tag ) String () string {
26+ if t .Value == "" {
27+ return t .Name
28+ }
29+ return fmt .Sprintf ("%s=%s" , t .Name , t .Value )
30+ }
31+
1932type FieldDef struct {
20- Name string
21- Tags []* Tag
33+ Name string
34+ Kind reflect.Kind
35+ Type string
36+ Tags []* Tag
37+ Fields []* FieldDef
38+ }
39+
40+ func (f * FieldDef ) String () string {
41+ var tags string
42+ if len (f .Tags ) > 0 {
43+ tt := make ([]string , 0 )
44+ for _ , t := range f .Tags {
45+ tt = append (tt , t .String ())
46+ }
47+ tags = fmt .Sprintf (" `%s`" , strings .Join (tt , "," ))
48+ }
49+ t := f .Kind .String ()
50+ if f .Kind == reflect .Struct {
51+ t = f .Type
52+ }
53+ return fmt .Sprintf ("%s %s%s" , f .Name , t , tags )
2254}
2355
2456func (f * FieldDef ) isIndex () bool {
2557 return f .isPrimaryKey () || f .hasTag ("index" , "unique" )
2658}
2759
60+ func (f * FieldDef ) getTag (name string ) * Tag {
61+ for _ , t := range f .Tags {
62+ if t .Name == name {
63+ return t
64+ }
65+ }
66+ return nil
67+ }
68+
2869func (f * FieldDef ) hasTag (tags ... string ) bool {
2970 for _ , t := range f .Tags {
3071 for _ , tag := range tags {
@@ -55,7 +96,7 @@ const (
5596 UniqueIndex
5697)
5798
58- func (f * FieldDef ) Type () IndexType {
99+ func (f * FieldDef ) indexType () IndexType {
59100 switch {
60101 case f .hasTag ("increment" , "id" ):
61102 return PrimaryKey
@@ -69,7 +110,7 @@ func (f *FieldDef) Type() IndexType {
69110}
70111
71112func (f * FieldDef ) indexKey (tableName string , value string ) (string , error ) {
72- switch f .Type () {
113+ switch f .indexType () {
73114 case PrimaryKey :
74115 return key .ID (tableName , value ), nil
75116 case SecondaryIndex , UniqueIndex :
@@ -79,27 +120,13 @@ func (f *FieldDef) indexKey(tableName string, value string) (string, error) {
79120 }
80121}
81122
82- type ModelDef struct {
83- Name string
84- Fields map [string ]* FieldDef
85-
86- t reflect.Type
87- }
88-
89- func NewModelDef (t reflect.Type ) * ModelDef {
90- if t .Kind () == reflect .Ptr {
91- t = t .Elem ()
92- }
93- if t .NumField () == 0 {
94- panic ("must have at least 1 struct field" )
95- }
96- m := & ModelDef {
97- Name : t .Name (),
98- Fields : make (map [string ]* FieldDef ),
99- t : t ,
100- }
123+ func newFieldDefs (t reflect.Type ) []* FieldDef {
124+ fields := make ([]* FieldDef , 0 )
101125 for i := 0 ; i < t .NumField (); i ++ {
102126 ft := t .Field (i )
127+ if unicode .IsLower ([]rune (ft .Name )[0 ]) {
128+ continue
129+ }
103130 tags := make ([]* Tag , 0 )
104131 if tagValue , ok := ft .Tag .Lookup ("e2db" ); ok {
105132 for _ , t := range strings .Split (tagValue , "," ) {
@@ -111,11 +138,58 @@ func NewModelDef(t reflect.Type) *ModelDef {
111138 }
112139 }
113140 }
114- m .Fields [ft .Name ] = & FieldDef {
141+ sort .Slice (tags , func (i , j int ) bool {
142+ return tags [i ].Name < tags [j ].Name
143+ })
144+ fd := & FieldDef {
115145 Name : ft .Name ,
146+ Kind : ft .Type .Kind (),
147+ Type : ft .Type .String (),
116148 Tags : tags ,
117149 }
150+ if ft .Type .Kind () == reflect .Struct {
151+ fd .Fields = newFieldDefs (ft .Type )
152+ }
153+ fields = append (fields , fd )
154+ }
155+ sort .Slice (fields , func (i , j int ) bool {
156+ return fields [i ].Name < fields [j ].Name
157+ })
158+ return fields
159+ }
160+
161+ type ModelDef struct {
162+ Name string
163+ Fields []* FieldDef
164+ CheckSum string
165+ Version string
166+
167+ t reflect.Type
168+ }
169+
170+ func NewModelDef (t reflect.Type ) * ModelDef {
171+ if t .Kind () == reflect .Ptr {
172+ t = t .Elem ()
118173 }
174+ if t .NumField () == 0 {
175+ panic ("must have at least 1 struct field" )
176+ }
177+ m := & ModelDef {
178+ Name : t .Name (),
179+ Fields : newFieldDefs (t ),
180+ t : t ,
181+ }
182+ if ! m .hasPrimaryKey () {
183+ panic ("must specify a primary key" )
184+ }
185+ pk := m .getPrimaryKey ()
186+ vt := pk .getTag ("v" )
187+ if vt == nil {
188+ vt = & Tag {Name : "v" , Value : "0" }
189+ pk .Tags = append (pk .Tags , vt )
190+ }
191+ m .Version = vt .Value
192+ m .CheckSum = SchemaCheckSum (m )
119193 return m
120194}
121195
@@ -127,18 +201,45 @@ func (m *ModelDef) New() *reflect.Value {
127201 return & v
128202}
129203
204+ func (m * ModelDef ) getPrimaryKey () * FieldDef {
205+ for _ , f := range m .Fields {
206+ if f .isPrimaryKey () {
207+ return f
208+ }
209+ }
210+ return nil
211+ }
212+
213+ func (m * ModelDef ) hasPrimaryKey () bool {
214+ return m .getPrimaryKey () != nil
215+ }
216+
217+ func (m * ModelDef ) getFieldByName (name string ) (* FieldDef , bool ) {
218+ for _ , f := range m .Fields {
219+ if f .Name == name {
220+ return f , true
221+ }
222+ }
223+ return nil , false
224+ }
225+
226+ func (m * ModelDef ) String () string {
227+ return m .t .String ()
228+ }
229+
130230type Field struct {
131231 * FieldDef
132- value reflect.Value
232+
233+ v reflect.Value
133234}
134235
135236func (f * Field ) isZero () bool {
136- return f .value .IsValid () && reflect .DeepEqual (f .value .Interface (), reflect .Zero (f .value .Type ()).Interface ())
237+ return f .v .IsValid () && reflect .DeepEqual (f .v .Interface (), reflect .Zero (f .v .Type ()).Interface ())
137238}
138239
139240type ModelItem struct {
140241 * ModelDef
141- Fields map [ string ]* Field
242+ Fields [ ]* Field
142243}
143244
144245func NewModelItem (v reflect.Value ) * ModelItem {
@@ -148,13 +249,13 @@ func NewModelItem(v reflect.Value) *ModelItem {
148249 }
149250 m := & ModelItem {
150251 ModelDef : NewModelDef (v .Type ()),
151- Fields : make (map [ string ]* Field ),
252+ Fields : make ([ ]* Field , 0 ),
152253 }
153- for name , f := range m .ModelDef .Fields {
154- m .Fields [ name ] = & Field {
254+ for _ , f := range m .ModelDef .Fields {
255+ m .Fields = append ( m . Fields , & Field {
155256 FieldDef : f ,
156- value : v .FieldByName (name ),
157- }
257+ v : v .FieldByName (f . Name ),
258+ })
158259 }
159260 return m
160261}
@@ -167,3 +268,54 @@ func (m *ModelItem) getPrimaryKey() (*Field, error) {
167268 }
168269 return nil , ErrNoPrimaryKey
169270}
271+
272+ func schemaCheckSumFieldDef (f * FieldDef ) string {
273+ var sb strings.Builder
274+ sb .WriteString (f .String ())
275+ for _ , f := range f .Fields {
276+ switch f .Kind {
277+ case reflect .Struct :
278+ sb .WriteString (schemaCheckSumFieldDef (f ))
279+ default :
280+ sb .WriteString (f .String ())
281+ }
282+ }
283+ return sb .String ()
284+ }
285+
286+ func SchemaCheckSum (m * ModelDef ) string {
287+ var b bytes.Buffer
288+ for _ , f := range m .Fields {
289+ b .WriteString (schemaCheckSumFieldDef (f ))
290+ }
291+ h := sha1 .Sum (b .Bytes ())
292+ name := hex .EncodeToString (h [:])
293+ if len (name ) > 5 {
294+ name = name [:5 ]
295+ }
296+ return strings .ToLower (name )
297+ }
298+
299+ func printFieldDef (f * FieldDef ) {
300+ fmt .Println (f )
301+ for _ , f := range f .Fields {
302+ switch f .Kind {
303+ case reflect .Struct :
304+ printFieldDef (f )
305+ default :
306+ fmt .Println (f )
307+ }
308+ }
309+ }
310+
311+ func PrintModelDef (m * ModelDef ) {
312+ fmt .Println (m )
313+ for _ , f := range m .Fields {
314+ switch f .Kind {
315+ case reflect .Struct :
316+ printFieldDef (f )
317+ default :
318+ fmt .Println (f )
319+ }
320+ }
321+ }
0 commit comments