forked from cosmos/cosmos-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
state_object.go
106 lines (85 loc) · 3.94 KB
/
state_object.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
package schema
import "fmt"
// StateObjectType describes an object type a module schema.
type StateObjectType struct {
// Name is the name of the object type. It must be unique within the module schema amongst all object and enum
// types and conform to the NameFormat regular expression.
Name string `json:"name"`
// KeyFields is a list of fields that make up the primary key of the object.
// It can be empty, in which case, indexers should assume that this object is
// a singleton and only has one value. Field names must be unique within the
// object between both key and value fields.
// Key fields CANNOT be nullable and Float32Kind, Float64Kind, JSONKind, StructKind,
// OneOfKind, RepeatedKind, ListKind or ObjectKind
// are NOT ALLOWED.
// It is an INCOMPATIBLE change to add, remove or change fields in the key as this
// changes the underlying primary key of the object.
KeyFields []Field `json:"key_fields,omitempty"`
// ValueFields is a list of fields that are not part of the primary key of the object.
// It can be empty in the case where all fields are part of the primary key.
// Field names must be unique within the object between both key and value fields.
// ObjectKind fields are not allowed.
// It is a COMPATIBLE change to add new value fields to an object type because
// this does not affect the primary key of the object.
// Existing value fields should not be removed or modified.
ValueFields []Field `json:"value_fields,omitempty"`
// RetainDeletions is a flag that indicates whether the indexer should retain
// deleted rows in the database and flag them as deleted rather than actually
// deleting the row. For many types of data in state, the data is deleted even
// though it is still valid in order to save space. Indexers will want to have
// the option of retaining such data and distinguishing from other "true" deletions.
RetainDeletions bool `json:"retain_deletions,omitempty"`
}
// TypeName implements the Type interface.
func (o StateObjectType) TypeName() string {
return o.Name
}
func (StateObjectType) isType() {}
// Validate validates the object type.
func (o StateObjectType) Validate(typeSet TypeSet) error {
if !ValidateName(o.Name) {
return fmt.Errorf("invalid object type name %q", o.Name)
}
fieldNames := map[string]bool{}
for _, field := range o.KeyFields {
if err := field.Validate(typeSet); err != nil {
return fmt.Errorf("invalid key field %q: %v", field.Name, err) //nolint:errorlint // false positive due to using go1.12
}
if !field.Kind.ValidKeyKind() {
return fmt.Errorf("key field %q of kind %q uses an invalid key field kind", field.Name, field.Kind)
}
if field.Nullable {
return fmt.Errorf("key field %q cannot be nullable", field.Name)
}
if fieldNames[field.Name] {
return fmt.Errorf("duplicate field name %q", field.Name)
}
fieldNames[field.Name] = true
}
for _, field := range o.ValueFields {
if err := field.Validate(typeSet); err != nil {
return fmt.Errorf("invalid value field %q: %v", field.Name, err) //nolint:errorlint // false positive due to using go1.12
}
if fieldNames[field.Name] {
return fmt.Errorf("duplicate field name %q", field.Name)
}
fieldNames[field.Name] = true
}
if len(o.KeyFields) == 0 && len(o.ValueFields) == 0 {
return fmt.Errorf("object type %q has no key or value fields", o.Name)
}
return nil
}
// ValidateObjectUpdate validates that the update conforms to the object type.
func (o StateObjectType) ValidateObjectUpdate(update StateObjectUpdate, typeSet TypeSet) error {
if o.Name != update.TypeName {
return fmt.Errorf("object type name %q does not match update type name %q", o.Name, update.TypeName)
}
if err := ValidateObjectKey(o.KeyFields, update.Key, typeSet); err != nil {
return fmt.Errorf("invalid key for object type %q: %v", update.TypeName, err) //nolint:errorlint // false positive due to using go1.12
}
if update.Delete {
return nil
}
return ValidateObjectValue(o.ValueFields, update.Value, typeSet)
}