diff --git a/api/cosmos/group/v1beta1/genesis.pulsar.go b/api/cosmos/group/v1beta1/genesis.pulsar.go index 61749ede8..1179d09b7 100644 --- a/api/cosmos/group/v1beta1/genesis.pulsar.go +++ b/api/cosmos/group/v1beta1/genesis.pulsar.go @@ -2,13 +2,14 @@ package groupv1beta1 import ( fmt "fmt" + io "io" + reflect "reflect" + sync "sync" + runtime "github.com/cosmos/cosmos-proto/runtime" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoiface "google.golang.org/protobuf/runtime/protoiface" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - io "io" - reflect "reflect" - sync "sync" ) var _ protoreflect.List = (*_GenesisState_2_list)(nil) diff --git a/orm/encoding/encodeutil/util.go b/orm/encoding/encodeutil/util.go new file mode 100644 index 000000000..025d4bae7 --- /dev/null +++ b/orm/encoding/encodeutil/util.go @@ -0,0 +1,42 @@ +package encodeutil + +import ( + "bytes" + "encoding/binary" + "io" + + "google.golang.org/protobuf/reflect/protoreflect" +) + +// SkipPrefix skips the provided prefix in the reader or returns an error. +// This is used for efficient logical decoding of keys. +func SkipPrefix(r *bytes.Reader, prefix []byte) error { + n := len(prefix) + if n > 0 { + // we skip checking the prefix for performance reasons because we assume + // that it was checked by the caller + _, err := r.Seek(int64(n), io.SeekCurrent) + return err + } + return nil +} + +// AppendVarUInt32 creates a new key prefix, by encoding and appending a +// var-uint32 to the provided prefix. +func AppendVarUInt32(prefix []byte, x uint32) []byte { + prefixLen := len(prefix) + res := make([]byte, prefixLen+binary.MaxVarintLen32) + copy(res, prefix) + n := binary.PutUvarint(res[prefixLen:], uint64(x)) + return res[:prefixLen+n] +} + +// ValuesOf takes the arguments and converts them to protoreflect.Value's. +func ValuesOf(values ...interface{}) []protoreflect.Value { + n := len(values) + res := make([]protoreflect.Value, n) + for i := 0; i < n; i++ { + res[i] = protoreflect.ValueOf(values[i]) + } + return res +} diff --git a/orm/encoding/ormkv/codec.go b/orm/encoding/ormkv/codec.go index 4ec62c891..afaa4b044 100644 --- a/orm/encoding/ormkv/codec.go +++ b/orm/encoding/ormkv/codec.go @@ -19,10 +19,30 @@ type EntryCodec interface { type IndexCodec interface { EntryCodec + // MessageType returns the message type this index codec applies to. + MessageType() protoreflect.MessageType + + // GetFieldNames returns the field names in the key of this index. + GetFieldNames() []protoreflect.Name + // DecodeIndexKey decodes a kv-pair into index-fields and primary-key field // values. These fields may or may not overlap depending on the index. DecodeIndexKey(k, v []byte) (indexFields, primaryKey []protoreflect.Value, err error) // EncodeKVFromMessage encodes a kv-pair for the index from a message. EncodeKVFromMessage(message protoreflect.Message) (k, v []byte, err error) + + // CompareKeys compares the provided values which must correspond to the + // fields in this key. Prefix keys of different lengths are supported but the + // function will panic if either array is too long. A negative value is returned + // if values1 is less than values2, 0 is returned if the two arrays are equal, + // and a positive value is returned if values2 is greater. + CompareKeys(key1, key2 []protoreflect.Value) int + + // EncodeKeyFromMessage encodes the key part of this index and returns both + // index values and encoded key. + EncodeKeyFromMessage(message protoreflect.Message) (keyValues []protoreflect.Value, key []byte, err error) + + // IsFullyOrdered returns true if all fields in the key are also ordered. + IsFullyOrdered() bool } diff --git a/orm/encoding/ormkv/entry.go b/orm/encoding/ormkv/entry.go index c1cd9793e..ac6016ee9 100644 --- a/orm/encoding/ormkv/entry.go +++ b/orm/encoding/ormkv/entry.go @@ -42,17 +42,11 @@ func (p *PrimaryKeyEntry) GetTableName() protoreflect.FullName { } func (p *PrimaryKeyEntry) String() string { - msg := p.Value - msgStr := "_" - if msg != nil { - msgBz, err := protojson.Marshal(msg) - if err == nil { - msgStr = string(msgBz) - } else { - msgStr = fmt.Sprintf("ERR:%v", err) - } + if p.Value == nil { + return fmt.Sprintf("PK %s %s -> _", p.TableName, fmtValues(p.Key)) + } else { + return fmt.Sprintf("PK %s %s -> %s", p.TableName, fmtValues(p.Key), p.Value) } - return fmt.Sprintf("PK:%s/%s:%s", p.TableName, fmtValues(p.Key), msgStr) } func fmtValues(values []protoreflect.Value) string { @@ -109,7 +103,7 @@ func (i *IndexKeyEntry) GetTableName() protoreflect.FullName { func (i *IndexKeyEntry) doNotImplement() {} func (i *IndexKeyEntry) string() string { - return fmt.Sprintf("%s/%s:%s:%s", i.TableName, fmtFields(i.Fields), fmtValues(i.IndexValues), fmtValues(i.PrimaryKey)) + return fmt.Sprintf("%s %s : %s -> %s", i.TableName, fmtFields(i.Fields), fmtValues(i.IndexValues), fmtValues(i.PrimaryKey)) } func fmtFields(fields []protoreflect.Name) string { @@ -122,10 +116,10 @@ func fmtFields(fields []protoreflect.Name) string { func (i *IndexKeyEntry) String() string { if i.IsUnique { - return fmt.Sprintf("UNIQ:%s", i.string()) + return fmt.Sprintf("UNIQ %s", i.string()) } else { - return fmt.Sprintf("IDX:%s", i.string()) + return fmt.Sprintf("IDX %s", i.string()) } } @@ -146,7 +140,7 @@ func (s *SeqEntry) GetTableName() protoreflect.FullName { func (s *SeqEntry) doNotImplement() {} func (s *SeqEntry) String() string { - return fmt.Sprintf("SEQ:%s:%d", s.TableName, s.Value) + return fmt.Sprintf("SEQ %s %d", s.TableName, s.Value) } var _, _, _ Entry = &PrimaryKeyEntry{}, &IndexKeyEntry{}, &SeqEntry{} diff --git a/orm/encoding/ormkv/entry_test.go b/orm/encoding/ormkv/entry_test.go index 24df6082f..1b060cea3 100644 --- a/orm/encoding/ormkv/entry_test.go +++ b/orm/encoding/ormkv/entry_test.go @@ -4,33 +4,31 @@ import ( "testing" "google.golang.org/protobuf/reflect/protoreflect" - - "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" - "gotest.tools/v3/assert" + "github.com/cosmos/cosmos-sdk/orm/encoding/encodeutil" + "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" "github.com/cosmos/cosmos-sdk/orm/internal/testpb" - "github.com/cosmos/cosmos-sdk/orm/internal/testutil" ) -var aFullName = (&testpb.A{}).ProtoReflect().Descriptor().FullName() +var aFullName = (&testpb.ExampleTable{}).ProtoReflect().Descriptor().FullName() func TestPrimaryKeyEntry(t *testing.T) { entry := &ormkv.PrimaryKeyEntry{ TableName: aFullName, - Key: testutil.ValuesOf(uint32(1), "abc"), - Value: &testpb.A{I32: -1}, + Key: encodeutil.ValuesOf(uint32(1), "abc"), + Value: &testpb.ExampleTable{I32: -1}, } - assert.Equal(t, `PK:testpb.A/1/"abc":{"i32":-1}`, entry.String()) + assert.Equal(t, `PK testpb.ExampleTable 1/"abc" -> i32:-1`, entry.String()) assert.Equal(t, aFullName, entry.GetTableName()) // prefix key entry = &ormkv.PrimaryKeyEntry{ TableName: aFullName, - Key: testutil.ValuesOf(uint32(1), "abc"), + Key: encodeutil.ValuesOf(uint32(1), "abc"), Value: nil, } - assert.Equal(t, `PK:testpb.A/1/"abc":_`, entry.String()) + assert.Equal(t, `PK testpb.ExampleTable 1/"abc" -> _`, entry.String()) assert.Equal(t, aFullName, entry.GetTableName()) } @@ -39,20 +37,20 @@ func TestIndexKeyEntry(t *testing.T) { TableName: aFullName, Fields: []protoreflect.Name{"u32", "i32", "str"}, IsUnique: false, - IndexValues: testutil.ValuesOf(uint32(10), int32(-1), "abc"), - PrimaryKey: testutil.ValuesOf("abc", int32(-1)), + IndexValues: encodeutil.ValuesOf(uint32(10), int32(-1), "abc"), + PrimaryKey: encodeutil.ValuesOf("abc", int32(-1)), } - assert.Equal(t, `IDX:testpb.A/u32/i32/str:10/-1/"abc":"abc"/-1`, entry.String()) + assert.Equal(t, `IDX testpb.ExampleTable u32/i32/str : 10/-1/"abc" -> "abc"/-1`, entry.String()) assert.Equal(t, aFullName, entry.GetTableName()) entry = &ormkv.IndexKeyEntry{ TableName: aFullName, Fields: []protoreflect.Name{"u32"}, IsUnique: true, - IndexValues: testutil.ValuesOf(uint32(10)), - PrimaryKey: testutil.ValuesOf("abc", int32(-1)), + IndexValues: encodeutil.ValuesOf(uint32(10)), + PrimaryKey: encodeutil.ValuesOf("abc", int32(-1)), } - assert.Equal(t, `UNIQ:testpb.A/u32:10:"abc"/-1`, entry.String()) + assert.Equal(t, `UNIQ testpb.ExampleTable u32 : 10 -> "abc"/-1`, entry.String()) assert.Equal(t, aFullName, entry.GetTableName()) // prefix key @@ -60,9 +58,9 @@ func TestIndexKeyEntry(t *testing.T) { TableName: aFullName, Fields: []protoreflect.Name{"u32", "i32", "str"}, IsUnique: false, - IndexValues: testutil.ValuesOf(uint32(10), int32(-1)), + IndexValues: encodeutil.ValuesOf(uint32(10), int32(-1)), } - assert.Equal(t, `IDX:testpb.A/u32/i32/str:10/-1:_`, entry.String()) + assert.Equal(t, `IDX testpb.ExampleTable u32/i32/str : 10/-1 -> _`, entry.String()) assert.Equal(t, aFullName, entry.GetTableName()) // prefix key @@ -70,8 +68,8 @@ func TestIndexKeyEntry(t *testing.T) { TableName: aFullName, Fields: []protoreflect.Name{"str", "i32"}, IsUnique: true, - IndexValues: testutil.ValuesOf("abc", int32(1)), + IndexValues: encodeutil.ValuesOf("abc", int32(1)), } - assert.Equal(t, `UNIQ:testpb.A/str/i32:"abc"/1:_`, entry.String()) + assert.Equal(t, `UNIQ testpb.ExampleTable str/i32 : "abc"/1 -> _`, entry.String()) assert.Equal(t, aFullName, entry.GetTableName()) } diff --git a/orm/encoding/ormkv/index_key.go b/orm/encoding/ormkv/index_key.go index 7f2ae36b6..335a5f820 100644 --- a/orm/encoding/ormkv/index_key.go +++ b/orm/encoding/ormkv/index_key.go @@ -12,7 +12,6 @@ import ( // IndexKeyCodec is the codec for (non-unique) index keys. type IndexKeyCodec struct { *KeyCodec - tableName protoreflect.FullName pkFieldOrder []int } @@ -20,7 +19,15 @@ var _ IndexCodec = &IndexKeyCodec{} // NewIndexKeyCodec creates a new IndexKeyCodec with an optional prefix for the // provided message descriptor, index and primary key fields. -func NewIndexKeyCodec(prefix []byte, messageDescriptor protoreflect.MessageDescriptor, indexFields, primaryKeyFields []protoreflect.Name) (*IndexKeyCodec, error) { +func NewIndexKeyCodec(prefix []byte, messageType protoreflect.MessageType, indexFields, primaryKeyFields []protoreflect.Name) (*IndexKeyCodec, error) { + if len(indexFields) == 0 { + return nil, ormerrors.InvalidTableDefinition.Wrapf("index fields are empty") + } + + if len(primaryKeyFields) == 0 { + return nil, ormerrors.InvalidTableDefinition.Wrapf("primary key fields are empty") + } + indexFieldMap := map[protoreflect.Name]int{} keyFields := make([]protoreflect.Name, 0, len(indexFields)+len(primaryKeyFields)) @@ -43,7 +50,7 @@ func NewIndexKeyCodec(prefix []byte, messageDescriptor protoreflect.MessageDescr k++ } - cdc, err := NewKeyCodec(prefix, messageDescriptor, keyFields) + cdc, err := NewKeyCodec(prefix, messageType, keyFields) if err != nil { return nil, err } @@ -51,13 +58,12 @@ func NewIndexKeyCodec(prefix []byte, messageDescriptor protoreflect.MessageDescr return &IndexKeyCodec{ KeyCodec: cdc, pkFieldOrder: pkFieldOrder, - tableName: messageDescriptor.FullName(), }, nil } func (cdc IndexKeyCodec) DecodeIndexKey(k, _ []byte) (indexFields, primaryKey []protoreflect.Value, err error) { - values, err := cdc.Decode(bytes.NewReader(k)) + values, err := cdc.DecodeKey(bytes.NewReader(k)) // got prefix key if err == io.EOF { return values, nil, nil @@ -87,7 +93,7 @@ func (cdc IndexKeyCodec) DecodeEntry(k, v []byte) (Entry, error) { } return &IndexKeyEntry{ - TableName: cdc.tableName, + TableName: cdc.messageType.Descriptor().FullName(), Fields: cdc.fieldNames, IndexValues: idxValues, PrimaryKey: pk, @@ -100,21 +106,19 @@ func (cdc IndexKeyCodec) EncodeEntry(entry Entry) (k, v []byte, err error) { return nil, nil, ormerrors.BadDecodeEntry } - if indexEntry.TableName != cdc.tableName { + if indexEntry.TableName != cdc.messageType.Descriptor().FullName() { return nil, nil, ormerrors.BadDecodeEntry } - bz, err := cdc.KeyCodec.Encode(indexEntry.IndexValues) + bz, err := cdc.KeyCodec.EncodeKey(indexEntry.IndexValues) if err != nil { return nil, nil, err } - return bz, sentinel, nil + return bz, []byte{}, nil } -var sentinel = []byte{0} - func (cdc IndexKeyCodec) EncodeKVFromMessage(message protoreflect.Message) (k, v []byte, err error) { - _, k, err = cdc.EncodeFromMessage(message) - return k, sentinel, err + _, k, err = cdc.EncodeKeyFromMessage(message) + return k, []byte{}, err } diff --git a/orm/encoding/ormkv/index_key_test.go b/orm/encoding/ormkv/index_key_test.go index afc019768..322f24c17 100644 --- a/orm/encoding/ormkv/index_key_test.go +++ b/orm/encoding/ormkv/index_key_test.go @@ -18,20 +18,20 @@ func TestIndexKeyCodec(t *testing.T) { idxPartCdc := testutil.TestKeyCodecGen(1, 5).Draw(t, "idxPartCdc").(testutil.TestKeyCodec) pkCodec := testutil.TestKeyCodecGen(1, 5).Draw(t, "pkCdc").(testutil.TestKeyCodec) prefix := rapid.SliceOfN(rapid.Byte(), 0, 5).Draw(t, "prefix").([]byte) - desc := (&testpb.A{}).ProtoReflect().Descriptor() + messageType := (&testpb.ExampleTable{}).ProtoReflect().Type() indexKeyCdc, err := ormkv.NewIndexKeyCodec( prefix, - desc, + messageType, idxPartCdc.Codec.GetFieldNames(), pkCodec.Codec.GetFieldNames(), ) assert.NilError(t, err) for i := 0; i < 100; i++ { - a := testutil.GenA.Draw(t, fmt.Sprintf("a%d", i)).(*testpb.A) - key := indexKeyCdc.GetValues(a.ProtoReflect()) - pk := pkCodec.Codec.GetValues(a.ProtoReflect()) + a := testutil.GenA.Draw(t, fmt.Sprintf("a%d", i)).(*testpb.ExampleTable) + key := indexKeyCdc.GetKeyValues(a.ProtoReflect()) + pk := pkCodec.Codec.GetKeyValues(a.ProtoReflect()) idx1 := &ormkv.IndexKeyEntry{ - TableName: desc.FullName(), + TableName: messageType.Descriptor().FullName(), Fields: indexKeyCdc.GetFieldNames(), IsUnique: false, IndexValues: key, @@ -48,16 +48,16 @@ func TestIndexKeyCodec(t *testing.T) { entry2, err := indexKeyCdc.DecodeEntry(k, v) assert.NilError(t, err) idx2 := entry2.(*ormkv.IndexKeyEntry) - assert.Equal(t, 0, indexKeyCdc.CompareValues(idx1.IndexValues, idx2.IndexValues)) - assert.Equal(t, 0, pkCodec.Codec.CompareValues(idx1.PrimaryKey, idx2.PrimaryKey)) + assert.Equal(t, 0, indexKeyCdc.CompareKeys(idx1.IndexValues, idx2.IndexValues)) + assert.Equal(t, 0, pkCodec.Codec.CompareKeys(idx1.PrimaryKey, idx2.PrimaryKey)) assert.Equal(t, false, idx2.IsUnique) - assert.Equal(t, desc.FullName(), idx2.TableName) + assert.Equal(t, messageType.Descriptor().FullName(), idx2.TableName) assert.DeepEqual(t, idx1.Fields, idx2.Fields) idxFields, pk2, err := indexKeyCdc.DecodeIndexKey(k, v) assert.NilError(t, err) - assert.Equal(t, 0, indexKeyCdc.CompareValues(key, idxFields)) - assert.Equal(t, 0, pkCodec.Codec.CompareValues(pk, pk2)) + assert.Equal(t, 0, indexKeyCdc.CompareKeys(key, idxFields)) + assert.Equal(t, 0, pkCodec.Codec.CompareKeys(pk, pk2)) } }) } diff --git a/orm/encoding/ormkv/key_codec.go b/orm/encoding/ormkv/key_codec.go index 61481e20c..58c04d93b 100644 --- a/orm/encoding/ormkv/key_codec.go +++ b/orm/encoding/ormkv/key_codec.go @@ -8,6 +8,7 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" + "github.com/cosmos/cosmos-sdk/orm/encoding/encodeutil" "github.com/cosmos/cosmos-sdk/orm/encoding/ormfield" ) @@ -22,11 +23,12 @@ type KeyCodec struct { fieldDescriptors []protoreflect.FieldDescriptor fieldNames []protoreflect.Name fieldCodecs []ormfield.Codec + messageType protoreflect.MessageType } // NewKeyCodec returns a new KeyCodec with an optional prefix for the provided // message descriptor and fields. -func NewKeyCodec(prefix []byte, messageDescriptor protoreflect.MessageDescriptor, fieldNames []protoreflect.Name) (*KeyCodec, error) { +func NewKeyCodec(prefix []byte, messageType protoreflect.MessageType, fieldNames []protoreflect.Name) (*KeyCodec, error) { n := len(fieldNames) fieldCodecs := make([]ormfield.Codec, n) fieldDescriptors := make([]protoreflect.FieldDescriptor, n) @@ -35,7 +37,7 @@ func NewKeyCodec(prefix []byte, messageDescriptor protoreflect.MessageDescriptor i int } fixedSize := 0 - messageFields := messageDescriptor.Fields() + messageFields := messageType.Descriptor().Fields() for i := 0; i < n; i++ { nonTerminal := i != n-1 @@ -63,15 +65,16 @@ func NewKeyCodec(prefix []byte, messageDescriptor protoreflect.MessageDescriptor prefix: prefix, fixedSize: fixedSize, variableSizers: variableSizers, + messageType: messageType, }, nil } -// Encode encodes the values assuming that they correspond to the fields +// EncodeKey encodes the values assuming that they correspond to the fields // specified for the key. If the array of values is shorter than the // number of fields in the key, a partial "prefix" key will be encoded // which can be used for constructing a prefix iterator. -func (cdc *KeyCodec) Encode(values []protoreflect.Value) ([]byte, error) { - sz, err := cdc.ComputeBufferSize(values) +func (cdc *KeyCodec) EncodeKey(values []protoreflect.Value) ([]byte, error) { + sz, err := cdc.ComputeKeyBufferSize(values) if err != nil { return nil, err } @@ -94,8 +97,8 @@ func (cdc *KeyCodec) Encode(values []protoreflect.Value) ([]byte, error) { return w.Bytes(), nil } -// GetValues extracts the values specified by the key fields from the message. -func (cdc *KeyCodec) GetValues(message protoreflect.Message) []protoreflect.Value { +// GetKeyValues extracts the values specified by the key fields from the message. +func (cdc *KeyCodec) GetKeyValues(message protoreflect.Message) []protoreflect.Value { res := make([]protoreflect.Value, len(cdc.fieldDescriptors)) for i, f := range cdc.fieldDescriptors { res[i] = message.Get(f) @@ -103,11 +106,11 @@ func (cdc *KeyCodec) GetValues(message protoreflect.Message) []protoreflect.Valu return res } -// Decode decodes the values in the key specified by the reader. If the +// DecodeKey decodes the values in the key specified by the reader. If the // provided key is a prefix key, the values that could be decoded will // be returned with io.EOF as the error. -func (cdc *KeyCodec) Decode(r *bytes.Reader) ([]protoreflect.Value, error) { - if err := skipPrefix(r, cdc.prefix); err != nil { +func (cdc *KeyCodec) DecodeKey(r *bytes.Reader) ([]protoreflect.Value, error) { + if err := encodeutil.SkipPrefix(r, cdc.prefix); err != nil { return nil, err } @@ -125,10 +128,10 @@ func (cdc *KeyCodec) Decode(r *bytes.Reader) ([]protoreflect.Value, error) { return values, nil } -// EncodeFromMessage combines GetValues and Encode. -func (cdc *KeyCodec) EncodeFromMessage(message protoreflect.Message) ([]protoreflect.Value, []byte, error) { - values := cdc.GetValues(message) - bz, err := cdc.Encode(values) +// EncodeKeyFromMessage combines GetKeyValues and EncodeKey. +func (cdc *KeyCodec) EncodeKeyFromMessage(message protoreflect.Message) ([]protoreflect.Value, []byte, error) { + values := cdc.GetKeyValues(message) + bz, err := cdc.EncodeKey(values) return values, bz, err } @@ -142,12 +145,12 @@ func (cdc *KeyCodec) IsFullyOrdered() bool { return true } -// CompareValues compares the provided values which must correspond to the +// CompareKeys compares the provided values which must correspond to the // fields in this key. Prefix keys of different lengths are supported but the // function will panic if either array is too long. A negative value is returned // if values1 is less than values2, 0 is returned if the two arrays are equal, // and a positive value is returned if values2 is greater. -func (cdc *KeyCodec) CompareValues(values1, values2 []protoreflect.Value) int { +func (cdc *KeyCodec) CompareKeys(values1, values2 []protoreflect.Value) int { j := len(values1) k := len(values2) n := j @@ -178,9 +181,9 @@ func (cdc *KeyCodec) CompareValues(values1, values2 []protoreflect.Value) int { } } -// ComputeBufferSize computes the required buffer size for the provided values +// ComputeKeyBufferSize computes the required buffer size for the provided values // which can represent a full or prefix key. -func (cdc KeyCodec) ComputeBufferSize(values []protoreflect.Value) (int, error) { +func (cdc KeyCodec) ComputeKeyBufferSize(values []protoreflect.Value) (int, error) { size := cdc.fixedSize n := len(values) for _, sz := range cdc.variableSizers { @@ -198,10 +201,10 @@ func (cdc KeyCodec) ComputeBufferSize(values []protoreflect.Value) (int, error) return size, nil } -// SetValues sets the provided values on the message which must correspond +// SetKeyValues sets the provided values on the message which must correspond // exactly to the field descriptors for this key. Prefix keys aren't // supported. -func (cdc *KeyCodec) SetValues(message protoreflect.Message, values []protoreflect.Value) { +func (cdc *KeyCodec) SetKeyValues(message protoreflect.Message, values []protoreflect.Value) { for i, f := range cdc.fieldDescriptors { message.Set(f, values[i]) } @@ -284,6 +287,13 @@ func (cdc *KeyCodec) GetFieldNames() []protoreflect.Name { return cdc.fieldNames } +// Prefix returns the prefix applied to keys in this codec before any field +// values are encoded. func (cdc *KeyCodec) Prefix() []byte { return cdc.prefix } + +// MessageType returns the message type of fields in this key. +func (cdc *KeyCodec) MessageType() protoreflect.MessageType { + return cdc.messageType +} diff --git a/orm/encoding/ormkv/key_codec_test.go b/orm/encoding/ormkv/key_codec_test.go index 948811024..4aa8ac5c5 100644 --- a/orm/encoding/ormkv/key_codec_test.go +++ b/orm/encoding/ormkv/key_codec_test.go @@ -5,14 +5,13 @@ import ( "io" "testing" - "github.com/cosmos/cosmos-sdk/orm/internal/testpb" - - "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" - "google.golang.org/protobuf/reflect/protoreflect" "gotest.tools/v3/assert" "pgregory.net/rapid" + "github.com/cosmos/cosmos-sdk/orm/encoding/encodeutil" + "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" + "github.com/cosmos/cosmos-sdk/orm/internal/testpb" "github.com/cosmos/cosmos-sdk/orm/internal/testutil" ) @@ -29,24 +28,24 @@ func TestKeyCodec(t *testing.T) { keyValues2 := key.Draw(t, "values2") bz2 := assertEncDecKey(t, key, keyValues2) // bytes comparison should equal comparison of values - assert.Equal(t, key.Codec.CompareValues(keyValues, keyValues2), bytes.Compare(bz1, bz2)) + assert.Equal(t, key.Codec.CompareKeys(keyValues, keyValues2), bytes.Compare(bz1, bz2)) } } }) } func assertEncDecKey(t *rapid.T, key testutil.TestKeyCodec, keyValues []protoreflect.Value) []byte { - bz, err := key.Codec.Encode(keyValues) + bz, err := key.Codec.EncodeKey(keyValues) assert.NilError(t, err) - keyValues2, err := key.Codec.Decode(bytes.NewReader(bz)) + keyValues2, err := key.Codec.DecodeKey(bytes.NewReader(bz)) assert.NilError(t, err) - assert.Equal(t, 0, key.Codec.CompareValues(keyValues, keyValues2)) + assert.Equal(t, 0, key.Codec.CompareKeys(keyValues, keyValues2)) return bz } func TestCompareValues(t *testing.T) { cdc, err := ormkv.NewKeyCodec(nil, - (&testpb.A{}).ProtoReflect().Descriptor(), + (&testpb.ExampleTable{}).ProtoReflect().Type(), []protoreflect.Name{"u32", "str", "i32"}) assert.NilError(t, err) @@ -59,113 +58,113 @@ func TestCompareValues(t *testing.T) { }{ { "eq", - testutil.ValuesOf(uint32(0), "abc", int32(-3)), - testutil.ValuesOf(uint32(0), "abc", int32(-3)), + encodeutil.ValuesOf(uint32(0), "abc", int32(-3)), + encodeutil.ValuesOf(uint32(0), "abc", int32(-3)), 0, false, }, { "eq prefix 0", - testutil.ValuesOf(), - testutil.ValuesOf(), + encodeutil.ValuesOf(), + encodeutil.ValuesOf(), 0, false, }, { "eq prefix 1", - testutil.ValuesOf(uint32(0)), - testutil.ValuesOf(uint32(0)), + encodeutil.ValuesOf(uint32(0)), + encodeutil.ValuesOf(uint32(0)), 0, false, }, { "eq prefix 2", - testutil.ValuesOf(uint32(0), "abc"), - testutil.ValuesOf(uint32(0), "abc"), + encodeutil.ValuesOf(uint32(0), "abc"), + encodeutil.ValuesOf(uint32(0), "abc"), 0, false, }, { "lt1", - testutil.ValuesOf(uint32(0), "abc", int32(-3)), - testutil.ValuesOf(uint32(1), "abc", int32(-3)), + encodeutil.ValuesOf(uint32(0), "abc", int32(-3)), + encodeutil.ValuesOf(uint32(1), "abc", int32(-3)), -1, true, }, { "lt2", - testutil.ValuesOf(uint32(1), "abb", int32(-3)), - testutil.ValuesOf(uint32(1), "abc", int32(-3)), + encodeutil.ValuesOf(uint32(1), "abb", int32(-3)), + encodeutil.ValuesOf(uint32(1), "abc", int32(-3)), -1, true, }, { "lt3", - testutil.ValuesOf(uint32(1), "abb", int32(-4)), - testutil.ValuesOf(uint32(1), "abb", int32(-3)), + encodeutil.ValuesOf(uint32(1), "abb", int32(-4)), + encodeutil.ValuesOf(uint32(1), "abb", int32(-3)), -1, true, }, { "less prefix 0", - testutil.ValuesOf(), - testutil.ValuesOf(uint32(1), "abb", int32(-4)), + encodeutil.ValuesOf(), + encodeutil.ValuesOf(uint32(1), "abb", int32(-4)), -1, true, }, { "less prefix 1", - testutil.ValuesOf(uint32(1)), - testutil.ValuesOf(uint32(1), "abb", int32(-4)), + encodeutil.ValuesOf(uint32(1)), + encodeutil.ValuesOf(uint32(1), "abb", int32(-4)), -1, true, }, { "less prefix 2", - testutil.ValuesOf(uint32(1), "abb"), - testutil.ValuesOf(uint32(1), "abb", int32(-4)), + encodeutil.ValuesOf(uint32(1), "abb"), + encodeutil.ValuesOf(uint32(1), "abb", int32(-4)), -1, true, }, { "gt1", - testutil.ValuesOf(uint32(2), "abb", int32(-4)), - testutil.ValuesOf(uint32(1), "abb", int32(-4)), + encodeutil.ValuesOf(uint32(2), "abb", int32(-4)), + encodeutil.ValuesOf(uint32(1), "abb", int32(-4)), 1, false, }, { "gt2", - testutil.ValuesOf(uint32(2), "abc", int32(-4)), - testutil.ValuesOf(uint32(2), "abb", int32(-4)), + encodeutil.ValuesOf(uint32(2), "abc", int32(-4)), + encodeutil.ValuesOf(uint32(2), "abb", int32(-4)), 1, false, }, { "gt3", - testutil.ValuesOf(uint32(2), "abc", int32(1)), - testutil.ValuesOf(uint32(2), "abc", int32(-3)), + encodeutil.ValuesOf(uint32(2), "abc", int32(1)), + encodeutil.ValuesOf(uint32(2), "abc", int32(-3)), 1, false, }, { "gt prefix 0", - testutil.ValuesOf(uint32(2), "abc", int32(-3)), - testutil.ValuesOf(), + encodeutil.ValuesOf(uint32(2), "abc", int32(-3)), + encodeutil.ValuesOf(), 1, true, }, { "gt prefix 1", - testutil.ValuesOf(uint32(2), "abc", int32(-3)), - testutil.ValuesOf(uint32(2)), + encodeutil.ValuesOf(uint32(2), "abc", int32(-3)), + encodeutil.ValuesOf(uint32(2)), 1, true, }, { "gt prefix 2", - testutil.ValuesOf(uint32(2), "abc", int32(-3)), - testutil.ValuesOf(uint32(2), "abc"), + encodeutil.ValuesOf(uint32(2), "abc", int32(-3)), + encodeutil.ValuesOf(uint32(2), "abc"), 1, true, }, @@ -174,7 +173,7 @@ func TestCompareValues(t *testing.T) { t.Run(test.name, func(t *testing.T) { assert.Equal( t, test.expect, - cdc.CompareValues(test.values1, test.values2), + cdc.CompareKeys(test.values1, test.values2), ) // CheckValidRangeIterationKeys should give comparable results err := cdc.CheckValidRangeIterationKeys(test.values1, test.values2) @@ -189,7 +188,7 @@ func TestCompareValues(t *testing.T) { func TestDecodePrefixKey(t *testing.T) { cdc, err := ormkv.NewKeyCodec(nil, - (&testpb.A{}).ProtoReflect().Descriptor(), + (&testpb.ExampleTable{}).ProtoReflect().Type(), []protoreflect.Name{"u32", "str", "bz", "i32"}) assert.NilError(t, err) @@ -199,23 +198,23 @@ func TestDecodePrefixKey(t *testing.T) { }{ { "1", - testutil.ValuesOf(uint32(5), "abc"), + encodeutil.ValuesOf(uint32(5), "abc"), }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - bz, err := cdc.Encode(test.values) + bz, err := cdc.EncodeKey(test.values) assert.NilError(t, err) - values, err := cdc.Decode(bytes.NewReader(bz)) + values, err := cdc.DecodeKey(bytes.NewReader(bz)) assert.ErrorType(t, err, io.EOF) - assert.Equal(t, 0, cdc.CompareValues(test.values, values)) + assert.Equal(t, 0, cdc.CompareKeys(test.values, values)) }) } } func TestValidRangeIterationKeys(t *testing.T) { cdc, err := ormkv.NewKeyCodec(nil, - (&testpb.A{}).ProtoReflect().Descriptor(), + (&testpb.ExampleTable{}).ProtoReflect().Type(), []protoreflect.Name{"u32", "str", "bz", "i32"}) assert.NilError(t, err) @@ -227,62 +226,62 @@ func TestValidRangeIterationKeys(t *testing.T) { }{ { "1 eq", - testutil.ValuesOf(uint32(0)), - testutil.ValuesOf(uint32(0)), + encodeutil.ValuesOf(uint32(0)), + encodeutil.ValuesOf(uint32(0)), true, }, { "1 lt", - testutil.ValuesOf(uint32(0)), - testutil.ValuesOf(uint32(1)), + encodeutil.ValuesOf(uint32(0)), + encodeutil.ValuesOf(uint32(1)), false, }, { "1 gt", - testutil.ValuesOf(uint32(1)), - testutil.ValuesOf(uint32(0)), + encodeutil.ValuesOf(uint32(1)), + encodeutil.ValuesOf(uint32(0)), true, }, { "1,2 lt", - testutil.ValuesOf(uint32(0)), - testutil.ValuesOf(uint32(0), "abc"), + encodeutil.ValuesOf(uint32(0)), + encodeutil.ValuesOf(uint32(0), "abc"), false, }, { "1,2 gt", - testutil.ValuesOf(uint32(0), "abc"), - testutil.ValuesOf(uint32(0)), + encodeutil.ValuesOf(uint32(0), "abc"), + encodeutil.ValuesOf(uint32(0)), false, }, { "1,2,3", - testutil.ValuesOf(uint32(0)), - testutil.ValuesOf(uint32(0), "abc", []byte{1, 2}), + encodeutil.ValuesOf(uint32(0)), + encodeutil.ValuesOf(uint32(0), "abc", []byte{1, 2}), true, }, { "1,2,3,4 lt", - testutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(-1)), - testutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(1)), + encodeutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(-1)), + encodeutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(1)), false, }, { "too long", - testutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(-1)), - testutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(1), int32(1)), + encodeutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(-1)), + encodeutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(1), int32(1)), true, }, { "1,2,3,4 eq", - testutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(1)), - testutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(1)), + encodeutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(1)), + encodeutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(1)), true, }, { "1,2,3,4 bz err", - testutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(-1)), - testutil.ValuesOf(uint32(0), "abc", []byte{1, 2, 3}, int32(1)), + encodeutil.ValuesOf(uint32(0), "abc", []byte{1, 2}, int32(-1)), + encodeutil.ValuesOf(uint32(0), "abc", []byte{1, 2, 3}, int32(1)), true, }, } @@ -300,19 +299,19 @@ func TestValidRangeIterationKeys(t *testing.T) { func TestGetSet(t *testing.T) { cdc, err := ormkv.NewKeyCodec(nil, - (&testpb.A{}).ProtoReflect().Descriptor(), + (&testpb.ExampleTable{}).ProtoReflect().Type(), []protoreflect.Name{"u32", "str", "i32"}) assert.NilError(t, err) - var a testpb.A - values := testutil.ValuesOf(uint32(4), "abc", int32(1)) - cdc.SetValues(a.ProtoReflect(), values) - values2 := cdc.GetValues(a.ProtoReflect()) - assert.Equal(t, 0, cdc.CompareValues(values, values2)) - bz, err := cdc.Encode(values) + var a testpb.ExampleTable + values := encodeutil.ValuesOf(uint32(4), "abc", int32(1)) + cdc.SetKeyValues(a.ProtoReflect(), values) + values2 := cdc.GetKeyValues(a.ProtoReflect()) + assert.Equal(t, 0, cdc.CompareKeys(values, values2)) + bz, err := cdc.EncodeKey(values) assert.NilError(t, err) - values3, bz2, err := cdc.EncodeFromMessage(a.ProtoReflect()) + values3, bz2, err := cdc.EncodeKeyFromMessage(a.ProtoReflect()) assert.NilError(t, err) - assert.Equal(t, 0, cdc.CompareValues(values, values3)) + assert.Equal(t, 0, cdc.CompareKeys(values, values3)) assert.Assert(t, bytes.Equal(bz, bz2)) } diff --git a/orm/encoding/ormkv/primary_key.go b/orm/encoding/ormkv/primary_key.go index fd37558a7..268cb1dc7 100644 --- a/orm/encoding/ormkv/primary_key.go +++ b/orm/encoding/ormkv/primary_key.go @@ -14,21 +14,21 @@ import ( // PrimaryKeyCodec is the codec for primary keys. type PrimaryKeyCodec struct { *KeyCodec - msgType protoreflect.MessageType unmarshalOptions proto.UnmarshalOptions } +var _ IndexCodec = &PrimaryKeyCodec{} + // NewPrimaryKeyCodec creates a new PrimaryKeyCodec for the provided msg and // fields, with an optional prefix and unmarshal options. func NewPrimaryKeyCodec(prefix []byte, msgType protoreflect.MessageType, fieldNames []protoreflect.Name, unmarshalOptions proto.UnmarshalOptions) (*PrimaryKeyCodec, error) { - keyCodec, err := NewKeyCodec(prefix, msgType.Descriptor(), fieldNames) + keyCodec, err := NewKeyCodec(prefix, msgType, fieldNames) if err != nil { return nil, err } return &PrimaryKeyCodec{ KeyCodec: keyCodec, - msgType: msgType, unmarshalOptions: unmarshalOptions, }, nil } @@ -36,7 +36,7 @@ func NewPrimaryKeyCodec(prefix []byte, msgType protoreflect.MessageType, fieldNa var _ IndexCodec = PrimaryKeyCodec{} func (p PrimaryKeyCodec) DecodeIndexKey(k, _ []byte) (indexFields, primaryKey []protoreflect.Value, err error) { - indexFields, err = p.Decode(bytes.NewReader(k)) + indexFields, err = p.DecodeKey(bytes.NewReader(k)) // got prefix key if err == io.EOF { @@ -55,16 +55,21 @@ func (p PrimaryKeyCodec) DecodeIndexKey(k, _ []byte) (indexFields, primaryKey [] } func (p PrimaryKeyCodec) DecodeEntry(k, v []byte) (Entry, error) { - values, err := p.Decode(bytes.NewReader(k)) - if err != nil { + values, err := p.DecodeKey(bytes.NewReader(k)) + if err == io.EOF { + return &PrimaryKeyEntry{ + TableName: p.messageType.Descriptor().FullName(), + Key: values, + }, nil + } else if err != nil { return nil, err } - msg := p.msgType.New().Interface() + msg := p.messageType.New().Interface() err = p.Unmarshal(values, v, msg) return &PrimaryKeyEntry{ - TableName: p.msgType.Descriptor().FullName(), + TableName: p.messageType.Descriptor().FullName(), Key: values, Value: msg, }, err @@ -76,15 +81,15 @@ func (p PrimaryKeyCodec) EncodeEntry(entry Entry) (k, v []byte, err error) { return nil, nil, ormerrors.BadDecodeEntry.Wrapf("expected %T, got %T", &PrimaryKeyEntry{}, entry) } - if pkEntry.TableName != p.msgType.Descriptor().FullName() { + if pkEntry.TableName != p.messageType.Descriptor().FullName() { return nil, nil, ormerrors.BadDecodeEntry.Wrapf( "wrong table name, got %s, expected %s", pkEntry.TableName, - p.msgType.Descriptor().FullName(), + p.messageType.Descriptor().FullName(), ) } - k, err = p.KeyCodec.Encode(pkEntry.Key) + k, err = p.KeyCodec.EncodeKey(pkEntry.Key) if err != nil { return nil, nil, err } @@ -104,7 +109,7 @@ func (p PrimaryKeyCodec) marshal(key []protoreflect.Value, message proto.Message } // set the primary key values again returning the message to its original state - p.SetValues(message.ProtoReflect(), key) + p.SetKeyValues(message.ProtoReflect(), key) return v, nil } @@ -122,12 +127,12 @@ func (p *PrimaryKeyCodec) Unmarshal(key []protoreflect.Value, value []byte, mess } // rehydrate primary key - p.SetValues(message.ProtoReflect(), key) + p.SetKeyValues(message.ProtoReflect(), key) return nil } func (p PrimaryKeyCodec) EncodeKVFromMessage(message protoreflect.Message) (k, v []byte, err error) { - ks, k, err := p.KeyCodec.EncodeFromMessage(message) + ks, k, err := p.KeyCodec.EncodeKeyFromMessage(message) if err != nil { return nil, nil, err } diff --git a/orm/encoding/ormkv/primary_key_test.go b/orm/encoding/ormkv/primary_key_test.go index 787c799e1..dba11a1be 100644 --- a/orm/encoding/ormkv/primary_key_test.go +++ b/orm/encoding/ormkv/primary_key_test.go @@ -20,14 +20,14 @@ func TestPrimaryKeyCodec(t *testing.T) { keyCodec := testutil.TestKeyCodecGen(0, 5).Draw(t, "keyCodec").(testutil.TestKeyCodec) pkCodec, err := ormkv.NewPrimaryKeyCodec( keyCodec.Codec.Prefix(), - (&testpb.A{}).ProtoReflect().Type(), + (&testpb.ExampleTable{}).ProtoReflect().Type(), keyCodec.Codec.GetFieldNames(), proto.UnmarshalOptions{}, ) assert.NilError(t, err) for i := 0; i < 100; i++ { - a := testutil.GenA.Draw(t, fmt.Sprintf("a%d", i)).(*testpb.A) - key := keyCodec.Codec.GetValues(a.ProtoReflect()) + a := testutil.GenA.Draw(t, fmt.Sprintf("a%d", i)).(*testpb.ExampleTable) + key := keyCodec.Codec.GetKeyValues(a.ProtoReflect()) pk1 := &ormkv.PrimaryKeyEntry{ TableName: aFullName, Key: key, @@ -44,16 +44,16 @@ func TestPrimaryKeyCodec(t *testing.T) { entry2, err := pkCodec.DecodeEntry(k, v) assert.NilError(t, err) pk2 := entry2.(*ormkv.PrimaryKeyEntry) - assert.Equal(t, 0, pkCodec.CompareValues(pk1.Key, pk2.Key)) + assert.Equal(t, 0, pkCodec.CompareKeys(pk1.Key, pk2.Key)) assert.DeepEqual(t, pk1.Value, pk2.Value, protocmp.Transform()) idxFields, pk3, err := pkCodec.DecodeIndexKey(k, v) assert.NilError(t, err) - assert.Equal(t, 0, pkCodec.CompareValues(pk1.Key, pk3)) - assert.Equal(t, 0, pkCodec.CompareValues(pk1.Key, idxFields)) + assert.Equal(t, 0, pkCodec.CompareKeys(pk1.Key, pk3)) + assert.Equal(t, 0, pkCodec.CompareKeys(pk1.Key, idxFields)) pkCodec.ClearValues(a.ProtoReflect()) - pkCodec.SetValues(a.ProtoReflect(), pk1.Key) + pkCodec.SetKeyValues(a.ProtoReflect(), pk1.Key) assert.DeepEqual(t, a, pk2.Value, protocmp.Transform()) } }) diff --git a/orm/encoding/ormkv/seq.go b/orm/encoding/ormkv/seq.go index def96bc2a..59e38dc0e 100644 --- a/orm/encoding/ormkv/seq.go +++ b/orm/encoding/ormkv/seq.go @@ -11,13 +11,13 @@ import ( // SeqCodec is the codec for auto-incrementing uint64 primary key sequences. type SeqCodec struct { - tableName protoreflect.FullName - prefix []byte + messageType protoreflect.FullName + prefix []byte } // NewSeqCodec creates a new SeqCodec. -func NewSeqCodec(tableName protoreflect.FullName, prefix []byte) *SeqCodec { - return &SeqCodec{tableName: tableName, prefix: prefix} +func NewSeqCodec(messageType protoreflect.MessageType, prefix []byte) *SeqCodec { + return &SeqCodec{messageType: messageType.Descriptor().FullName(), prefix: prefix} } var _ EntryCodec = &SeqCodec{} @@ -33,7 +33,7 @@ func (s SeqCodec) DecodeEntry(k, v []byte) (Entry, error) { } return &SeqEntry{ - TableName: s.tableName, + TableName: s.messageType, Value: x, }, nil } @@ -44,7 +44,7 @@ func (s SeqCodec) EncodeEntry(entry Entry) (k, v []byte, err error) { return nil, nil, ormerrors.BadDecodeEntry } - if seqEntry.TableName != s.tableName { + if seqEntry.TableName != s.messageType { return nil, nil, ormerrors.BadDecodeEntry } diff --git a/orm/encoding/ormkv/seq_test.go b/orm/encoding/ormkv/seq_test.go index 836d39ae7..29ecf2ed0 100644 --- a/orm/encoding/ormkv/seq_test.go +++ b/orm/encoding/ormkv/seq_test.go @@ -15,8 +15,9 @@ import ( func TestSeqCodec(t *testing.T) { rapid.Check(t, func(t *rapid.T) { prefix := rapid.SliceOfN(rapid.Byte(), 0, 5).Draw(t, "prefix").([]byte) - tableName := (&testpb.A{}).ProtoReflect().Descriptor().FullName() - cdc := ormkv.NewSeqCodec(tableName, prefix) + typ := (&testpb.ExampleTable{}).ProtoReflect().Type() + tableName := typ.Descriptor().FullName() + cdc := ormkv.NewSeqCodec(typ, prefix) seq, err := cdc.DecodeValue(nil) assert.NilError(t, err) diff --git a/orm/encoding/ormkv/unique_key.go b/orm/encoding/ormkv/unique_key.go index 2f5af9a69..93d2a3033 100644 --- a/orm/encoding/ormkv/unique_key.go +++ b/orm/encoding/ormkv/unique_key.go @@ -11,7 +11,6 @@ import ( // UniqueKeyCodec is the codec for unique indexes. type UniqueKeyCodec struct { - tableName protoreflect.FullName pkFieldOrder []struct { inKey bool i int @@ -20,10 +19,20 @@ type UniqueKeyCodec struct { valueCodec *KeyCodec } +var _ IndexCodec = &UniqueKeyCodec{} + // NewUniqueKeyCodec creates a new UniqueKeyCodec with an optional prefix for the // provided message descriptor, index and primary key fields. -func NewUniqueKeyCodec(prefix []byte, messageDescriptor protoreflect.MessageDescriptor, indexFields, primaryKeyFields []protoreflect.Name) (*UniqueKeyCodec, error) { - keyCodec, err := NewKeyCodec(prefix, messageDescriptor, indexFields) +func NewUniqueKeyCodec(prefix []byte, messageType protoreflect.MessageType, indexFields, primaryKeyFields []protoreflect.Name) (*UniqueKeyCodec, error) { + if len(indexFields) == 0 { + return nil, ormerrors.InvalidTableDefinition.Wrapf("index fields are empty") + } + + if len(primaryKeyFields) == 0 { + return nil, ormerrors.InvalidTableDefinition.Wrapf("primary key fields are empty") + } + + keyCodec, err := NewKeyCodec(prefix, messageType, indexFields) if err != nil { return nil, err } @@ -55,23 +64,20 @@ func NewUniqueKeyCodec(prefix []byte, messageDescriptor protoreflect.MessageDesc } } - valueCodec, err := NewKeyCodec(nil, messageDescriptor, valueFields) + valueCodec, err := NewKeyCodec(nil, messageType, valueFields) if err != nil { return nil, err } return &UniqueKeyCodec{ - tableName: messageDescriptor.FullName(), pkFieldOrder: pkFieldOrder, keyCodec: keyCodec, valueCodec: valueCodec, }, nil } -var _ IndexCodec = &UniqueKeyCodec{} - func (u UniqueKeyCodec) DecodeIndexKey(k, v []byte) (indexFields, primaryKey []protoreflect.Value, err error) { - ks, err := u.keyCodec.Decode(bytes.NewReader(k)) + ks, err := u.keyCodec.DecodeKey(bytes.NewReader(k)) // got prefix key if err == io.EOF { @@ -85,7 +91,7 @@ func (u UniqueKeyCodec) DecodeIndexKey(k, v []byte) (indexFields, primaryKey []p return ks, nil, err } - vs, err := u.valueCodec.Decode(bytes.NewReader(v)) + vs, err := u.valueCodec.DecodeKey(bytes.NewReader(v)) if err != nil { return nil, nil, err } @@ -117,7 +123,7 @@ func (u UniqueKeyCodec) DecodeEntry(k, v []byte) (Entry, error) { } return &IndexKeyEntry{ - TableName: u.tableName, + TableName: u.MessageType().Descriptor().FullName(), Fields: u.keyCodec.fieldNames, IsUnique: true, IndexValues: idxVals, @@ -130,7 +136,7 @@ func (u UniqueKeyCodec) EncodeEntry(entry Entry) (k, v []byte, err error) { if !ok { return nil, nil, ormerrors.BadDecodeEntry } - k, err = u.keyCodec.Encode(indexEntry.IndexValues) + k, err = u.keyCodec.EncodeKey(indexEntry.IndexValues) if err != nil { return nil, nil, err } @@ -155,16 +161,44 @@ func (u UniqueKeyCodec) EncodeEntry(entry Entry) (k, v []byte, err error) { } } - v, err = u.valueCodec.Encode(values) + v, err = u.valueCodec.EncodeKey(values) return k, v, err } func (u UniqueKeyCodec) EncodeKVFromMessage(message protoreflect.Message) (k, v []byte, err error) { - _, k, err = u.keyCodec.EncodeFromMessage(message) + _, k, err = u.keyCodec.EncodeKeyFromMessage(message) if err != nil { return nil, nil, err } - _, v, err = u.valueCodec.EncodeFromMessage(message) + _, v, err = u.valueCodec.EncodeKeyFromMessage(message) return k, v, err } + +func (u UniqueKeyCodec) GetFieldNames() []protoreflect.Name { + return u.keyCodec.GetFieldNames() +} + +func (u UniqueKeyCodec) GetKeyCodec() *KeyCodec { + return u.keyCodec +} + +func (u UniqueKeyCodec) GetValueCodec() *KeyCodec { + return u.valueCodec +} + +func (u UniqueKeyCodec) CompareKeys(key1, key2 []protoreflect.Value) int { + return u.keyCodec.CompareKeys(key1, key2) +} + +func (u UniqueKeyCodec) EncodeKeyFromMessage(message protoreflect.Message) (keyValues []protoreflect.Value, key []byte, err error) { + return u.keyCodec.EncodeKeyFromMessage(message) +} + +func (u UniqueKeyCodec) IsFullyOrdered() bool { + return u.keyCodec.IsFullyOrdered() +} + +func (u UniqueKeyCodec) MessageType() protoreflect.MessageType { + return u.keyCodec.messageType +} diff --git a/orm/encoding/ormkv/unique_key_test.go b/orm/encoding/ormkv/unique_key_test.go index 3c113c8e0..3ee688f39 100644 --- a/orm/encoding/ormkv/unique_key_test.go +++ b/orm/encoding/ormkv/unique_key_test.go @@ -17,20 +17,20 @@ func TestUniqueKeyCodec(t *testing.T) { rapid.Check(t, func(t *rapid.T) { keyCodec := testutil.TestKeyCodecGen(1, 5).Draw(t, "keyCodec").(testutil.TestKeyCodec) pkCodec := testutil.TestKeyCodecGen(1, 5).Draw(t, "primaryKeyCodec").(testutil.TestKeyCodec) - desc := (&testpb.A{}).ProtoReflect().Descriptor() + messageType := (&testpb.ExampleTable{}).ProtoReflect().Type() uniqueKeyCdc, err := ormkv.NewUniqueKeyCodec( keyCodec.Codec.Prefix(), - desc, + messageType, keyCodec.Codec.GetFieldNames(), pkCodec.Codec.GetFieldNames(), ) assert.NilError(t, err) for i := 0; i < 100; i++ { - a := testutil.GenA.Draw(t, fmt.Sprintf("a%d", i)).(*testpb.A) - key := keyCodec.Codec.GetValues(a.ProtoReflect()) - pk := pkCodec.Codec.GetValues(a.ProtoReflect()) + a := testutil.GenA.Draw(t, fmt.Sprintf("a%d", i)).(*testpb.ExampleTable) + key := keyCodec.Codec.GetKeyValues(a.ProtoReflect()) + pk := pkCodec.Codec.GetKeyValues(a.ProtoReflect()) uniq1 := &ormkv.IndexKeyEntry{ - TableName: desc.FullName(), + TableName: messageType.Descriptor().FullName(), Fields: keyCodec.Codec.GetFieldNames(), IsUnique: true, IndexValues: key, @@ -47,16 +47,16 @@ func TestUniqueKeyCodec(t *testing.T) { entry2, err := uniqueKeyCdc.DecodeEntry(k, v) assert.NilError(t, err) uniq2 := entry2.(*ormkv.IndexKeyEntry) - assert.Equal(t, 0, keyCodec.Codec.CompareValues(uniq1.IndexValues, uniq2.IndexValues)) - assert.Equal(t, 0, pkCodec.Codec.CompareValues(uniq1.PrimaryKey, uniq2.PrimaryKey)) + assert.Equal(t, 0, keyCodec.Codec.CompareKeys(uniq1.IndexValues, uniq2.IndexValues)) + assert.Equal(t, 0, pkCodec.Codec.CompareKeys(uniq1.PrimaryKey, uniq2.PrimaryKey)) assert.Equal(t, true, uniq2.IsUnique) - assert.Equal(t, desc.FullName(), uniq2.TableName) + assert.Equal(t, messageType.Descriptor().FullName(), uniq2.TableName) assert.DeepEqual(t, uniq1.Fields, uniq2.Fields) idxFields, pk2, err := uniqueKeyCdc.DecodeIndexKey(k, v) assert.NilError(t, err) - assert.Equal(t, 0, keyCodec.Codec.CompareValues(key, idxFields)) - assert.Equal(t, 0, pkCodec.Codec.CompareValues(pk, pk2)) + assert.Equal(t, 0, keyCodec.Codec.CompareKeys(key, idxFields)) + assert.Equal(t, 0, pkCodec.Codec.CompareKeys(pk, pk2)) } }) } diff --git a/orm/encoding/ormkv/util.go b/orm/encoding/ormkv/util.go deleted file mode 100644 index 7d9fee7e2..000000000 --- a/orm/encoding/ormkv/util.go +++ /dev/null @@ -1,17 +0,0 @@ -package ormkv - -import ( - "bytes" - "io" -) - -func skipPrefix(r *bytes.Reader, prefix []byte) error { - n := len(prefix) - if n > 0 { - // we skip checking the prefix for performance reasons because we assume - // that it was checked by the caller - _, err := r.Seek(int64(n), io.SeekCurrent) - return err - } - return nil -} diff --git a/orm/go.mod b/orm/go.mod index 79e3f9737..fc36d4ff0 100644 --- a/orm/go.mod +++ b/orm/go.mod @@ -4,18 +4,37 @@ go 1.17 require ( github.com/cosmos/cosmos-proto v1.0.0-alpha6 - github.com/cosmos/cosmos-sdk/api v0.1.0-alpha1 + github.com/cosmos/cosmos-sdk/api v0.1.0-alpha2 github.com/cosmos/cosmos-sdk/errors v1.0.0-beta.2 + github.com/tendermint/tm-db v0.6.6 google.golang.org/protobuf v1.27.1 gotest.tools/v3 v3.1.0 pgregory.net/rapid v0.4.7 ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/DataDog/zstd v1.4.5 // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/dgraph-io/badger/v2 v2.2007.2 // indirect + github.com/dgraph-io/ristretto v0.0.3 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect + github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 // indirect + github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect + github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3 // indirect + github.com/google/btree v1.0.0 // indirect github.com/google/go-cmp v0.5.5 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // indirect + github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect + go.etcd.io/bbolt v1.3.6 // indirect + golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f // indirect + golang.org/x/sys v0.0.0-20210903071746-97244b99971b // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect ) replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 diff --git a/orm/go.sum b/orm/go.sum index c6bcb55e5..42a482eaa 100644 --- a/orm/go.sum +++ b/orm/go.sum @@ -1,56 +1,283 @@ -github.com/cosmos/cosmos-proto v1.0.0-alpha1/go.mod h1:msdDWOvfStHLG+Z2y2SJ0dcqimZ2vc8M1MPnZ4jOF7U= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cosmos/cosmos-proto v1.0.0-alpha4/go.mod h1:msdDWOvfStHLG+Z2y2SJ0dcqimZ2vc8M1MPnZ4jOF7U= github.com/cosmos/cosmos-proto v1.0.0-alpha6 h1:N2BvV2AyzGAXCJnvlw1pMzEQ+76tj5FDBrkYQYIDCdU= github.com/cosmos/cosmos-proto v1.0.0-alpha6/go.mod h1:msdDWOvfStHLG+Z2y2SJ0dcqimZ2vc8M1MPnZ4jOF7U= -github.com/cosmos/cosmos-sdk/api v0.1.0-alpha1 h1:inilHdPSVUHHp8R+uW2MNPXkC3AFmTySE1kHWwc8XjM= -github.com/cosmos/cosmos-sdk/api v0.1.0-alpha1/go.mod h1:cJoD3zcka5CZsRloy0auZiVDQtlXAfZSUxLyJMVJ/uk= +github.com/cosmos/cosmos-sdk/api v0.1.0-alpha2 h1:47aK2mZ8oh3wyr5Q4OiZxyrMkQZRW67Ah/HfC8dW8hs= +github.com/cosmos/cosmos-sdk/api v0.1.0-alpha2/go.mod h1:xWm3hne2f6upv80eIS+fJnnUaed/R2EJno1It4Zb9aw= github.com/cosmos/cosmos-sdk/errors v1.0.0-beta.2 h1:bBglNlra8ZHb4dmbEE8V85ihLA+DkriSm7tcx6x/JWo= github.com/cosmos/cosmos-sdk/errors v1.0.0-beta.2/go.mod h1:Gi7pzVRnvZ1N16JAXpLADzng0ePoE7YeEHaULSFB2Ts= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgraph-io/badger/v2 v2.2007.2 h1:EjjK0KqwaFMlPin1ajhP943VPENHJdEz1KLIegjaI3k= +github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= +github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgraph-io/ristretto v0.0.3 h1:jh22xisGBjrEVnRZ1DVTpBVQm0Xndu8sMl0CWDzSIBI= +github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3 h1:ur2rms48b3Ep1dxh7aUV2FZEQ8jEVO2F6ILKx8ofkAg= +github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk= +github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= +github.com/tendermint/tm-db v0.6.6 h1:EzhaOfR0bdKyATqcd5PNeyeq8r+V4bRPHBfyFdD9kGM= +github.com/tendermint/tm-db v0.6.6/go.mod h1:wP8d49A85B7/erz/r4YbKssKw6ylsO/hKtFk7E1aWZI= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg= +golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210903071746-97244b99971b h1:3Dq0eVHn0uaQJmPO+/aYPI/fRMqdrVDbu7MQcku54gg= +golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.1.0 h1:rVV8Tcg/8jHUkPUorwjaMTtemIMVXfIPKiOqnhEhakk= gotest.tools/v3 v3.1.0/go.mod h1:fHy7eyTmJFO5bQbUsEGQ1v4m2J3Jz9eWL54TP2/ZuYQ= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g= pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= diff --git a/orm/internal/listinternal/options.go b/orm/internal/listinternal/options.go new file mode 100644 index 000000000..6db3af3cf --- /dev/null +++ b/orm/internal/listinternal/options.go @@ -0,0 +1,40 @@ +package listinternal + +import ( + "fmt" + + "google.golang.org/protobuf/reflect/protoreflect" +) + +// Options is the internal list options struct. +type Options struct { + Start, End, Prefix []protoreflect.Value + Reverse bool + Cursor []byte +} + +func (o Options) Validate() error { + if o.Start != nil || o.End != nil { + if o.Prefix != nil { + return fmt.Errorf("can either use Start/End or Prefix, not both") + } + } + + return nil +} + +type Option interface { + apply(*Options) +} + +type FuncOption func(*Options) + +func (f FuncOption) apply(options *Options) { + f(options) +} + +func ApplyOptions(opts *Options, funcOpts []Option) { + for _, opt := range funcOpts { + opt.apply(opts) + } +} diff --git a/orm/internal/testkv/debug.go b/orm/internal/testkv/debug.go new file mode 100644 index 000000000..eda657c6d --- /dev/null +++ b/orm/internal/testkv/debug.go @@ -0,0 +1,247 @@ +package testkv + +import ( + "fmt" + + "google.golang.org/protobuf/proto" + + "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" + "github.com/cosmos/cosmos-sdk/orm/model/kv" + "github.com/cosmos/cosmos-sdk/orm/model/ormtable" +) + +// Debugger is an interface that handles debug info from the debug store wrapper. +type Debugger interface { + + // Log logs a single log message. + Log(string) + + // Decode decodes a key-value entry into a debug string. + Decode(key, value []byte) string +} + +// NewDebugBackend wraps both stores from a Backend with a debugger. +func NewDebugBackend(backend ormtable.Backend, debugger Debugger) ormtable.Backend { + return ormtable.NewBackend(ormtable.BackendOptions{ + CommitmentStore: NewDebugStore(backend.CommitmentStore(), debugger, "commit"), + IndexStore: NewDebugStore(backend.IndexStore(), debugger, "index"), + Hooks: debugHooks{debugger: debugger, hooks: backend.Hooks()}, + }) +} + +type debugStore struct { + store kv.Store + debugger Debugger + storeName string +} + +// NewDebugStore wraps the store with the debugger instance returning a debug store wrapper. +func NewDebugStore(store kv.Store, debugger Debugger, storeName string) kv.Store { + return &debugStore{store: store, debugger: debugger, storeName: storeName} +} + +func (t debugStore) Get(key []byte) ([]byte, error) { + val, err := t.store.Get(key) + if err != nil { + if t.debugger != nil { + t.debugger.Log(fmt.Sprintf("ERR on GET %s: %v", t.debugger.Decode(key, nil), err)) + } + return nil, err + } + if t.debugger != nil { + t.debugger.Log(fmt.Sprintf("GET %x %x", key, val)) + t.debugger.Log(fmt.Sprintf(" %s", t.debugger.Decode(key, val))) + } + return val, nil +} + +func (t debugStore) Has(key []byte) (bool, error) { + has, err := t.store.Has(key) + if err != nil { + if t.debugger != nil { + t.debugger.Log(fmt.Sprintf("ERR on HAS %s: %v", t.debugger.Decode(key, nil), err)) + } + return has, err + } + if t.debugger != nil { + t.debugger.Log(fmt.Sprintf("HAS %x", key)) + t.debugger.Log(fmt.Sprintf(" %s", t.debugger.Decode(key, nil))) + } + return has, nil +} + +func (t debugStore) Iterator(start, end []byte) (kv.Iterator, error) { + if t.debugger != nil { + t.debugger.Log(fmt.Sprintf("ITERATOR %x -> %x", start, end)) + } + it, err := t.store.Iterator(start, end) + if err != nil { + return nil, err + } + return &debugIterator{ + iterator: it, + storeName: t.storeName, + debugger: t.debugger, + }, nil +} + +func (t debugStore) ReverseIterator(start, end []byte) (kv.Iterator, error) { + if t.debugger != nil { + t.debugger.Log(fmt.Sprintf("ITERATOR %x <- %x", start, end)) + } + it, err := t.store.ReverseIterator(start, end) + if err != nil { + return nil, err + } + return &debugIterator{ + iterator: it, + storeName: t.storeName, + debugger: t.debugger, + }, nil +} + +func (t debugStore) Set(key, value []byte) error { + if t.debugger != nil { + t.debugger.Log(fmt.Sprintf("SET %x %x", key, value)) + t.debugger.Log(fmt.Sprintf(" %s", t.debugger.Decode(key, value))) + } + err := t.store.Set(key, value) + if err != nil { + if t.debugger != nil { + t.debugger.Log(fmt.Sprintf("ERR on SET %s: %v", t.debugger.Decode(key, value), err)) + } + return err + } + return nil +} + +func (t debugStore) Delete(key []byte) error { + if t.debugger != nil { + t.debugger.Log(fmt.Sprintf("DEL %x", key)) + t.debugger.Log(fmt.Sprintf("DEL %s", t.debugger.Decode(key, nil))) + } + err := t.store.Delete(key) + if err != nil { + if t.debugger != nil { + t.debugger.Log(fmt.Sprintf("ERR on SET %s: %v", t.debugger.Decode(key, nil), err)) + } + return err + } + return nil +} + +var _ kv.Store = &debugStore{} + +type debugIterator struct { + iterator kv.Iterator + storeName string + debugger Debugger +} + +func (d debugIterator) Domain() (start []byte, end []byte) { + start, end = d.iterator.Domain() + d.debugger.Log(fmt.Sprintf(" DOMAIN %x -> %x", start, end)) + return start, end +} + +func (d debugIterator) Valid() bool { + valid := d.iterator.Valid() + d.debugger.Log(fmt.Sprintf(" VALID %t", valid)) + return valid +} + +func (d debugIterator) Next() { + d.debugger.Log(" NEXT") + d.iterator.Next() +} + +func (d debugIterator) Key() (key []byte) { + key = d.iterator.Key() + value := d.iterator.Value() + d.debugger.Log(fmt.Sprintf(" KEY %x %x", key, value)) + d.debugger.Log(fmt.Sprintf(" %s", d.debugger.Decode(key, value))) + return key +} + +func (d debugIterator) Value() (value []byte) { + return d.iterator.Value() +} + +func (d debugIterator) Error() error { + err := d.iterator.Error() + d.debugger.Log(fmt.Sprintf(" ERR %+v", err)) + return err +} + +func (d debugIterator) Close() error { + d.debugger.Log(" CLOSE") + return d.iterator.Close() +} + +var _ kv.Iterator = &debugIterator{} + +// EntryCodecDebugger is a Debugger instance that uses an EntryCodec and Print +// function for debugging. +type EntryCodecDebugger struct { + EntryCodec ormkv.EntryCodec + Print func(string) +} + +func (d *EntryCodecDebugger) Log(s string) { + if d.Print != nil { + d.Print(s) + } else { + fmt.Println(s) + } +} + +func (d *EntryCodecDebugger) Decode(key, value []byte) string { + entry, err := d.EntryCodec.DecodeEntry(key, value) + if err != nil { + return fmt.Sprintf("ERR:%v", err) + } + + return entry.String() +} + +type debugHooks struct { + debugger Debugger + hooks ormtable.Hooks +} + +func (d debugHooks) OnInsert(message proto.Message) error { + d.debugger.Log(fmt.Sprintf( + "ORM INSERT %s %s", + message.ProtoReflect().Descriptor().FullName(), + message, + )) + if d.hooks != nil { + return d.hooks.OnInsert(message) + } + return nil +} + +func (d debugHooks) OnUpdate(existing, new proto.Message) error { + d.debugger.Log(fmt.Sprintf( + "ORM UPDATE %s %s -> %s", + existing.ProtoReflect().Descriptor().FullName(), + existing, + new, + )) + if d.hooks != nil { + return d.hooks.OnUpdate(existing, new) + } + return nil +} + +func (d debugHooks) OnDelete(message proto.Message) error { + d.debugger.Log(fmt.Sprintf( + "ORM DELETE %s %s", + message.ProtoReflect().Descriptor().FullName(), + message, + )) + if d.hooks != nil { + return d.hooks.OnDelete(message) + } + return nil +} diff --git a/orm/internal/testkv/mem.go b/orm/internal/testkv/mem.go new file mode 100644 index 000000000..f5944a2fa --- /dev/null +++ b/orm/internal/testkv/mem.go @@ -0,0 +1,27 @@ +package testkv + +import ( + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/orm/model/ormtable" +) + +// NewSplitMemBackend returns a Backend instance +// which uses two separate memory stores to simulate behavior when there +// are really two separate backing stores. +func NewSplitMemBackend() ormtable.Backend { + return ormtable.NewBackend(ormtable.BackendOptions{ + CommitmentStore: dbm.NewMemDB(), + IndexStore: dbm.NewMemDB(), + }) +} + +// NewSharedMemBackend returns a Backend instance +// which uses a single backing memory store to simulate legacy scenarios +// where only a single KV-store is available to modules. +func NewSharedMemBackend() ormtable.Backend { + return ormtable.NewBackend(ormtable.BackendOptions{ + CommitmentStore: dbm.NewMemDB(), + // commit store is automatically used as the index store + }) +} diff --git a/orm/internal/testpb/testschema.proto b/orm/internal/testpb/testschema.proto index 565bc539e..814f68aaf 100644 --- a/orm/internal/testpb/testschema.proto +++ b/orm/internal/testpb/testschema.proto @@ -8,15 +8,16 @@ import "cosmos/orm/v1alpha1/orm.proto"; option go_package = "github.com/cosmos/cosmos-sdk/orm/internal/testpb"; -message A { +message ExampleTable { option (cosmos.orm.v1alpha1.table) = { id: 1; primary_key: { - fields: "u32,u64,str" + fields: "u32,i64,str" } index:{ id: 1; fields:"u64,str" + unique: true } index:{ id: 2; @@ -49,10 +50,15 @@ message A { // Invalid key fields: repeated uint32 repeated = 17; map map = 18; - B msg = 19; + ExampleMessage msg = 19; oneof sum { uint32 oneof = 20; } + + message ExampleMessage { + string foo = 1; + int32 bar = 2; + } } enum Enum { @@ -63,20 +69,28 @@ enum Enum { ENUM_NEG_THREE = -3; } -message B { - option (cosmos.orm.v1alpha1.singleton) = {id: 2}; - string x = 1; -} -message C { +message ExampleAutoIncrementTable { option (cosmos.orm.v1alpha1.table) = { id: 3 primary_key:{ fields:"id" auto_increment: true } + index:{ + id: 1 + fields:"x" + unique: true + } }; uint64 id = 1; string x = 2; + int32 y = 3; +} + +message ExampleSingleton { + option (cosmos.orm.v1alpha1.singleton) = {id: 2}; + string foo = 1; + int32 bar = 2; } diff --git a/orm/internal/testpb/testschema.pulsar.go b/orm/internal/testpb/testschema.pulsar.go index 62638d908..d32dd7e37 100644 --- a/orm/internal/testpb/testschema.pulsar.go +++ b/orm/internal/testpb/testschema.pulsar.go @@ -16,66 +16,66 @@ import ( sync "sync" ) -var _ protoreflect.List = (*_A_17_list)(nil) +var _ protoreflect.List = (*_ExampleTable_17_list)(nil) -type _A_17_list struct { +type _ExampleTable_17_list struct { list *[]uint32 } -func (x *_A_17_list) Len() int { +func (x *_ExampleTable_17_list) Len() int { if x.list == nil { return 0 } return len(*x.list) } -func (x *_A_17_list) Get(i int) protoreflect.Value { +func (x *_ExampleTable_17_list) Get(i int) protoreflect.Value { return protoreflect.ValueOfUint32((*x.list)[i]) } -func (x *_A_17_list) Set(i int, value protoreflect.Value) { +func (x *_ExampleTable_17_list) Set(i int, value protoreflect.Value) { valueUnwrapped := value.Uint() concreteValue := (uint32)(valueUnwrapped) (*x.list)[i] = concreteValue } -func (x *_A_17_list) Append(value protoreflect.Value) { +func (x *_ExampleTable_17_list) Append(value protoreflect.Value) { valueUnwrapped := value.Uint() concreteValue := (uint32)(valueUnwrapped) *x.list = append(*x.list, concreteValue) } -func (x *_A_17_list) AppendMutable() protoreflect.Value { - panic(fmt.Errorf("AppendMutable can not be called on message A at list field Repeated as it is not of Message kind")) +func (x *_ExampleTable_17_list) AppendMutable() protoreflect.Value { + panic(fmt.Errorf("AppendMutable can not be called on message ExampleTable at list field Repeated as it is not of Message kind")) } -func (x *_A_17_list) Truncate(n int) { +func (x *_ExampleTable_17_list) Truncate(n int) { *x.list = (*x.list)[:n] } -func (x *_A_17_list) NewElement() protoreflect.Value { +func (x *_ExampleTable_17_list) NewElement() protoreflect.Value { v := uint32(0) return protoreflect.ValueOfUint32(v) } -func (x *_A_17_list) IsValid() bool { +func (x *_ExampleTable_17_list) IsValid() bool { return x.list != nil } -var _ protoreflect.Map = (*_A_18_map)(nil) +var _ protoreflect.Map = (*_ExampleTable_18_map)(nil) -type _A_18_map struct { +type _ExampleTable_18_map struct { m *map[string]uint32 } -func (x *_A_18_map) Len() int { +func (x *_ExampleTable_18_map) Len() int { if x.m == nil { return 0 } return len(*x.m) } -func (x *_A_18_map) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) { +func (x *_ExampleTable_18_map) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) { if x.m == nil { return } @@ -88,7 +88,7 @@ func (x *_A_18_map) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) } } -func (x *_A_18_map) Has(key protoreflect.MapKey) bool { +func (x *_ExampleTable_18_map) Has(key protoreflect.MapKey) bool { if x.m == nil { return false } @@ -98,7 +98,7 @@ func (x *_A_18_map) Has(key protoreflect.MapKey) bool { return ok } -func (x *_A_18_map) Clear(key protoreflect.MapKey) { +func (x *_ExampleTable_18_map) Clear(key protoreflect.MapKey) { if x.m == nil { return } @@ -107,7 +107,7 @@ func (x *_A_18_map) Clear(key protoreflect.MapKey) { delete(*x.m, concreteKey) } -func (x *_A_18_map) Get(key protoreflect.MapKey) protoreflect.Value { +func (x *_ExampleTable_18_map) Get(key protoreflect.MapKey) protoreflect.Value { if x.m == nil { return protoreflect.Value{} } @@ -120,7 +120,7 @@ func (x *_A_18_map) Get(key protoreflect.MapKey) protoreflect.Value { return protoreflect.ValueOfUint32(v) } -func (x *_A_18_map) Set(key protoreflect.MapKey, value protoreflect.Value) { +func (x *_ExampleTable_18_map) Set(key protoreflect.MapKey, value protoreflect.Value) { if !key.IsValid() || !value.IsValid() { panic("invalid key or value provided") } @@ -131,77 +131,77 @@ func (x *_A_18_map) Set(key protoreflect.MapKey, value protoreflect.Value) { (*x.m)[concreteKey] = concreteValue } -func (x *_A_18_map) Mutable(key protoreflect.MapKey) protoreflect.Value { +func (x *_ExampleTable_18_map) Mutable(key protoreflect.MapKey) protoreflect.Value { panic("should not call Mutable on protoreflect.Map whose value is not of type protoreflect.Message") } -func (x *_A_18_map) NewValue() protoreflect.Value { +func (x *_ExampleTable_18_map) NewValue() protoreflect.Value { v := uint32(0) return protoreflect.ValueOfUint32(v) } -func (x *_A_18_map) IsValid() bool { +func (x *_ExampleTable_18_map) IsValid() bool { return x.m != nil } var ( - md_A protoreflect.MessageDescriptor - fd_A_u32 protoreflect.FieldDescriptor - fd_A_u64 protoreflect.FieldDescriptor - fd_A_str protoreflect.FieldDescriptor - fd_A_bz protoreflect.FieldDescriptor - fd_A_ts protoreflect.FieldDescriptor - fd_A_dur protoreflect.FieldDescriptor - fd_A_i32 protoreflect.FieldDescriptor - fd_A_s32 protoreflect.FieldDescriptor - fd_A_sf32 protoreflect.FieldDescriptor - fd_A_i64 protoreflect.FieldDescriptor - fd_A_s64 protoreflect.FieldDescriptor - fd_A_sf64 protoreflect.FieldDescriptor - fd_A_f32 protoreflect.FieldDescriptor - fd_A_f64 protoreflect.FieldDescriptor - fd_A_b protoreflect.FieldDescriptor - fd_A_e protoreflect.FieldDescriptor - fd_A_repeated protoreflect.FieldDescriptor - fd_A_map protoreflect.FieldDescriptor - fd_A_msg protoreflect.FieldDescriptor - fd_A_oneof protoreflect.FieldDescriptor + md_ExampleTable protoreflect.MessageDescriptor + fd_ExampleTable_u32 protoreflect.FieldDescriptor + fd_ExampleTable_u64 protoreflect.FieldDescriptor + fd_ExampleTable_str protoreflect.FieldDescriptor + fd_ExampleTable_bz protoreflect.FieldDescriptor + fd_ExampleTable_ts protoreflect.FieldDescriptor + fd_ExampleTable_dur protoreflect.FieldDescriptor + fd_ExampleTable_i32 protoreflect.FieldDescriptor + fd_ExampleTable_s32 protoreflect.FieldDescriptor + fd_ExampleTable_sf32 protoreflect.FieldDescriptor + fd_ExampleTable_i64 protoreflect.FieldDescriptor + fd_ExampleTable_s64 protoreflect.FieldDescriptor + fd_ExampleTable_sf64 protoreflect.FieldDescriptor + fd_ExampleTable_f32 protoreflect.FieldDescriptor + fd_ExampleTable_f64 protoreflect.FieldDescriptor + fd_ExampleTable_b protoreflect.FieldDescriptor + fd_ExampleTable_e protoreflect.FieldDescriptor + fd_ExampleTable_repeated protoreflect.FieldDescriptor + fd_ExampleTable_map protoreflect.FieldDescriptor + fd_ExampleTable_msg protoreflect.FieldDescriptor + fd_ExampleTable_oneof protoreflect.FieldDescriptor ) func init() { file_testpb_testschema_proto_init() - md_A = File_testpb_testschema_proto.Messages().ByName("A") - fd_A_u32 = md_A.Fields().ByName("u32") - fd_A_u64 = md_A.Fields().ByName("u64") - fd_A_str = md_A.Fields().ByName("str") - fd_A_bz = md_A.Fields().ByName("bz") - fd_A_ts = md_A.Fields().ByName("ts") - fd_A_dur = md_A.Fields().ByName("dur") - fd_A_i32 = md_A.Fields().ByName("i32") - fd_A_s32 = md_A.Fields().ByName("s32") - fd_A_sf32 = md_A.Fields().ByName("sf32") - fd_A_i64 = md_A.Fields().ByName("i64") - fd_A_s64 = md_A.Fields().ByName("s64") - fd_A_sf64 = md_A.Fields().ByName("sf64") - fd_A_f32 = md_A.Fields().ByName("f32") - fd_A_f64 = md_A.Fields().ByName("f64") - fd_A_b = md_A.Fields().ByName("b") - fd_A_e = md_A.Fields().ByName("e") - fd_A_repeated = md_A.Fields().ByName("repeated") - fd_A_map = md_A.Fields().ByName("map") - fd_A_msg = md_A.Fields().ByName("msg") - fd_A_oneof = md_A.Fields().ByName("oneof") + md_ExampleTable = File_testpb_testschema_proto.Messages().ByName("ExampleTable") + fd_ExampleTable_u32 = md_ExampleTable.Fields().ByName("u32") + fd_ExampleTable_u64 = md_ExampleTable.Fields().ByName("u64") + fd_ExampleTable_str = md_ExampleTable.Fields().ByName("str") + fd_ExampleTable_bz = md_ExampleTable.Fields().ByName("bz") + fd_ExampleTable_ts = md_ExampleTable.Fields().ByName("ts") + fd_ExampleTable_dur = md_ExampleTable.Fields().ByName("dur") + fd_ExampleTable_i32 = md_ExampleTable.Fields().ByName("i32") + fd_ExampleTable_s32 = md_ExampleTable.Fields().ByName("s32") + fd_ExampleTable_sf32 = md_ExampleTable.Fields().ByName("sf32") + fd_ExampleTable_i64 = md_ExampleTable.Fields().ByName("i64") + fd_ExampleTable_s64 = md_ExampleTable.Fields().ByName("s64") + fd_ExampleTable_sf64 = md_ExampleTable.Fields().ByName("sf64") + fd_ExampleTable_f32 = md_ExampleTable.Fields().ByName("f32") + fd_ExampleTable_f64 = md_ExampleTable.Fields().ByName("f64") + fd_ExampleTable_b = md_ExampleTable.Fields().ByName("b") + fd_ExampleTable_e = md_ExampleTable.Fields().ByName("e") + fd_ExampleTable_repeated = md_ExampleTable.Fields().ByName("repeated") + fd_ExampleTable_map = md_ExampleTable.Fields().ByName("map") + fd_ExampleTable_msg = md_ExampleTable.Fields().ByName("msg") + fd_ExampleTable_oneof = md_ExampleTable.Fields().ByName("oneof") } -var _ protoreflect.Message = (*fastReflection_A)(nil) +var _ protoreflect.Message = (*fastReflection_ExampleTable)(nil) -type fastReflection_A A +type fastReflection_ExampleTable ExampleTable -func (x *A) ProtoReflect() protoreflect.Message { - return (*fastReflection_A)(x) +func (x *ExampleTable) ProtoReflect() protoreflect.Message { + return (*fastReflection_ExampleTable)(x) } -func (x *A) slowProtoReflect() protoreflect.Message { +func (x *ExampleTable) slowProtoReflect() protoreflect.Message { mi := &file_testpb_testschema_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -213,43 +213,43 @@ func (x *A) slowProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -var _fastReflection_A_messageType fastReflection_A_messageType -var _ protoreflect.MessageType = fastReflection_A_messageType{} +var _fastReflection_ExampleTable_messageType fastReflection_ExampleTable_messageType +var _ protoreflect.MessageType = fastReflection_ExampleTable_messageType{} -type fastReflection_A_messageType struct{} +type fastReflection_ExampleTable_messageType struct{} -func (x fastReflection_A_messageType) Zero() protoreflect.Message { - return (*fastReflection_A)(nil) +func (x fastReflection_ExampleTable_messageType) Zero() protoreflect.Message { + return (*fastReflection_ExampleTable)(nil) } -func (x fastReflection_A_messageType) New() protoreflect.Message { - return new(fastReflection_A) +func (x fastReflection_ExampleTable_messageType) New() protoreflect.Message { + return new(fastReflection_ExampleTable) } -func (x fastReflection_A_messageType) Descriptor() protoreflect.MessageDescriptor { - return md_A +func (x fastReflection_ExampleTable_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_ExampleTable } // Descriptor returns message descriptor, which contains only the protobuf // type information for the message. -func (x *fastReflection_A) Descriptor() protoreflect.MessageDescriptor { - return md_A +func (x *fastReflection_ExampleTable) Descriptor() protoreflect.MessageDescriptor { + return md_ExampleTable } // Type returns the message type, which encapsulates both Go and protobuf // type information. If the Go type information is not needed, // it is recommended that the message descriptor be used instead. -func (x *fastReflection_A) Type() protoreflect.MessageType { - return _fastReflection_A_messageType +func (x *fastReflection_ExampleTable) Type() protoreflect.MessageType { + return _fastReflection_ExampleTable_messageType } // New returns a newly allocated and mutable empty message. -func (x *fastReflection_A) New() protoreflect.Message { - return new(fastReflection_A) +func (x *fastReflection_ExampleTable) New() protoreflect.Message { + return new(fastReflection_ExampleTable) } // Interface unwraps the message reflection interface and // returns the underlying ProtoMessage interface. -func (x *fastReflection_A) Interface() protoreflect.ProtoMessage { - return (*A)(x) +func (x *fastReflection_ExampleTable) Interface() protoreflect.ProtoMessage { + return (*ExampleTable)(x) } // Range iterates over every populated field in an undefined order, @@ -257,127 +257,127 @@ func (x *fastReflection_A) Interface() protoreflect.ProtoMessage { // Range returns immediately if f returns false. // While iterating, mutating operations may only be performed // on the current field descriptor. -func (x *fastReflection_A) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { +func (x *fastReflection_ExampleTable) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { if x.U32 != uint32(0) { value := protoreflect.ValueOfUint32(x.U32) - if !f(fd_A_u32, value) { + if !f(fd_ExampleTable_u32, value) { return } } if x.U64 != uint64(0) { value := protoreflect.ValueOfUint64(x.U64) - if !f(fd_A_u64, value) { + if !f(fd_ExampleTable_u64, value) { return } } if x.Str != "" { value := protoreflect.ValueOfString(x.Str) - if !f(fd_A_str, value) { + if !f(fd_ExampleTable_str, value) { return } } if len(x.Bz) != 0 { value := protoreflect.ValueOfBytes(x.Bz) - if !f(fd_A_bz, value) { + if !f(fd_ExampleTable_bz, value) { return } } if x.Ts != nil { value := protoreflect.ValueOfMessage(x.Ts.ProtoReflect()) - if !f(fd_A_ts, value) { + if !f(fd_ExampleTable_ts, value) { return } } if x.Dur != nil { value := protoreflect.ValueOfMessage(x.Dur.ProtoReflect()) - if !f(fd_A_dur, value) { + if !f(fd_ExampleTable_dur, value) { return } } if x.I32 != int32(0) { value := protoreflect.ValueOfInt32(x.I32) - if !f(fd_A_i32, value) { + if !f(fd_ExampleTable_i32, value) { return } } if x.S32 != int32(0) { value := protoreflect.ValueOfInt32(x.S32) - if !f(fd_A_s32, value) { + if !f(fd_ExampleTable_s32, value) { return } } if x.Sf32 != int32(0) { value := protoreflect.ValueOfInt32(x.Sf32) - if !f(fd_A_sf32, value) { + if !f(fd_ExampleTable_sf32, value) { return } } if x.I64 != int64(0) { value := protoreflect.ValueOfInt64(x.I64) - if !f(fd_A_i64, value) { + if !f(fd_ExampleTable_i64, value) { return } } if x.S64 != int64(0) { value := protoreflect.ValueOfInt64(x.S64) - if !f(fd_A_s64, value) { + if !f(fd_ExampleTable_s64, value) { return } } if x.Sf64 != int64(0) { value := protoreflect.ValueOfInt64(x.Sf64) - if !f(fd_A_sf64, value) { + if !f(fd_ExampleTable_sf64, value) { return } } if x.F32 != uint32(0) { value := protoreflect.ValueOfUint32(x.F32) - if !f(fd_A_f32, value) { + if !f(fd_ExampleTable_f32, value) { return } } if x.F64 != uint64(0) { value := protoreflect.ValueOfUint64(x.F64) - if !f(fd_A_f64, value) { + if !f(fd_ExampleTable_f64, value) { return } } if x.B != false { value := protoreflect.ValueOfBool(x.B) - if !f(fd_A_b, value) { + if !f(fd_ExampleTable_b, value) { return } } if x.E != 0 { value := protoreflect.ValueOfEnum((protoreflect.EnumNumber)(x.E)) - if !f(fd_A_e, value) { + if !f(fd_ExampleTable_e, value) { return } } if len(x.Repeated) != 0 { - value := protoreflect.ValueOfList(&_A_17_list{list: &x.Repeated}) - if !f(fd_A_repeated, value) { + value := protoreflect.ValueOfList(&_ExampleTable_17_list{list: &x.Repeated}) + if !f(fd_ExampleTable_repeated, value) { return } } if len(x.Map) != 0 { - value := protoreflect.ValueOfMap(&_A_18_map{m: &x.Map}) - if !f(fd_A_map, value) { + value := protoreflect.ValueOfMap(&_ExampleTable_18_map{m: &x.Map}) + if !f(fd_ExampleTable_map, value) { return } } if x.Msg != nil { value := protoreflect.ValueOfMessage(x.Msg.ProtoReflect()) - if !f(fd_A_msg, value) { + if !f(fd_ExampleTable_msg, value) { return } } if x.Sum != nil { switch o := x.Sum.(type) { - case *A_Oneof: + case *ExampleTable_Oneof: v := o.Oneof value := protoreflect.ValueOfUint32(v) - if !f(fd_A_oneof, value) { + if !f(fd_ExampleTable_oneof, value) { return } } @@ -395,59 +395,59 @@ func (x *fastReflection_A) Range(f func(protoreflect.FieldDescriptor, protorefle // In other cases (aside from the nullable cases above), // a proto3 scalar field is populated if it contains a non-zero value, and // a repeated field is populated if it is non-empty. -func (x *fastReflection_A) Has(fd protoreflect.FieldDescriptor) bool { +func (x *fastReflection_ExampleTable) Has(fd protoreflect.FieldDescriptor) bool { switch fd.FullName() { - case "testpb.A.u32": + case "testpb.ExampleTable.u32": return x.U32 != uint32(0) - case "testpb.A.u64": + case "testpb.ExampleTable.u64": return x.U64 != uint64(0) - case "testpb.A.str": + case "testpb.ExampleTable.str": return x.Str != "" - case "testpb.A.bz": + case "testpb.ExampleTable.bz": return len(x.Bz) != 0 - case "testpb.A.ts": + case "testpb.ExampleTable.ts": return x.Ts != nil - case "testpb.A.dur": + case "testpb.ExampleTable.dur": return x.Dur != nil - case "testpb.A.i32": + case "testpb.ExampleTable.i32": return x.I32 != int32(0) - case "testpb.A.s32": + case "testpb.ExampleTable.s32": return x.S32 != int32(0) - case "testpb.A.sf32": + case "testpb.ExampleTable.sf32": return x.Sf32 != int32(0) - case "testpb.A.i64": + case "testpb.ExampleTable.i64": return x.I64 != int64(0) - case "testpb.A.s64": + case "testpb.ExampleTable.s64": return x.S64 != int64(0) - case "testpb.A.sf64": + case "testpb.ExampleTable.sf64": return x.Sf64 != int64(0) - case "testpb.A.f32": + case "testpb.ExampleTable.f32": return x.F32 != uint32(0) - case "testpb.A.f64": + case "testpb.ExampleTable.f64": return x.F64 != uint64(0) - case "testpb.A.b": + case "testpb.ExampleTable.b": return x.B != false - case "testpb.A.e": + case "testpb.ExampleTable.e": return x.E != 0 - case "testpb.A.repeated": + case "testpb.ExampleTable.repeated": return len(x.Repeated) != 0 - case "testpb.A.map": + case "testpb.ExampleTable.map": return len(x.Map) != 0 - case "testpb.A.msg": + case "testpb.ExampleTable.msg": return x.Msg != nil - case "testpb.A.oneof": + case "testpb.ExampleTable.oneof": if x.Sum == nil { return false - } else if _, ok := x.Sum.(*A_Oneof); ok { + } else if _, ok := x.Sum.(*ExampleTable_Oneof); ok { return true } else { return false } default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.A")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleTable")) } - panic(fmt.Errorf("message testpb.A does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleTable does not contain field %s", fd.FullName())) } } @@ -457,53 +457,53 @@ func (x *fastReflection_A) Has(fd protoreflect.FieldDescriptor) bool { // associated with the given field number. // // Clear is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_A) Clear(fd protoreflect.FieldDescriptor) { +func (x *fastReflection_ExampleTable) Clear(fd protoreflect.FieldDescriptor) { switch fd.FullName() { - case "testpb.A.u32": + case "testpb.ExampleTable.u32": x.U32 = uint32(0) - case "testpb.A.u64": + case "testpb.ExampleTable.u64": x.U64 = uint64(0) - case "testpb.A.str": + case "testpb.ExampleTable.str": x.Str = "" - case "testpb.A.bz": + case "testpb.ExampleTable.bz": x.Bz = nil - case "testpb.A.ts": + case "testpb.ExampleTable.ts": x.Ts = nil - case "testpb.A.dur": + case "testpb.ExampleTable.dur": x.Dur = nil - case "testpb.A.i32": + case "testpb.ExampleTable.i32": x.I32 = int32(0) - case "testpb.A.s32": + case "testpb.ExampleTable.s32": x.S32 = int32(0) - case "testpb.A.sf32": + case "testpb.ExampleTable.sf32": x.Sf32 = int32(0) - case "testpb.A.i64": + case "testpb.ExampleTable.i64": x.I64 = int64(0) - case "testpb.A.s64": + case "testpb.ExampleTable.s64": x.S64 = int64(0) - case "testpb.A.sf64": + case "testpb.ExampleTable.sf64": x.Sf64 = int64(0) - case "testpb.A.f32": + case "testpb.ExampleTable.f32": x.F32 = uint32(0) - case "testpb.A.f64": + case "testpb.ExampleTable.f64": x.F64 = uint64(0) - case "testpb.A.b": + case "testpb.ExampleTable.b": x.B = false - case "testpb.A.e": + case "testpb.ExampleTable.e": x.E = 0 - case "testpb.A.repeated": + case "testpb.ExampleTable.repeated": x.Repeated = nil - case "testpb.A.map": + case "testpb.ExampleTable.map": x.Map = nil - case "testpb.A.msg": + case "testpb.ExampleTable.msg": x.Msg = nil - case "testpb.A.oneof": + case "testpb.ExampleTable.oneof": x.Sum = nil default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.A")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleTable")) } - panic(fmt.Errorf("message testpb.A does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleTable does not contain field %s", fd.FullName())) } } @@ -513,84 +513,84 @@ func (x *fastReflection_A) Clear(fd protoreflect.FieldDescriptor) { // the default value of a bytes scalar is guaranteed to be a copy. // For unpopulated composite types, it returns an empty, read-only view // of the value; to obtain a mutable reference, use Mutable. -func (x *fastReflection_A) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { +func (x *fastReflection_ExampleTable) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { switch descriptor.FullName() { - case "testpb.A.u32": + case "testpb.ExampleTable.u32": value := x.U32 return protoreflect.ValueOfUint32(value) - case "testpb.A.u64": + case "testpb.ExampleTable.u64": value := x.U64 return protoreflect.ValueOfUint64(value) - case "testpb.A.str": + case "testpb.ExampleTable.str": value := x.Str return protoreflect.ValueOfString(value) - case "testpb.A.bz": + case "testpb.ExampleTable.bz": value := x.Bz return protoreflect.ValueOfBytes(value) - case "testpb.A.ts": + case "testpb.ExampleTable.ts": value := x.Ts return protoreflect.ValueOfMessage(value.ProtoReflect()) - case "testpb.A.dur": + case "testpb.ExampleTable.dur": value := x.Dur return protoreflect.ValueOfMessage(value.ProtoReflect()) - case "testpb.A.i32": + case "testpb.ExampleTable.i32": value := x.I32 return protoreflect.ValueOfInt32(value) - case "testpb.A.s32": + case "testpb.ExampleTable.s32": value := x.S32 return protoreflect.ValueOfInt32(value) - case "testpb.A.sf32": + case "testpb.ExampleTable.sf32": value := x.Sf32 return protoreflect.ValueOfInt32(value) - case "testpb.A.i64": + case "testpb.ExampleTable.i64": value := x.I64 return protoreflect.ValueOfInt64(value) - case "testpb.A.s64": + case "testpb.ExampleTable.s64": value := x.S64 return protoreflect.ValueOfInt64(value) - case "testpb.A.sf64": + case "testpb.ExampleTable.sf64": value := x.Sf64 return protoreflect.ValueOfInt64(value) - case "testpb.A.f32": + case "testpb.ExampleTable.f32": value := x.F32 return protoreflect.ValueOfUint32(value) - case "testpb.A.f64": + case "testpb.ExampleTable.f64": value := x.F64 return protoreflect.ValueOfUint64(value) - case "testpb.A.b": + case "testpb.ExampleTable.b": value := x.B return protoreflect.ValueOfBool(value) - case "testpb.A.e": + case "testpb.ExampleTable.e": value := x.E return protoreflect.ValueOfEnum((protoreflect.EnumNumber)(value)) - case "testpb.A.repeated": + case "testpb.ExampleTable.repeated": if len(x.Repeated) == 0 { - return protoreflect.ValueOfList(&_A_17_list{}) + return protoreflect.ValueOfList(&_ExampleTable_17_list{}) } - listValue := &_A_17_list{list: &x.Repeated} + listValue := &_ExampleTable_17_list{list: &x.Repeated} return protoreflect.ValueOfList(listValue) - case "testpb.A.map": + case "testpb.ExampleTable.map": if len(x.Map) == 0 { - return protoreflect.ValueOfMap(&_A_18_map{}) + return protoreflect.ValueOfMap(&_ExampleTable_18_map{}) } - mapValue := &_A_18_map{m: &x.Map} + mapValue := &_ExampleTable_18_map{m: &x.Map} return protoreflect.ValueOfMap(mapValue) - case "testpb.A.msg": + case "testpb.ExampleTable.msg": value := x.Msg return protoreflect.ValueOfMessage(value.ProtoReflect()) - case "testpb.A.oneof": + case "testpb.ExampleTable.oneof": if x.Sum == nil { return protoreflect.ValueOfUint32(uint32(0)) - } else if v, ok := x.Sum.(*A_Oneof); ok { + } else if v, ok := x.Sum.(*ExampleTable_Oneof); ok { return protoreflect.ValueOfUint32(v.Oneof) } else { return protoreflect.ValueOfUint32(uint32(0)) } default: if descriptor.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.A")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleTable")) } - panic(fmt.Errorf("message testpb.A does not contain field %s", descriptor.FullName())) + panic(fmt.Errorf("message testpb.ExampleTable does not contain field %s", descriptor.FullName())) } } @@ -604,58 +604,58 @@ func (x *fastReflection_A) Get(descriptor protoreflect.FieldDescriptor) protoref // empty, read-only value, then it panics. // // Set is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_A) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { +func (x *fastReflection_ExampleTable) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { switch fd.FullName() { - case "testpb.A.u32": + case "testpb.ExampleTable.u32": x.U32 = uint32(value.Uint()) - case "testpb.A.u64": + case "testpb.ExampleTable.u64": x.U64 = value.Uint() - case "testpb.A.str": + case "testpb.ExampleTable.str": x.Str = value.Interface().(string) - case "testpb.A.bz": + case "testpb.ExampleTable.bz": x.Bz = value.Bytes() - case "testpb.A.ts": + case "testpb.ExampleTable.ts": x.Ts = value.Message().Interface().(*timestamppb.Timestamp) - case "testpb.A.dur": + case "testpb.ExampleTable.dur": x.Dur = value.Message().Interface().(*durationpb.Duration) - case "testpb.A.i32": + case "testpb.ExampleTable.i32": x.I32 = int32(value.Int()) - case "testpb.A.s32": + case "testpb.ExampleTable.s32": x.S32 = int32(value.Int()) - case "testpb.A.sf32": + case "testpb.ExampleTable.sf32": x.Sf32 = int32(value.Int()) - case "testpb.A.i64": + case "testpb.ExampleTable.i64": x.I64 = value.Int() - case "testpb.A.s64": + case "testpb.ExampleTable.s64": x.S64 = value.Int() - case "testpb.A.sf64": + case "testpb.ExampleTable.sf64": x.Sf64 = value.Int() - case "testpb.A.f32": + case "testpb.ExampleTable.f32": x.F32 = uint32(value.Uint()) - case "testpb.A.f64": + case "testpb.ExampleTable.f64": x.F64 = value.Uint() - case "testpb.A.b": + case "testpb.ExampleTable.b": x.B = value.Bool() - case "testpb.A.e": + case "testpb.ExampleTable.e": x.E = (Enum)(value.Enum()) - case "testpb.A.repeated": + case "testpb.ExampleTable.repeated": lv := value.List() - clv := lv.(*_A_17_list) + clv := lv.(*_ExampleTable_17_list) x.Repeated = *clv.list - case "testpb.A.map": + case "testpb.ExampleTable.map": mv := value.Map() - cmv := mv.(*_A_18_map) + cmv := mv.(*_ExampleTable_18_map) x.Map = *cmv.m - case "testpb.A.msg": - x.Msg = value.Message().Interface().(*B) - case "testpb.A.oneof": + case "testpb.ExampleTable.msg": + x.Msg = value.Message().Interface().(*ExampleTable_ExampleMessage) + case "testpb.ExampleTable.oneof": cv := uint32(value.Uint()) - x.Sum = &A_Oneof{Oneof: cv} + x.Sum = &ExampleTable_Oneof{Oneof: cv} default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.A")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleTable")) } - panic(fmt.Errorf("message testpb.A does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleTable does not contain field %s", fd.FullName())) } } @@ -669,146 +669,146 @@ func (x *fastReflection_A) Set(fd protoreflect.FieldDescriptor, value protorefle // It panics if the field does not contain a composite type. // // Mutable is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_A) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { +func (x *fastReflection_ExampleTable) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { - case "testpb.A.ts": + case "testpb.ExampleTable.ts": if x.Ts == nil { x.Ts = new(timestamppb.Timestamp) } return protoreflect.ValueOfMessage(x.Ts.ProtoReflect()) - case "testpb.A.dur": + case "testpb.ExampleTable.dur": if x.Dur == nil { x.Dur = new(durationpb.Duration) } return protoreflect.ValueOfMessage(x.Dur.ProtoReflect()) - case "testpb.A.repeated": + case "testpb.ExampleTable.repeated": if x.Repeated == nil { x.Repeated = []uint32{} } - value := &_A_17_list{list: &x.Repeated} + value := &_ExampleTable_17_list{list: &x.Repeated} return protoreflect.ValueOfList(value) - case "testpb.A.map": + case "testpb.ExampleTable.map": if x.Map == nil { x.Map = make(map[string]uint32) } - value := &_A_18_map{m: &x.Map} + value := &_ExampleTable_18_map{m: &x.Map} return protoreflect.ValueOfMap(value) - case "testpb.A.msg": + case "testpb.ExampleTable.msg": if x.Msg == nil { - x.Msg = new(B) + x.Msg = new(ExampleTable_ExampleMessage) } return protoreflect.ValueOfMessage(x.Msg.ProtoReflect()) - case "testpb.A.u32": - panic(fmt.Errorf("field u32 of message testpb.A is not mutable")) - case "testpb.A.u64": - panic(fmt.Errorf("field u64 of message testpb.A is not mutable")) - case "testpb.A.str": - panic(fmt.Errorf("field str of message testpb.A is not mutable")) - case "testpb.A.bz": - panic(fmt.Errorf("field bz of message testpb.A is not mutable")) - case "testpb.A.i32": - panic(fmt.Errorf("field i32 of message testpb.A is not mutable")) - case "testpb.A.s32": - panic(fmt.Errorf("field s32 of message testpb.A is not mutable")) - case "testpb.A.sf32": - panic(fmt.Errorf("field sf32 of message testpb.A is not mutable")) - case "testpb.A.i64": - panic(fmt.Errorf("field i64 of message testpb.A is not mutable")) - case "testpb.A.s64": - panic(fmt.Errorf("field s64 of message testpb.A is not mutable")) - case "testpb.A.sf64": - panic(fmt.Errorf("field sf64 of message testpb.A is not mutable")) - case "testpb.A.f32": - panic(fmt.Errorf("field f32 of message testpb.A is not mutable")) - case "testpb.A.f64": - panic(fmt.Errorf("field f64 of message testpb.A is not mutable")) - case "testpb.A.b": - panic(fmt.Errorf("field b of message testpb.A is not mutable")) - case "testpb.A.e": - panic(fmt.Errorf("field e of message testpb.A is not mutable")) - case "testpb.A.oneof": - panic(fmt.Errorf("field oneof of message testpb.A is not mutable")) + case "testpb.ExampleTable.u32": + panic(fmt.Errorf("field u32 of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.u64": + panic(fmt.Errorf("field u64 of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.str": + panic(fmt.Errorf("field str of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.bz": + panic(fmt.Errorf("field bz of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.i32": + panic(fmt.Errorf("field i32 of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.s32": + panic(fmt.Errorf("field s32 of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.sf32": + panic(fmt.Errorf("field sf32 of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.i64": + panic(fmt.Errorf("field i64 of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.s64": + panic(fmt.Errorf("field s64 of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.sf64": + panic(fmt.Errorf("field sf64 of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.f32": + panic(fmt.Errorf("field f32 of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.f64": + panic(fmt.Errorf("field f64 of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.b": + panic(fmt.Errorf("field b of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.e": + panic(fmt.Errorf("field e of message testpb.ExampleTable is not mutable")) + case "testpb.ExampleTable.oneof": + panic(fmt.Errorf("field oneof of message testpb.ExampleTable is not mutable")) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.A")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleTable")) } - panic(fmt.Errorf("message testpb.A does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleTable does not contain field %s", fd.FullName())) } } // NewField returns a new value that is assignable to the field // for the given descriptor. For scalars, this returns the default value. // For lists, maps, and messages, this returns a new, empty, mutable value. -func (x *fastReflection_A) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { +func (x *fastReflection_ExampleTable) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { - case "testpb.A.u32": + case "testpb.ExampleTable.u32": return protoreflect.ValueOfUint32(uint32(0)) - case "testpb.A.u64": + case "testpb.ExampleTable.u64": return protoreflect.ValueOfUint64(uint64(0)) - case "testpb.A.str": + case "testpb.ExampleTable.str": return protoreflect.ValueOfString("") - case "testpb.A.bz": + case "testpb.ExampleTable.bz": return protoreflect.ValueOfBytes(nil) - case "testpb.A.ts": + case "testpb.ExampleTable.ts": m := new(timestamppb.Timestamp) return protoreflect.ValueOfMessage(m.ProtoReflect()) - case "testpb.A.dur": + case "testpb.ExampleTable.dur": m := new(durationpb.Duration) return protoreflect.ValueOfMessage(m.ProtoReflect()) - case "testpb.A.i32": + case "testpb.ExampleTable.i32": return protoreflect.ValueOfInt32(int32(0)) - case "testpb.A.s32": + case "testpb.ExampleTable.s32": return protoreflect.ValueOfInt32(int32(0)) - case "testpb.A.sf32": + case "testpb.ExampleTable.sf32": return protoreflect.ValueOfInt32(int32(0)) - case "testpb.A.i64": + case "testpb.ExampleTable.i64": return protoreflect.ValueOfInt64(int64(0)) - case "testpb.A.s64": + case "testpb.ExampleTable.s64": return protoreflect.ValueOfInt64(int64(0)) - case "testpb.A.sf64": + case "testpb.ExampleTable.sf64": return protoreflect.ValueOfInt64(int64(0)) - case "testpb.A.f32": + case "testpb.ExampleTable.f32": return protoreflect.ValueOfUint32(uint32(0)) - case "testpb.A.f64": + case "testpb.ExampleTable.f64": return protoreflect.ValueOfUint64(uint64(0)) - case "testpb.A.b": + case "testpb.ExampleTable.b": return protoreflect.ValueOfBool(false) - case "testpb.A.e": + case "testpb.ExampleTable.e": return protoreflect.ValueOfEnum(0) - case "testpb.A.repeated": + case "testpb.ExampleTable.repeated": list := []uint32{} - return protoreflect.ValueOfList(&_A_17_list{list: &list}) - case "testpb.A.map": + return protoreflect.ValueOfList(&_ExampleTable_17_list{list: &list}) + case "testpb.ExampleTable.map": m := make(map[string]uint32) - return protoreflect.ValueOfMap(&_A_18_map{m: &m}) - case "testpb.A.msg": - m := new(B) + return protoreflect.ValueOfMap(&_ExampleTable_18_map{m: &m}) + case "testpb.ExampleTable.msg": + m := new(ExampleTable_ExampleMessage) return protoreflect.ValueOfMessage(m.ProtoReflect()) - case "testpb.A.oneof": + case "testpb.ExampleTable.oneof": return protoreflect.ValueOfUint32(uint32(0)) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.A")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleTable")) } - panic(fmt.Errorf("message testpb.A does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleTable does not contain field %s", fd.FullName())) } } // WhichOneof reports which field within the oneof is populated, // returning nil if none are populated. // It panics if the oneof descriptor does not belong to this message. -func (x *fastReflection_A) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { +func (x *fastReflection_ExampleTable) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { switch d.FullName() { - case "testpb.A.sum": + case "testpb.ExampleTable.sum": if x.Sum == nil { return nil } switch x.Sum.(type) { - case *A_Oneof: + case *ExampleTable_Oneof: return x.Descriptor().Fields().ByName("oneof") } default: - panic(fmt.Errorf("%s is not a oneof field in testpb.A", d.FullName())) + panic(fmt.Errorf("%s is not a oneof field in testpb.ExampleTable", d.FullName())) } panic("unreachable") } @@ -816,7 +816,7 @@ func (x *fastReflection_A) WhichOneof(d protoreflect.OneofDescriptor) protorefle // GetUnknown retrieves the entire list of unknown fields. // The caller may only mutate the contents of the RawFields // if the mutated bytes are stored back into the message with SetUnknown. -func (x *fastReflection_A) GetUnknown() protoreflect.RawFields { +func (x *fastReflection_ExampleTable) GetUnknown() protoreflect.RawFields { return x.unknownFields } @@ -827,7 +827,7 @@ func (x *fastReflection_A) GetUnknown() protoreflect.RawFields { // An empty RawFields may be passed to clear the fields. // // SetUnknown is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_A) SetUnknown(fields protoreflect.RawFields) { +func (x *fastReflection_ExampleTable) SetUnknown(fields protoreflect.RawFields) { x.unknownFields = fields } @@ -839,7 +839,7 @@ func (x *fastReflection_A) SetUnknown(fields protoreflect.RawFields) { // message type, but the details are implementation dependent. // Validity is not part of the protobuf data model, and may not // be preserved in marshaling or other operations. -func (x *fastReflection_A) IsValid() bool { +func (x *fastReflection_ExampleTable) IsValid() bool { return x != nil } @@ -849,9 +849,9 @@ func (x *fastReflection_A) IsValid() bool { // The returned methods type is identical to // "google.golang.org/protobuf/runtime/protoiface".Methods. // Consult the protoiface package documentation for details. -func (x *fastReflection_A) ProtoMethods() *protoiface.Methods { +func (x *fastReflection_ExampleTable) ProtoMethods() *protoiface.Methods { size := func(input protoiface.SizeInput) protoiface.SizeOutput { - x := input.Message.Interface().(*A) + x := input.Message.Interface().(*ExampleTable) if x == nil { return protoiface.SizeOutput{ NoUnkeyedLiterals: input.NoUnkeyedLiterals, @@ -948,7 +948,7 @@ func (x *fastReflection_A) ProtoMethods() *protoiface.Methods { n += 2 + l + runtime.Sov(uint64(l)) } switch x := x.Sum.(type) { - case *A_Oneof: + case *ExampleTable_Oneof: if x == nil { break } @@ -964,7 +964,7 @@ func (x *fastReflection_A) ProtoMethods() *protoiface.Methods { } marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { - x := input.Message.Interface().(*A) + x := input.Message.Interface().(*ExampleTable) if x == nil { return protoiface.MarshalOutput{ NoUnkeyedLiterals: input.NoUnkeyedLiterals, @@ -984,7 +984,7 @@ func (x *fastReflection_A) ProtoMethods() *protoiface.Methods { copy(dAtA[i:], x.unknownFields) } switch x := x.Sum.(type) { - case *A_Oneof: + case *ExampleTable_Oneof: i = runtime.EncodeVarint(dAtA, i, uint64(x.Oneof)) i-- dAtA[i] = 0x1 @@ -1196,7 +1196,7 @@ func (x *fastReflection_A) ProtoMethods() *protoiface.Methods { }, nil } unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { - x := input.Message.Interface().(*A) + x := input.Message.Interface().(*ExampleTable) if x == nil { return protoiface.UnmarshalOutput{ NoUnkeyedLiterals: input.NoUnkeyedLiterals, @@ -1228,10 +1228,10 @@ func (x *fastReflection_A) ProtoMethods() *protoiface.Methods { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: A: wiretype end group for non-group") + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ExampleTable: wiretype end group for non-group") } if fieldNum <= 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: A: illegal tag %d (wire type %d)", fieldNum, wire) + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ExampleTable: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -1788,7 +1788,7 @@ func (x *fastReflection_A) ProtoMethods() *protoiface.Methods { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF } if x.Msg == nil { - x.Msg = &B{} + x.Msg = &ExampleTable_ExampleMessage{} } if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Msg); err != nil { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err @@ -1813,7 +1813,7 @@ func (x *fastReflection_A) ProtoMethods() *protoiface.Methods { break } } - x.Sum = &A_Oneof{v} + x.Sum = &ExampleTable_Oneof{v} default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -1850,26 +1850,28 @@ func (x *fastReflection_A) ProtoMethods() *protoiface.Methods { } var ( - md_B protoreflect.MessageDescriptor - fd_B_x protoreflect.FieldDescriptor + md_ExampleTable_ExampleMessage protoreflect.MessageDescriptor + fd_ExampleTable_ExampleMessage_foo protoreflect.FieldDescriptor + fd_ExampleTable_ExampleMessage_bar protoreflect.FieldDescriptor ) func init() { file_testpb_testschema_proto_init() - md_B = File_testpb_testschema_proto.Messages().ByName("B") - fd_B_x = md_B.Fields().ByName("x") + md_ExampleTable_ExampleMessage = File_testpb_testschema_proto.Messages().ByName("ExampleTable").Messages().ByName("ExampleMessage") + fd_ExampleTable_ExampleMessage_foo = md_ExampleTable_ExampleMessage.Fields().ByName("foo") + fd_ExampleTable_ExampleMessage_bar = md_ExampleTable_ExampleMessage.Fields().ByName("bar") } -var _ protoreflect.Message = (*fastReflection_B)(nil) +var _ protoreflect.Message = (*fastReflection_ExampleTable_ExampleMessage)(nil) -type fastReflection_B B +type fastReflection_ExampleTable_ExampleMessage ExampleTable_ExampleMessage -func (x *B) ProtoReflect() protoreflect.Message { - return (*fastReflection_B)(x) +func (x *ExampleTable_ExampleMessage) ProtoReflect() protoreflect.Message { + return (*fastReflection_ExampleTable_ExampleMessage)(x) } -func (x *B) slowProtoReflect() protoreflect.Message { - mi := &file_testpb_testschema_proto_msgTypes[1] +func (x *ExampleTable_ExampleMessage) slowProtoReflect() protoreflect.Message { + mi := &file_testpb_testschema_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1880,43 +1882,43 @@ func (x *B) slowProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -var _fastReflection_B_messageType fastReflection_B_messageType -var _ protoreflect.MessageType = fastReflection_B_messageType{} +var _fastReflection_ExampleTable_ExampleMessage_messageType fastReflection_ExampleTable_ExampleMessage_messageType +var _ protoreflect.MessageType = fastReflection_ExampleTable_ExampleMessage_messageType{} -type fastReflection_B_messageType struct{} +type fastReflection_ExampleTable_ExampleMessage_messageType struct{} -func (x fastReflection_B_messageType) Zero() protoreflect.Message { - return (*fastReflection_B)(nil) +func (x fastReflection_ExampleTable_ExampleMessage_messageType) Zero() protoreflect.Message { + return (*fastReflection_ExampleTable_ExampleMessage)(nil) } -func (x fastReflection_B_messageType) New() protoreflect.Message { - return new(fastReflection_B) +func (x fastReflection_ExampleTable_ExampleMessage_messageType) New() protoreflect.Message { + return new(fastReflection_ExampleTable_ExampleMessage) } -func (x fastReflection_B_messageType) Descriptor() protoreflect.MessageDescriptor { - return md_B +func (x fastReflection_ExampleTable_ExampleMessage_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_ExampleTable_ExampleMessage } // Descriptor returns message descriptor, which contains only the protobuf // type information for the message. -func (x *fastReflection_B) Descriptor() protoreflect.MessageDescriptor { - return md_B +func (x *fastReflection_ExampleTable_ExampleMessage) Descriptor() protoreflect.MessageDescriptor { + return md_ExampleTable_ExampleMessage } // Type returns the message type, which encapsulates both Go and protobuf // type information. If the Go type information is not needed, // it is recommended that the message descriptor be used instead. -func (x *fastReflection_B) Type() protoreflect.MessageType { - return _fastReflection_B_messageType +func (x *fastReflection_ExampleTable_ExampleMessage) Type() protoreflect.MessageType { + return _fastReflection_ExampleTable_ExampleMessage_messageType } // New returns a newly allocated and mutable empty message. -func (x *fastReflection_B) New() protoreflect.Message { - return new(fastReflection_B) +func (x *fastReflection_ExampleTable_ExampleMessage) New() protoreflect.Message { + return new(fastReflection_ExampleTable_ExampleMessage) } // Interface unwraps the message reflection interface and // returns the underlying ProtoMessage interface. -func (x *fastReflection_B) Interface() protoreflect.ProtoMessage { - return (*B)(x) +func (x *fastReflection_ExampleTable_ExampleMessage) Interface() protoreflect.ProtoMessage { + return (*ExampleTable_ExampleMessage)(x) } // Range iterates over every populated field in an undefined order, @@ -1924,10 +1926,16 @@ func (x *fastReflection_B) Interface() protoreflect.ProtoMessage { // Range returns immediately if f returns false. // While iterating, mutating operations may only be performed // on the current field descriptor. -func (x *fastReflection_B) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { - if x.X != "" { - value := protoreflect.ValueOfString(x.X) - if !f(fd_B_x, value) { +func (x *fastReflection_ExampleTable_ExampleMessage) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Foo != "" { + value := protoreflect.ValueOfString(x.Foo) + if !f(fd_ExampleTable_ExampleMessage_foo, value) { + return + } + } + if x.Bar != int32(0) { + value := protoreflect.ValueOfInt32(x.Bar) + if !f(fd_ExampleTable_ExampleMessage_bar, value) { return } } @@ -1944,15 +1952,17 @@ func (x *fastReflection_B) Range(f func(protoreflect.FieldDescriptor, protorefle // In other cases (aside from the nullable cases above), // a proto3 scalar field is populated if it contains a non-zero value, and // a repeated field is populated if it is non-empty. -func (x *fastReflection_B) Has(fd protoreflect.FieldDescriptor) bool { +func (x *fastReflection_ExampleTable_ExampleMessage) Has(fd protoreflect.FieldDescriptor) bool { switch fd.FullName() { - case "testpb.B.x": - return x.X != "" + case "testpb.ExampleTable.ExampleMessage.foo": + return x.Foo != "" + case "testpb.ExampleTable.ExampleMessage.bar": + return x.Bar != int32(0) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.B")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleTable.ExampleMessage")) } - panic(fmt.Errorf("message testpb.B does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleTable.ExampleMessage does not contain field %s", fd.FullName())) } } @@ -1962,15 +1972,17 @@ func (x *fastReflection_B) Has(fd protoreflect.FieldDescriptor) bool { // associated with the given field number. // // Clear is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_B) Clear(fd protoreflect.FieldDescriptor) { +func (x *fastReflection_ExampleTable_ExampleMessage) Clear(fd protoreflect.FieldDescriptor) { switch fd.FullName() { - case "testpb.B.x": - x.X = "" + case "testpb.ExampleTable.ExampleMessage.foo": + x.Foo = "" + case "testpb.ExampleTable.ExampleMessage.bar": + x.Bar = int32(0) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.B")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleTable.ExampleMessage")) } - panic(fmt.Errorf("message testpb.B does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleTable.ExampleMessage does not contain field %s", fd.FullName())) } } @@ -1980,16 +1992,19 @@ func (x *fastReflection_B) Clear(fd protoreflect.FieldDescriptor) { // the default value of a bytes scalar is guaranteed to be a copy. // For unpopulated composite types, it returns an empty, read-only view // of the value; to obtain a mutable reference, use Mutable. -func (x *fastReflection_B) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { +func (x *fastReflection_ExampleTable_ExampleMessage) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { switch descriptor.FullName() { - case "testpb.B.x": - value := x.X + case "testpb.ExampleTable.ExampleMessage.foo": + value := x.Foo return protoreflect.ValueOfString(value) + case "testpb.ExampleTable.ExampleMessage.bar": + value := x.Bar + return protoreflect.ValueOfInt32(value) default: if descriptor.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.B")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleTable.ExampleMessage")) } - panic(fmt.Errorf("message testpb.B does not contain field %s", descriptor.FullName())) + panic(fmt.Errorf("message testpb.ExampleTable.ExampleMessage does not contain field %s", descriptor.FullName())) } } @@ -2003,15 +2018,17 @@ func (x *fastReflection_B) Get(descriptor protoreflect.FieldDescriptor) protoref // empty, read-only value, then it panics. // // Set is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_B) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { +func (x *fastReflection_ExampleTable_ExampleMessage) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { switch fd.FullName() { - case "testpb.B.x": - x.X = value.Interface().(string) + case "testpb.ExampleTable.ExampleMessage.foo": + x.Foo = value.Interface().(string) + case "testpb.ExampleTable.ExampleMessage.bar": + x.Bar = int32(value.Int()) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.B")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleTable.ExampleMessage")) } - panic(fmt.Errorf("message testpb.B does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleTable.ExampleMessage does not contain field %s", fd.FullName())) } } @@ -2025,40 +2042,44 @@ func (x *fastReflection_B) Set(fd protoreflect.FieldDescriptor, value protorefle // It panics if the field does not contain a composite type. // // Mutable is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_B) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { +func (x *fastReflection_ExampleTable_ExampleMessage) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { - case "testpb.B.x": - panic(fmt.Errorf("field x of message testpb.B is not mutable")) + case "testpb.ExampleTable.ExampleMessage.foo": + panic(fmt.Errorf("field foo of message testpb.ExampleTable.ExampleMessage is not mutable")) + case "testpb.ExampleTable.ExampleMessage.bar": + panic(fmt.Errorf("field bar of message testpb.ExampleTable.ExampleMessage is not mutable")) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.B")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleTable.ExampleMessage")) } - panic(fmt.Errorf("message testpb.B does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleTable.ExampleMessage does not contain field %s", fd.FullName())) } } // NewField returns a new value that is assignable to the field // for the given descriptor. For scalars, this returns the default value. // For lists, maps, and messages, this returns a new, empty, mutable value. -func (x *fastReflection_B) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { +func (x *fastReflection_ExampleTable_ExampleMessage) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { - case "testpb.B.x": + case "testpb.ExampleTable.ExampleMessage.foo": return protoreflect.ValueOfString("") + case "testpb.ExampleTable.ExampleMessage.bar": + return protoreflect.ValueOfInt32(int32(0)) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.B")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleTable.ExampleMessage")) } - panic(fmt.Errorf("message testpb.B does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleTable.ExampleMessage does not contain field %s", fd.FullName())) } } // WhichOneof reports which field within the oneof is populated, // returning nil if none are populated. // It panics if the oneof descriptor does not belong to this message. -func (x *fastReflection_B) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { +func (x *fastReflection_ExampleTable_ExampleMessage) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { switch d.FullName() { default: - panic(fmt.Errorf("%s is not a oneof field in testpb.B", d.FullName())) + panic(fmt.Errorf("%s is not a oneof field in testpb.ExampleTable.ExampleMessage", d.FullName())) } panic("unreachable") } @@ -2066,7 +2087,7 @@ func (x *fastReflection_B) WhichOneof(d protoreflect.OneofDescriptor) protorefle // GetUnknown retrieves the entire list of unknown fields. // The caller may only mutate the contents of the RawFields // if the mutated bytes are stored back into the message with SetUnknown. -func (x *fastReflection_B) GetUnknown() protoreflect.RawFields { +func (x *fastReflection_ExampleTable_ExampleMessage) GetUnknown() protoreflect.RawFields { return x.unknownFields } @@ -2077,7 +2098,7 @@ func (x *fastReflection_B) GetUnknown() protoreflect.RawFields { // An empty RawFields may be passed to clear the fields. // // SetUnknown is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_B) SetUnknown(fields protoreflect.RawFields) { +func (x *fastReflection_ExampleTable_ExampleMessage) SetUnknown(fields protoreflect.RawFields) { x.unknownFields = fields } @@ -2089,7 +2110,7 @@ func (x *fastReflection_B) SetUnknown(fields protoreflect.RawFields) { // message type, but the details are implementation dependent. // Validity is not part of the protobuf data model, and may not // be preserved in marshaling or other operations. -func (x *fastReflection_B) IsValid() bool { +func (x *fastReflection_ExampleTable_ExampleMessage) IsValid() bool { return x != nil } @@ -2099,9 +2120,9 @@ func (x *fastReflection_B) IsValid() bool { // The returned methods type is identical to // "google.golang.org/protobuf/runtime/protoiface".Methods. // Consult the protoiface package documentation for details. -func (x *fastReflection_B) ProtoMethods() *protoiface.Methods { +func (x *fastReflection_ExampleTable_ExampleMessage) ProtoMethods() *protoiface.Methods { size := func(input protoiface.SizeInput) protoiface.SizeOutput { - x := input.Message.Interface().(*B) + x := input.Message.Interface().(*ExampleTable_ExampleMessage) if x == nil { return protoiface.SizeOutput{ NoUnkeyedLiterals: input.NoUnkeyedLiterals, @@ -2113,10 +2134,13 @@ func (x *fastReflection_B) ProtoMethods() *protoiface.Methods { var n int var l int _ = l - l = len(x.X) + l = len(x.Foo) if l > 0 { n += 1 + l + runtime.Sov(uint64(l)) } + if x.Bar != 0 { + n += 1 + runtime.Sov(uint64(x.Bar)) + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -2127,7 +2151,7 @@ func (x *fastReflection_B) ProtoMethods() *protoiface.Methods { } marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { - x := input.Message.Interface().(*B) + x := input.Message.Interface().(*ExampleTable_ExampleMessage) if x == nil { return protoiface.MarshalOutput{ NoUnkeyedLiterals: input.NoUnkeyedLiterals, @@ -2146,10 +2170,15 @@ func (x *fastReflection_B) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } - if len(x.X) > 0 { - i -= len(x.X) - copy(dAtA[i:], x.X) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.X))) + if x.Bar != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.Bar)) + i-- + dAtA[i] = 0x10 + } + if len(x.Foo) > 0 { + i -= len(x.Foo) + copy(dAtA[i:], x.Foo) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Foo))) i-- dAtA[i] = 0xa } @@ -2164,7 +2193,7 @@ func (x *fastReflection_B) ProtoMethods() *protoiface.Methods { }, nil } unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { - x := input.Message.Interface().(*B) + x := input.Message.Interface().(*ExampleTable_ExampleMessage) if x == nil { return protoiface.UnmarshalOutput{ NoUnkeyedLiterals: input.NoUnkeyedLiterals, @@ -2196,15 +2225,15 @@ func (x *fastReflection_B) ProtoMethods() *protoiface.Methods { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: B: wiretype end group for non-group") + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ExampleTable_ExampleMessage: wiretype end group for non-group") } if fieldNum <= 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: B: illegal tag %d (wire type %d)", fieldNum, wire) + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ExampleTable_ExampleMessage: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field X", wireType) + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Foo", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -2232,8 +2261,27 @@ func (x *fastReflection_B) ProtoMethods() *protoiface.Methods { if postIndex > l { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF } - x.X = string(dAtA[iNdEx:postIndex]) + x.Foo = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 2: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Bar", wireType) + } + x.Bar = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + x.Bar |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -2270,28 +2318,30 @@ func (x *fastReflection_B) ProtoMethods() *protoiface.Methods { } var ( - md_C protoreflect.MessageDescriptor - fd_C_id protoreflect.FieldDescriptor - fd_C_x protoreflect.FieldDescriptor + md_ExampleAutoIncrementTable protoreflect.MessageDescriptor + fd_ExampleAutoIncrementTable_id protoreflect.FieldDescriptor + fd_ExampleAutoIncrementTable_x protoreflect.FieldDescriptor + fd_ExampleAutoIncrementTable_y protoreflect.FieldDescriptor ) func init() { file_testpb_testschema_proto_init() - md_C = File_testpb_testschema_proto.Messages().ByName("C") - fd_C_id = md_C.Fields().ByName("id") - fd_C_x = md_C.Fields().ByName("x") + md_ExampleAutoIncrementTable = File_testpb_testschema_proto.Messages().ByName("ExampleAutoIncrementTable") + fd_ExampleAutoIncrementTable_id = md_ExampleAutoIncrementTable.Fields().ByName("id") + fd_ExampleAutoIncrementTable_x = md_ExampleAutoIncrementTable.Fields().ByName("x") + fd_ExampleAutoIncrementTable_y = md_ExampleAutoIncrementTable.Fields().ByName("y") } -var _ protoreflect.Message = (*fastReflection_C)(nil) +var _ protoreflect.Message = (*fastReflection_ExampleAutoIncrementTable)(nil) -type fastReflection_C C +type fastReflection_ExampleAutoIncrementTable ExampleAutoIncrementTable -func (x *C) ProtoReflect() protoreflect.Message { - return (*fastReflection_C)(x) +func (x *ExampleAutoIncrementTable) ProtoReflect() protoreflect.Message { + return (*fastReflection_ExampleAutoIncrementTable)(x) } -func (x *C) slowProtoReflect() protoreflect.Message { - mi := &file_testpb_testschema_proto_msgTypes[2] +func (x *ExampleAutoIncrementTable) slowProtoReflect() protoreflect.Message { + mi := &file_testpb_testschema_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2302,43 +2352,43 @@ func (x *C) slowProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -var _fastReflection_C_messageType fastReflection_C_messageType -var _ protoreflect.MessageType = fastReflection_C_messageType{} +var _fastReflection_ExampleAutoIncrementTable_messageType fastReflection_ExampleAutoIncrementTable_messageType +var _ protoreflect.MessageType = fastReflection_ExampleAutoIncrementTable_messageType{} -type fastReflection_C_messageType struct{} +type fastReflection_ExampleAutoIncrementTable_messageType struct{} -func (x fastReflection_C_messageType) Zero() protoreflect.Message { - return (*fastReflection_C)(nil) +func (x fastReflection_ExampleAutoIncrementTable_messageType) Zero() protoreflect.Message { + return (*fastReflection_ExampleAutoIncrementTable)(nil) } -func (x fastReflection_C_messageType) New() protoreflect.Message { - return new(fastReflection_C) +func (x fastReflection_ExampleAutoIncrementTable_messageType) New() protoreflect.Message { + return new(fastReflection_ExampleAutoIncrementTable) } -func (x fastReflection_C_messageType) Descriptor() protoreflect.MessageDescriptor { - return md_C +func (x fastReflection_ExampleAutoIncrementTable_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_ExampleAutoIncrementTable } // Descriptor returns message descriptor, which contains only the protobuf // type information for the message. -func (x *fastReflection_C) Descriptor() protoreflect.MessageDescriptor { - return md_C +func (x *fastReflection_ExampleAutoIncrementTable) Descriptor() protoreflect.MessageDescriptor { + return md_ExampleAutoIncrementTable } // Type returns the message type, which encapsulates both Go and protobuf // type information. If the Go type information is not needed, // it is recommended that the message descriptor be used instead. -func (x *fastReflection_C) Type() protoreflect.MessageType { - return _fastReflection_C_messageType +func (x *fastReflection_ExampleAutoIncrementTable) Type() protoreflect.MessageType { + return _fastReflection_ExampleAutoIncrementTable_messageType } // New returns a newly allocated and mutable empty message. -func (x *fastReflection_C) New() protoreflect.Message { - return new(fastReflection_C) +func (x *fastReflection_ExampleAutoIncrementTable) New() protoreflect.Message { + return new(fastReflection_ExampleAutoIncrementTable) } // Interface unwraps the message reflection interface and // returns the underlying ProtoMessage interface. -func (x *fastReflection_C) Interface() protoreflect.ProtoMessage { - return (*C)(x) +func (x *fastReflection_ExampleAutoIncrementTable) Interface() protoreflect.ProtoMessage { + return (*ExampleAutoIncrementTable)(x) } // Range iterates over every populated field in an undefined order, @@ -2346,16 +2396,22 @@ func (x *fastReflection_C) Interface() protoreflect.ProtoMessage { // Range returns immediately if f returns false. // While iterating, mutating operations may only be performed // on the current field descriptor. -func (x *fastReflection_C) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { +func (x *fastReflection_ExampleAutoIncrementTable) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { if x.Id != uint64(0) { value := protoreflect.ValueOfUint64(x.Id) - if !f(fd_C_id, value) { + if !f(fd_ExampleAutoIncrementTable_id, value) { return } } if x.X != "" { value := protoreflect.ValueOfString(x.X) - if !f(fd_C_x, value) { + if !f(fd_ExampleAutoIncrementTable_x, value) { + return + } + } + if x.Y != int32(0) { + value := protoreflect.ValueOfInt32(x.Y) + if !f(fd_ExampleAutoIncrementTable_y, value) { return } } @@ -2372,17 +2428,19 @@ func (x *fastReflection_C) Range(f func(protoreflect.FieldDescriptor, protorefle // In other cases (aside from the nullable cases above), // a proto3 scalar field is populated if it contains a non-zero value, and // a repeated field is populated if it is non-empty. -func (x *fastReflection_C) Has(fd protoreflect.FieldDescriptor) bool { +func (x *fastReflection_ExampleAutoIncrementTable) Has(fd protoreflect.FieldDescriptor) bool { switch fd.FullName() { - case "testpb.C.id": + case "testpb.ExampleAutoIncrementTable.id": return x.Id != uint64(0) - case "testpb.C.x": + case "testpb.ExampleAutoIncrementTable.x": return x.X != "" + case "testpb.ExampleAutoIncrementTable.y": + return x.Y != int32(0) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.C")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleAutoIncrementTable")) } - panic(fmt.Errorf("message testpb.C does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleAutoIncrementTable does not contain field %s", fd.FullName())) } } @@ -2392,17 +2450,19 @@ func (x *fastReflection_C) Has(fd protoreflect.FieldDescriptor) bool { // associated with the given field number. // // Clear is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_C) Clear(fd protoreflect.FieldDescriptor) { +func (x *fastReflection_ExampleAutoIncrementTable) Clear(fd protoreflect.FieldDescriptor) { switch fd.FullName() { - case "testpb.C.id": + case "testpb.ExampleAutoIncrementTable.id": x.Id = uint64(0) - case "testpb.C.x": + case "testpb.ExampleAutoIncrementTable.x": x.X = "" + case "testpb.ExampleAutoIncrementTable.y": + x.Y = int32(0) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.C")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleAutoIncrementTable")) } - panic(fmt.Errorf("message testpb.C does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleAutoIncrementTable does not contain field %s", fd.FullName())) } } @@ -2412,19 +2472,22 @@ func (x *fastReflection_C) Clear(fd protoreflect.FieldDescriptor) { // the default value of a bytes scalar is guaranteed to be a copy. // For unpopulated composite types, it returns an empty, read-only view // of the value; to obtain a mutable reference, use Mutable. -func (x *fastReflection_C) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { +func (x *fastReflection_ExampleAutoIncrementTable) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { switch descriptor.FullName() { - case "testpb.C.id": + case "testpb.ExampleAutoIncrementTable.id": value := x.Id return protoreflect.ValueOfUint64(value) - case "testpb.C.x": + case "testpb.ExampleAutoIncrementTable.x": value := x.X return protoreflect.ValueOfString(value) + case "testpb.ExampleAutoIncrementTable.y": + value := x.Y + return protoreflect.ValueOfInt32(value) default: if descriptor.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.C")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleAutoIncrementTable")) } - panic(fmt.Errorf("message testpb.C does not contain field %s", descriptor.FullName())) + panic(fmt.Errorf("message testpb.ExampleAutoIncrementTable does not contain field %s", descriptor.FullName())) } } @@ -2438,17 +2501,19 @@ func (x *fastReflection_C) Get(descriptor protoreflect.FieldDescriptor) protoref // empty, read-only value, then it panics. // // Set is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_C) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { +func (x *fastReflection_ExampleAutoIncrementTable) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { switch fd.FullName() { - case "testpb.C.id": + case "testpb.ExampleAutoIncrementTable.id": x.Id = value.Uint() - case "testpb.C.x": + case "testpb.ExampleAutoIncrementTable.x": x.X = value.Interface().(string) + case "testpb.ExampleAutoIncrementTable.y": + x.Y = int32(value.Int()) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.C")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleAutoIncrementTable")) } - panic(fmt.Errorf("message testpb.C does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleAutoIncrementTable does not contain field %s", fd.FullName())) } } @@ -2462,44 +2527,48 @@ func (x *fastReflection_C) Set(fd protoreflect.FieldDescriptor, value protorefle // It panics if the field does not contain a composite type. // // Mutable is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_C) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { +func (x *fastReflection_ExampleAutoIncrementTable) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { - case "testpb.C.id": - panic(fmt.Errorf("field id of message testpb.C is not mutable")) - case "testpb.C.x": - panic(fmt.Errorf("field x of message testpb.C is not mutable")) + case "testpb.ExampleAutoIncrementTable.id": + panic(fmt.Errorf("field id of message testpb.ExampleAutoIncrementTable is not mutable")) + case "testpb.ExampleAutoIncrementTable.x": + panic(fmt.Errorf("field x of message testpb.ExampleAutoIncrementTable is not mutable")) + case "testpb.ExampleAutoIncrementTable.y": + panic(fmt.Errorf("field y of message testpb.ExampleAutoIncrementTable is not mutable")) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.C")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleAutoIncrementTable")) } - panic(fmt.Errorf("message testpb.C does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleAutoIncrementTable does not contain field %s", fd.FullName())) } } // NewField returns a new value that is assignable to the field // for the given descriptor. For scalars, this returns the default value. // For lists, maps, and messages, this returns a new, empty, mutable value. -func (x *fastReflection_C) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { +func (x *fastReflection_ExampleAutoIncrementTable) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { - case "testpb.C.id": + case "testpb.ExampleAutoIncrementTable.id": return protoreflect.ValueOfUint64(uint64(0)) - case "testpb.C.x": + case "testpb.ExampleAutoIncrementTable.x": return protoreflect.ValueOfString("") + case "testpb.ExampleAutoIncrementTable.y": + return protoreflect.ValueOfInt32(int32(0)) default: if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.C")) + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleAutoIncrementTable")) } - panic(fmt.Errorf("message testpb.C does not contain field %s", fd.FullName())) + panic(fmt.Errorf("message testpb.ExampleAutoIncrementTable does not contain field %s", fd.FullName())) } } // WhichOneof reports which field within the oneof is populated, // returning nil if none are populated. // It panics if the oneof descriptor does not belong to this message. -func (x *fastReflection_C) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { +func (x *fastReflection_ExampleAutoIncrementTable) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { switch d.FullName() { default: - panic(fmt.Errorf("%s is not a oneof field in testpb.C", d.FullName())) + panic(fmt.Errorf("%s is not a oneof field in testpb.ExampleAutoIncrementTable", d.FullName())) } panic("unreachable") } @@ -2507,7 +2576,7 @@ func (x *fastReflection_C) WhichOneof(d protoreflect.OneofDescriptor) protorefle // GetUnknown retrieves the entire list of unknown fields. // The caller may only mutate the contents of the RawFields // if the mutated bytes are stored back into the message with SetUnknown. -func (x *fastReflection_C) GetUnknown() protoreflect.RawFields { +func (x *fastReflection_ExampleAutoIncrementTable) GetUnknown() protoreflect.RawFields { return x.unknownFields } @@ -2518,7 +2587,7 @@ func (x *fastReflection_C) GetUnknown() protoreflect.RawFields { // An empty RawFields may be passed to clear the fields. // // SetUnknown is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_C) SetUnknown(fields protoreflect.RawFields) { +func (x *fastReflection_ExampleAutoIncrementTable) SetUnknown(fields protoreflect.RawFields) { x.unknownFields = fields } @@ -2530,7 +2599,7 @@ func (x *fastReflection_C) SetUnknown(fields protoreflect.RawFields) { // message type, but the details are implementation dependent. // Validity is not part of the protobuf data model, and may not // be preserved in marshaling or other operations. -func (x *fastReflection_C) IsValid() bool { +func (x *fastReflection_ExampleAutoIncrementTable) IsValid() bool { return x != nil } @@ -2540,9 +2609,9 @@ func (x *fastReflection_C) IsValid() bool { // The returned methods type is identical to // "google.golang.org/protobuf/runtime/protoiface".Methods. // Consult the protoiface package documentation for details. -func (x *fastReflection_C) ProtoMethods() *protoiface.Methods { +func (x *fastReflection_ExampleAutoIncrementTable) ProtoMethods() *protoiface.Methods { size := func(input protoiface.SizeInput) protoiface.SizeOutput { - x := input.Message.Interface().(*C) + x := input.Message.Interface().(*ExampleAutoIncrementTable) if x == nil { return protoiface.SizeOutput{ NoUnkeyedLiterals: input.NoUnkeyedLiterals, @@ -2561,6 +2630,9 @@ func (x *fastReflection_C) ProtoMethods() *protoiface.Methods { if l > 0 { n += 1 + l + runtime.Sov(uint64(l)) } + if x.Y != 0 { + n += 1 + runtime.Sov(uint64(x.Y)) + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -2571,7 +2643,7 @@ func (x *fastReflection_C) ProtoMethods() *protoiface.Methods { } marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { - x := input.Message.Interface().(*C) + x := input.Message.Interface().(*ExampleAutoIncrementTable) if x == nil { return protoiface.MarshalOutput{ NoUnkeyedLiterals: input.NoUnkeyedLiterals, @@ -2590,6 +2662,11 @@ func (x *fastReflection_C) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if x.Y != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.Y)) + i-- + dAtA[i] = 0x18 + } if len(x.X) > 0 { i -= len(x.X) copy(dAtA[i:], x.X) @@ -2613,7 +2690,7 @@ func (x *fastReflection_C) ProtoMethods() *protoiface.Methods { }, nil } unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { - x := input.Message.Interface().(*C) + x := input.Message.Interface().(*ExampleAutoIncrementTable) if x == nil { return protoiface.UnmarshalOutput{ NoUnkeyedLiterals: input.NoUnkeyedLiterals, @@ -2645,10 +2722,10 @@ func (x *fastReflection_C) ProtoMethods() *protoiface.Methods { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: C: wiretype end group for non-group") + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ExampleAutoIncrementTable: wiretype end group for non-group") } if fieldNum <= 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: C: illegal tag %d (wire type %d)", fieldNum, wire) + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ExampleAutoIncrementTable: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -2702,6 +2779,493 @@ func (x *fastReflection_C) ProtoMethods() *protoiface.Methods { } x.X = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 3: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Y", wireType) + } + x.Y = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + x.Y |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var ( + md_ExampleSingleton protoreflect.MessageDescriptor + fd_ExampleSingleton_foo protoreflect.FieldDescriptor + fd_ExampleSingleton_bar protoreflect.FieldDescriptor +) + +func init() { + file_testpb_testschema_proto_init() + md_ExampleSingleton = File_testpb_testschema_proto.Messages().ByName("ExampleSingleton") + fd_ExampleSingleton_foo = md_ExampleSingleton.Fields().ByName("foo") + fd_ExampleSingleton_bar = md_ExampleSingleton.Fields().ByName("bar") +} + +var _ protoreflect.Message = (*fastReflection_ExampleSingleton)(nil) + +type fastReflection_ExampleSingleton ExampleSingleton + +func (x *ExampleSingleton) ProtoReflect() protoreflect.Message { + return (*fastReflection_ExampleSingleton)(x) +} + +func (x *ExampleSingleton) slowProtoReflect() protoreflect.Message { + mi := &file_testpb_testschema_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_ExampleSingleton_messageType fastReflection_ExampleSingleton_messageType +var _ protoreflect.MessageType = fastReflection_ExampleSingleton_messageType{} + +type fastReflection_ExampleSingleton_messageType struct{} + +func (x fastReflection_ExampleSingleton_messageType) Zero() protoreflect.Message { + return (*fastReflection_ExampleSingleton)(nil) +} +func (x fastReflection_ExampleSingleton_messageType) New() protoreflect.Message { + return new(fastReflection_ExampleSingleton) +} +func (x fastReflection_ExampleSingleton_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_ExampleSingleton +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_ExampleSingleton) Descriptor() protoreflect.MessageDescriptor { + return md_ExampleSingleton +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_ExampleSingleton) Type() protoreflect.MessageType { + return _fastReflection_ExampleSingleton_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_ExampleSingleton) New() protoreflect.Message { + return new(fastReflection_ExampleSingleton) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_ExampleSingleton) Interface() protoreflect.ProtoMessage { + return (*ExampleSingleton)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_ExampleSingleton) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Foo != "" { + value := protoreflect.ValueOfString(x.Foo) + if !f(fd_ExampleSingleton_foo, value) { + return + } + } + if x.Bar != int32(0) { + value := protoreflect.ValueOfInt32(x.Bar) + if !f(fd_ExampleSingleton_bar, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_ExampleSingleton) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "testpb.ExampleSingleton.foo": + return x.Foo != "" + case "testpb.ExampleSingleton.bar": + return x.Bar != int32(0) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleSingleton")) + } + panic(fmt.Errorf("message testpb.ExampleSingleton does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_ExampleSingleton) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "testpb.ExampleSingleton.foo": + x.Foo = "" + case "testpb.ExampleSingleton.bar": + x.Bar = int32(0) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleSingleton")) + } + panic(fmt.Errorf("message testpb.ExampleSingleton does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_ExampleSingleton) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "testpb.ExampleSingleton.foo": + value := x.Foo + return protoreflect.ValueOfString(value) + case "testpb.ExampleSingleton.bar": + value := x.Bar + return protoreflect.ValueOfInt32(value) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleSingleton")) + } + panic(fmt.Errorf("message testpb.ExampleSingleton does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_ExampleSingleton) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "testpb.ExampleSingleton.foo": + x.Foo = value.Interface().(string) + case "testpb.ExampleSingleton.bar": + x.Bar = int32(value.Int()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleSingleton")) + } + panic(fmt.Errorf("message testpb.ExampleSingleton does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_ExampleSingleton) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "testpb.ExampleSingleton.foo": + panic(fmt.Errorf("field foo of message testpb.ExampleSingleton is not mutable")) + case "testpb.ExampleSingleton.bar": + panic(fmt.Errorf("field bar of message testpb.ExampleSingleton is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleSingleton")) + } + panic(fmt.Errorf("message testpb.ExampleSingleton does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_ExampleSingleton) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "testpb.ExampleSingleton.foo": + return protoreflect.ValueOfString("") + case "testpb.ExampleSingleton.bar": + return protoreflect.ValueOfInt32(int32(0)) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: testpb.ExampleSingleton")) + } + panic(fmt.Errorf("message testpb.ExampleSingleton does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_ExampleSingleton) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in testpb.ExampleSingleton", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_ExampleSingleton) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_ExampleSingleton) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_ExampleSingleton) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_ExampleSingleton) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*ExampleSingleton) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.Foo) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.Bar != 0 { + n += 1 + runtime.Sov(uint64(x.Bar)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*ExampleSingleton) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if x.Bar != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.Bar)) + i-- + dAtA[i] = 0x10 + } + if len(x.Foo) > 0 { + i -= len(x.Foo) + copy(dAtA[i:], x.Foo) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Foo))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*ExampleSingleton) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ExampleSingleton: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: ExampleSingleton: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Foo", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Foo = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Bar", wireType) + } + x.Bar = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + x.Bar |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -2805,7 +3369,7 @@ func (Enum) EnumDescriptor() ([]byte, []int) { return file_testpb_testschema_proto_rawDescGZIP(), []int{0} } -type A struct { +type ExampleTable struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -2828,16 +3392,16 @@ type A struct { B bool `protobuf:"varint,15,opt,name=b,proto3" json:"b,omitempty"` E Enum `protobuf:"varint,16,opt,name=e,proto3,enum=testpb.Enum" json:"e,omitempty"` // Invalid key fields: - Repeated []uint32 `protobuf:"varint,17,rep,packed,name=repeated,proto3" json:"repeated,omitempty"` - Map map[string]uint32 `protobuf:"bytes,18,rep,name=map,proto3" json:"map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` - Msg *B `protobuf:"bytes,19,opt,name=msg,proto3" json:"msg,omitempty"` + Repeated []uint32 `protobuf:"varint,17,rep,packed,name=repeated,proto3" json:"repeated,omitempty"` + Map map[string]uint32 `protobuf:"bytes,18,rep,name=map,proto3" json:"map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + Msg *ExampleTable_ExampleMessage `protobuf:"bytes,19,opt,name=msg,proto3" json:"msg,omitempty"` // Types that are assignable to Sum: - // *A_Oneof - Sum isA_Sum `protobuf_oneof:"sum"` + // *ExampleTable_Oneof + Sum isExampleTable_Sum `protobuf_oneof:"sum"` } -func (x *A) Reset() { - *x = A{} +func (x *ExampleTable) Reset() { + *x = ExampleTable{} if protoimpl.UnsafeEnabled { mi := &file_testpb_testschema_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -2845,184 +3409,186 @@ func (x *A) Reset() { } } -func (x *A) String() string { +func (x *ExampleTable) String() string { return protoimpl.X.MessageStringOf(x) } -func (*A) ProtoMessage() {} +func (*ExampleTable) ProtoMessage() {} -// Deprecated: Use A.ProtoReflect.Descriptor instead. -func (*A) Descriptor() ([]byte, []int) { +// Deprecated: Use ExampleTable.ProtoReflect.Descriptor instead. +func (*ExampleTable) Descriptor() ([]byte, []int) { return file_testpb_testschema_proto_rawDescGZIP(), []int{0} } -func (x *A) GetU32() uint32 { +func (x *ExampleTable) GetU32() uint32 { if x != nil { return x.U32 } return 0 } -func (x *A) GetU64() uint64 { +func (x *ExampleTable) GetU64() uint64 { if x != nil { return x.U64 } return 0 } -func (x *A) GetStr() string { +func (x *ExampleTable) GetStr() string { if x != nil { return x.Str } return "" } -func (x *A) GetBz() []byte { +func (x *ExampleTable) GetBz() []byte { if x != nil { return x.Bz } return nil } -func (x *A) GetTs() *timestamppb.Timestamp { +func (x *ExampleTable) GetTs() *timestamppb.Timestamp { if x != nil { return x.Ts } return nil } -func (x *A) GetDur() *durationpb.Duration { +func (x *ExampleTable) GetDur() *durationpb.Duration { if x != nil { return x.Dur } return nil } -func (x *A) GetI32() int32 { +func (x *ExampleTable) GetI32() int32 { if x != nil { return x.I32 } return 0 } -func (x *A) GetS32() int32 { +func (x *ExampleTable) GetS32() int32 { if x != nil { return x.S32 } return 0 } -func (x *A) GetSf32() int32 { +func (x *ExampleTable) GetSf32() int32 { if x != nil { return x.Sf32 } return 0 } -func (x *A) GetI64() int64 { +func (x *ExampleTable) GetI64() int64 { if x != nil { return x.I64 } return 0 } -func (x *A) GetS64() int64 { +func (x *ExampleTable) GetS64() int64 { if x != nil { return x.S64 } return 0 } -func (x *A) GetSf64() int64 { +func (x *ExampleTable) GetSf64() int64 { if x != nil { return x.Sf64 } return 0 } -func (x *A) GetF32() uint32 { +func (x *ExampleTable) GetF32() uint32 { if x != nil { return x.F32 } return 0 } -func (x *A) GetF64() uint64 { +func (x *ExampleTable) GetF64() uint64 { if x != nil { return x.F64 } return 0 } -func (x *A) GetB() bool { +func (x *ExampleTable) GetB() bool { if x != nil { return x.B } return false } -func (x *A) GetE() Enum { +func (x *ExampleTable) GetE() Enum { if x != nil { return x.E } return Enum_ENUM_UNSPECIFIED } -func (x *A) GetRepeated() []uint32 { +func (x *ExampleTable) GetRepeated() []uint32 { if x != nil { return x.Repeated } return nil } -func (x *A) GetMap() map[string]uint32 { +func (x *ExampleTable) GetMap() map[string]uint32 { if x != nil { return x.Map } return nil } -func (x *A) GetMsg() *B { +func (x *ExampleTable) GetMsg() *ExampleTable_ExampleMessage { if x != nil { return x.Msg } return nil } -func (x *A) GetSum() isA_Sum { +func (x *ExampleTable) GetSum() isExampleTable_Sum { if x != nil { return x.Sum } return nil } -func (x *A) GetOneof() uint32 { - if x, ok := x.GetSum().(*A_Oneof); ok { +func (x *ExampleTable) GetOneof() uint32 { + if x, ok := x.GetSum().(*ExampleTable_Oneof); ok { return x.Oneof } return 0 } -type isA_Sum interface { - isA_Sum() +type isExampleTable_Sum interface { + isExampleTable_Sum() } -type A_Oneof struct { +type ExampleTable_Oneof struct { Oneof uint32 `protobuf:"varint,20,opt,name=oneof,proto3,oneof"` } -func (*A_Oneof) isA_Sum() {} +func (*ExampleTable_Oneof) isExampleTable_Sum() {} -type B struct { +type ExampleAutoIncrementTable struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - X string `protobuf:"bytes,1,opt,name=x,proto3" json:"x,omitempty"` + Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + X string `protobuf:"bytes,2,opt,name=x,proto3" json:"x,omitempty"` + Y int32 `protobuf:"varint,3,opt,name=y,proto3" json:"y,omitempty"` } -func (x *B) Reset() { - *x = B{} +func (x *ExampleAutoIncrementTable) Reset() { + *x = ExampleAutoIncrementTable{} if protoimpl.UnsafeEnabled { mi := &file_testpb_testschema_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -3030,35 +3596,49 @@ func (x *B) Reset() { } } -func (x *B) String() string { +func (x *ExampleAutoIncrementTable) String() string { return protoimpl.X.MessageStringOf(x) } -func (*B) ProtoMessage() {} +func (*ExampleAutoIncrementTable) ProtoMessage() {} -// Deprecated: Use B.ProtoReflect.Descriptor instead. -func (*B) Descriptor() ([]byte, []int) { +// Deprecated: Use ExampleAutoIncrementTable.ProtoReflect.Descriptor instead. +func (*ExampleAutoIncrementTable) Descriptor() ([]byte, []int) { return file_testpb_testschema_proto_rawDescGZIP(), []int{1} } -func (x *B) GetX() string { +func (x *ExampleAutoIncrementTable) GetId() uint64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *ExampleAutoIncrementTable) GetX() string { if x != nil { return x.X } return "" } -type C struct { +func (x *ExampleAutoIncrementTable) GetY() int32 { + if x != nil { + return x.Y + } + return 0 +} + +type ExampleSingleton struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - X string `protobuf:"bytes,2,opt,name=x,proto3" json:"x,omitempty"` + Foo string `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"` + Bar int32 `protobuf:"varint,2,opt,name=bar,proto3" json:"bar,omitempty"` } -func (x *C) Reset() { - *x = C{} +func (x *ExampleSingleton) Reset() { + *x = ExampleSingleton{} if protoimpl.UnsafeEnabled { mi := &file_testpb_testschema_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -3066,31 +3646,74 @@ func (x *C) Reset() { } } -func (x *C) String() string { +func (x *ExampleSingleton) String() string { return protoimpl.X.MessageStringOf(x) } -func (*C) ProtoMessage() {} +func (*ExampleSingleton) ProtoMessage() {} -// Deprecated: Use C.ProtoReflect.Descriptor instead. -func (*C) Descriptor() ([]byte, []int) { +// Deprecated: Use ExampleSingleton.ProtoReflect.Descriptor instead. +func (*ExampleSingleton) Descriptor() ([]byte, []int) { return file_testpb_testschema_proto_rawDescGZIP(), []int{2} } -func (x *C) GetId() uint64 { +func (x *ExampleSingleton) GetFoo() string { if x != nil { - return x.Id + return x.Foo + } + return "" +} + +func (x *ExampleSingleton) GetBar() int32 { + if x != nil { + return x.Bar } return 0 } -func (x *C) GetX() string { +type ExampleTable_ExampleMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Foo string `protobuf:"bytes,1,opt,name=foo,proto3" json:"foo,omitempty"` + Bar int32 `protobuf:"varint,2,opt,name=bar,proto3" json:"bar,omitempty"` +} + +func (x *ExampleTable_ExampleMessage) Reset() { + *x = ExampleTable_ExampleMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_testpb_testschema_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExampleTable_ExampleMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExampleTable_ExampleMessage) ProtoMessage() {} + +// Deprecated: Use ExampleTable_ExampleMessage.ProtoReflect.Descriptor instead. +func (*ExampleTable_ExampleMessage) Descriptor() ([]byte, []int) { + return file_testpb_testschema_proto_rawDescGZIP(), []int{0, 1} +} + +func (x *ExampleTable_ExampleMessage) GetFoo() string { if x != nil { - return x.X + return x.Foo } return "" } +func (x *ExampleTable_ExampleMessage) GetBar() int32 { + if x != nil { + return x.Bar + } + return 0 +} + var File_testpb_testschema_proto protoreflect.FileDescriptor var file_testpb_testschema_proto_rawDesc = []byte{ @@ -3102,65 +3725,76 @@ var file_testpb_testschema_proto_rawDesc = []byte{ 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x6f, 0x72, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x6f, 0x72, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0xd5, 0x04, 0x0a, 0x01, 0x41, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x33, 0x32, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x75, 0x33, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x36, 0x34, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x75, 0x36, 0x34, 0x12, 0x10, 0x0a, 0x03, 0x73, - 0x74, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x74, 0x72, 0x12, 0x0e, 0x0a, - 0x02, 0x62, 0x7a, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x62, 0x7a, 0x12, 0x2a, 0x0a, - 0x02, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x02, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x03, 0x64, 0x75, 0x72, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x03, 0x64, 0x75, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x33, 0x32, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x03, 0x69, 0x33, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x33, 0x32, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x11, 0x52, 0x03, 0x73, 0x33, 0x32, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x66, - 0x33, 0x32, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x04, 0x73, 0x66, 0x33, 0x32, 0x12, 0x10, - 0x0a, 0x03, 0x69, 0x36, 0x34, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x69, 0x36, 0x34, - 0x12, 0x10, 0x0a, 0x03, 0x73, 0x36, 0x34, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x12, 0x52, 0x03, 0x73, - 0x36, 0x34, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x66, 0x36, 0x34, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x10, - 0x52, 0x04, 0x73, 0x66, 0x36, 0x34, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x33, 0x32, 0x18, 0x0d, 0x20, - 0x01, 0x28, 0x07, 0x52, 0x03, 0x66, 0x33, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x36, 0x34, 0x18, - 0x0e, 0x20, 0x01, 0x28, 0x06, 0x52, 0x03, 0x66, 0x36, 0x34, 0x12, 0x0c, 0x0a, 0x01, 0x62, 0x18, - 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x01, 0x62, 0x12, 0x1a, 0x0a, 0x01, 0x65, 0x18, 0x10, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x0c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x6e, 0x75, - 0x6d, 0x52, 0x01, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x18, 0x11, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x12, 0x24, 0x0a, 0x03, 0x6d, 0x61, 0x70, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x2e, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x03, 0x6d, 0x61, 0x70, 0x12, 0x1b, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x13, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x42, 0x52, 0x03, + 0x6f, 0x22, 0xbd, 0x05, 0x0a, 0x0c, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x03, 0x75, 0x33, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x36, 0x34, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x03, 0x75, 0x36, 0x34, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x74, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x74, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x62, 0x7a, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x62, 0x7a, 0x12, 0x2a, 0x0a, 0x02, 0x74, 0x73, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x02, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x03, 0x64, 0x75, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x64, 0x75, + 0x72, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x33, 0x32, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, + 0x69, 0x33, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x33, 0x32, 0x18, 0x08, 0x20, 0x01, 0x28, 0x11, + 0x52, 0x03, 0x73, 0x33, 0x32, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x66, 0x33, 0x32, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x0f, 0x52, 0x04, 0x73, 0x66, 0x33, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x36, 0x34, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x69, 0x36, 0x34, 0x12, 0x10, 0x0a, 0x03, 0x73, + 0x36, 0x34, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x12, 0x52, 0x03, 0x73, 0x36, 0x34, 0x12, 0x12, 0x0a, + 0x04, 0x73, 0x66, 0x36, 0x34, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x10, 0x52, 0x04, 0x73, 0x66, 0x36, + 0x34, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x33, 0x32, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x07, 0x52, 0x03, + 0x66, 0x33, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x36, 0x34, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x06, + 0x52, 0x03, 0x66, 0x36, 0x34, 0x12, 0x0c, 0x0a, 0x01, 0x62, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x01, 0x62, 0x12, 0x1a, 0x0a, 0x01, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0c, + 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x01, 0x65, 0x12, + 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x11, 0x20, 0x03, 0x28, + 0x0d, 0x52, 0x08, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2f, 0x0a, 0x03, 0x6d, + 0x61, 0x70, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, + 0x62, 0x2e, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x4d, + 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x6d, 0x61, 0x70, 0x12, 0x35, 0x0a, 0x03, + 0x6d, 0x73, 0x67, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x73, 0x74, + 0x70, 0x62, 0x2e, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x2e, + 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x16, 0x0a, 0x05, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x05, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x1a, 0x36, 0x0a, 0x08, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x3a, 0x3d, 0xf2, 0x9e, 0xd3, 0x8e, 0x03, 0x37, 0x0a, 0x0d, 0x0a, 0x0b, 0x75, - 0x33, 0x32, 0x2c, 0x75, 0x36, 0x34, 0x2c, 0x73, 0x74, 0x72, 0x12, 0x0b, 0x0a, 0x07, 0x75, 0x36, - 0x34, 0x2c, 0x73, 0x74, 0x72, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x73, 0x74, 0x72, 0x2c, 0x75, - 0x33, 0x32, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x62, 0x7a, 0x2c, 0x73, 0x74, 0x72, 0x10, 0x03, - 0x18, 0x01, 0x42, 0x05, 0x0a, 0x03, 0x73, 0x75, 0x6d, 0x22, 0x1b, 0x0a, 0x01, 0x42, 0x12, 0x0c, - 0x0a, 0x01, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x01, 0x78, 0x3a, 0x08, 0xfa, 0x9e, - 0xd3, 0x8e, 0x03, 0x02, 0x08, 0x02, 0x22, 0x33, 0x0a, 0x01, 0x43, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x0c, 0x0a, 0x01, 0x78, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x01, 0x78, 0x3a, 0x10, 0xf2, 0x9e, 0xd3, 0x8e, 0x03, - 0x0a, 0x0a, 0x06, 0x0a, 0x02, 0x69, 0x64, 0x10, 0x01, 0x18, 0x03, 0x2a, 0x64, 0x0a, 0x04, 0x45, - 0x6e, 0x75, 0x6d, 0x12, 0x14, 0x0a, 0x10, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, - 0x4d, 0x5f, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, 0x5f, - 0x54, 0x57, 0x4f, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x46, 0x49, - 0x56, 0x45, 0x10, 0x05, 0x12, 0x1b, 0x0a, 0x0e, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4e, 0x45, 0x47, - 0x5f, 0x54, 0x48, 0x52, 0x45, 0x45, 0x10, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x01, 0x42, 0x87, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, - 0x42, 0x0f, 0x54, 0x65, 0x73, 0x74, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, - 0x6b, 0x2f, 0x6f, 0x72, 0x6d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, - 0x65, 0x73, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, 0x54, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x54, 0x65, - 0x73, 0x74, 0x70, 0x62, 0xca, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0xe2, 0x02, 0x12, - 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x02, 0x38, 0x01, 0x1a, 0x34, 0x0a, 0x0e, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x62, 0x61, 0x72, 0x3a, 0x3f, 0xf2, 0x9e, 0xd3, 0x8e, 0x03, + 0x39, 0x0a, 0x0d, 0x0a, 0x0b, 0x75, 0x33, 0x32, 0x2c, 0x69, 0x36, 0x34, 0x2c, 0x73, 0x74, 0x72, + 0x12, 0x0d, 0x0a, 0x07, 0x75, 0x36, 0x34, 0x2c, 0x73, 0x74, 0x72, 0x10, 0x01, 0x18, 0x01, 0x12, + 0x0b, 0x0a, 0x07, 0x73, 0x74, 0x72, 0x2c, 0x75, 0x33, 0x32, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, + 0x62, 0x7a, 0x2c, 0x73, 0x74, 0x72, 0x10, 0x03, 0x18, 0x01, 0x42, 0x05, 0x0a, 0x03, 0x73, 0x75, + 0x6d, 0x22, 0x62, 0x0a, 0x19, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x41, 0x75, 0x74, 0x6f, + 0x49, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x0c, + 0x0a, 0x01, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x01, 0x78, 0x12, 0x0c, 0x0a, 0x01, + 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x01, 0x79, 0x3a, 0x19, 0xf2, 0x9e, 0xd3, 0x8e, + 0x03, 0x13, 0x0a, 0x06, 0x0a, 0x02, 0x69, 0x64, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x01, 0x78, 0x10, + 0x01, 0x18, 0x01, 0x18, 0x03, 0x22, 0x40, 0x0a, 0x10, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x74, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x6f, 0x6f, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x62, + 0x61, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x62, 0x61, 0x72, 0x3a, 0x08, 0xfa, + 0x9e, 0xd3, 0x8e, 0x03, 0x02, 0x08, 0x02, 0x2a, 0x64, 0x0a, 0x04, 0x45, 0x6e, 0x75, 0x6d, 0x12, + 0x14, 0x0a, 0x10, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4f, 0x4e, + 0x45, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x54, 0x57, 0x4f, 0x10, + 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x46, 0x49, 0x56, 0x45, 0x10, 0x05, + 0x12, 0x1b, 0x0a, 0x0e, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x4e, 0x45, 0x47, 0x5f, 0x54, 0x48, 0x52, + 0x45, 0x45, 0x10, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x42, 0x87, 0x01, + 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0x42, 0x0f, 0x54, 0x65, + 0x73, 0x74, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x6f, 0x72, + 0x6d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, + 0x62, 0xa2, 0x02, 0x03, 0x54, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, + 0xca, 0x02, 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0xe2, 0x02, 0x12, 0x54, 0x65, 0x73, 0x74, + 0x70, 0x62, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, + 0x06, 0x54, 0x65, 0x73, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3176,22 +3810,23 @@ func file_testpb_testschema_proto_rawDescGZIP() []byte { } var file_testpb_testschema_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_testpb_testschema_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_testpb_testschema_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_testpb_testschema_proto_goTypes = []interface{}{ - (Enum)(0), // 0: testpb.Enum - (*A)(nil), // 1: testpb.A - (*B)(nil), // 2: testpb.B - (*C)(nil), // 3: testpb.C - nil, // 4: testpb.A.MapEntry - (*timestamppb.Timestamp)(nil), // 5: google.protobuf.Timestamp - (*durationpb.Duration)(nil), // 6: google.protobuf.Duration + (Enum)(0), // 0: testpb.Enum + (*ExampleTable)(nil), // 1: testpb.ExampleTable + (*ExampleAutoIncrementTable)(nil), // 2: testpb.ExampleAutoIncrementTable + (*ExampleSingleton)(nil), // 3: testpb.ExampleSingleton + nil, // 4: testpb.ExampleTable.MapEntry + (*ExampleTable_ExampleMessage)(nil), // 5: testpb.ExampleTable.ExampleMessage + (*timestamppb.Timestamp)(nil), // 6: google.protobuf.Timestamp + (*durationpb.Duration)(nil), // 7: google.protobuf.Duration } var file_testpb_testschema_proto_depIdxs = []int32{ - 5, // 0: testpb.A.ts:type_name -> google.protobuf.Timestamp - 6, // 1: testpb.A.dur:type_name -> google.protobuf.Duration - 0, // 2: testpb.A.e:type_name -> testpb.Enum - 4, // 3: testpb.A.map:type_name -> testpb.A.MapEntry - 2, // 4: testpb.A.msg:type_name -> testpb.B + 6, // 0: testpb.ExampleTable.ts:type_name -> google.protobuf.Timestamp + 7, // 1: testpb.ExampleTable.dur:type_name -> google.protobuf.Duration + 0, // 2: testpb.ExampleTable.e:type_name -> testpb.Enum + 4, // 3: testpb.ExampleTable.map:type_name -> testpb.ExampleTable.MapEntry + 5, // 4: testpb.ExampleTable.msg:type_name -> testpb.ExampleTable.ExampleMessage 5, // [5:5] is the sub-list for method output_type 5, // [5:5] is the sub-list for method input_type 5, // [5:5] is the sub-list for extension type_name @@ -3206,7 +3841,7 @@ func file_testpb_testschema_proto_init() { } if !protoimpl.UnsafeEnabled { file_testpb_testschema_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*A); i { + switch v := v.(*ExampleTable); i { case 0: return &v.state case 1: @@ -3218,7 +3853,7 @@ func file_testpb_testschema_proto_init() { } } file_testpb_testschema_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*B); i { + switch v := v.(*ExampleAutoIncrementTable); i { case 0: return &v.state case 1: @@ -3230,7 +3865,19 @@ func file_testpb_testschema_proto_init() { } } file_testpb_testschema_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*C); i { + switch v := v.(*ExampleSingleton); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_testpb_testschema_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExampleTable_ExampleMessage); i { case 0: return &v.state case 1: @@ -3243,7 +3890,7 @@ func file_testpb_testschema_proto_init() { } } file_testpb_testschema_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*A_Oneof)(nil), + (*ExampleTable_Oneof)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -3251,7 +3898,7 @@ func file_testpb_testschema_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_testpb_testschema_proto_rawDesc, NumEnums: 1, - NumMessages: 4, + NumMessages: 5, NumExtensions: 0, NumServices: 0, }, diff --git a/orm/internal/testutil/testutil.go b/orm/internal/testutil/testutil.go index 04a9100e3..f98b7e334 100644 --- a/orm/internal/testutil/testutil.go +++ b/orm/internal/testutil/testutil.go @@ -4,8 +4,9 @@ import ( "fmt" "strings" - "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/known/durationpb" + + "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/known/timestamppb" "pgregory.net/rapid" @@ -14,7 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/orm/internal/testpb" ) -// TestFieldSpec defines a test field against the testpb.A message. +// TestFieldSpec defines a test field against the testpb.ExampleTable message. type TestFieldSpec struct { FieldName protoreflect.Name Gen *rapid.Generator @@ -78,19 +79,23 @@ var TestFieldSpecs = []TestFieldSpec{ }, { "ts", - rapid.ArrayOf(2, rapid.Int64()).Map(func(xs [2]int64) protoreflect.Message { + rapid.Custom(func(t *rapid.T) protoreflect.Message { + seconds := rapid.Int64Range(-9999999999, 9999999999).Draw(t, "seconds").(int64) + nanos := rapid.Int32Range(0, 999999999).Draw(t, "nanos").(int32) return (×tamppb.Timestamp{ - Seconds: xs[0], - Nanos: int32(xs[1]), + Seconds: seconds, + Nanos: nanos, }).ProtoReflect() }), }, { "dur", - rapid.ArrayOf(2, rapid.Int64()).Map(func(xs [2]int64) protoreflect.Message { + rapid.Custom(func(t *rapid.T) protoreflect.Message { + seconds := rapid.Int64Range(0, 315576000000).Draw(t, "seconds").(int64) + nanos := rapid.Int32Range(0, 999999999).Draw(t, "nanos").(int32) return (&durationpb.Duration{ - Seconds: xs[0], - Nanos: int32(xs[1]), + Seconds: seconds, + Nanos: nanos, }).ProtoReflect() }), }, @@ -111,7 +116,7 @@ func MakeTestCodec(fname protoreflect.Name, nonTerminal bool) (ormfield.Codec, e } func GetTestField(fname protoreflect.Name) protoreflect.FieldDescriptor { - a := &testpb.A{} + a := &testpb.ExampleTable{} return a.ProtoReflect().Descriptor().Fields().ByName(fname) } @@ -147,8 +152,8 @@ func TestKeyCodecGen(minLen, maxLen int) *rapid.Generator { prefix := rapid.SliceOfN(rapid.Byte(), 0, 5).Draw(t, "prefix").([]byte) - desc := (&testpb.A{}).ProtoReflect().Descriptor() - cdc, err := ormkv.NewKeyCodec(prefix, desc, fields) + msgType := (&testpb.ExampleTable{}).ProtoReflect().Type() + cdc, err := ormkv.NewKeyCodec(prefix, msgType, fields) if err != nil { panic(err) } @@ -169,8 +174,8 @@ func (k TestKeyCodec) Draw(t *rapid.T, id string) []protoreflect.Value { return keyValues } -var GenA = rapid.Custom(func(t *rapid.T) *testpb.A { - a := &testpb.A{} +var GenA = rapid.Custom(func(t *rapid.T) *testpb.ExampleTable { + a := &testpb.ExampleTable{} ref := a.ProtoReflect() for _, spec := range TestFieldSpecs { field := GetTestField(spec.FieldName) @@ -179,12 +184,3 @@ var GenA = rapid.Custom(func(t *rapid.T) *testpb.A { } return a }) - -func ValuesOf(values ...interface{}) []protoreflect.Value { - n := len(values) - res := make([]protoreflect.Value, n) - for i := 0; i < n; i++ { - res[i] = protoreflect.ValueOf(values[i]) - } - return res -} diff --git a/orm/model/doc.go b/orm/model/doc.go new file mode 100644 index 000000000..af731c839 --- /dev/null +++ b/orm/model/doc.go @@ -0,0 +1,3 @@ +// Package model contains packages which define ORM data "model" types +// such as tables, indexes, and schemas. +package model diff --git a/orm/model/kv/store.go b/orm/model/kv/store.go new file mode 100644 index 000000000..0ca5cbc9f --- /dev/null +++ b/orm/model/kv/store.go @@ -0,0 +1,50 @@ +// Package kvstore defines the abstract interfaces which ORM tables and indexes +// use for reading and writing data against a KV-store backend. +package kv + +import ( + dbm "github.com/tendermint/tm-db" +) + +// ReadonlyStore is an interface for readonly access to a kv-store. +type ReadonlyStore interface { + // Get fetches the value of the given key, or nil if it does not exist. + // CONTRACT: key, value readonly []byte + Get(key []byte) ([]byte, error) + + // Has checks if a key exists. + // CONTRACT: key, value readonly []byte + Has(key []byte) (bool, error) + + // Iterator returns an iterator over a domain of keys, in ascending order. The caller must call + // Close when done. End is exclusive, and start must be less than end. A nil start iterates + // from the first key, and a nil end iterates to the last key (inclusive). Empty keys are not + // valid. + // CONTRACT: No writes may happen within a domain while an iterator exists over it. + // CONTRACT: start, end readonly []byte + Iterator(start, end []byte) (Iterator, error) + + // ReverseIterator returns an iterator over a domain of keys, in descending order. The caller + // must call Close when done. End is exclusive, and start must be less than end. A nil end + // iterates from the last key (inclusive), and a nil start iterates to the first key (inclusive). + // Empty keys are not valid. + // CONTRACT: No writes may happen within a domain while an iterator exists over it. + // CONTRACT: start, end readonly []byte + ReverseIterator(start, end []byte) (Iterator, error) +} + +// Iterator aliases github.com/tendermint/tm-db.Iterator. +type Iterator = dbm.Iterator + +// Store is an interface for writing to a kv-store. +type Store interface { + ReadonlyStore + + // Set sets the value for the given key, replacing it if it already exists. + // CONTRACT: key, value readonly []byte + Set(key, value []byte) error + + // Delete deletes the key, or does nothing if the key does not exist. + // CONTRACT: key readonly []byte + Delete(key []byte) error +} diff --git a/orm/model/ormlist/options.go b/orm/model/ormlist/options.go new file mode 100644 index 000000000..c917921e8 --- /dev/null +++ b/orm/model/ormlist/options.go @@ -0,0 +1,77 @@ +// Package ormlist defines options for listing items from ORM indexes. +package ormlist + +import ( + "github.com/cosmos/cosmos-sdk/orm/encoding/encodeutil" + "github.com/cosmos/cosmos-sdk/orm/internal/listinternal" +) + +// Option represents a list option. +type Option = listinternal.Option + +// Start defines the values to use to start range iteration. It cannot be +// combined with Prefix. +// +// Values must correspond in type to the index's fields and the number of values +// provided cannot exceed the number of fields in the index, although fewer +// values can be provided. +// +// Range iteration can only be done for start and end values which are +// well-ordered, meaning that any unordered components must be equal. Ex. +// the bytes type is considered unordered, so a range iterator is created +// over an index with a bytes field, both start and end must have the same +// value for bytes. +func Start(values ...interface{}) Option { + return listinternal.FuncOption(func(options *listinternal.Options) { + options.Start = encodeutil.ValuesOf(values...) + }) +} + +// End defines the values to use to end range iteration. It cannot be +// combined with Prefix. +// +// Values must correspond in type to the index's fields and the number of values +// provided cannot exceed the number of fields in the index, although fewer +// values can be provided. +// +// Range iteration can only be done for start and end values which are +// well-ordered, meaning that any unordered components must be equal. Ex. +// the bytes type is considered unordered, so a range iterator is created +// over an index with a bytes field, both start and end must have the same +// value for bytes. +func End(values ...interface{}) Option { + return listinternal.FuncOption(func(options *listinternal.Options) { + options.End = encodeutil.ValuesOf(values...) + }) +} + +// Prefix defines values to use for prefix iteration. It cannot be used +// together with Start or End. +// +// Values must correspond in type to the index's fields and the number of values +// provided cannot exceed the number of fields in the index, although fewer +// values can be provided. +func Prefix(values ...interface{}) Option { + return listinternal.FuncOption(func(options *listinternal.Options) { + options.Prefix = encodeutil.ValuesOf(values...) + }) +} + +// Reverse reverses the direction of iteration. If Reverse is +// provided twice, iteration will happen in the forward direction. +func Reverse() Option { + return listinternal.FuncOption(func(options *listinternal.Options) { + options.Reverse = !options.Reverse + }) +} + +// Cursor specifies a cursor after which to restart iteration. Cursor values +// are returned by iterators and in pagination results. +func Cursor(cursor CursorT) Option { + return listinternal.FuncOption(func(options *listinternal.Options) { + options.Cursor = cursor + }) +} + +// CursorT defines a cursor type. +type CursorT []byte diff --git a/orm/model/ormtable/auto_increment.go b/orm/model/ormtable/auto_increment.go new file mode 100644 index 000000000..a373edf8b --- /dev/null +++ b/orm/model/ormtable/auto_increment.go @@ -0,0 +1,218 @@ +package ormtable + +import ( + "context" + "encoding/json" + "fmt" + "io" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + + "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" + "github.com/cosmos/cosmos-sdk/orm/model/kv" + "github.com/cosmos/cosmos-sdk/orm/types/ormerrors" +) + +// autoIncrementTable is a Table implementation for tables with an +// auto-incrementing uint64 primary key. +type autoIncrementTable struct { + *tableImpl + autoIncField protoreflect.FieldDescriptor + seqCodec *ormkv.SeqCodec +} + +func (t autoIncrementTable) Save(ctx context.Context, message proto.Message) error { + backend, err := t.getBackend(ctx) + if err != nil { + return err + } + + return t.save(backend, message, saveModeDefault) +} + +func (t autoIncrementTable) Insert(ctx context.Context, message proto.Message) error { + backend, err := t.getBackend(ctx) + if err != nil { + return err + } + + return t.save(backend, message, saveModeInsert) +} + +func (t autoIncrementTable) Update(ctx context.Context, message proto.Message) error { + backend, err := t.getBackend(ctx) + if err != nil { + return err + } + + return t.save(backend, message, saveModeUpdate) +} + +func (t *autoIncrementTable) save(backend Backend, message proto.Message, mode saveMode) error { + messageRef := message.ProtoReflect() + val := messageRef.Get(t.autoIncField).Uint() + writer := newBatchIndexCommitmentWriter(backend) + defer writer.Close() + + if val == 0 { + if mode == saveModeUpdate { + return ormerrors.PrimaryKeyInvalidOnUpdate + } + + mode = saveModeInsert + key, err := t.nextSeqValue(writer.IndexStore()) + if err != nil { + return err + } + + messageRef.Set(t.autoIncField, protoreflect.ValueOfUint64(key)) + } else { + if mode == saveModeInsert { + return ormerrors.AutoIncrementKeyAlreadySet + } + + mode = saveModeUpdate + } + + return t.tableImpl.doSave(writer, message, mode) +} + +func (t *autoIncrementTable) curSeqValue(kv kv.ReadonlyStore) (uint64, error) { + bz, err := kv.Get(t.seqCodec.Prefix()) + if err != nil { + return 0, err + } + + return t.seqCodec.DecodeValue(bz) +} + +func (t *autoIncrementTable) nextSeqValue(kv kv.Store) (uint64, error) { + seq, err := t.curSeqValue(kv) + if err != nil { + return 0, err + } + + seq++ + return seq, t.setSeqValue(kv, seq) +} + +func (t *autoIncrementTable) setSeqValue(kv kv.Store, seq uint64) error { + return kv.Set(t.seqCodec.Prefix(), t.seqCodec.EncodeValue(seq)) +} + +func (t autoIncrementTable) EncodeEntry(entry ormkv.Entry) (k, v []byte, err error) { + if _, ok := entry.(*ormkv.SeqEntry); ok { + return t.seqCodec.EncodeEntry(entry) + } + return t.tableImpl.EncodeEntry(entry) +} + +func (t autoIncrementTable) ValidateJSON(reader io.Reader) error { + return t.decodeAutoIncJson(nil, reader, func(message proto.Message, maxID uint64) error { + messageRef := message.ProtoReflect() + id := messageRef.Get(t.autoIncField).Uint() + if id > maxID { + return fmt.Errorf("invalid ID %d, expected a value <= %d", id, maxID) + } + + if t.customJSONValidator != nil { + return t.customJSONValidator(message) + } else { + return DefaultJSONValidator(message) + } + }) +} + +func (t autoIncrementTable) ImportJSON(ctx context.Context, reader io.Reader) error { + backend, err := t.getBackend(ctx) + if err != nil { + return err + } + + return t.decodeAutoIncJson(backend, reader, func(message proto.Message, maxID uint64) error { + messageRef := message.ProtoReflect() + id := messageRef.Get(t.autoIncField).Uint() + if id == 0 { + // we don't have an ID in the JSON, so we call Save to insert and + // generate one + return t.save(backend, message, saveModeInsert) + } else { + if id > maxID { + return fmt.Errorf("invalid ID %d, expected a value <= %d", id, maxID) + } + // we do have an ID and calling Save will fail because it expects + // either no ID or SAVE_MODE_UPDATE. So instead we drop one level + // down and insert using tableImpl which doesn't know about + // auto-incrementing IDs + return t.tableImpl.save(backend, message, saveModeInsert) + } + }) +} + +func (t autoIncrementTable) decodeAutoIncJson(backend Backend, reader io.Reader, onMsg func(message proto.Message, maxID uint64) error) error { + decoder, err := t.startDecodeJson(reader) + if err != nil { + return err + } + + var seq uint64 + + return t.doDecodeJson(decoder, + func(message json.RawMessage) bool { + err = json.Unmarshal(message, &seq) + if err == nil { + // writer is nil during validation + if backend != nil { + writer := newBatchIndexCommitmentWriter(backend) + defer writer.Close() + err = t.setSeqValue(writer.IndexStore(), seq) + if err != nil { + panic(err) + } + err = writer.Write() + if err != nil { + panic(err) + } + } + return true + } + return false + }, + func(message proto.Message) error { + return onMsg(message, seq) + }) +} + +func (t autoIncrementTable) ExportJSON(ctx context.Context, writer io.Writer) error { + backend, err := t.getBackend(ctx) + if err != nil { + return err + } + + _, err = writer.Write([]byte("[")) + if err != nil { + return err + } + + seq, err := t.curSeqValue(backend.IndexStoreReader()) + if err != nil { + return err + } + + bz, err := json.Marshal(seq) + if err != nil { + return err + } + _, err = writer.Write(bz) + if err != nil { + return err + } + + _, err = writer.Write([]byte(",\n")) + if err != nil { + return err + } + + return t.doExportJSON(ctx, writer) +} diff --git a/orm/model/ormtable/auto_increment_test.go b/orm/model/ormtable/auto_increment_test.go new file mode 100644 index 000000000..8da0735cb --- /dev/null +++ b/orm/model/ormtable/auto_increment_test.go @@ -0,0 +1,74 @@ +package ormtable_test + +import ( + "bytes" + "context" + "os" + "strings" + "testing" + + "gotest.tools/v3/assert" + "gotest.tools/v3/golden" + + "github.com/cosmos/cosmos-sdk/orm/internal/testkv" + "github.com/cosmos/cosmos-sdk/orm/internal/testpb" + "github.com/cosmos/cosmos-sdk/orm/model/ormtable" +) + +func TestAutoIncrementScenario(t *testing.T) { + table, err := ormtable.Build(ormtable.Options{ + MessageType: (&testpb.ExampleAutoIncrementTable{}).ProtoReflect().Type(), + }) + assert.NilError(t, err) + + // first run tests with a split index-commitment store + runAutoIncrementScenario(t, table, ormtable.WrapContextDefault(testkv.NewSplitMemBackend())) + + // now run with shared store and debugging + debugBuf := &strings.Builder{} + store := testkv.NewDebugBackend( + testkv.NewSharedMemBackend(), + &testkv.EntryCodecDebugger{ + EntryCodec: table, + Print: func(s string) { debugBuf.WriteString(s + "\n") }, + }, + ) + runAutoIncrementScenario(t, table, ormtable.WrapContextDefault(store)) + + golden.Assert(t, debugBuf.String(), "test_auto_inc.golden") + checkEncodeDecodeEntries(t, table, store.IndexStoreReader()) +} + +func runAutoIncrementScenario(t *testing.T, table ormtable.Table, context context.Context) { + err := table.Save(context, &testpb.ExampleAutoIncrementTable{Id: 5}) + assert.ErrorContains(t, err, "update") + + ex1 := &testpb.ExampleAutoIncrementTable{X: "foo", Y: 5} + assert.NilError(t, table.Save(context, ex1)) + assert.Equal(t, uint64(1), ex1.Id) + + buf := &bytes.Buffer{} + assert.NilError(t, table.ExportJSON(context, buf)) + golden.Assert(t, string(buf.Bytes()), "auto_inc_json.golden") + + assert.NilError(t, table.ValidateJSON(bytes.NewReader(buf.Bytes()))) + store2 := ormtable.WrapContextDefault(testkv.NewSplitMemBackend()) + assert.NilError(t, table.ImportJSON(store2, bytes.NewReader(buf.Bytes()))) + assertTablesEqual(t, table, context, store2) +} + +func TestBadJSON(t *testing.T) { + table, err := ormtable.Build(ormtable.Options{ + MessageType: (&testpb.ExampleAutoIncrementTable{}).ProtoReflect().Type(), + }) + assert.NilError(t, err) + + store := ormtable.WrapContextDefault(testkv.NewSplitMemBackend()) + f, err := os.Open("testdata/bad_auto_inc.json") + assert.NilError(t, err) + assert.ErrorContains(t, table.ImportJSON(store, f), "invalid ID") + + f, err = os.Open("testdata/bad_auto_inc2.json") + assert.NilError(t, err) + assert.ErrorContains(t, table.ImportJSON(store, f), "invalid ID") +} diff --git a/orm/model/ormtable/backend.go b/orm/model/ormtable/backend.go new file mode 100644 index 000000000..e3757feb5 --- /dev/null +++ b/orm/model/ormtable/backend.go @@ -0,0 +1,156 @@ +package ormtable + +import ( + "context" + + "github.com/cosmos/cosmos-sdk/orm/model/kv" +) + +// ReadBackend defines the type used for read-only ORM operations. +type ReadBackend interface { + // CommitmentStoreReader returns the reader for the commitment store. + CommitmentStoreReader() kv.ReadonlyStore + + // IndexStoreReader returns the reader for the index store. + IndexStoreReader() kv.ReadonlyStore + + private() +} + +// Backend defines the type used for read-write ORM operations. +// Unlike ReadBackend, write access to the underlying kv-store +// is hidden so that this can be fully encapsulated by the ORM. +type Backend interface { + ReadBackend + + // CommitmentStore returns the merklized commitment store. + CommitmentStore() kv.Store + + // IndexStore returns the index store if a separate one exists, + // otherwise it the commitment store. + IndexStore() kv.Store + + // Hooks returns a Hooks instance or nil. + Hooks() Hooks +} + +// ReadBackendOptions defines options for creating a ReadBackend. +// Read context can optionally define two stores - a commitment store +// that is backed by a merkle tree and an index store that isn't. +// If the index store is not defined, the commitment store will be +// used for all operations. +type ReadBackendOptions struct { + + // CommitmentStoreReader is a reader for the commitment store. + CommitmentStoreReader kv.ReadonlyStore + + // IndexStoreReader is an optional reader for the index store. + // If it is nil the CommitmentStoreReader will be used. + IndexStoreReader kv.ReadonlyStore +} + +type readBackend struct { + commitmentReader kv.ReadonlyStore + indexReader kv.ReadonlyStore +} + +func (r readBackend) CommitmentStoreReader() kv.ReadonlyStore { + return r.commitmentReader +} + +func (r readBackend) IndexStoreReader() kv.ReadonlyStore { + return r.indexReader +} + +func (readBackend) private() {} + +// NewReadBackend creates a new ReadBackend. +func NewReadBackend(options ReadBackendOptions) ReadBackend { + indexReader := options.IndexStoreReader + if indexReader == nil { + indexReader = options.CommitmentStoreReader + } + return &readBackend{ + commitmentReader: options.CommitmentStoreReader, + indexReader: indexReader, + } +} + +type backend struct { + commitmentStore kv.Store + indexStore kv.Store + hooks Hooks +} + +func (backend) private() {} + +func (c backend) CommitmentStoreReader() kv.ReadonlyStore { + return c.commitmentStore +} + +func (c backend) IndexStoreReader() kv.ReadonlyStore { + return c.indexStore +} + +func (c backend) CommitmentStore() kv.Store { + return c.commitmentStore +} + +func (c backend) IndexStore() kv.Store { + return c.indexStore +} + +func (c backend) Hooks() Hooks { + return c.hooks +} + +// BackendOptions defines options for creating a Backend. +// Context can optionally define two stores - a commitment store +// that is backed by a merkle tree and an index store that isn't. +// If the index store is not defined, the commitment store will be +// used for all operations. +type BackendOptions struct { + + // CommitmentStore is the commitment store. + CommitmentStore kv.Store + + // IndexStore is the optional index store. + // If it is nil the CommitmentStore will be used. + IndexStore kv.Store + + // Hooks are optional hooks into ORM insert, update and delete operations. + Hooks Hooks +} + +// NewBackend creates a new Backend. +func NewBackend(options BackendOptions) Backend { + indexStore := options.IndexStore + if indexStore == nil { + indexStore = options.CommitmentStore + } + return &backend{ + commitmentStore: options.CommitmentStore, + indexStore: indexStore, + hooks: options.Hooks, + } +} + +// WrapContextDefault performs the default wrapping of a backend in a context. +// This should be used primarily for testing purposes and production code +// should use some other framework specific wrapping (for instance using +// "store keys"). +func WrapContextDefault(backend ReadBackend) context.Context { + return context.WithValue(context.Background(), defaultContextKey, backend) +} + +type contextKeyType string + +var defaultContextKey = contextKeyType("backend") + +func getBackendDefault(ctx context.Context) (Backend, error) { + return ctx.Value(defaultContextKey).(Backend), nil +} + +func getReadBackendDefault(ctx context.Context) (ReadBackend, error) { + return ctx.Value(defaultContextKey).(ReadBackend), nil +} diff --git a/orm/model/ormtable/batch.go b/orm/model/ormtable/batch.go new file mode 100644 index 000000000..62653fa7e --- /dev/null +++ b/orm/model/ormtable/batch.go @@ -0,0 +1,96 @@ +package ormtable + +import "github.com/cosmos/cosmos-sdk/orm/model/kv" + +type batchIndexCommitmentWriter struct { + Backend + commitmentWriter *batchStoreWriter + indexWriter *batchStoreWriter +} + +func newBatchIndexCommitmentWriter(store Backend) *batchIndexCommitmentWriter { + return &batchIndexCommitmentWriter{ + Backend: store, + // optimal array capacities are estimated here: + commitmentWriter: &batchStoreWriter{ + ReadonlyStore: store.CommitmentStoreReader(), + writes: make([]batchWriterEntry, 0, 2), + }, + indexWriter: &batchStoreWriter{ + ReadonlyStore: store.IndexStoreReader(), + writes: make([]batchWriterEntry, 0, 16), + }, + } +} + +func (w *batchIndexCommitmentWriter) CommitmentStore() kv.Store { + return w.commitmentWriter +} + +func (w *batchIndexCommitmentWriter) IndexStore() kv.Store { + return w.indexWriter +} + +// Write flushes any pending writes. +func (w *batchIndexCommitmentWriter) Write() error { + err := flushWrites(w.Backend.CommitmentStore(), w.commitmentWriter.writes) + if err != nil { + return err + } + + err = flushWrites(w.Backend.IndexStore(), w.indexWriter.writes) + if err != nil { + return err + } + + // clear writes + w.Close() + + return err +} + +func flushWrites(writer kv.Store, writes []batchWriterEntry) error { + for _, write := range writes { + if !write.delete { + err := writer.Set(write.key, write.value) + if err != nil { + return err + } + } else { + err := writer.Delete(write.key) + if err != nil { + return err + } + } + } + return nil +} + +// Close discards any pending writes and should generally be called using +// a defer statement. +func (w *batchIndexCommitmentWriter) Close() { + w.commitmentWriter.writes = nil + w.indexWriter.writes = nil +} + +type batchWriterEntry struct { + key, value []byte + delete bool +} + +type batchStoreWriter struct { + kv.ReadonlyStore + writes []batchWriterEntry +} + +func (b *batchStoreWriter) Set(key, value []byte) error { + b.writes = append(b.writes, batchWriterEntry{key: key, value: value}) + return nil +} + +func (b *batchStoreWriter) Delete(key []byte) error { + b.writes = append(b.writes, batchWriterEntry{key: key, delete: true}) + return nil +} + +var _ Backend = &batchIndexCommitmentWriter{} diff --git a/orm/model/ormtable/build.go b/orm/model/ormtable/build.go new file mode 100644 index 000000000..d9c9dac3c --- /dev/null +++ b/orm/model/ormtable/build.go @@ -0,0 +1,296 @@ +package ormtable + +import ( + "context" + "fmt" + + "github.com/cosmos/cosmos-sdk/orm/encoding/encodeutil" + + "google.golang.org/protobuf/reflect/protoregistry" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + + ormv1alpha1 "github.com/cosmos/cosmos-sdk/api/cosmos/orm/v1alpha1" + "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" + "github.com/cosmos/cosmos-sdk/orm/types/ormerrors" +) + +const ( + primaryKeyId uint32 = 0 + indexIdLimit uint32 = 32768 + seqId = indexIdLimit +) + +// Options are options for building a Table. +type Options struct { + // Prefix is an optional prefix used to build the table's prefix. + Prefix []byte + + // MessageType is the protobuf message type of the table. + MessageType protoreflect.MessageType + + // TableDescriptor is an optional table descriptor to be explicitly used + // with the table. Generally this should be nil and the table descriptor + // should be pulled from the table message option. TableDescriptor + // cannot be used together with SingletonDescriptor. + TableDescriptor *ormv1alpha1.TableDescriptor + + // SingletonDescriptor is an optional singleton descriptor to be explicitly used. + // Generally this should be nil and the table descriptor + // should be pulled from the singleton message option. SingletonDescriptor + // cannot be used together with TableDescriptor. + SingletonDescriptor *ormv1alpha1.SingletonDescriptor + + // TypeResolver is an optional type resolver to be used when unmarshaling + // protobuf messages. + TypeResolver TypeResolver + + // JSONValidator is an optional validator that can be used for validating + // messaging when using ValidateJSON. If it is nil, DefaultJSONValidator + // will be used + JSONValidator func(proto.Message) error + + // GetBackend is an optional function which retrieves a Backend from the context. + // If it is nil, the default behavior will be to attempt to retrieve a + // backend using the method that WrapContextDefault uses. This method + // can be used to imlement things like "store keys" which would allow a + // table to only be used with a specific backend and to hide direct + // access to the backend other than through the table interface. + GetBackend func(context.Context) (Backend, error) + + // GetReadBackend is an optional function which retrieves a ReadBackend from the context. + // If it is nil, the default behavior will be to attempt to retrieve a + // backend using the method that WrapContextDefault uses. + GetReadBackend func(context.Context) (ReadBackend, error) +} + +// TypeResolver is an interface that can be used for the protoreflect.UnmarshalOptions.Resolver option. +type TypeResolver interface { + protoregistry.MessageTypeResolver + protoregistry.ExtensionTypeResolver +} + +// Build builds a Table instance from the provided Options. +func Build(options Options) (Table, error) { + messageDescriptor := options.MessageType.Descriptor() + + getReadBackend := options.GetReadBackend + if getReadBackend == nil { + getReadBackend = getReadBackendDefault + } + getBackend := options.GetBackend + if getBackend == nil { + getBackend = getBackendDefault + } + + table := &tableImpl{ + primaryKeyIndex: &primaryKeyIndex{ + indexers: []indexer{}, + getBackend: getBackend, + getReadBackend: getReadBackend, + }, + indexes: []Index{}, + indexesByFields: map[fieldNames]concreteIndex{}, + uniqueIndexesByFields: map[fieldNames]UniqueIndex{}, + entryCodecsById: map[uint32]ormkv.EntryCodec{}, + typeResolver: options.TypeResolver, + customJSONValidator: options.JSONValidator, + } + + pkIndex := table.primaryKeyIndex + + tableDesc := options.TableDescriptor + if tableDesc == nil { + tableDesc = proto.GetExtension(messageDescriptor.Options(), ormv1alpha1.E_Table).(*ormv1alpha1.TableDescriptor) + } + + singletonDesc := options.SingletonDescriptor + if singletonDesc == nil { + singletonDesc = proto.GetExtension(messageDescriptor.Options(), ormv1alpha1.E_Singleton).(*ormv1alpha1.SingletonDescriptor) + } + + switch { + case tableDesc != nil: + if singletonDesc != nil { + return nil, ormerrors.InvalidTableDefinition.Wrapf("message %s cannot be declared as both a table and a singleton", messageDescriptor.FullName()) + } + case singletonDesc != nil: + if singletonDesc.Id == 0 { + return nil, ormerrors.InvalidTableId.Wrapf("%s", messageDescriptor.FullName()) + } + + prefix := encodeutil.AppendVarUInt32(options.Prefix, singletonDesc.Id) + pkCodec, err := ormkv.NewPrimaryKeyCodec( + prefix, + options.MessageType, + nil, + proto.UnmarshalOptions{Resolver: options.TypeResolver}, + ) + if err != nil { + return nil, err + } + + pkIndex.PrimaryKeyCodec = pkCodec + table.tablePrefix = prefix + table.tableId = singletonDesc.Id + + return &singleton{table}, nil + default: + return nil, ormerrors.InvalidTableDefinition.Wrapf("missing table descriptor for %s", messageDescriptor.FullName()) + } + + tableId := tableDesc.Id + if tableId == 0 { + return nil, ormerrors.InvalidTableId.Wrapf("table %s", messageDescriptor.FullName()) + } + + prefix := options.Prefix + prefix = encodeutil.AppendVarUInt32(prefix, tableId) + table.tablePrefix = prefix + table.tableId = tableId + + if tableDesc.PrimaryKey == nil { + return nil, ormerrors.MissingPrimaryKey.Wrap(string(messageDescriptor.FullName())) + } + + pkFields := commaSeparatedFieldNames(tableDesc.PrimaryKey.Fields) + table.primaryKeyIndex.fields = pkFields + pkFieldNames := pkFields.Names() + if len(pkFieldNames) == 0 { + return nil, ormerrors.InvalidTableDefinition.Wrapf("empty primary key fields for %s", messageDescriptor.FullName()) + } + + pkPrefix := encodeutil.AppendVarUInt32(prefix, primaryKeyId) + pkCodec, err := ormkv.NewPrimaryKeyCodec( + pkPrefix, + options.MessageType, + pkFieldNames, + proto.UnmarshalOptions{Resolver: options.TypeResolver}, + ) + if err != nil { + return nil, err + } + + pkIndex.PrimaryKeyCodec = pkCodec + table.indexesByFields[pkFields] = pkIndex + table.uniqueIndexesByFields[pkFields] = pkIndex + table.entryCodecsById[primaryKeyId] = pkIndex + table.indexes = append(table.indexes, pkIndex) + + for _, idxDesc := range tableDesc.Index { + id := idxDesc.Id + if id == 0 || id >= indexIdLimit { + return nil, ormerrors.InvalidIndexId.Wrapf("index on table %s with fields %s, invalid id %d", messageDescriptor.FullName(), idxDesc.Fields, id) + } + + if _, ok := table.entryCodecsById[id]; ok { + return nil, ormerrors.DuplicateIndexId.Wrapf("id %d on table %s", id, messageDescriptor.FullName()) + } + + idxFields := commaSeparatedFieldNames(idxDesc.Fields) + idxPrefix := encodeutil.AppendVarUInt32(prefix, id) + var index concreteIndex + + // altNames contains all the alternative "names" of this index + altNames := map[fieldNames]bool{idxFields: true} + + if idxDesc.Unique && isNonTrivialUniqueKey(idxFields.Names(), pkFieldNames) { + uniqCdc, err := ormkv.NewUniqueKeyCodec( + idxPrefix, + options.MessageType, + idxFields.Names(), + pkFieldNames, + ) + if err != nil { + return nil, err + } + uniqIdx := &uniqueKeyIndex{ + UniqueKeyCodec: uniqCdc, + fields: idxFields, + primaryKey: pkIndex, + getReadBackend: getReadBackend, + } + table.uniqueIndexesByFields[idxFields] = uniqIdx + index = uniqIdx + } else { + idxCdc, err := ormkv.NewIndexKeyCodec( + idxPrefix, + options.MessageType, + idxFields.Names(), + pkFieldNames, + ) + if err != nil { + return nil, err + } + index = &indexKeyIndex{ + IndexKeyCodec: idxCdc, + fields: idxFields, + primaryKey: pkIndex, + getReadBackend: getReadBackend, + } + + // non-unique indexes can sometimes be named by several sub-lists of + // fields and we need to handle all of them. For example consider, + // a primary key for fields "a,b,c" and an index on field "c". Because the + // rest of the primary key gets appended to the index key, the index for "c" + // is actually stored as "c,a,b". So this index can be referred to + // by the fields "c", "c,a", or "c,a,b". + allFields := index.GetFieldNames() + allFieldNames := fieldsFromNames(allFields) + altNames[allFieldNames] = true + for i := 1; i < len(allFields); i++ { + altName := fieldsFromNames(allFields[:i]) + if altNames[altName] { + continue + } + + // we check by generating a codec for each sub-list of fields, + // then we see if the full list of fields matches. + altIdxCdc, err := ormkv.NewIndexKeyCodec( + idxPrefix, + options.MessageType, + allFields[:i], + pkFieldNames, + ) + if err != nil { + return nil, err + } + + if fieldsFromNames(altIdxCdc.GetFieldNames()) == allFieldNames { + altNames[altName] = true + } + } + } + + for name := range altNames { + if _, ok := table.indexesByFields[name]; ok { + return nil, fmt.Errorf("duplicate index for fields %s", name) + } + + table.indexesByFields[name] = index + } + + table.entryCodecsById[id] = index + table.indexes = append(table.indexes, index) + table.indexers = append(table.indexers, index.(indexer)) + } + + if tableDesc.PrimaryKey.AutoIncrement { + autoIncField := pkCodec.GetFieldDescriptors()[0] + if len(pkFieldNames) != 1 && autoIncField.Kind() != protoreflect.Uint64Kind { + return nil, ormerrors.InvalidAutoIncrementKey.Wrapf("field %s", autoIncField.FullName()) + } + + seqPrefix := encodeutil.AppendVarUInt32(prefix, seqId) + seqCodec := ormkv.NewSeqCodec(options.MessageType, seqPrefix) + table.entryCodecsById[seqId] = seqCodec + return &autoIncrementTable{ + tableImpl: table, + autoIncField: autoIncField, + seqCodec: seqCodec, + }, nil + } + + return table, nil +} diff --git a/orm/model/ormtable/doc.go b/orm/model/ormtable/doc.go new file mode 100644 index 000000000..4421dd69a --- /dev/null +++ b/orm/model/ormtable/doc.go @@ -0,0 +1,3 @@ +// Package ormtable defines the interfaces and implementations of tables and +// indexes. +package ormtable diff --git a/orm/model/ormtable/field_names.go b/orm/model/ormtable/field_names.go new file mode 100644 index 000000000..a90edab60 --- /dev/null +++ b/orm/model/ormtable/field_names.go @@ -0,0 +1,55 @@ +package ormtable + +import ( + "strings" + + "google.golang.org/protobuf/reflect/protoreflect" +) + +// fieldNames abstractly represents a list of fields with a comparable type which +// can be used as a map key. It is used primarily to lookup indexes. +type fieldNames struct { + fields string +} + +// commaSeparatedFieldNames creates a fieldNames instance from a list of comma-separated +// fields. +func commaSeparatedFieldNames(fields string) fieldNames { + // normalize cases where there are spaces + if strings.IndexByte(fields, ' ') >= 0 { + parts := strings.Split(fields, ",") + for i, part := range parts { + parts[i] = strings.TrimSpace(part) + } + fields = strings.Join(parts, ",") + } + return fieldNames{fields: fields} +} + +// fieldsFromNames creates a fieldNames instance from an array of field +// names. +func fieldsFromNames(fnames []protoreflect.Name) fieldNames { + var names []string + for _, name := range fnames { + names = append(names, string(name)) + } + return fieldNames{fields: strings.Join(names, ",")} +} + +// Names returns the array of names this fieldNames instance represents. +func (f fieldNames) Names() []protoreflect.Name { + if f.fields == "" { + return nil + } + + fields := strings.Split(f.fields, ",") + names := make([]protoreflect.Name, len(fields)) + for i, field := range fields { + names[i] = protoreflect.Name(field) + } + return names +} + +func (f fieldNames) String() string { + return f.fields +} diff --git a/orm/model/ormtable/field_names_test.go b/orm/model/ormtable/field_names_test.go new file mode 100644 index 000000000..ae7dd9024 --- /dev/null +++ b/orm/model/ormtable/field_names_test.go @@ -0,0 +1,43 @@ +package ormtable + +import ( + "testing" + + "google.golang.org/protobuf/reflect/protoreflect" + + "gotest.tools/v3/assert" +) + +func TestFieldNames(t *testing.T) { + names := []protoreflect.Name{"a", "b", "c"} + + abc := "a,b,c" + f := commaSeparatedFieldNames(abc) + assert.Equal(t, fieldNames{abc}, f) + assert.DeepEqual(t, names, f.Names()) + assert.Equal(t, abc, f.String()) + + f = commaSeparatedFieldNames("a, b ,c") + assert.Equal(t, fieldNames{abc}, f) + assert.DeepEqual(t, names, f.Names()) + assert.Equal(t, abc, f.String()) + + // empty okay + f = commaSeparatedFieldNames("") + assert.Equal(t, fieldNames{""}, f) + assert.Equal(t, 0, len(f.Names())) + assert.Equal(t, "", f.String()) + + f = fieldsFromNames(names) + assert.Equal(t, fieldNames{abc}, f) + assert.DeepEqual(t, names, f.Names()) + assert.Equal(t, abc, f.String()) + + // empty okay + f = fieldsFromNames([]protoreflect.Name{}) + assert.Equal(t, fieldNames{""}, f) + f = fieldsFromNames(nil) + assert.Equal(t, fieldNames{""}, f) + assert.Equal(t, 0, len(f.Names())) + assert.Equal(t, "", f.String()) +} diff --git a/orm/model/ormtable/hooks.go b/orm/model/ormtable/hooks.go new file mode 100644 index 000000000..93881bf37 --- /dev/null +++ b/orm/model/ormtable/hooks.go @@ -0,0 +1,21 @@ +package ormtable + +import "google.golang.org/protobuf/proto" + +// Hooks defines an interface for a table hooks which can intercept +// insert, update and delete operations. Table.Save and Table.Delete methods will +// do a type assertion on kvstore.IndexCommitmentStore and if the Hooks +// interface is defined call the appropriate hooks. +type Hooks interface { + // OnInsert is called before the message is inserted. + // If error is not nil the operation will fail. + OnInsert(proto.Message) error + + // OnUpdate is called before the existing message is updated with the new one. + // If error is not nil the operation will fail. + OnUpdate(existing, new proto.Message) error + + // OnDelete is called before the message is deleted. + // If error is not nil the operation will fail. + OnDelete(proto.Message) error +} diff --git a/orm/model/ormtable/index.go b/orm/model/ormtable/index.go new file mode 100644 index 000000000..a85960652 --- /dev/null +++ b/orm/model/ormtable/index.go @@ -0,0 +1,57 @@ +package ormtable + +import ( + "context" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + + "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" + "github.com/cosmos/cosmos-sdk/orm/model/kv" + "github.com/cosmos/cosmos-sdk/orm/model/ormlist" +) + +// Index defines an index on a table. Index instances +// are stateless, with all state existing only in the store passed +// to index methods. +type Index interface { + + // Iterator returns an iterator for this index with the provided list options. + Iterator(ctx context.Context, options ...ormlist.Option) (Iterator, error) + + // MessageType returns the protobuf message type of the index. + MessageType() protoreflect.MessageType + + // Fields returns the canonical field names of the index. + Fields() string + + doNotImplement() +} + +// concreteIndex is used internally by table implementations. +type concreteIndex interface { + Index + ormkv.IndexCodec + + readValueFromIndexKey(context ReadBackend, primaryKey []protoreflect.Value, value []byte, message proto.Message) error +} + +// UniqueIndex defines an unique index on a table. +type UniqueIndex interface { + Index + + // Has returns true if the key values are present in the store for this index. + Has(context context.Context, keyValues ...interface{}) (found bool, err error) + + // Get retrieves the message if one exists for the provided key values. + Get(context context.Context, message proto.Message, keyValues ...interface{}) (found bool, err error) + + // DeleteByKey deletes the message if one exists in for the provided key values. + DeleteByKey(context context.Context, keyValues ...interface{}) error +} + +type indexer interface { + onInsert(store kv.Store, message protoreflect.Message) error + onUpdate(store kv.Store, new, existing protoreflect.Message) error + onDelete(store kv.Store, message protoreflect.Message) error +} diff --git a/orm/model/ormtable/index_impl.go b/orm/model/ormtable/index_impl.go new file mode 100644 index 000000000..7fa8283b3 --- /dev/null +++ b/orm/model/ormtable/index_impl.go @@ -0,0 +1,93 @@ +package ormtable + +import ( + "context" + + "github.com/cosmos/cosmos-sdk/orm/model/kv" + "github.com/cosmos/cosmos-sdk/orm/model/ormlist" + + "github.com/cosmos/cosmos-sdk/orm/types/ormerrors" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + + "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" +) + +// indexKeyIndex implements Index for a regular IndexKey. +type indexKeyIndex struct { + *ormkv.IndexKeyCodec + fields fieldNames + primaryKey *primaryKeyIndex + getReadBackend func(context.Context) (ReadBackend, error) +} + +func (i indexKeyIndex) Iterator(ctx context.Context, options ...ormlist.Option) (Iterator, error) { + backend, err := i.getReadBackend(ctx) + if err != nil { + return nil, err + } + + return iterator(backend, backend.IndexStoreReader(), i, i.KeyCodec, options) +} + +var _ indexer = &indexKeyIndex{} +var _ Index = &indexKeyIndex{} + +func (i indexKeyIndex) doNotImplement() {} + +func (i indexKeyIndex) onInsert(store kv.Store, message protoreflect.Message) error { + k, v, err := i.EncodeKVFromMessage(message) + if err != nil { + return err + } + return store.Set(k, v) +} + +func (i indexKeyIndex) onUpdate(store kv.Store, new, existing protoreflect.Message) error { + newValues := i.GetKeyValues(new) + existingValues := i.GetKeyValues(existing) + if i.CompareKeys(newValues, existingValues) == 0 { + return nil + } + + existingKey, err := i.EncodeKey(existingValues) + if err != nil { + return err + } + err = store.Delete(existingKey) + if err != nil { + return err + } + + newKey, err := i.EncodeKey(newValues) + if err != nil { + return err + } + return store.Set(newKey, []byte{}) +} + +func (i indexKeyIndex) onDelete(store kv.Store, message protoreflect.Message) error { + _, key, err := i.EncodeKeyFromMessage(message) + if err != nil { + return err + } + return store.Delete(key) +} + +func (i indexKeyIndex) readValueFromIndexKey(backend ReadBackend, primaryKey []protoreflect.Value, _ []byte, message proto.Message) error { + found, err := i.primaryKey.get(backend, message, primaryKey) + if err != nil { + return err + } + + if !found { + return ormerrors.UnexpectedError.Wrapf("can't find primary key") + } + + return nil +} + +func (p indexKeyIndex) Fields() string { + return p.fields.String() +} diff --git a/orm/model/ormtable/iterator.go b/orm/model/ormtable/iterator.go new file mode 100644 index 000000000..cefbc2276 --- /dev/null +++ b/orm/model/ormtable/iterator.go @@ -0,0 +1,239 @@ +package ormtable + +import ( + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + + "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" + "github.com/cosmos/cosmos-sdk/orm/internal/listinternal" + "github.com/cosmos/cosmos-sdk/orm/model/kv" + "github.com/cosmos/cosmos-sdk/orm/model/ormlist" +) + +// Iterator defines the interface for iterating over indexes. +type Iterator interface { + + // Next advances the iterator and returns true if a valid entry is found. + // Next must be called before starting iteration. + Next() bool + + // Keys returns the current index key and primary key values that the + // iterator points to. + Keys() (indexKey, primaryKey []protoreflect.Value, err error) + + // UnmarshalMessage unmarshals the entry the iterator currently points to + // the provided proto.Message. + UnmarshalMessage(proto.Message) error + + // GetMessage retrieves the proto.Message that the iterator currently points + // to. + GetMessage() (proto.Message, error) + + // Cursor returns the cursor referencing the current iteration position + // and can be used to restart iteration right after this position. + Cursor() ormlist.CursorT + + // Close closes the iterator and must always be called when done using + // the iterator. The defer keyword should generally be used for this. + Close() + + doNotImplement() +} + +func iterator( + backend ReadBackend, + reader kv.ReadonlyStore, + index concreteIndex, + codec *ormkv.KeyCodec, + options []listinternal.Option, +) (Iterator, error) { + opts := &listinternal.Options{} + listinternal.ApplyOptions(opts, options) + if err := opts.Validate(); err != nil { + return nil, err + } + + if opts.Start != nil || opts.End != nil { + err := codec.CheckValidRangeIterationKeys(opts.Start, opts.End) + if err != nil { + return nil, err + } + + startBz, err := codec.EncodeKey(opts.Start) + if err != nil { + return nil, err + } + + endBz, err := codec.EncodeKey(opts.End) + if err != nil { + return nil, err + } + + fullEndKey := len(codec.GetFieldNames()) == len(opts.End) + + return rangeIterator(reader, backend, index, startBz, endBz, fullEndKey, opts) + } else { + prefixBz, err := codec.EncodeKey(opts.Prefix) + if err != nil { + return nil, err + } + + return prefixIterator(reader, backend, index, prefixBz, opts) + } +} + +func prefixIterator(iteratorStore kv.ReadonlyStore, backend ReadBackend, index concreteIndex, prefix []byte, options *listinternal.Options) (Iterator, error) { + if !options.Reverse { + var start []byte + if len(options.Cursor) != 0 { + // must start right after cursor + start = append(options.Cursor, 0x0) + } else { + start = prefix + } + end := prefixEndBytes(prefix) + it, err := iteratorStore.Iterator(start, end) + if err != nil { + return nil, err + } + return &indexIterator{ + index: index, + store: backend, + iterator: it, + started: false, + }, nil + } else { + var end []byte + if len(options.Cursor) != 0 { + // end bytes is already exclusive by default + end = options.Cursor + } else { + end = prefixEndBytes(prefix) + } + it, err := iteratorStore.ReverseIterator(prefix, end) + if err != nil { + return nil, err + } + + return &indexIterator{ + index: index, + store: backend, + iterator: it, + started: false, + }, nil + } +} + +// NOTE: fullEndKey indicates whether the end key contained all the fields of the key, +// if it did then we need to use inclusive end bytes, otherwise we prefix the end bytes +func rangeIterator(iteratorStore kv.ReadonlyStore, reader ReadBackend, index concreteIndex, start, end []byte, fullEndKey bool, options *listinternal.Options) (Iterator, error) { + if !options.Reverse { + if len(options.Cursor) != 0 { + start = append(options.Cursor, 0) + } + + if fullEndKey { + end = inclusiveEndBytes(end) + } else { + end = prefixEndBytes(end) + } + + it, err := iteratorStore.Iterator(start, end) + if err != nil { + return nil, err + } + return &indexIterator{ + index: index, + store: reader, + iterator: it, + started: false, + }, nil + } else { + if len(options.Cursor) != 0 { + end = options.Cursor + } else { + if fullEndKey { + end = inclusiveEndBytes(end) + } else { + end = prefixEndBytes(end) + } + } + it, err := iteratorStore.ReverseIterator(start, end) + if err != nil { + return nil, err + } + + return &indexIterator{ + index: index, + store: reader, + iterator: it, + started: false, + }, nil + } +} + +type indexIterator struct { + index concreteIndex + store ReadBackend + iterator kv.Iterator + + indexValues []protoreflect.Value + primaryKey []protoreflect.Value + value []byte + started bool +} + +func (i *indexIterator) Next() bool { + if !i.started { + i.started = true + } else { + i.iterator.Next() + } + + return i.iterator.Valid() +} + +func (i *indexIterator) Keys() (indexKey, primaryKey []protoreflect.Value, err error) { + if i.indexValues != nil { + return i.indexValues, i.primaryKey, nil + } + + i.value = i.iterator.Value() + i.indexValues, i.primaryKey, err = i.index.DecodeIndexKey(i.iterator.Key(), i.value) + if err != nil { + return nil, nil, err + } + + return i.indexValues, i.primaryKey, nil +} + +func (i indexIterator) UnmarshalMessage(message proto.Message) error { + _, pk, err := i.Keys() + if err != nil { + return err + } + return i.index.readValueFromIndexKey(i.store, pk, i.value, message) +} + +func (i *indexIterator) GetMessage() (proto.Message, error) { + msg := i.index.MessageType().New().Interface() + err := i.UnmarshalMessage(msg) + return msg, err +} + +func (i indexIterator) Cursor() ormlist.CursorT { + return i.iterator.Key() +} + +func (i indexIterator) Close() { + err := i.iterator.Close() + if err != nil { + panic(err) + } +} + +func (indexIterator) doNotImplement() { + +} + +var _ Iterator = &indexIterator{} diff --git a/orm/model/ormtable/paginate.go b/orm/model/ormtable/paginate.go new file mode 100644 index 000000000..d3e29d2d2 --- /dev/null +++ b/orm/model/ormtable/paginate.go @@ -0,0 +1,124 @@ +package ormtable + +import ( + "context" + "fmt" + + "google.golang.org/protobuf/proto" + + queryv1beta1 "github.com/cosmos/cosmos-sdk/api/cosmos/base/query/v1beta1" + "github.com/cosmos/cosmos-sdk/orm/model/ormlist" +) + +// PaginationRequest is a request to the Paginate function and extends the +// options in query.PageRequest. +type PaginationRequest struct { + *queryv1beta1.PageRequest + + // Filter is an optional filter function that can be used to filter + // the results in the underlying iterator and should return true to include + // an item in the result. + Filter func(message proto.Message) bool +} + +// PaginationResponse is a response from the Paginate function and extends the +// options in query.PageResponse. +type PaginationResponse struct { + *queryv1beta1.PageResponse + + // HaveMore indicates whether there are more pages. + HaveMore bool + + // Cursors returns a cursor for each item and can be used to implement + // GraphQL connection edges. + Cursors []ormlist.CursorT +} + +// Paginate retrieves a "page" of data from the provided index and context. +func Paginate( + index Index, + ctx context.Context, + request *PaginationRequest, + onItem func(proto.Message), + options ...ormlist.Option, +) (*PaginationResponse, error) { + offset := int(request.Offset) + if len(request.Key) != 0 { + if offset > 0 { + return nil, fmt.Errorf("can only specify one of cursor or offset") + } + + options = append(options, ormlist.Cursor(request.Key)) + } + + if request.Reverse { + options = append(options, ormlist.Reverse()) + } + + it, err := index.Iterator(ctx, options...) + if err != nil { + return nil, err + } + defer it.Close() + + limit := int(request.Limit) + if limit == 0 { + return nil, fmt.Errorf("limit not specified") + } + + i := 0 + if offset != 0 { + for ; i < offset; i++ { + if !it.Next() { + return &PaginationResponse{ + PageResponse: &queryv1beta1.PageResponse{Total: uint64(i)}, + }, nil + } + } + } + + haveMore := false + cursors := make([]ormlist.CursorT, 0, limit) + done := limit + offset + for it.Next() { + if i == done { + haveMore = true + if request.CountTotal { + for { + i++ + if !it.Next() { + break + } + } + } + break + } + + message, err := it.GetMessage() + if err != nil { + return nil, err + } + + if request.Filter != nil && !request.Filter(message) { + continue + } + + i++ + cursors = append(cursors, it.Cursor()) + onItem(message) + } + + pageRes := &queryv1beta1.PageResponse{} + if request.CountTotal { + pageRes.Total = uint64(i) + } + n := len(cursors) + if n != 0 { + pageRes.NextKey = cursors[n-1] + } + return &PaginationResponse{ + PageResponse: pageRes, + HaveMore: haveMore, + Cursors: cursors, + }, nil +} diff --git a/orm/model/ormtable/primary_key.go b/orm/model/ormtable/primary_key.go new file mode 100644 index 000000000..2150f19e7 --- /dev/null +++ b/orm/model/ormtable/primary_key.go @@ -0,0 +1,142 @@ +package ormtable + +import ( + "context" + + "github.com/cosmos/cosmos-sdk/orm/model/ormlist" + + "github.com/cosmos/cosmos-sdk/orm/encoding/encodeutil" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + + "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" +) + +// primaryKeyIndex defines an UniqueIndex for the primary key. +type primaryKeyIndex struct { + *ormkv.PrimaryKeyCodec + fields fieldNames + indexers []indexer + getBackend func(context.Context) (Backend, error) + getReadBackend func(context.Context) (ReadBackend, error) +} + +func (p primaryKeyIndex) Iterator(ctx context.Context, options ...ormlist.Option) (Iterator, error) { + backend, err := p.getReadBackend(ctx) + if err != nil { + return nil, err + } + + return iterator(backend, backend.CommitmentStoreReader(), p, p.KeyCodec, options) +} + +func (p primaryKeyIndex) doNotImplement() {} + +func (p primaryKeyIndex) Has(context context.Context, key ...interface{}) (found bool, err error) { + ctx, err := p.getReadBackend(context) + if err != nil { + return false, err + } + + keyBz, err := p.EncodeKey(encodeutil.ValuesOf(key...)) + if err != nil { + return false, err + } + + return ctx.CommitmentStoreReader().Has(keyBz) +} + +func (p primaryKeyIndex) Get(ctx context.Context, message proto.Message, values ...interface{}) (found bool, err error) { + backend, err := p.getReadBackend(ctx) + if err != nil { + return false, err + } + + return p.get(backend, message, encodeutil.ValuesOf(values...)) +} + +func (t primaryKeyIndex) DeleteByKey(ctx context.Context, primaryKeyValues ...interface{}) error { + return t.doDeleteByKey(ctx, encodeutil.ValuesOf(primaryKeyValues...)) +} + +func (t primaryKeyIndex) doDeleteByKey(ctx context.Context, primaryKeyValues []protoreflect.Value) error { + backend, err := t.getBackend(ctx) + if err != nil { + return err + } + + pk, err := t.EncodeKey(primaryKeyValues) + if err != nil { + return err + } + + msg := t.MessageType().New().Interface() + found, err := t.getByKeyBytes(backend, pk, primaryKeyValues, msg) + if err != nil { + return err + } + + if !found { + return nil + } + + if hooks := backend.Hooks(); hooks != nil { + err = hooks.OnDelete(msg) + if err != nil { + return err + } + } + + // delete object + writer := newBatchIndexCommitmentWriter(backend) + defer writer.Close() + err = writer.CommitmentStore().Delete(pk) + if err != nil { + return err + } + + // clear indexes + mref := msg.ProtoReflect() + indexStoreWriter := writer.IndexStore() + for _, idx := range t.indexers { + err := idx.onDelete(indexStoreWriter, mref) + if err != nil { + return err + } + } + + return writer.Write() +} + +func (p primaryKeyIndex) get(backend ReadBackend, message proto.Message, values []protoreflect.Value) (found bool, err error) { + key, err := p.EncodeKey(values) + if err != nil { + return false, err + } + + return p.getByKeyBytes(backend, key, values, message) +} + +func (p primaryKeyIndex) getByKeyBytes(store ReadBackend, key []byte, keyValues []protoreflect.Value, message proto.Message) (found bool, err error) { + bz, err := store.CommitmentStoreReader().Get(key) + if err != nil { + return false, err + } + + if bz == nil { + return false, nil + } + + return true, p.Unmarshal(keyValues, bz, message) +} + +func (p primaryKeyIndex) readValueFromIndexKey(_ ReadBackend, primaryKey []protoreflect.Value, value []byte, message proto.Message) error { + return p.Unmarshal(primaryKey, value, message) +} + +func (p primaryKeyIndex) Fields() string { + return p.fields.String() +} + +var _ UniqueIndex = &primaryKeyIndex{} diff --git a/orm/model/ormtable/singleton.go b/orm/model/ormtable/singleton.go new file mode 100644 index 000000000..c701ada20 --- /dev/null +++ b/orm/model/ormtable/singleton.go @@ -0,0 +1,93 @@ +package ormtable + +import ( + "context" + "encoding/json" + "io" + + "google.golang.org/protobuf/encoding/protojson" +) + +// singleton implements a Table instance for singletons. +type singleton struct { + *tableImpl +} + +func (t singleton) DefaultJSON() json.RawMessage { + msg := t.MessageType().New().Interface() + bz, err := t.jsonMarshalOptions().Marshal(msg) + if err != nil { + return json.RawMessage("{}") + } + return bz +} + +func (t singleton) ValidateJSON(reader io.Reader) error { + bz, err := io.ReadAll(reader) + if err != nil { + return err + } + + msg := t.MessageType().New().Interface() + err = protojson.Unmarshal(bz, msg) + if err != nil { + return err + } + + if t.customJSONValidator != nil { + return t.customJSONValidator(msg) + } else { + return DefaultJSONValidator(msg) + } +} + +func (t singleton) ImportJSON(ctx context.Context, reader io.Reader) error { + backend, err := t.getBackend(ctx) + if err != nil { + return err + } + + bz, err := io.ReadAll(reader) + if err != nil { + return err + } + + msg := t.MessageType().New().Interface() + err = protojson.Unmarshal(bz, msg) + if err != nil { + return err + } + + return t.save(backend, msg, saveModeDefault) +} + +func (t singleton) ExportJSON(ctx context.Context, writer io.Writer) error { + msg := t.MessageType().New().Interface() + found, err := t.Get(ctx, msg) + if err != nil { + return err + } + + var bz []byte + if !found { + bz = t.DefaultJSON() + } else { + bz, err = t.jsonMarshalOptions().Marshal(msg) + if err != nil { + return err + } + } + + _, err = writer.Write(bz) + return err +} + +func (t singleton) jsonMarshalOptions() protojson.MarshalOptions { + return protojson.MarshalOptions{ + Multiline: true, + Indent: "", + UseProtoNames: true, + EmitUnpopulated: true, + Resolver: t.typeResolver, + } +} diff --git a/orm/model/ormtable/singleton_test.go b/orm/model/ormtable/singleton_test.go new file mode 100644 index 000000000..3de20d729 --- /dev/null +++ b/orm/model/ormtable/singleton_test.go @@ -0,0 +1,52 @@ +package ormtable_test + +import ( + "bytes" + "testing" + + "github.com/cosmos/cosmos-sdk/orm/model/ormtable" + + "google.golang.org/protobuf/testing/protocmp" + + "gotest.tools/v3/assert" + + "github.com/cosmos/cosmos-sdk/orm/internal/testkv" + "github.com/cosmos/cosmos-sdk/orm/internal/testpb" +) + +func TestSingleton(t *testing.T) { + val := &testpb.ExampleSingleton{} + singleton, err := ormtable.Build(ormtable.Options{ + MessageType: val.ProtoReflect().Type(), + }) + assert.NilError(t, err) + store := ormtable.WrapContextDefault(testkv.NewSplitMemBackend()) + + found, err := singleton.Has(store) + assert.NilError(t, err) + assert.Assert(t, !found) + assert.NilError(t, singleton.Save(store, val)) + found, err = singleton.Has(store) + assert.NilError(t, err) + assert.Assert(t, found) + + val.Foo = "abc" + val.Bar = 3 + assert.NilError(t, singleton.Save(store, val)) + + var val2 testpb.ExampleSingleton + found, err = singleton.Get(store, &val2) + assert.NilError(t, err) + assert.DeepEqual(t, val, &val2, protocmp.Transform()) + + buf := &bytes.Buffer{} + assert.NilError(t, singleton.ExportJSON(store, buf)) + assert.NilError(t, singleton.ValidateJSON(bytes.NewReader(buf.Bytes()))) + store2 := ormtable.WrapContextDefault(testkv.NewSplitMemBackend()) + assert.NilError(t, singleton.ImportJSON(store2, bytes.NewReader(buf.Bytes()))) + + var val3 testpb.ExampleSingleton + found, err = singleton.Get(store, &val3) + assert.NilError(t, err) + assert.DeepEqual(t, val, &val3, protocmp.Transform()) +} diff --git a/orm/model/ormtable/table.go b/orm/model/ormtable/table.go new file mode 100644 index 000000000..c48c7e18c --- /dev/null +++ b/orm/model/ormtable/table.go @@ -0,0 +1,113 @@ +package ormtable + +import ( + "context" + "encoding/json" + "io" + + "google.golang.org/protobuf/proto" + + "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" +) + +// View defines a read-only table. +// +// It exists as a separate interacted to support future scenarios where +// tables may be "supported" virtually to provide compatibility between +// systems, for instance to enable backwards compatibility when a major +// migration needs to be performed. +type View interface { + UniqueIndex + + // GetIndex returns the index referenced by the provided fields if + // one exists or nil. Note that some concrete indexes can be retrieved by + // multiple lists of fields. + GetIndex(fields string) Index + + // GetUniqueIndex returns the unique index referenced by the provided fields if + // one exists or nil. Note that some concrete indexes can be retrieved by + // multiple lists of fields. + GetUniqueIndex(fields string) UniqueIndex + + // Indexes returns all the concrete indexes for the table. + Indexes() []Index +} + +// Table is an abstract interface around a concrete table. Table instances +// are stateless, with all state existing only in the store passed +// to table and index methods. +type Table interface { + View + + ormkv.EntryCodec + + // Save saves the provided entry in the store either inserting it or + // updating it if needed. + // + // If store implement the Hooks interface, the appropriate OnInsert or + // OnUpdate hook method will be called. + // + // Save attempts to be atomic with respect to the underlying store, + // meaning that either the full save operation is written or the store is + // left unchanged, unless there is an error with the underlying store. + Save(context context.Context, message proto.Message) error + + // Insert inserts the provided entry in the store and fails if there is + // an unique key violation. See Save for more details on behavior. + Insert(context context.Context, message proto.Message) error + + // Update updates the provided entry in the store and fails if an entry + // with a matching primary key does not exist. See Save for more details + // on behavior. + Update(context context.Context, message proto.Message) error + + // Delete deletes the entry with the provided primary key from the store. + // + // If store implement the Hooks interface, the OnDelete hook method will + // be called. + // + // Delete attempts to be atomic with respect to the underlying store, + // meaning that either the full save operation is written or the store is + // left unchanged, unless there is an error with the underlying store. + Delete(context context.Context, message proto.Message) error + + // DefaultJSON returns default JSON that can be used as a template for + // genesis files. + // + // For regular tables this an empty JSON array, but for singletons an + // empty instance of the singleton is marshaled. + DefaultJSON() json.RawMessage + + // ValidateJSON validates JSON streamed from the reader. + ValidateJSON(io.Reader) error + + // ImportJSON imports JSON into the store, streaming one entry at a time. + // Each table should be import from a separate JSON file to enable proper + // streaming. + // + // Regular tables should be stored as an array of objects with each object + // corresponding to a single record in the table. + // + // Auto-incrementing tables + // can optionally have the last sequence value as the first element in the + // array. If the last sequence value is provided, then each value of the + // primary key in the file must be <= this last sequence value or omitted + // entirely. If no last sequence value is provided, no entries should + // contain the primary key as this will be auto-assigned. + // + // Singletons should define a single object and not an array. + // + // ImportJSON is not atomic with respect to the underlying store, meaning + // that in the case of an error, some records may already have been + // imported. It is assumed that ImportJSON is called in the context of some + // larger transaction isolation. + ImportJSON(context.Context, io.Reader) error + + // ExportJSON exports JSON in the format accepted by ImportJSON. + // Auto-incrementing tables will export the last sequence number as the + // first element in the JSON array. + ExportJSON(context.Context, io.Writer) error + + // ID is the ID of this table within the schema of its FileDescriptor. + ID() uint32 +} diff --git a/orm/model/ormtable/table_impl.go b/orm/model/ormtable/table_impl.go new file mode 100644 index 000000000..92c607a7c --- /dev/null +++ b/orm/model/ormtable/table_impl.go @@ -0,0 +1,375 @@ +package ormtable + +import ( + "bytes" + "context" + "encoding/binary" + "encoding/json" + "io" + "math" + + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" + + "github.com/cosmos/cosmos-sdk/orm/encoding/encodeutil" + "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" + "github.com/cosmos/cosmos-sdk/orm/types/ormerrors" +) + +// tableImpl implements Table. +type tableImpl struct { + *primaryKeyIndex + indexes []Index + indexesByFields map[fieldNames]concreteIndex + uniqueIndexesByFields map[fieldNames]UniqueIndex + entryCodecsById map[uint32]ormkv.EntryCodec + tablePrefix []byte + tableId uint32 + typeResolver TypeResolver + customJSONValidator func(message proto.Message) error +} + +func (t tableImpl) Save(ctx context.Context, message proto.Message) error { + backend, err := t.getBackend(ctx) + if err != nil { + return err + } + + return t.save(backend, message, saveModeDefault) +} + +func (t tableImpl) Insert(ctx context.Context, message proto.Message) error { + backend, err := t.getBackend(ctx) + if err != nil { + return err + } + + return t.save(backend, message, saveModeInsert) +} + +func (t tableImpl) Update(ctx context.Context, message proto.Message) error { + backend, err := t.getBackend(ctx) + if err != nil { + return err + } + + return t.save(backend, message, saveModeUpdate) +} + +func (t tableImpl) save(backend Backend, message proto.Message, mode saveMode) error { + writer := newBatchIndexCommitmentWriter(backend) + defer writer.Close() + return t.doSave(writer, message, mode) +} + +func (t tableImpl) doSave(writer *batchIndexCommitmentWriter, message proto.Message, mode saveMode) error { + mref := message.ProtoReflect() + pkValues, pk, err := t.EncodeKeyFromMessage(mref) + if err != nil { + return err + } + + existing := mref.New().Interface() + haveExisting, err := t.getByKeyBytes(writer, pk, pkValues, existing) + if err != nil { + return err + } + + if haveExisting { + if mode == saveModeInsert { + return ormerrors.PrimaryKeyConstraintViolation.Wrapf("%q:%+v", mref.Descriptor().FullName(), pkValues) + } + + if hooks := writer.Hooks(); hooks != nil { + err = hooks.OnUpdate(existing, message) + if err != nil { + return err + } + } + } else { + if mode == saveModeUpdate { + return ormerrors.NotFoundOnUpdate.Wrapf("%q", mref.Descriptor().FullName()) + } + + if hooks := writer.Hooks(); hooks != nil { + err = hooks.OnInsert(message) + if err != nil { + return err + } + } + } + + // temporarily clear primary key + t.ClearValues(mref) + + // store object + bz, err := proto.MarshalOptions{Deterministic: true}.Marshal(message) + err = writer.CommitmentStore().Set(pk, bz) + if err != nil { + return err + } + + // set primary key again + t.SetKeyValues(mref, pkValues) + + // set indexes + indexStoreWriter := writer.IndexStore() + if !haveExisting { + for _, idx := range t.indexers { + err = idx.onInsert(indexStoreWriter, mref) + if err != nil { + return err + } + + } + } else { + existingMref := existing.ProtoReflect() + for _, idx := range t.indexers { + err = idx.onUpdate(indexStoreWriter, mref, existingMref) + if err != nil { + return err + } + } + } + + return writer.Write() +} + +func (t tableImpl) Delete(context context.Context, message proto.Message) error { + pk := t.PrimaryKeyCodec.GetKeyValues(message.ProtoReflect()) + return t.DeleteByKey(context, pk) +} + +func (t tableImpl) GetIndex(fields string) Index { + return t.indexesByFields[commaSeparatedFieldNames(fields)] +} + +func (t tableImpl) GetUniqueIndex(fields string) UniqueIndex { + return t.uniqueIndexesByFields[commaSeparatedFieldNames(fields)] +} + +func (t tableImpl) Indexes() []Index { + return t.indexes +} + +func (t tableImpl) DefaultJSON() json.RawMessage { + return json.RawMessage("[]") +} + +func (t tableImpl) decodeJson(reader io.Reader, onMsg func(message proto.Message) error) error { + decoder, err := t.startDecodeJson(reader) + if err != nil { + return err + } + + return t.doDecodeJson(decoder, nil, onMsg) +} + +func (t tableImpl) startDecodeJson(reader io.Reader) (*json.Decoder, error) { + decoder := json.NewDecoder(reader) + token, err := decoder.Token() + if err != nil { + return nil, err + } + + if token != json.Delim('[') { + return nil, ormerrors.JSONImportError.Wrapf("expected [ got %s", token) + } + + return decoder, nil +} + +// onFirst is called on the first RawMessage and used for auto-increment tables +// to decode the sequence in which case it should return true. +// onMsg is called on every decoded message +func (t tableImpl) doDecodeJson(decoder *json.Decoder, onFirst func(message json.RawMessage) bool, onMsg func(message proto.Message) error) error { + unmarshalOptions := protojson.UnmarshalOptions{Resolver: t.typeResolver} + + first := true + for decoder.More() { + var rawJson json.RawMessage + err := decoder.Decode(&rawJson) + if err != nil { + return ormerrors.JSONImportError.Wrapf("%s", err) + } + + if first { + first = false + if onFirst != nil { + if onFirst(rawJson) { + // if onFirst handled this, skip decoding into a proto message + continue + } + } + } + + msg := t.MessageType().New().Interface() + err = unmarshalOptions.Unmarshal(rawJson, msg) + if err != nil { + return err + } + + err = onMsg(msg) + if err != nil { + return err + } + } + + token, err := decoder.Token() + if err != nil { + return err + } + + if token != json.Delim(']') { + return ormerrors.JSONImportError.Wrapf("expected ] got %s", token) + } + + return nil +} + +// DefaultJSONValidator is the default validator used when calling +// Table.ValidateJSON(). It will call methods with the signature `ValidateBasic() error` +// and/or `Validate() error` to validate the message. +func DefaultJSONValidator(message proto.Message) error { + if v, ok := message.(interface{ ValidateBasic() error }); ok { + err := v.ValidateBasic() + if err != nil { + return err + } + } + + if v, ok := message.(interface{ Validate() error }); ok { + err := v.Validate() + if err != nil { + return err + } + } + + return nil +} + +func (t tableImpl) ValidateJSON(reader io.Reader) error { + return t.decodeJson(reader, func(message proto.Message) error { + if t.customJSONValidator != nil { + return t.customJSONValidator(message) + } else { + return DefaultJSONValidator(message) + } + }) +} + +func (t tableImpl) ImportJSON(ctx context.Context, reader io.Reader) error { + backend, err := t.getBackend(ctx) + if err != nil { + return err + } + + return t.decodeJson(reader, func(message proto.Message) error { + return t.save(backend, message, saveModeDefault) + }) +} + +func (t tableImpl) ExportJSON(context context.Context, writer io.Writer) error { + _, err := writer.Write([]byte("[")) + if err != nil { + return err + } + + return t.doExportJSON(context, writer) +} + +func (t tableImpl) doExportJSON(ctx context.Context, writer io.Writer) error { + marshalOptions := protojson.MarshalOptions{ + UseProtoNames: true, + Resolver: t.typeResolver, + } + + var err error + it, _ := t.Iterator(ctx) + start := true + for { + found := it.Next() + + if !found { + _, err = writer.Write([]byte("]")) + return err + } else if !start { + _, err = writer.Write([]byte(",\n")) + if err != nil { + return err + } + } + start = false + + msg := t.MessageType().New().Interface() + err = it.UnmarshalMessage(msg) + if err != nil { + return err + } + + bz, err := marshalOptions.Marshal(msg) + if err != nil { + return err + } + + _, err = writer.Write(bz) + if err != nil { + return err + } + + } +} + +func (t tableImpl) DecodeEntry(k, v []byte) (ormkv.Entry, error) { + r := bytes.NewReader(k) + err := encodeutil.SkipPrefix(r, t.tablePrefix) + if err != nil { + return nil, err + } + + id, err := binary.ReadUvarint(r) + if err != nil { + return nil, err + } + + if id > math.MaxUint32 { + return nil, ormerrors.UnexpectedDecodePrefix.Wrapf("uint32 varint id out of range %d", id) + } + + idx, ok := t.entryCodecsById[uint32(id)] + if !ok { + return nil, ormerrors.UnexpectedDecodePrefix.Wrapf("can't find field with id %d", id) + } + + return idx.DecodeEntry(k, v) +} + +func (t tableImpl) EncodeEntry(entry ormkv.Entry) (k, v []byte, err error) { + switch entry := entry.(type) { + case *ormkv.PrimaryKeyEntry: + return t.PrimaryKeyCodec.EncodeEntry(entry) + case *ormkv.IndexKeyEntry: + idx, ok := t.indexesByFields[fieldsFromNames(entry.Fields)] + if !ok { + return nil, nil, ormerrors.BadDecodeEntry.Wrapf("can't find index with fields %s", entry.Fields) + } + + return idx.EncodeEntry(entry) + default: + return nil, nil, ormerrors.BadDecodeEntry.Wrapf("%s", entry) + } +} + +func (t tableImpl) ID() uint32 { + return t.tableId +} + +var _ Table = &tableImpl{} + +type saveMode int + +const ( + saveModeDefault saveMode = iota + saveModeInsert + saveModeUpdate +) diff --git a/orm/model/ormtable/table_test.go b/orm/model/ormtable/table_test.go new file mode 100644 index 000000000..868fa67c3 --- /dev/null +++ b/orm/model/ormtable/table_test.go @@ -0,0 +1,692 @@ +package ormtable_test + +import ( + "bytes" + "context" + "fmt" + "sort" + "strings" + "testing" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/testing/protocmp" + "gotest.tools/v3/assert" + "gotest.tools/v3/golden" + "pgregory.net/rapid" + + queryv1beta1 "github.com/cosmos/cosmos-sdk/api/cosmos/base/query/v1beta1" + sdkerrors "github.com/cosmos/cosmos-sdk/errors" + "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" + "github.com/cosmos/cosmos-sdk/orm/internal/testkv" + "github.com/cosmos/cosmos-sdk/orm/internal/testpb" + "github.com/cosmos/cosmos-sdk/orm/internal/testutil" + "github.com/cosmos/cosmos-sdk/orm/model/kv" + "github.com/cosmos/cosmos-sdk/orm/model/ormlist" + "github.com/cosmos/cosmos-sdk/orm/model/ormtable" + "github.com/cosmos/cosmos-sdk/orm/types/ormerrors" +) + +func TestScenario(t *testing.T) { + table, err := ormtable.Build(ormtable.Options{ + MessageType: (&testpb.ExampleTable{}).ProtoReflect().Type(), + }) + assert.NilError(t, err) + + // first run tests with a split index-commitment store + runTestScenario(t, table, testkv.NewSplitMemBackend()) + + // now run tests with a shared index-commitment store + + // we're going to wrap this test in a debug store and save the decoded debug + // messages, these will be checked against a golden file at the end of the + // test. the golden file can be used for fine-grained debugging of kv-store + // layout + debugBuf := &strings.Builder{} + store := testkv.NewDebugBackend( + testkv.NewSharedMemBackend(), + &testkv.EntryCodecDebugger{ + EntryCodec: table, + Print: func(s string) { debugBuf.WriteString(s + "\n") }, + }, + ) + + runTestScenario(t, table, store) + + // we're going to store debug data in a golden file to make sure that + // logical decoding works successfully + // run `go test pkgname -test.update-golden` to update the golden file + // see https://pkg.go.dev/gotest.tools/v3/golden for docs + golden.Assert(t, debugBuf.String(), "test_scenario.golden") + + checkEncodeDecodeEntries(t, table, store.IndexStoreReader()) +} + +// check that the ormkv.Entry's decode and encode to the same bytes +func checkEncodeDecodeEntries(t *testing.T, table ormtable.Table, store kv.ReadonlyStore) { + it, err := store.Iterator(nil, nil) + assert.NilError(t, err) + for it.Valid() { + key := it.Key() + value := it.Value() + entry, err := table.DecodeEntry(key, value) + assert.NilError(t, err) + k, v, err := table.EncodeEntry(entry) + assert.Assert(t, bytes.Equal(key, k), "%x %x %s", key, k, entry) + assert.Assert(t, bytes.Equal(value, v), "%x %x %s", value, v, entry) + it.Next() + } +} + +func runTestScenario(t *testing.T, table ormtable.Table, backend ormtable.Backend) { + ctx := ormtable.WrapContextDefault(backend) + + // let's create 10 data items we'll use later and give them indexes + data := []*testpb.ExampleTable{ + {U32: 4, I64: -2, Str: "abc", U64: 7}, // 0 + {U32: 4, I64: -2, Str: "abd", U64: 7}, // 1 + {U32: 4, I64: -1, Str: "abc", U64: 8}, // 2 + {U32: 5, I64: -2, Str: "abd", U64: 8}, // 3 + {U32: 5, I64: -2, Str: "abe", U64: 9}, // 4 + {U32: 7, I64: -2, Str: "abe", U64: 10}, // 5 + {U32: 7, I64: -1, Str: "abe", U64: 11}, // 6 + {U32: 8, I64: -4, Str: "abc", U64: 11}, // 7 + {U32: 8, I64: 1, Str: "abc", U64: 12}, // 8 + {U32: 8, I64: 1, Str: "abd", U64: 10}, // 9 + } + + // let's make a function to match what's in our iterator with what we + // expect using indexes in the data array above + assertIteratorItems := func(it ormtable.Iterator, xs ...int) { + for _, i := range xs { + assert.Assert(t, it.Next()) + msg, err := it.GetMessage() + assert.NilError(t, err) + //t.Logf("data[%d] %v == %v", i, data[i], msg) + assert.DeepEqual(t, data[i], msg, protocmp.Transform()) + } + // make sure the iterator is done + assert.Assert(t, !it.Next()) + } + + // insert one record + err := table.Insert(ctx, data[0]) + // trivial prefix query has one record + it, err := table.Iterator(ctx) + assert.NilError(t, err) + assertIteratorItems(it, 0) + + // insert one record + err = table.Insert(ctx, data[1]) + // trivial prefix query has two records + it, err = table.Iterator(ctx) + assert.NilError(t, err) + assertIteratorItems(it, 0, 1) + + // insert the other records + assert.NilError(t, err) + for i := 2; i < len(data); i++ { + err = table.Insert(ctx, data[i]) + assert.NilError(t, err) + } + + // let's do a prefix query on the primary key + it, err = table.Iterator(ctx, ormlist.Prefix(uint32(8))) + assert.NilError(t, err) + assertIteratorItems(it, 7, 8, 9) + + // let's try a reverse prefix query + it, err = table.Iterator(ctx, ormlist.Prefix(uint32(4)), ormlist.Reverse()) + assert.NilError(t, err) + defer it.Close() + assertIteratorItems(it, 2, 1, 0) + + // let's try a range query + it, err = table.Iterator(ctx, + ormlist.Start(uint32(4), int64(-1)), + ormlist.End(uint32(7)), + ) + assert.NilError(t, err) + defer it.Close() + assertIteratorItems(it, 2, 3, 4, 5, 6) + + // and another range query + it, err = table.Iterator(ctx, + ormlist.Start(uint32(5), int64(-3)), + ormlist.End(uint32(8), int64(1), "abc"), + ) + assert.NilError(t, err) + defer it.Close() + assertIteratorItems(it, 3, 4, 5, 6, 7, 8) + + // now a reverse range query on a different index + strU32Index := table.GetIndex("str,u32") + assert.Assert(t, strU32Index != nil) + it, err = strU32Index.Iterator(ctx, + ormlist.Start("abc"), + ormlist.End("abd"), + ormlist.Reverse(), + ) + assertIteratorItems(it, 9, 3, 1, 8, 7, 2, 0) + + // another prefix query forwards + it, err = strU32Index.Iterator(ctx, ormlist.Prefix("abe", uint32(7))) + assertIteratorItems(it, 5, 6) + // and backwards + it, err = strU32Index.Iterator(ctx, ormlist.Prefix("abc", uint32(4)), ormlist.Reverse()) + assertIteratorItems(it, 2, 0) + + // try an unique index + u64StrIndex := table.GetUniqueIndex("u64,str") + assert.Assert(t, u64StrIndex != nil) + found, err := u64StrIndex.Has(ctx, uint64(12), "abc") + assert.NilError(t, err) + assert.Assert(t, found) + var a testpb.ExampleTable + found, err = u64StrIndex.Get(ctx, &a, uint64(12), "abc") + assert.NilError(t, err) + assert.Assert(t, found) + assert.DeepEqual(t, data[8], &a, protocmp.Transform()) + + // let's try paginating some stuff + + // first create a function to test what we got from pagination + assertGotItems := func(items []proto.Message, xs ...int) { + n := len(xs) + assert.Equal(t, n, len(items)) + for i := 0; i < n; i++ { + j := xs[i] + //t.Logf("data[%d] %v == %v", j, data[j], items[i]) + assert.DeepEqual(t, data[j], items[i], protocmp.Transform()) + } + } + + // now do some pagination + var items []proto.Message + onItem := func(item proto.Message) { + items = append(items, item) + } + res, err := ormtable.Paginate(table, ctx, &ormtable.PaginationRequest{ + PageRequest: &queryv1beta1.PageRequest{ + Limit: 4, + CountTotal: true, + }}, onItem) + assert.NilError(t, err) + assert.Assert(t, res != nil) + assert.Equal(t, uint64(10), res.Total) + assert.Assert(t, res.NextKey != nil) + assert.Assert(t, res.HaveMore) + assert.Equal(t, 4, len(res.Cursors)) + assertGotItems(items, 0, 1, 2, 3) + + // read another page + items = nil + res, err = ormtable.Paginate(table, ctx, &ormtable.PaginationRequest{ + PageRequest: &queryv1beta1.PageRequest{ + Key: res.NextKey, + Limit: 4, + }}, onItem) + assert.NilError(t, err) + assert.Assert(t, res != nil) + assert.Assert(t, res.NextKey != nil) + assert.Assert(t, res.HaveMore) + assert.Equal(t, 4, len(res.Cursors)) + assertGotItems(items, 4, 5, 6, 7) + + // and the last page + items = nil + res, err = ormtable.Paginate(table, ctx, &ormtable.PaginationRequest{ + PageRequest: &queryv1beta1.PageRequest{ + Key: res.NextKey, + Limit: 4, + }}, onItem) + assert.NilError(t, err) + assert.Assert(t, res != nil) + assert.Assert(t, res.NextKey != nil) + assert.Assert(t, !res.HaveMore) + assert.Equal(t, 2, len(res.Cursors)) + assertGotItems(items, 8, 9) + + // let's go backwards + items = nil + res, err = ormtable.Paginate(table, ctx, &ormtable.PaginationRequest{ + PageRequest: &queryv1beta1.PageRequest{ + Limit: 2, + CountTotal: true, + Reverse: true, + }}, onItem) + assert.NilError(t, err) + assert.Assert(t, res != nil) + assert.Assert(t, res.NextKey != nil) + assert.Equal(t, uint64(10), res.Total) + assert.Assert(t, res.HaveMore) + assert.Equal(t, 2, len(res.Cursors)) + assertGotItems(items, 9, 8) + + // a bit more + items = nil + res, err = ormtable.Paginate(table, ctx, &ormtable.PaginationRequest{ + PageRequest: &queryv1beta1.PageRequest{ + Key: res.NextKey, + Limit: 2, + Reverse: true, + }}, onItem) + assert.NilError(t, err) + assert.Assert(t, res != nil) + assert.Assert(t, res.NextKey != nil) + assert.Assert(t, res.HaveMore) + assert.Equal(t, 2, len(res.Cursors)) + assertGotItems(items, 7, 6) + + // range query + items = nil + res, err = ormtable.Paginate(table, ctx, + &ormtable.PaginationRequest{ + PageRequest: &queryv1beta1.PageRequest{ + Limit: 10, + }, + }, + onItem, + ormlist.Start(uint32(4), int64(-1), "abc"), + ormlist.End(uint32(7), int64(-2), "abe"), + ) + assert.NilError(t, err) + assert.Assert(t, res != nil) + assert.Assert(t, !res.HaveMore) + assert.Equal(t, 4, len(res.Cursors)) + assertGotItems(items, 2, 3, 4, 5) + + // let's try an offset + items = nil + res, err = ormtable.Paginate(table, ctx, &ormtable.PaginationRequest{ + PageRequest: &queryv1beta1.PageRequest{ + Limit: 2, + CountTotal: true, + Offset: 3, + }}, onItem) + assert.NilError(t, err) + assert.Assert(t, res != nil) + assert.Assert(t, res.NextKey != nil) + assert.Equal(t, uint64(10), res.Total) + assert.Assert(t, res.HaveMore) + assert.Equal(t, 2, len(res.Cursors)) + assertGotItems(items, 3, 4) + + // and reverse + items = nil + res, err = ormtable.Paginate(table, ctx, &ormtable.PaginationRequest{ + PageRequest: &queryv1beta1.PageRequest{ + Limit: 3, + CountTotal: true, + Offset: 5, + Reverse: true, + }}, onItem) + assert.NilError(t, err) + assert.Assert(t, res != nil) + assert.Assert(t, res.NextKey != nil) + assert.Equal(t, uint64(10), res.Total) + assert.Assert(t, res.HaveMore) + assert.Equal(t, 3, len(res.Cursors)) + assertGotItems(items, 4, 3, 2) + + // now an offset that's slightly too big + items = nil + res, err = ormtable.Paginate(table, ctx, &ormtable.PaginationRequest{ + PageRequest: &queryv1beta1.PageRequest{ + Limit: 1, + CountTotal: true, + Offset: 10, + }}, onItem) + assert.NilError(t, err) + assert.Equal(t, 0, len(items)) + assert.Assert(t, !res.HaveMore) + assert.Equal(t, uint64(10), res.Total) + + // another offset that's too big + items = nil + res, err = ormtable.Paginate(table, ctx, &ormtable.PaginationRequest{ + PageRequest: &queryv1beta1.PageRequest{ + Limit: 1, + CountTotal: true, + Offset: 14, + }}, onItem) + assert.NilError(t, err) + assert.Equal(t, 0, len(items)) + assert.Assert(t, !res.HaveMore) + assert.Equal(t, uint64(10), res.Total) + + // now let's update some things + for i := 0; i < 5; i++ { + data[i].U64 = data[i].U64 * 2 + data[i].Bz = []byte(data[i].Str) + err = table.Update(ctx, data[i]) + assert.NilError(t, err) + } + it, err = table.Iterator(ctx) + assert.NilError(t, err) + // we should still get everything in the same order + assertIteratorItems(it, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + + // let's use SAVE_MODE_DEFAULT and add something + data = append(data, &testpb.ExampleTable{U32: 9}) + err = table.Save(ctx, data[10]) + assert.NilError(t, err) + found, err = table.Get(ctx, &a, uint32(9), int64(0), "") + assert.NilError(t, err) + assert.Assert(t, found) + assert.DeepEqual(t, data[10], &a, protocmp.Transform()) + // and update it + data[10].B = true + assert.NilError(t, table.Save(ctx, data[10])) + found, err = table.Get(ctx, &a, uint32(9), int64(0), "") + assert.NilError(t, err) + assert.Assert(t, found) + assert.DeepEqual(t, data[10], &a, protocmp.Transform()) + // and iterate + it, err = table.Iterator(ctx) + assert.NilError(t, err) + assertIteratorItems(it, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + + // let's export and import JSON and use a read-only backend + buf := &bytes.Buffer{} + readBackend := ormtable.NewReadBackend(ormtable.ReadBackendOptions{ + CommitmentStoreReader: backend.CommitmentStoreReader(), + IndexStoreReader: backend.IndexStoreReader(), + }) + assert.NilError(t, table.ExportJSON(ormtable.WrapContextDefault(readBackend), buf)) + assert.NilError(t, table.ValidateJSON(bytes.NewReader(buf.Bytes()))) + store2 := ormtable.WrapContextDefault(testkv.NewSplitMemBackend()) + assert.NilError(t, table.ImportJSON(store2, bytes.NewReader(buf.Bytes()))) + assertTablesEqual(t, table, ctx, store2) + + // let's delete item 5 + key5 := []interface{}{uint32(7), int64(-2), "abe"} + err = table.DeleteByKey(ctx, key5...) + assert.NilError(t, err) + // it should be gone + found, err = table.Has(ctx, key5...) + assert.NilError(t, err) + assert.Assert(t, !found) + // and missing from the iterator + it, err = table.Iterator(ctx) + assert.NilError(t, err) + assertIteratorItems(it, 0, 1, 2, 3, 4, 6, 7, 8, 9, 10) +} + +func TestRandomTableData(t *testing.T) { + testTable(t, TableDataGen(testutil.GenA, 100).Example().(*TableData)) +} + +func testTable(t *testing.T, tableData *TableData) { + for _, index := range tableData.table.Indexes() { + indexModel := &IndexModel{ + TableData: tableData, + index: index.(TestIndex), + } + sort.Sort(indexModel) + if _, ok := index.(ormtable.UniqueIndex); ok { + testUniqueIndex(t, indexModel) + } + testIndex(t, indexModel) + } +} + +func testUniqueIndex(t *testing.T, model *IndexModel) { + index := model.index.(ormtable.UniqueIndex) + t.Logf("testing unique index %T %s", index, index.Fields()) + for i := 0; i < len(model.data); i++ { + x := model.data[i] + ks, _, err := index.(ormkv.IndexCodec).EncodeKeyFromMessage(x.ProtoReflect()) + assert.NilError(t, err) + + values := protoValuesToInterfaces(ks) + + found, err := index.Has(model.context, values...) + assert.NilError(t, err) + assert.Assert(t, found) + + msg := model.table.MessageType().New().Interface() + found, err = index.Get(model.context, msg, values...) + assert.NilError(t, err) + assert.Assert(t, found) + assert.DeepEqual(t, x, msg, protocmp.Transform()) + } +} + +func testIndex(t *testing.T, model *IndexModel) { + index := model.index + if index.IsFullyOrdered() { + t.Logf("testing index %T %s", index, index.Fields()) + + it, err := model.index.Iterator(model.context) + assert.NilError(t, err) + checkIteratorAgainstSlice(t, it, model.data) + + it, err = model.index.Iterator(model.context, ormlist.Reverse()) + assert.NilError(t, err) + checkIteratorAgainstSlice(t, it, reverseData(model.data)) + + rapid.Check(t, func(t *rapid.T) { + i := rapid.IntRange(0, len(model.data)-2).Draw(t, "i").(int) + j := rapid.IntRange(i+1, len(model.data)-1).Draw(t, "j").(int) + + start, _, err := model.index.(ormkv.IndexCodec).EncodeKeyFromMessage(model.data[i].ProtoReflect()) + assert.NilError(t, err) + end, _, err := model.index.(ormkv.IndexCodec).EncodeKeyFromMessage(model.data[j].ProtoReflect()) + assert.NilError(t, err) + + startVals := protoValuesToInterfaces(start) + endVals := protoValuesToInterfaces(end) + + it, err = model.index.Iterator(model.context, ormlist.Start(startVals...), ormlist.End(endVals...)) + assert.NilError(t, err) + checkIteratorAgainstSlice(t, it, model.data[i:j+1]) + + it, err = model.index.Iterator(model.context, ormlist.Start(startVals...), ormlist.End(endVals...), ormlist.Reverse()) + assert.NilError(t, err) + checkIteratorAgainstSlice(t, it, reverseData(model.data[i:j+1])) + }) + } else { + t.Logf("testing unordered index %T %s", index, index.Fields()) + + // get all the data + it, err := model.index.Iterator(model.context) + assert.NilError(t, err) + var data2 []proto.Message + for it.Next() { + msg, err := it.GetMessage() + assert.NilError(t, err) + data2 = append(data2, msg) + } + assert.Equal(t, len(model.data), len(data2)) + + // sort it + model2 := &IndexModel{ + TableData: &TableData{ + table: model.table, + data: data2, + context: model.context, + }, + index: model.index, + } + sort.Sort(model2) + + // compare + for i := 0; i < len(data2); i++ { + assert.DeepEqual(t, model.data[i], data2[i], protocmp.Transform()) + } + } + +} + +func reverseData(data []proto.Message) []proto.Message { + n := len(data) + reverse := make([]proto.Message, n) + for i := 0; i < n; i++ { + reverse[n-i-1] = data[i] + } + return reverse +} + +func checkIteratorAgainstSlice(t assert.TestingT, iterator ormtable.Iterator, data []proto.Message) { + i := 0 + for iterator.Next() { + if i >= len(data) { + for iterator.Next() { + i++ + } + t.Log(fmt.Sprintf("too many elements in iterator, len(data) = %d, i = %d", len(data), i)) + t.FailNow() + } + msg, err := iterator.GetMessage() + assert.NilError(t, err) + assert.DeepEqual(t, data[i], msg, protocmp.Transform()) + i++ + } +} + +func TableDataGen(elemGen *rapid.Generator, n int) *rapid.Generator { + return rapid.Custom(func(t *rapid.T) *TableData { + prefix := rapid.SliceOfN(rapid.Byte(), 0, 5).Draw(t, "prefix").([]byte) + message := elemGen.Draw(t, "message").(proto.Message) + table, err := ormtable.Build(ormtable.Options{ + Prefix: prefix, + MessageType: message.ProtoReflect().Type(), + }) + if err != nil { + panic(err) + } + + data := make([]proto.Message, n) + store := ormtable.WrapContextDefault(testkv.NewSplitMemBackend()) + + for i := 0; i < n; { + message = elemGen.Draw(t, fmt.Sprintf("message[%d]", i)).(proto.Message) + err := table.Insert(store, message) + if sdkerrors.IsOf(err, ormerrors.PrimaryKeyConstraintViolation, ormerrors.UniqueKeyViolation) { + continue + } else if err != nil { + panic(err) + } + data[i] = message + i++ + } + + return &TableData{ + data: data, + table: table, + context: store, + } + }) +} + +type TableData struct { + table ormtable.Table + data []proto.Message + context context.Context +} + +type IndexModel struct { + *TableData + index TestIndex +} + +// TestIndex exposes methods that all index implementations expose publicly +// but on private structs because they are intended only to be used for testing. +type TestIndex interface { + ormtable.Index + + // CompareKeys the two keys against the underlying IndexCodec, returning a + // negative value if key1 is less than key2, 0 if they are equal, and a + // positive value otherwise. + CompareKeys(key1, key2 []protoreflect.Value) int + + // IsFullyOrdered returns true if all of the fields in the index are + // considered "well-ordered" in terms of sorted iteration. + IsFullyOrdered() bool +} + +func (m *IndexModel) Len() int { + return len(m.data) +} + +func (m *IndexModel) Less(i, j int) bool { + is, _, err := m.index.(ormkv.IndexCodec).EncodeKeyFromMessage(m.data[i].ProtoReflect()) + if err != nil { + panic(err) + } + js, _, err := m.index.(ormkv.IndexCodec).EncodeKeyFromMessage(m.data[j].ProtoReflect()) + if err != nil { + panic(err) + } + return m.index.CompareKeys(is, js) < 0 +} + +func (m *IndexModel) Swap(i, j int) { + x := m.data[i] + m.data[i] = m.data[j] + m.data[j] = x +} + +var _ sort.Interface = &IndexModel{} + +func TestJSONExportImport(t *testing.T) { + table, err := ormtable.Build(ormtable.Options{ + MessageType: (&testpb.ExampleTable{}).ProtoReflect().Type(), + }) + assert.NilError(t, err) + store := ormtable.WrapContextDefault(testkv.NewSplitMemBackend()) + + for i := 0; i < 100; { + x := testutil.GenA.Example().(proto.Message) + err = table.Insert(store, x) + if sdkerrors.IsOf(err, ormerrors.PrimaryKeyConstraintViolation, ormerrors.UniqueKeyViolation) { + continue + } else { + assert.NilError(t, err) + } + i++ + } + + buf := &bytes.Buffer{} + assert.NilError(t, table.ExportJSON(store, buf)) + + assert.NilError(t, table.ValidateJSON(bytes.NewReader(buf.Bytes()))) + + store2 := ormtable.WrapContextDefault(testkv.NewSplitMemBackend()) + assert.NilError(t, table.ImportJSON(store2, bytes.NewReader(buf.Bytes()))) + + assertTablesEqual(t, table, store, store2) +} + +func assertTablesEqual(t assert.TestingT, table ormtable.Table, ctx, ctx2 context.Context) { + it, err := table.Iterator(ctx) + assert.NilError(t, err) + it2, err := table.Iterator(ctx2) + assert.NilError(t, err) + + for { + have := it.Next() + have2 := it2.Next() + assert.Equal(t, have, have2) + if !have { + break + } + + msg1, err := it.GetMessage() + assert.NilError(t, err) + msg2, err := it.GetMessage() + assert.NilError(t, err) + + assert.DeepEqual(t, msg1, msg2, protocmp.Transform()) + } +} + +func protoValuesToInterfaces(ks []protoreflect.Value) []interface{} { + values := make([]interface{}, len(ks)) + for i := 0; i < len(ks); i++ { + values[i] = ks[i].Interface() + } + + return values +} diff --git a/orm/model/ormtable/testdata/auto_inc_json.golden b/orm/model/ormtable/testdata/auto_inc_json.golden new file mode 100644 index 000000000..31cea2059 --- /dev/null +++ b/orm/model/ormtable/testdata/auto_inc_json.golden @@ -0,0 +1,2 @@ +[1, +{"id":"1","x":"foo","y":5}] \ No newline at end of file diff --git a/orm/model/ormtable/testdata/bad_auto_inc.json b/orm/model/ormtable/testdata/bad_auto_inc.json new file mode 100644 index 000000000..48521d55d --- /dev/null +++ b/orm/model/ormtable/testdata/bad_auto_inc.json @@ -0,0 +1,2 @@ +[1, + {"id":"2","x":"foo","y":5}] diff --git a/orm/model/ormtable/testdata/bad_auto_inc2.json b/orm/model/ormtable/testdata/bad_auto_inc2.json new file mode 100644 index 000000000..dbdbbbf91 --- /dev/null +++ b/orm/model/ormtable/testdata/bad_auto_inc2.json @@ -0,0 +1 @@ +[{"id":"1","x":"foo","y":5}] diff --git a/orm/model/ormtable/testdata/test_auto_inc.golden b/orm/model/ormtable/testdata/test_auto_inc.golden new file mode 100644 index 000000000..2224e148a --- /dev/null +++ b/orm/model/ormtable/testdata/test_auto_inc.golden @@ -0,0 +1,31 @@ +GET 03000000000000000005 + PK testpb.ExampleAutoIncrementTable 5 -> id:5 +GET 03808002 + SEQ testpb.ExampleAutoIncrementTable 0 +GET 03000000000000000001 + PK testpb.ExampleAutoIncrementTable 1 -> id:1 +ORM INSERT testpb.ExampleAutoIncrementTable id:1 x:"foo" y:5 +HAS 0301666f6f + ERR:EOF +SET 03000000000000000001 1203666f6f1805 + PK testpb.ExampleAutoIncrementTable 1 -> id:1 x:"foo" y:5 +SET 03808002 01 + SEQ testpb.ExampleAutoIncrementTable 1 +SET 0301666f6f 0000000000000001 + UNIQ testpb.ExampleAutoIncrementTable x : "foo" -> 1 +GET 03808002 01 + SEQ testpb.ExampleAutoIncrementTable 1 +ITERATOR 0300 -> 0301 + VALID true + KEY 03000000000000000001 1203666f6f1805 + PK testpb.ExampleAutoIncrementTable 1 -> id:1 x:"foo" y:5 + NEXT + VALID false +ITERATOR 0300 -> 0301 + VALID true + KEY 03000000000000000001 1203666f6f1805 + PK testpb.ExampleAutoIncrementTable 1 -> id:1 x:"foo" y:5 + KEY 03000000000000000001 1203666f6f1805 + PK testpb.ExampleAutoIncrementTable 1 -> id:1 x:"foo" y:5 + NEXT + VALID false diff --git a/orm/model/ormtable/testdata/test_scenario.golden b/orm/model/ormtable/testdata/test_scenario.golden new file mode 100644 index 000000000..a8ba54f3f --- /dev/null +++ b/orm/model/ormtable/testdata/test_scenario.golden @@ -0,0 +1,923 @@ +GET 0100000000047ffffffffffffffe616263 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 str:"abc" i64:-2 +ORM INSERT testpb.ExampleTable u32:4 u64:7 str:"abc" i64:-2 +HAS 01010000000000000007616263 + ERR:EOF +SET 0100000000047ffffffffffffffe616263 1007 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:7 str:"abc" i64:-2 +SET 01010000000000000007616263 000000047ffffffffffffffe + UNIQ testpb.ExampleTable u64/str : 7/"abc" -> 4/-2/"abc" +SET 010261626300000000047ffffffffffffffe + IDX testpb.ExampleTable str/u32/i64 : "abc"/4/-2 -> 4/-2/"abc" +SET 01030061626300000000047ffffffffffffffe + IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abc"/4/-2 -> 4/-2/"abc" +ITERATOR 0100 -> 0101 + VALID true + KEY 0100000000047ffffffffffffffe616263 1007 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:7 str:"abc" i64:-2 + NEXT + VALID false +GET 0100000000047ffffffffffffffe616264 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 str:"abd" i64:-2 +ORM INSERT testpb.ExampleTable u32:4 u64:7 str:"abd" i64:-2 +HAS 01010000000000000007616264 + ERR:EOF +SET 0100000000047ffffffffffffffe616264 1007 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:7 str:"abd" i64:-2 +SET 01010000000000000007616264 000000047ffffffffffffffe + UNIQ testpb.ExampleTable u64/str : 7/"abd" -> 4/-2/"abd" +SET 010261626400000000047ffffffffffffffe + IDX testpb.ExampleTable str/u32/i64 : "abd"/4/-2 -> 4/-2/"abd" +SET 01030061626400000000047ffffffffffffffe + IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abd"/4/-2 -> 4/-2/"abd" +ITERATOR 0100 -> 0101 + VALID true + KEY 0100000000047ffffffffffffffe616263 1007 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:7 str:"abc" i64:-2 + NEXT + VALID true + KEY 0100000000047ffffffffffffffe616264 1007 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:7 str:"abd" i64:-2 + NEXT + VALID false +GET 0100000000047fffffffffffffff616263 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 str:"abc" i64:-1 +ORM INSERT testpb.ExampleTable u32:4 u64:8 str:"abc" i64:-1 +HAS 01010000000000000008616263 + ERR:EOF +SET 0100000000047fffffffffffffff616263 1008 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:8 str:"abc" i64:-1 +SET 01010000000000000008616263 000000047fffffffffffffff + UNIQ testpb.ExampleTable u64/str : 8/"abc" -> 4/-1/"abc" +SET 010261626300000000047fffffffffffffff + IDX testpb.ExampleTable str/u32/i64 : "abc"/4/-1 -> 4/-1/"abc" +SET 01030061626300000000047fffffffffffffff + IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abc"/4/-1 -> 4/-1/"abc" +GET 0100000000057ffffffffffffffe616264 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 str:"abd" i64:-2 +ORM INSERT testpb.ExampleTable u32:5 u64:8 str:"abd" i64:-2 +HAS 01010000000000000008616264 + ERR:EOF +SET 0100000000057ffffffffffffffe616264 1008 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:8 str:"abd" i64:-2 +SET 01010000000000000008616264 000000057ffffffffffffffe + UNIQ testpb.ExampleTable u64/str : 8/"abd" -> 5/-2/"abd" +SET 010261626400000000057ffffffffffffffe + IDX testpb.ExampleTable str/u32/i64 : "abd"/5/-2 -> 5/-2/"abd" +SET 01030061626400000000057ffffffffffffffe + IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abd"/5/-2 -> 5/-2/"abd" +GET 0100000000057ffffffffffffffe616265 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 str:"abe" i64:-2 +ORM INSERT testpb.ExampleTable u32:5 u64:9 str:"abe" i64:-2 +HAS 01010000000000000009616265 + ERR:EOF +SET 0100000000057ffffffffffffffe616265 1009 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:9 str:"abe" i64:-2 +SET 01010000000000000009616265 000000057ffffffffffffffe + UNIQ testpb.ExampleTable u64/str : 9/"abe" -> 5/-2/"abe" +SET 010261626500000000057ffffffffffffffe + IDX testpb.ExampleTable str/u32/i64 : "abe"/5/-2 -> 5/-2/"abe" +SET 01030061626500000000057ffffffffffffffe + IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abe"/5/-2 -> 5/-2/"abe" +GET 0100000000077ffffffffffffffe616265 + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 str:"abe" i64:-2 +ORM INSERT testpb.ExampleTable u32:7 u64:10 str:"abe" i64:-2 +HAS 0101000000000000000a616265 + ERR:EOF +SET 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 +SET 0101000000000000000a616265 000000077ffffffffffffffe + UNIQ testpb.ExampleTable u64/str : 10/"abe" -> 7/-2/"abe" +SET 010261626500000000077ffffffffffffffe + IDX testpb.ExampleTable str/u32/i64 : "abe"/7/-2 -> 7/-2/"abe" +SET 01030061626500000000077ffffffffffffffe + IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abe"/7/-2 -> 7/-2/"abe" +GET 0100000000077fffffffffffffff616265 + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 str:"abe" i64:-1 +ORM INSERT testpb.ExampleTable u32:7 u64:11 str:"abe" i64:-1 +HAS 0101000000000000000b616265 + ERR:EOF +SET 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 +SET 0101000000000000000b616265 000000077fffffffffffffff + UNIQ testpb.ExampleTable u64/str : 11/"abe" -> 7/-1/"abe" +SET 010261626500000000077fffffffffffffff + IDX testpb.ExampleTable str/u32/i64 : "abe"/7/-1 -> 7/-1/"abe" +SET 01030061626500000000077fffffffffffffff + IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abe"/7/-1 -> 7/-1/"abe" +GET 0100000000087ffffffffffffffc616263 + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 str:"abc" i64:-4 +ORM INSERT testpb.ExampleTable u32:8 u64:11 str:"abc" i64:-4 +HAS 0101000000000000000b616263 + ERR:EOF +SET 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 +SET 0101000000000000000b616263 000000087ffffffffffffffc + UNIQ testpb.ExampleTable u64/str : 11/"abc" -> 8/-4/"abc" +SET 010261626300000000087ffffffffffffffc + IDX testpb.ExampleTable str/u32/i64 : "abc"/8/-4 -> 8/-4/"abc" +SET 01030061626300000000087ffffffffffffffc + IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abc"/8/-4 -> 8/-4/"abc" +GET 0100000000088000000000000001616263 + PK testpb.ExampleTable 8/1/"abc" -> u32:8 str:"abc" i64:1 +ORM INSERT testpb.ExampleTable u32:8 u64:12 str:"abc" i64:1 +HAS 0101000000000000000c616263 + ERR:EOF +SET 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 +SET 0101000000000000000c616263 000000088000000000000001 + UNIQ testpb.ExampleTable u64/str : 12/"abc" -> 8/1/"abc" +SET 010261626300000000088000000000000001 + IDX testpb.ExampleTable str/u32/i64 : "abc"/8/1 -> 8/1/"abc" +SET 01030061626300000000088000000000000001 + IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abc"/8/1 -> 8/1/"abc" +GET 0100000000088000000000000001616264 + PK testpb.ExampleTable 8/1/"abd" -> u32:8 str:"abd" i64:1 +ORM INSERT testpb.ExampleTable u32:8 u64:10 str:"abd" i64:1 +HAS 0101000000000000000a616264 + ERR:EOF +SET 0100000000088000000000000001616264 100a + PK testpb.ExampleTable 8/1/"abd" -> u32:8 u64:10 str:"abd" i64:1 +SET 0101000000000000000a616264 000000088000000000000001 + UNIQ testpb.ExampleTable u64/str : 10/"abd" -> 8/1/"abd" +SET 010261626400000000088000000000000001 + IDX testpb.ExampleTable str/u32/i64 : "abd"/8/1 -> 8/1/"abd" +SET 01030061626400000000088000000000000001 + IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abd"/8/1 -> 8/1/"abd" +ITERATOR 010000000008 -> 010000000009 + VALID true + KEY 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 + NEXT + VALID true + KEY 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 + NEXT + VALID true + KEY 0100000000088000000000000001616264 100a + PK testpb.ExampleTable 8/1/"abd" -> u32:8 u64:10 str:"abd" i64:1 + NEXT + VALID false +ITERATOR 010000000004 <- 010000000005 + VALID true + KEY 0100000000047fffffffffffffff616263 1008 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:8 str:"abc" i64:-1 + NEXT + VALID true + KEY 0100000000047ffffffffffffffe616264 1007 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:7 str:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000047ffffffffffffffe616263 1007 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:7 str:"abc" i64:-2 + NEXT + VALID false +ITERATOR 0100000000047fffffffffffffff -> 010000000008 + VALID true + KEY 0100000000047fffffffffffffff616263 1008 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:8 str:"abc" i64:-1 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616264 1008 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:8 str:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616265 1009 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:9 str:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 + NEXT + VALID false +ITERATOR 0100000000057ffffffffffffffd -> 010000000008800000000000000161626300 + VALID true + KEY 0100000000057ffffffffffffffe616264 1008 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:8 str:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616265 1009 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:9 str:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 + NEXT + VALID true + KEY 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 + NEXT + VALID true + KEY 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 + NEXT + VALID false +ITERATOR 010261626300 <- 010261626401 + VALID true + KEY 010261626400000000088000000000000001 + IDX testpb.ExampleTable str/u32/i64 : "abd"/8/1 -> 8/1/"abd" +GET 0100000000088000000000000001616264 100a + PK testpb.ExampleTable 8/1/"abd" -> u32:8 u64:10 str:"abd" i64:1 + NEXT + VALID true + KEY 010261626400000000057ffffffffffffffe + IDX testpb.ExampleTable str/u32/i64 : "abd"/5/-2 -> 5/-2/"abd" +GET 0100000000057ffffffffffffffe616264 1008 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:8 str:"abd" i64:-2 + NEXT + VALID true + KEY 010261626400000000047ffffffffffffffe + IDX testpb.ExampleTable str/u32/i64 : "abd"/4/-2 -> 4/-2/"abd" +GET 0100000000047ffffffffffffffe616264 1007 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:7 str:"abd" i64:-2 + NEXT + VALID true + KEY 010261626300000000088000000000000001 + IDX testpb.ExampleTable str/u32/i64 : "abc"/8/1 -> 8/1/"abc" +GET 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 + NEXT + VALID true + KEY 010261626300000000087ffffffffffffffc + IDX testpb.ExampleTable str/u32/i64 : "abc"/8/-4 -> 8/-4/"abc" +GET 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 + NEXT + VALID true + KEY 010261626300000000047fffffffffffffff + IDX testpb.ExampleTable str/u32/i64 : "abc"/4/-1 -> 4/-1/"abc" +GET 0100000000047fffffffffffffff616263 1008 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:8 str:"abc" i64:-1 + NEXT + VALID true + KEY 010261626300000000047ffffffffffffffe + IDX testpb.ExampleTable str/u32/i64 : "abc"/4/-2 -> 4/-2/"abc" +GET 0100000000047ffffffffffffffe616263 1007 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:7 str:"abc" i64:-2 + NEXT + VALID false +ITERATOR 01026162650000000007 -> 01026162650000000008 + VALID true + KEY 010261626500000000077ffffffffffffffe + IDX testpb.ExampleTable str/u32/i64 : "abe"/7/-2 -> 7/-2/"abe" +GET 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 + NEXT + VALID true + KEY 010261626500000000077fffffffffffffff + IDX testpb.ExampleTable str/u32/i64 : "abe"/7/-1 -> 7/-1/"abe" +GET 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 + NEXT + VALID false +ITERATOR 01026162630000000004 <- 01026162630000000005 + VALID true + KEY 010261626300000000047fffffffffffffff + IDX testpb.ExampleTable str/u32/i64 : "abc"/4/-1 -> 4/-1/"abc" +GET 0100000000047fffffffffffffff616263 1008 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:8 str:"abc" i64:-1 + NEXT + VALID true + KEY 010261626300000000047ffffffffffffffe + IDX testpb.ExampleTable str/u32/i64 : "abc"/4/-2 -> 4/-2/"abc" +GET 0100000000047ffffffffffffffe616263 1007 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:7 str:"abc" i64:-2 + NEXT + VALID false +HAS 0101000000000000000c616263 + ERR:EOF +GET 0101000000000000000c616263 000000088000000000000001 + UNIQ testpb.ExampleTable u64/str : 12/"abc" -> 8/1/"abc" +GET 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 +ITERATOR 0100 -> 0101 + VALID true + KEY 0100000000047ffffffffffffffe616263 1007 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:7 str:"abc" i64:-2 + KEY 0100000000047ffffffffffffffe616263 1007 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:7 str:"abc" i64:-2 + NEXT + VALID true + KEY 0100000000047ffffffffffffffe616264 1007 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:7 str:"abd" i64:-2 + KEY 0100000000047ffffffffffffffe616264 1007 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:7 str:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000047fffffffffffffff616263 1008 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:8 str:"abc" i64:-1 + KEY 0100000000047fffffffffffffff616263 1008 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:8 str:"abc" i64:-1 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616264 1008 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:8 str:"abd" i64:-2 + KEY 0100000000057ffffffffffffffe616264 1008 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:8 str:"abd" i64:-2 + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID false + CLOSE +ITERATOR 0100000000057ffffffffffffffe61626400 -> 0101 + VALID true + KEY 0100000000057ffffffffffffffe616265 1009 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:9 str:"abe" i64:-2 + KEY 0100000000057ffffffffffffffe616265 1009 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:9 str:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 + KEY 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 + KEY 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 + NEXT + VALID true + KEY 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 + KEY 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 + NEXT + VALID true + CLOSE +ITERATOR 0100000000087ffffffffffffffc61626300 -> 0101 + VALID true + KEY 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 + KEY 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 + NEXT + VALID true + KEY 0100000000088000000000000001616264 100a + PK testpb.ExampleTable 8/1/"abd" -> u32:8 u64:10 str:"abd" i64:1 + KEY 0100000000088000000000000001616264 100a + PK testpb.ExampleTable 8/1/"abd" -> u32:8 u64:10 str:"abd" i64:1 + NEXT + VALID false + CLOSE +ITERATOR 0100 <- 0101 + VALID true + KEY 0100000000088000000000000001616264 100a + PK testpb.ExampleTable 8/1/"abd" -> u32:8 u64:10 str:"abd" i64:1 + KEY 0100000000088000000000000001616264 100a + PK testpb.ExampleTable 8/1/"abd" -> u32:8 u64:10 str:"abd" i64:1 + NEXT + VALID true + KEY 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 + KEY 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID false + CLOSE +ITERATOR 0100 <- 0100000000088000000000000001616263 + VALID true + KEY 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 + KEY 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 + NEXT + VALID true + KEY 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 + KEY 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 + NEXT + VALID true + CLOSE +ITERATOR 0100000000047fffffffffffffff616263 -> 0100000000077ffffffffffffffe61626500 + VALID true + KEY 0100000000047fffffffffffffff616263 1008 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:8 str:"abc" i64:-1 + KEY 0100000000047fffffffffffffff616263 1008 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:8 str:"abc" i64:-1 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616264 1008 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:8 str:"abd" i64:-2 + KEY 0100000000057ffffffffffffffe616264 1008 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:8 str:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616265 1009 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:9 str:"abe" i64:-2 + KEY 0100000000057ffffffffffffffe616265 1009 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:9 str:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 + KEY 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 + NEXT + VALID false + CLOSE +ITERATOR 0100 -> 0101 + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616264 1008 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:8 str:"abd" i64:-2 + KEY 0100000000057ffffffffffffffe616264 1008 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:8 str:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616265 1009 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:9 str:"abe" i64:-2 + KEY 0100000000057ffffffffffffffe616265 1009 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:9 str:"abe" i64:-2 + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID false + CLOSE +ITERATOR 0100 <- 0101 + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616265 1009 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:9 str:"abe" i64:-2 + KEY 0100000000057ffffffffffffffe616265 1009 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:9 str:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616264 1008 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:8 str:"abd" i64:-2 + KEY 0100000000057ffffffffffffffe616264 1008 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:8 str:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000047fffffffffffffff616263 1008 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:8 str:"abc" i64:-1 + KEY 0100000000047fffffffffffffff616263 1008 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:8 str:"abc" i64:-1 + NEXT + VALID true + NEXT + VALID true + NEXT + VALID false + CLOSE +ITERATOR 0100 -> 0101 + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID false + CLOSE +ITERATOR 0100 -> 0101 + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID true + NEXT + VALID false + CLOSE +GET 0100000000047ffffffffffffffe616263 1007 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:7 str:"abc" i64:-2 +ORM UPDATE testpb.ExampleTable u32:4 u64:7 str:"abc" i64:-2 -> u32:4 u64:14 str:"abc" bz:"abc" i64:-2 +HAS 0101000000000000000e616263 + ERR:EOF +SET 0100000000047ffffffffffffffe616263 100e2203616263 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:14 str:"abc" bz:"abc" i64:-2 +DEL 01010000000000000007616263 +DEL ERR:EOF +SET 0101000000000000000e616263 000000047ffffffffffffffe + UNIQ testpb.ExampleTable u64/str : 14/"abc" -> 4/-2/"abc" +DEL 01030061626300000000047ffffffffffffffe +DEL IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abc"/4/-2 -> 4/-2/"abc" +SET 01030361626361626300000000047ffffffffffffffe + IDX testpb.ExampleTable bz/str/u32/i64 : "YWJj"/"abc"/4/-2 -> 4/-2/"abc" +GET 0100000000047ffffffffffffffe616264 1007 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:7 str:"abd" i64:-2 +ORM UPDATE testpb.ExampleTable u32:4 u64:7 str:"abd" i64:-2 -> u32:4 u64:14 str:"abd" bz:"abd" i64:-2 +HAS 0101000000000000000e616264 + ERR:EOF +SET 0100000000047ffffffffffffffe616264 100e2203616264 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:14 str:"abd" bz:"abd" i64:-2 +DEL 01010000000000000007616264 +DEL ERR:EOF +SET 0101000000000000000e616264 000000047ffffffffffffffe + UNIQ testpb.ExampleTable u64/str : 14/"abd" -> 4/-2/"abd" +DEL 01030061626400000000047ffffffffffffffe +DEL IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abd"/4/-2 -> 4/-2/"abd" +SET 01030361626461626400000000047ffffffffffffffe + IDX testpb.ExampleTable bz/str/u32/i64 : "YWJk"/"abd"/4/-2 -> 4/-2/"abd" +GET 0100000000047fffffffffffffff616263 1008 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:8 str:"abc" i64:-1 +ORM UPDATE testpb.ExampleTable u32:4 u64:8 str:"abc" i64:-1 -> u32:4 u64:16 str:"abc" bz:"abc" i64:-1 +HAS 01010000000000000010616263 + ERR:EOF +SET 0100000000047fffffffffffffff616263 10102203616263 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:16 str:"abc" bz:"abc" i64:-1 +DEL 01010000000000000008616263 +DEL ERR:EOF +SET 01010000000000000010616263 000000047fffffffffffffff + UNIQ testpb.ExampleTable u64/str : 16/"abc" -> 4/-1/"abc" +DEL 01030061626300000000047fffffffffffffff +DEL IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abc"/4/-1 -> 4/-1/"abc" +SET 01030361626361626300000000047fffffffffffffff + IDX testpb.ExampleTable bz/str/u32/i64 : "YWJj"/"abc"/4/-1 -> 4/-1/"abc" +GET 0100000000057ffffffffffffffe616264 1008 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:8 str:"abd" i64:-2 +ORM UPDATE testpb.ExampleTable u32:5 u64:8 str:"abd" i64:-2 -> u32:5 u64:16 str:"abd" bz:"abd" i64:-2 +HAS 01010000000000000010616264 + ERR:EOF +SET 0100000000057ffffffffffffffe616264 10102203616264 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:16 str:"abd" bz:"abd" i64:-2 +DEL 01010000000000000008616264 +DEL ERR:EOF +SET 01010000000000000010616264 000000057ffffffffffffffe + UNIQ testpb.ExampleTable u64/str : 16/"abd" -> 5/-2/"abd" +DEL 01030061626400000000057ffffffffffffffe +DEL IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abd"/5/-2 -> 5/-2/"abd" +SET 01030361626461626400000000057ffffffffffffffe + IDX testpb.ExampleTable bz/str/u32/i64 : "YWJk"/"abd"/5/-2 -> 5/-2/"abd" +GET 0100000000057ffffffffffffffe616265 1009 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:9 str:"abe" i64:-2 +ORM UPDATE testpb.ExampleTable u32:5 u64:9 str:"abe" i64:-2 -> u32:5 u64:18 str:"abe" bz:"abe" i64:-2 +HAS 01010000000000000012616265 + ERR:EOF +SET 0100000000057ffffffffffffffe616265 10122203616265 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:18 str:"abe" bz:"abe" i64:-2 +DEL 01010000000000000009616265 +DEL ERR:EOF +SET 01010000000000000012616265 000000057ffffffffffffffe + UNIQ testpb.ExampleTable u64/str : 18/"abe" -> 5/-2/"abe" +DEL 01030061626500000000057ffffffffffffffe +DEL IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abe"/5/-2 -> 5/-2/"abe" +SET 01030361626561626500000000057ffffffffffffffe + IDX testpb.ExampleTable bz/str/u32/i64 : "YWJl"/"abe"/5/-2 -> 5/-2/"abe" +ITERATOR 0100 -> 0101 + VALID true + KEY 0100000000047ffffffffffffffe616263 100e2203616263 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:14 str:"abc" bz:"abc" i64:-2 + NEXT + VALID true + KEY 0100000000047ffffffffffffffe616264 100e2203616264 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:14 str:"abd" bz:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000047fffffffffffffff616263 10102203616263 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:16 str:"abc" bz:"abc" i64:-1 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616264 10102203616264 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:16 str:"abd" bz:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616265 10122203616265 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:18 str:"abe" bz:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 + NEXT + VALID true + KEY 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 + NEXT + VALID true + KEY 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 + NEXT + VALID true + KEY 0100000000088000000000000001616264 100a + PK testpb.ExampleTable 8/1/"abd" -> u32:8 u64:10 str:"abd" i64:1 + NEXT + VALID false +GET 0100000000098000000000000000 + PK testpb.ExampleTable 9/0/"" -> u32:9 +ORM INSERT testpb.ExampleTable u32:9 +HAS 01010000000000000000 + ERR:EOF +SET 0100000000098000000000000000 + PK testpb.ExampleTable 9/0/"" -> u32:9 +SET 01010000000000000000 000000098000000000000000 + UNIQ testpb.ExampleTable u64/str : 0/"" -> 9/0/"" +SET 010200000000098000000000000000 + IDX testpb.ExampleTable str/u32/i64 : ""/9/0 -> 9/0/"" +SET 01030000000000098000000000000000 + IDX testpb.ExampleTable bz/str/u32/i64 : ""/""/9/0 -> 9/0/"" +GET 0100000000098000000000000000 + PK testpb.ExampleTable 9/0/"" -> u32:9 +GET 0100000000098000000000000000 + PK testpb.ExampleTable 9/0/"" -> u32:9 +ORM UPDATE testpb.ExampleTable u32:9 -> u32:9 b:true +SET 0100000000098000000000000000 7801 + PK testpb.ExampleTable 9/0/"" -> u32:9 b:true +GET 0100000000098000000000000000 7801 + PK testpb.ExampleTable 9/0/"" -> u32:9 b:true +ITERATOR 0100 -> 0101 + VALID true + KEY 0100000000047ffffffffffffffe616263 100e2203616263 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:14 str:"abc" bz:"abc" i64:-2 + NEXT + VALID true + KEY 0100000000047ffffffffffffffe616264 100e2203616264 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:14 str:"abd" bz:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000047fffffffffffffff616263 10102203616263 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:16 str:"abc" bz:"abc" i64:-1 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616264 10102203616264 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:16 str:"abd" bz:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616265 10122203616265 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:18 str:"abe" bz:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 + NEXT + VALID true + KEY 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 + NEXT + VALID true + KEY 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 + NEXT + VALID true + KEY 0100000000088000000000000001616264 100a + PK testpb.ExampleTable 8/1/"abd" -> u32:8 u64:10 str:"abd" i64:1 + NEXT + VALID true + KEY 0100000000098000000000000000 7801 + PK testpb.ExampleTable 9/0/"" -> u32:9 b:true + NEXT + VALID false +ITERATOR 0100 -> 0101 + VALID true + KEY 0100000000047ffffffffffffffe616263 100e2203616263 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:14 str:"abc" bz:"abc" i64:-2 + NEXT + VALID true + KEY 0100000000047ffffffffffffffe616264 100e2203616264 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:14 str:"abd" bz:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000047fffffffffffffff616263 10102203616263 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:16 str:"abc" bz:"abc" i64:-1 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616264 10102203616264 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:16 str:"abd" bz:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616265 10122203616265 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:18 str:"abe" bz:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 + NEXT + VALID true + KEY 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 + NEXT + VALID true + KEY 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 + NEXT + VALID true + KEY 0100000000088000000000000001616264 100a + PK testpb.ExampleTable 8/1/"abd" -> u32:8 u64:10 str:"abd" i64:1 + NEXT + VALID true + KEY 0100000000098000000000000000 7801 + PK testpb.ExampleTable 9/0/"" -> u32:9 b:true + NEXT + VALID false +ITERATOR 0100 -> 0101 + VALID true + KEY 0100000000047ffffffffffffffe616263 100e2203616263 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:14 str:"abc" bz:"abc" i64:-2 + KEY 0100000000047ffffffffffffffe616263 100e2203616263 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:14 str:"abc" bz:"abc" i64:-2 + NEXT + VALID true + KEY 0100000000047ffffffffffffffe616264 100e2203616264 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:14 str:"abd" bz:"abd" i64:-2 + KEY 0100000000047ffffffffffffffe616264 100e2203616264 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:14 str:"abd" bz:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000047fffffffffffffff616263 10102203616263 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:16 str:"abc" bz:"abc" i64:-1 + KEY 0100000000047fffffffffffffff616263 10102203616263 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:16 str:"abc" bz:"abc" i64:-1 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616264 10102203616264 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:16 str:"abd" bz:"abd" i64:-2 + KEY 0100000000057ffffffffffffffe616264 10102203616264 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:16 str:"abd" bz:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616265 10122203616265 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:18 str:"abe" bz:"abe" i64:-2 + KEY 0100000000057ffffffffffffffe616265 10122203616265 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:18 str:"abe" bz:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 + KEY 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 + KEY 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 + NEXT + VALID true + KEY 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 + KEY 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 + NEXT + VALID true + KEY 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 + KEY 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 + NEXT + VALID true + KEY 0100000000088000000000000001616264 100a + PK testpb.ExampleTable 8/1/"abd" -> u32:8 u64:10 str:"abd" i64:1 + KEY 0100000000088000000000000001616264 100a + PK testpb.ExampleTable 8/1/"abd" -> u32:8 u64:10 str:"abd" i64:1 + NEXT + VALID true + KEY 0100000000098000000000000000 7801 + PK testpb.ExampleTable 9/0/"" -> u32:9 b:true + KEY 0100000000098000000000000000 7801 + PK testpb.ExampleTable 9/0/"" -> u32:9 b:true + NEXT + VALID false +GET 0100000000077ffffffffffffffe616265 100a + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 u64:10 str:"abe" i64:-2 +ORM DELETE testpb.ExampleTable u32:7 u64:10 str:"abe" i64:-2 +DEL 0100000000077ffffffffffffffe616265 +DEL PK testpb.ExampleTable 7/-2/"abe" -> u32:7 str:"abe" i64:-2 +DEL 0101000000000000000a616265 +DEL ERR:EOF +DEL 010261626500000000077ffffffffffffffe +DEL IDX testpb.ExampleTable str/u32/i64 : "abe"/7/-2 -> 7/-2/"abe" +DEL 01030061626500000000077ffffffffffffffe +DEL IDX testpb.ExampleTable bz/str/u32/i64 : ""/"abe"/7/-2 -> 7/-2/"abe" +HAS 0100000000077ffffffffffffffe616265 + PK testpb.ExampleTable 7/-2/"abe" -> u32:7 str:"abe" i64:-2 +ITERATOR 0100 -> 0101 + VALID true + KEY 0100000000047ffffffffffffffe616263 100e2203616263 + PK testpb.ExampleTable 4/-2/"abc" -> u32:4 u64:14 str:"abc" bz:"abc" i64:-2 + NEXT + VALID true + KEY 0100000000047ffffffffffffffe616264 100e2203616264 + PK testpb.ExampleTable 4/-2/"abd" -> u32:4 u64:14 str:"abd" bz:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000047fffffffffffffff616263 10102203616263 + PK testpb.ExampleTable 4/-1/"abc" -> u32:4 u64:16 str:"abc" bz:"abc" i64:-1 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616264 10102203616264 + PK testpb.ExampleTable 5/-2/"abd" -> u32:5 u64:16 str:"abd" bz:"abd" i64:-2 + NEXT + VALID true + KEY 0100000000057ffffffffffffffe616265 10122203616265 + PK testpb.ExampleTable 5/-2/"abe" -> u32:5 u64:18 str:"abe" bz:"abe" i64:-2 + NEXT + VALID true + KEY 0100000000077fffffffffffffff616265 100b + PK testpb.ExampleTable 7/-1/"abe" -> u32:7 u64:11 str:"abe" i64:-1 + NEXT + VALID true + KEY 0100000000087ffffffffffffffc616263 100b + PK testpb.ExampleTable 8/-4/"abc" -> u32:8 u64:11 str:"abc" i64:-4 + NEXT + VALID true + KEY 0100000000088000000000000001616263 100c + PK testpb.ExampleTable 8/1/"abc" -> u32:8 u64:12 str:"abc" i64:1 + NEXT + VALID true + KEY 0100000000088000000000000001616264 100a + PK testpb.ExampleTable 8/1/"abd" -> u32:8 u64:10 str:"abd" i64:1 + NEXT + VALID true + KEY 0100000000098000000000000000 7801 + PK testpb.ExampleTable 9/0/"" -> u32:9 b:true + NEXT + VALID false + CLOSE + CLOSE + CLOSE diff --git a/orm/model/ormtable/unique.go b/orm/model/ormtable/unique.go new file mode 100644 index 000000000..05513bff1 --- /dev/null +++ b/orm/model/ormtable/unique.go @@ -0,0 +1,211 @@ +package ormtable + +import ( + "context" + + "github.com/cosmos/cosmos-sdk/orm/model/kv" + "github.com/cosmos/cosmos-sdk/orm/model/ormlist" + + "github.com/cosmos/cosmos-sdk/orm/encoding/encodeutil" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + + "github.com/cosmos/cosmos-sdk/orm/encoding/ormkv" + "github.com/cosmos/cosmos-sdk/orm/types/ormerrors" +) + +type uniqueKeyIndex struct { + *ormkv.UniqueKeyCodec + fields fieldNames + primaryKey *primaryKeyIndex + getReadBackend func(context.Context) (ReadBackend, error) +} + +func (u uniqueKeyIndex) Iterator(ctx context.Context, options ...ormlist.Option) (Iterator, error) { + backend, err := u.getReadBackend(ctx) + if err != nil { + return nil, err + } + + return iterator(backend, backend.IndexStoreReader(), u, u.GetKeyCodec(), options) +} + +func (u uniqueKeyIndex) doNotImplement() {} + +func (u uniqueKeyIndex) Has(ctx context.Context, values ...interface{}) (found bool, err error) { + backend, err := u.getReadBackend(ctx) + if err != nil { + return false, err + } + + key, err := u.GetKeyCodec().EncodeKey(encodeutil.ValuesOf(values...)) + if err != nil { + return false, err + } + + return backend.IndexStoreReader().Has(key) +} + +func (u uniqueKeyIndex) Get(ctx context.Context, message proto.Message, keyValues ...interface{}) (found bool, err error) { + backend, err := u.getReadBackend(ctx) + if err != nil { + return false, err + } + + key, err := u.GetKeyCodec().EncodeKey(encodeutil.ValuesOf(keyValues...)) + if err != nil { + return false, err + } + + value, err := backend.IndexStoreReader().Get(key) + if err != nil { + return false, err + } + + // for unique keys, value can be empty and the entry still exists + if value == nil { + return false, nil + } + + _, pk, err := u.DecodeIndexKey(key, value) + if err != nil { + return true, err + } + + return u.primaryKey.get(backend, message, pk) +} + +func (u uniqueKeyIndex) DeleteByKey(ctx context.Context, keyValues ...interface{}) error { + backend, err := u.getReadBackend(ctx) + if err != nil { + return err + } + + key, err := u.GetKeyCodec().EncodeKey(encodeutil.ValuesOf(keyValues...)) + if err != nil { + return err + } + + value, err := backend.IndexStoreReader().Get(key) + if err != nil { + return err + } + + // for unique keys, value can be empty and the entry still exists + if value == nil { + return nil + } + + _, pk, err := u.DecodeIndexKey(key, value) + if err != nil { + return err + } + + return u.primaryKey.doDeleteByKey(ctx, pk) +} + +func (u uniqueKeyIndex) onInsert(store kv.Store, message protoreflect.Message) error { + k, v, err := u.EncodeKVFromMessage(message) + if err != nil { + return err + } + + has, err := store.Has(k) + if err != nil { + return err + } + + if has { + return ormerrors.UniqueKeyViolation + } + + return store.Set(k, v) +} + +func (u uniqueKeyIndex) onUpdate(store kv.Store, new, existing protoreflect.Message) error { + keyCodec := u.GetKeyCodec() + newValues := keyCodec.GetKeyValues(new) + existingValues := keyCodec.GetKeyValues(existing) + if keyCodec.CompareKeys(newValues, existingValues) == 0 { + return nil + } + + newKey, err := keyCodec.EncodeKey(newValues) + if err != nil { + return err + } + + has, err := store.Has(newKey) + if err != nil { + return err + } + + if has { + return ormerrors.UniqueKeyViolation + } + + existingKey, err := keyCodec.EncodeKey(existingValues) + if err != nil { + return err + } + + err = store.Delete(existingKey) + if err != nil { + return err + } + + _, value, err := u.GetValueCodec().EncodeKeyFromMessage(new) + if err != nil { + return err + } + + return store.Set(newKey, value) +} + +func (u uniqueKeyIndex) onDelete(store kv.Store, message protoreflect.Message) error { + _, key, err := u.GetKeyCodec().EncodeKeyFromMessage(message) + if err != nil { + return err + } + + return store.Delete(key) +} + +func (u uniqueKeyIndex) readValueFromIndexKey(store ReadBackend, primaryKey []protoreflect.Value, _ []byte, message proto.Message) error { + found, err := u.primaryKey.get(store, message, primaryKey) + if err != nil { + return err + } + + if !found { + return ormerrors.UnexpectedError.Wrapf("can't find primary key") + } + + return nil +} + +func (p uniqueKeyIndex) Fields() string { + return p.fields.String() +} + +var _ indexer = &uniqueKeyIndex{} +var _ UniqueIndex = &uniqueKeyIndex{} + +// isNonTrivialUniqueKey checks if unique key fields are non-trivial, meaning that they +// don't contain the full primary key. If they contain the full primary key, then +// we can just use a regular index because there is no new unique constraint. +func isNonTrivialUniqueKey(fields []protoreflect.Name, primaryKeyFields []protoreflect.Name) bool { + have := map[protoreflect.Name]bool{} + for _, field := range fields { + have[field] = true + } + + for _, field := range primaryKeyFields { + if !have[field] { + return true + } + } + + return false +} diff --git a/orm/model/ormtable/util.go b/orm/model/ormtable/util.go new file mode 100644 index 000000000..c3098d0ee --- /dev/null +++ b/orm/model/ormtable/util.go @@ -0,0 +1,35 @@ +package ormtable + +// prefixEndBytes returns the []byte that would end a +// range query for all []byte with a certain prefix +// Deals with last byte of prefix being FF without overflowing +func prefixEndBytes(prefix []byte) []byte { + if len(prefix) == 0 { + return nil + } + + end := make([]byte, len(prefix)) + copy(end, prefix) + + for { + if end[len(end)-1] != byte(255) { + end[len(end)-1]++ + break + } + + end = end[:len(end)-1] + + if len(end) == 0 { + end = nil + break + } + } + + return end +} + +// inclusiveEndBytes returns the []byte that would end a +// range query such that the input would be included +func inclusiveEndBytes(inclusiveBytes []byte) []byte { + return append(inclusiveBytes, byte(0x00)) +} diff --git a/orm/types/ormerrors/errors.go b/orm/types/ormerrors/errors.go index 4b4662566..755e6c784 100644 --- a/orm/types/ormerrors/errors.go +++ b/orm/types/ormerrors/errors.go @@ -11,7 +11,7 @@ var ( DuplicateKeyField = errors.New(codespace, 4, "duplicate field in key") FieldNotFound = errors.New(codespace, 5, "field not found") InvalidAutoIncrementKey = errors.New(codespace, 6, "an auto-increment primary key must specify a single uint64 field") - InvalidIndexId = errors.New(codespace, 7, "invalid or missing index id, need a non-zero value") + InvalidIndexId = errors.New(codespace, 7, "invalid or missing index id, need a value >= 0 and < 32768") DuplicateIndexId = errors.New(codespace, 8, "duplicate index id") PrimaryKeyConstraintViolation = errors.New(codespace, 9, "object with primary key already exists") NotFoundOnUpdate = errors.New(codespace, 10, "can't update object which doesn't exist") @@ -28,4 +28,6 @@ var ( UnexpectedError = errors.New(codespace, 21, "unexpected error") InvalidRangeIterationKeys = errors.New(codespace, 22, "invalid range iteration keys") JSONImportError = errors.New(codespace, 23, "json import error") + UniqueKeyViolation = errors.New(codespace, 24, "unique key violation") + InvalidTableDefinition = errors.New(codespace, 25, "invalid table definition") ) diff --git a/proto/cosmos/orm/v1alpha1/orm.proto b/proto/cosmos/orm/v1alpha1/orm.proto index d9ea4e633..317521904 100644 --- a/proto/cosmos/orm/v1alpha1/orm.proto +++ b/proto/cosmos/orm/v1alpha1/orm.proto @@ -88,7 +88,8 @@ message SecondaryIndexDescriptor { string fields = 1; // id is a non-zero integer ID that must be unique within the indexes for this - // table. It may be deprecated in the future when this can be auto-generated. + // table and less than 32768. It may be deprecated in the future when this can + // be auto-generated. uint32 id = 2; // unique specifies that this an unique index.