-
Notifications
You must be signed in to change notification settings - Fork 0
/
record.go
176 lines (150 loc) · 4.49 KB
/
record.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package dal
import (
"errors"
"fmt"
"reflect"
)
// ErrDoesNotExist indicates a record does not exist
// Deprecated: use ErrRecordNotFound instead
//var ErrDoesNotExist = errors.New("does not exist")
// Record is a gateway to a database record.
type Record interface {
// Key keeps a `table` Name of an entity and an ID within that table or a chain of nested keys
Key() *Key
// Error keeps an error for the last operation on the record. Not found is not treated as an error
Error() error
// Exists indicates if record was found in database. Throws panic if called before a `Get` or `Set`.
Exists() bool
// SetError sets error relevant to specific record. Intended to be used only by DALgo DB drivers.
// Returns the record itself for convenience.
SetError(err error) Record
// Data returns record data (without ID/key).
// Requires either record to be created by NewRecordWithData()
// or DataTo() to be called first, otherwise panics.
Data() any
// HasChanged & MarkAsChanged are methods of convenience
HasChanged() bool
// MarkAsChanged & HasChanged are methods of convenience
MarkAsChanged()
//// SetDataTo sets DataTo handler
//SetDataTo(dataTo func(target any) error)
//// DataTo deserializes record data into a struct. Throws panic if called before `Get`.
//// Uses a handler set by SetDataTo.
//DataTo(target any) error
}
type record struct {
key *Key
err error
changed bool
data any
//dataTo func(target any) error
}
// Exists returns if records exists.
func (v *record) Exists() bool {
if v.err != nil {
if IsNotFound(v.err) {
return false
}
if v.err == NoError {
return true
}
}
panic("an attempt to check if record exists before it was retrieved from database and SetError(error) called")
}
// Key returns key of a record
func (v *record) Key() *Key {
return v.key
}
// HasChanged indicates if the record has changed since loading
func (v *record) HasChanged() bool {
return v.changed
}
// MarkAsChanged marks the record as changed since loading
func (v *record) MarkAsChanged() {
v.changed = true
}
func (v *record) Data() any {
if v.err == nil {
panic("an attempt to access record data before it was retrieved from database and SetError(error) called")
}
if errors.Is(v.err, NoError) || IsNotFound(v.err) {
return v.data
}
panic(fmt.Errorf("an attempt to retrieve data from a record with an error: %w", v.err))
}
//// SetDataTo sets DataTo handler
//func (v *record) SetDataTo(dataTo func(target any) error) {
// v.dataTo = dataTo
//}
//
//// DataTo marshals record data into target
//func (v record) DataTo(target any) error {
// if target == nil {
// panic("not possible to marshall data into a nil value")
// }
// if v.dataTo == nil {
// panic(fmt.Sprintf("method DataTo(%T) is called before data retrieval", target))
// }
// if err := v.dataTo(target); err != nil {
// return fmt.Errorf("failed to marshal record data into %T: %w", target, err)
// }
// v.data = target
// return nil
//}
// Error returns error associated with a record
func (v *record) Error() error {
if v.err == nil {
return nil
}
if errors.Is(v.err, NoError) {
return nil
}
if IsNotFound(v.err) { // TODO: Is it wrong?
return nil
}
return v.err
}
// SetError sets error associated with a record
func (v *record) SetError(err error) Record {
return v.setError(err)
}
func (v *record) setError(err error) *record {
if err == nil {
v.err = NoError
} else {
v.err = err
}
return v
}
// NewRecord creates a new record
func NewRecord(key *Key) Record {
return newRecordWithOnlyKey(key)
}
func newRecordWithOnlyKey(key *Key) *record {
if key == nil {
panic("parameter 'key' is required for dalgo.NewRecord()")
}
if err := key.Validate(); err != nil {
panic(fmt.Errorf("invalid key: %w", err))
}
return &record{key: key}
}
// NewRecordWithData creates a new record with a data target struct
func NewRecordWithData(key *Key, data any) Record {
record := newRecordWithOnlyKey(key)
record.data = data
return record
}
// NewRecordWithIncompleteKey creates a new record with an incomplete key
// This is mostly intended for use in Select queries
func NewRecordWithIncompleteKey(collection string, idKind reflect.Kind, data any) Record {
return &record{
key: NewIncompleteKey(collection, idKind, nil),
data: data,
}
}
// NewRecordWithoutKey creates a new record without a key
// Obsolete, use NewRecordWithIncompleteKey instead
//func NewRecordWithoutKey(collection string, idKind reflect.Kind, data any) Record {
// return NewRecordWithIncompleteKey(collection, idKind, data)
//}