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,24 +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-
87- func NewModelDef (t reflect.Type ) * ModelDef {
88- if t .Kind () == reflect .Ptr {
89- t = t .Elem ()
90- }
91- if t .NumField () == 0 {
92- panic ("must have at least 1 struct field" )
93- }
94- m := & ModelDef {
95- Name : t .Name (),
96- Fields : make (map [string ]* FieldDef ),
97- }
123+ func newFieldDefs (t reflect.Type ) []* FieldDef {
124+ fields := make ([]* FieldDef , 0 )
98125 for i := 0 ; i < t .NumField (); i ++ {
99126 ft := t .Field (i )
127+ if unicode .IsLower ([]rune (ft .Name )[0 ]) {
128+ continue
129+ }
100130 tags := make ([]* Tag , 0 )
101131 if tagValue , ok := ft .Tag .Lookup ("e2db" ); ok {
102132 for _ , t := range strings .Split (tagValue , "," ) {
@@ -108,26 +138,100 @@ func NewModelDef(t reflect.Type) *ModelDef {
108138 }
109139 }
110140 }
111- 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 {
112145 Name : ft .Name ,
146+ Kind : ft .Type .Kind (),
147+ Type : ft .Type .String (),
113148 Tags : tags ,
114149 }
150+ if ft .Type .Kind () == reflect .Struct {
151+ fd .Fields = newFieldDefs (ft .Type )
152+ }
153+ fields = append (fields , fd )
115154 }
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 ()
173+ }
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 )
116193 return m
117194}
118195
196+ func (m * ModelDef ) getPrimaryKey () * FieldDef {
197+ for _ , f := range m .Fields {
198+ if f .isPrimaryKey () {
199+ return f
200+ }
201+ }
202+ return nil
203+ }
204+
205+ func (m * ModelDef ) hasPrimaryKey () bool {
206+ return m .getPrimaryKey () != nil
207+ }
208+
209+ func (m * ModelDef ) getFieldByName (name string ) (* FieldDef , bool ) {
210+ for _ , f := range m .Fields {
211+ if f .Name == name {
212+ return f , true
213+ }
214+ }
215+ return nil , false
216+ }
217+
218+ func (m * ModelDef ) String () string {
219+ return m .t .String ()
220+ }
221+
119222type Field struct {
120223 * FieldDef
121- value reflect.Value
224+
225+ v reflect.Value
122226}
123227
124228func (f * Field ) isZero () bool {
125- return f .value .IsValid () && reflect .DeepEqual (f .value .Interface (), reflect .Zero (f .value .Type ()).Interface ())
229+ return f .v .IsValid () && reflect .DeepEqual (f .v .Interface (), reflect .Zero (f .v .Type ()).Interface ())
126230}
127231
128232type ModelItem struct {
129233 * ModelDef
130- Fields map [ string ]* Field
234+ Fields [ ]* Field
131235}
132236
133237func NewModelItem (v reflect.Value ) * ModelItem {
@@ -137,13 +241,13 @@ func NewModelItem(v reflect.Value) *ModelItem {
137241 }
138242 m := & ModelItem {
139243 ModelDef : NewModelDef (v .Type ()),
140- Fields : make (map [ string ]* Field ),
244+ Fields : make ([ ]* Field , 0 ),
141245 }
142- for name , f := range m .ModelDef .Fields {
143- m .Fields [ name ] = & Field {
246+ for _ , f := range m .ModelDef .Fields {
247+ m .Fields = append ( m . Fields , & Field {
144248 FieldDef : f ,
145- value : v .FieldByName (name ),
146- }
249+ v : v .FieldByName (f . Name ),
250+ })
147251 }
148252 return m
149253}
@@ -156,3 +260,54 @@ func (m *ModelItem) getPrimaryKey() (*Field, error) {
156260 }
157261 return nil , ErrNoPrimaryKey
158262}
263+
264+ func schemaCheckSumFieldDef (f * FieldDef ) string {
265+ var sb strings.Builder
266+ sb .WriteString (f .String ())
267+ for _ , f := range f .Fields {
268+ switch f .Kind {
269+ case reflect .Struct :
270+ sb .WriteString (schemaCheckSumFieldDef (f ))
271+ default :
272+ sb .WriteString (f .String ())
273+ }
274+ }
275+ return sb .String ()
276+ }
277+
278+ func SchemaCheckSum (m * ModelDef ) string {
279+ var b bytes.Buffer
280+ for _ , f := range m .Fields {
281+ b .WriteString (schemaCheckSumFieldDef (f ))
282+ }
283+ h := sha1 .Sum (b .Bytes ())
284+ name := hex .EncodeToString (h [:])
285+ if len (name ) > 5 {
286+ name = name [:5 ]
287+ }
288+ return strings .ToLower (name )
289+ }
290+
291+ func printFieldDef (f * FieldDef ) {
292+ fmt .Println (f )
293+ for _ , f := range f .Fields {
294+ switch f .Kind {
295+ case reflect .Struct :
296+ printFieldDef (f )
297+ default :
298+ fmt .Println (f )
299+ }
300+ }
301+ }
302+
303+ func PrintModelDef (m * ModelDef ) {
304+ fmt .Println (m )
305+ for _ , f := range m .Fields {
306+ switch f .Kind {
307+ case reflect .Struct :
308+ printFieldDef (f )
309+ default :
310+ fmt .Println (f )
311+ }
312+ }
313+ }
0 commit comments