@@ -41,7 +41,10 @@ func (r *{{.Name}}) SetRelationship(field string, rel interface{}) error {
4141 if !ok {
4242 return fmt.Errorf("kallax: record of type %t can't be assigned to relationship {{.Name}}", rel)
4343 }
44- r.{{.Name}} = {{if or (not .IsPtr) .IsOneToManyRelationship}}*{{end}}val
44+ {{if .IsPtr}}if !val.Model.ID.IsEmpty() {
45+ r.{{.Name}} = val
46+ }
47+ {{else}}r.{{.Name}} = *val{{end}}
4548 return nil
4649 {{else}}case "{{.Name}}":
4750 records, ok := rel.([]kallax.Record)
@@ -72,8 +75,45 @@ type {{.StoreName}} struct {
7275// New{{.StoreName}} creates a new instance of {{.StoreName}}
7376// using a SQL database.
7477func New{{.StoreName}}(db *sql.DB) *{{.StoreName}} {
75- return &{{.StoreName}}{kallax.NewStore(db, Schema.{{.Name}}.BaseSchema)}
78+ return &{{.StoreName}}{kallax.NewStore(db)}
79+ }
80+
81+ {{if .HasRelationships}}
82+ func (s *{{.StoreName}}) relationshipRecords(record *{{.Name}}) []kallax.RecordWithSchema {
83+ record.ClearVirtualColumns()
84+ var records []kallax.RecordWithSchema
85+ {{range .Relationships}}
86+ {{if .IsInverse}}
87+ if {{if .IsPtr}}record.{{.Name}} != nil{{else}}!record.{{.Name}}.ID.IsEmpty(){{end}} {
88+ record.AddVirtualColumn("{{.ForeignKey}}", record.{{.Name}}.ID)
89+ records = append(records, kallax.RecordWithSchema{
90+ Schema.{{.TypeSchemaName}}.BaseSchema,
91+ {{if not .IsPtr}}&{{end}}record.{{.Name}},
92+ })
93+ }
94+ {{else if .IsOneToManyRelationship}}
95+ for _, rec := range record.{{.Name}} {
96+ rec.ClearVirtualColumns()
97+ rec.AddVirtualColumn("{{.ForeignKey}}", record.ID)
98+ records = append(records, kallax.RecordWithSchema{
99+ Schema.{{.TypeSchemaName}}.BaseSchema,
100+ {{if not ($.IsPtrSlice .)}}&{{end}}rec,
101+ })
102+ }
103+ {{else}}
104+ if {{if .IsPtr}}record.{{.Name}} != nil{{else}}!record.{{.Name}}.ID.IsEmpty(){{end}} {
105+ record.{{.Name}}.ClearVirtualColumns()
106+ record.{{.Name}}.AddVirtualColumn("{{.ForeignKey}}", record.ID)
107+ records = append(records, kallax.RecordWithSchema{
108+ Schema.{{.TypeSchemaName}}.BaseSchema,
109+ {{if not .IsPtr}}&{{end}}record.{{.Name}},
110+ })
111+ }
112+ {{end}}
113+ {{end}}
114+ return records
76115}
116+ {{end}}
77117
78118// Insert inserts a {{.Name}} in the database. A non-persisted object is
79119// required for this operation.
@@ -87,7 +127,25 @@ func (s *{{.StoreName}}) Insert(record *{{.Name}}) error {
87127 if err := record.BeforeInsert(); err != nil {
88128 }
89129 {{end}}
90- return s.Store.Insert(record)
130+ {{if .HasRelationships}}
131+ records := s.relationshipRecords(record)
132+ if len(records) > 0 {
133+ return s.Store.Transaction(func(s *kallax.Store) error {
134+ if err := s.Insert(Schema.{{.Name}}.BaseSchema, record); err != nil {
135+ return err
136+ }
137+
138+ for _, r := range records {
139+ if _, err := s.Save(r.Schema, r.Record); err != nil {
140+ return err
141+ }
142+ }
143+
144+ return nil
145+ })
146+ }
147+ {{end}}
148+ return s.Store.Insert(Schema.{{.Name}}.BaseSchema, record)
91149}
92150
93151// Update updates the given record on the database. If the columns are given,
@@ -96,7 +154,7 @@ func (s *{{.StoreName}}) Insert(record *{{.Name}}) error {
96154// in memory but not on the database.
97155// Only writable records can be updated. Writable objects are those that have
98156// been just inserted or retrieved using a query with no custom select fields.
99- func (s *{{.StoreName}}) Update(record *{{.Name}}, cols ...kallax.SchemaField) (int64, error) {
157+ func (s *{{.StoreName}}) Update(record *{{.Name}}, cols ...kallax.SchemaField) (updated int64, err error) {
100158 {{if .Events.Has "BeforeSave"}}
101159 if err := record.BeforeSave(); err != nil {
102160 return 0, err
@@ -107,7 +165,26 @@ func (s *{{.StoreName}}) Update(record *{{.Name}}, cols ...kallax.SchemaField) (
107165 return 0, err
108166 }
109167 {{end}}
110- return s.Store.Update(record, cols...)
168+ {{if .HasRelationships}}
169+ records := s.relationshipRecords(record)
170+ if len(records) > 0 {
171+ err = s.Store.Transaction(func(s *kallax.Store) error {
172+ updated, err = s.Update(Schema.{{.Name}}.BaseSchema, record, cols...)
173+ if err != nil {
174+ return err
175+ }
176+
177+ for _, r := range records {
178+ if _, err := s.Save(r.Schema, r.Record); err != nil {
179+ return err
180+ }
181+ }
182+ return nil
183+ })
184+ return updated, err
185+ }
186+ {{end}}
187+ return s.Store.Update(Schema.{{.Name}}.BaseSchema, record, cols...)
111188}
112189
113190// Save inserts the object if the record is not persisted, otherwise it updates
@@ -132,12 +209,21 @@ func (s *{{.StoreName}}) Save(record *{{.Name}}) (updated bool, err error) {
132209 }
133210 }
134211 {{end}}
135- return s.Store.Save(record)
212+ if !record.IsPersisted() {
213+ return false, s.Insert(record)
214+ }
215+
216+ rowsUpdated, err := s.Update(record)
217+ if err != nil {
218+ return false, err
219+ }
220+
221+ return rowsUpdated > 0, nil
136222}
137223
138224// Delete removes the given record from the database.
139225func (s *{{.StoreName}}) Delete(record *{{.Name}}) error {
140- return s.Store.Delete(record)
226+ return s.Store.Delete(Schema.{{.Name}}.BaseSchema, record)
141227}
142228
143229// Find returns the set of results for the given query.
@@ -172,6 +258,7 @@ func (s *{{.StoreName}}) MustCount(q *{{.QueryName}}) int64 {
172258// `sql.ErrNoRows` is returned if there are no results.
173259func (s *{{.StoreName}}) FindOne(q *{{.QueryName}}) (*{{.Name}}, error) {
174260 q.Limit(1)
261+ q.Offset(0)
175262 rs, err := s.Find(q)
176263 if err != nil {
177264 return nil, err
@@ -206,7 +293,7 @@ func (s *{{.StoreName}}) MustFindOne(q *{{.QueryName}}) *{{.Name}} {
206293// Reload refreshes the {{.Name}} with the data in the database and
207294// makes it writable.
208295func (s *{{.StoreName}}) Reload(record *{{.Name}}) error {
209- return s.Store.Reload(record)
296+ return s.Store.Reload(Schema.{{.Name}}.BaseSchema, record)
210297}
211298
212299// Transaction executes the given callback in a transaction and rollbacks if
@@ -223,6 +310,75 @@ func (s *{{.StoreName}}) Transaction(callback func(*{{.StoreName}}) error) error
223310 })
224311}
225312
313+ {{range .Relationships}}{{if .IsOneToManyRelationship}}
314+ // Remove{{.Name}} removes the given items of the {{.Name}} field of the
315+ // model. If no items are given, it removes all of them.
316+ // The items will also be removed from the passed record inside this method.
317+ func (s *{{.Model.StoreName}}) Remove{{.Name}}(record *{{.Model.Name}}, deleted ...{{if $.IsPtrSlice .}}*{{end}}{{$.GenTypeName .}}) error {
318+ var updated []{{if $.IsPtrSlice .}}*{{end}}{{$.GenTypeName .}}
319+ var clear bool
320+ if len(deleted) == 0 {
321+ clear = true
322+ deleted = record.{{.Name}}
323+ if len(deleted) == 0 {
324+ return nil
325+ }
326+ }
327+
328+ if len(deleted) > 1 {
329+ err := s.Store.Transaction(func(s *kallax.Store) error {
330+ for _, d := range deleted {
331+ if err := s.Delete(Schema.{{.TypeSchemaName}}.BaseSchema, {{if not ($.IsPtrSlice .)}}&{{end}}d); err != nil {
332+ return err
333+ }
334+ }
335+ return nil
336+ })
337+
338+ if err != nil {
339+ return err
340+ }
341+
342+ if clear {
343+ record.{{.Name}} = nil
344+ return nil
345+ }
346+ } else {
347+ if err := s.Store.Delete(Schema.{{.TypeSchemaName}}.BaseSchema, {{if not ($.IsPtrSlice .)}}&{{end}}deleted[0]); err != nil {
348+ return err
349+ }
350+ }
351+
352+
353+ for _, r := range record.{{.Name}} {
354+ var found bool
355+ for _, d := range deleted {
356+ if d.ID == r.ID {
357+ found = true
358+ break
359+ }
360+ }
361+ if !found {
362+ updated = append(updated, r)
363+ }
364+ }
365+ record.{{.Name}} = updated
366+ return nil
367+ }
368+ {{else if not .IsInverse}}
369+ // Remove{{.Name}} removes from the database the given relationship of the
370+ // model. It also resets the field {{.Name}} of the model.
371+ func (s *{{.Model.StoreName}}) Remove{{.Name}}(record *{{.Model.Name}}) error {
372+ err := s.Store.Delete(Schema.{{.TypeSchemaName}}.BaseSchema, {{if not .IsPtr}}&{{end}}record.{{.Name}})
373+ if err != nil {
374+ return err
375+ }
376+
377+ record.{{.Name}} = {{if .IsPtr}}nil{{else}}{{$.GenTypeName .}}{}{{end}}
378+ return nil
379+ }
380+ {{end}}{{end}}
381+
226382{{template "query" .}}
227383
228384{{template "resultset" .}}
0 commit comments