feat(orm): add sequence getter for auto increment tables (#15320)

Co-authored-by: Aaron Craelius <aaron@regen.network>
This commit is contained in:
Julien Robert 2023-03-09 15:56:09 +01:00 committed by GitHub
parent 112d071598
commit ddd18ff2eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 76 additions and 12 deletions

View File

@ -36,10 +36,14 @@ Ref: https://keepachangelog.com/en/1.0.0/
## [Unreleased]
### Feature
* [#15320](https://github.com/cosmos/cosmos-sdk/pull/15320) Add current sequence getter (`LastInsertedSequence`) for auto increment tables.
### API Breaking Changes
- [14822](https://github.com/cosmos/cosmos-sdk/pull/14822) Migrate to cosmossdk.io/core genesis API
* [#14822](https://github.com/cosmos/cosmos-sdk/pull/14822) Migrate to cosmossdk.io/core genesis API
### State-machine Breaking Changes
- [12273](https://github.com/cosmos/cosmos-sdk/pull/12273) The timestamp key encoding was reworked to properly handle nil values. Existing users will need to manually migrate their data to the new encoding before upgrading.
* [#12273](https://github.com/cosmos/cosmos-sdk/pull/12273) The timestamp key encoding was reworked to properly handle nil values. Existing users will need to manually migrate their data to the new encoding before upgrading.

View File

@ -62,6 +62,7 @@ func (t tableGen) getTableInterface() {
t.P("Insert(ctx ", contextPkg.Ident("Context"), ", ", t.param(t.msg.GoIdent.GoName), " *", t.QualifiedGoIdent(t.msg.GoIdent), ") error")
if t.table.PrimaryKey.AutoIncrement {
t.P("InsertReturning", fieldsToCamelCase(t.table.PrimaryKey.Fields), "(ctx ", contextPkg.Ident("Context"), ", ", t.param(t.msg.GoIdent.GoName), " *", t.QualifiedGoIdent(t.msg.GoIdent), ") (uint64, error)")
t.P("LastInsertedSequence(ctx ", contextPkg.Ident("Context"), ") (uint64, error)")
}
t.P("Update(ctx ", contextPkg.Ident("Context"), ", ", t.param(t.msg.GoIdent.GoName), " *", t.QualifiedGoIdent(t.msg.GoIdent), ") error")
t.P("Save(ctx ", contextPkg.Ident("Context"), ", ", t.param(t.msg.GoIdent.GoName), " *", t.QualifiedGoIdent(t.msg.GoIdent), ") error")
@ -184,6 +185,11 @@ func (t tableGen) genTableImpl() {
t.P("return ", receiverVar, ".table.InsertReturningPKey(ctx, ", varName, ")")
t.P("}")
t.P()
t.P(receiver, "LastInsertedSequence(ctx ", contextPkg.Ident("Context"), ") (uint64, error) {")
t.P("return ", receiverVar, ".table.LastInsertedSequence(ctx)")
t.P("}")
t.P()
}
// Has

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc-gen-go v1.28.1
// protoc (unknown)
// source: testpb/bank.proto

View File

@ -2,7 +2,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc-gen-go v1.28.1
// protoc (unknown)
// source: testpb/bank_query.proto
@ -139,6 +139,7 @@ type ListBalanceRequest struct {
// query specifies the type of query - either a prefix or range query.
//
// Types that are assignable to Query:
//
// *ListBalanceRequest_PrefixQuery
// *ListBalanceRequest_RangeQuery_
Query isListBalanceRequest_Query `protobuf_oneof:"query"`
@ -389,6 +390,7 @@ type ListSupplyRequest struct {
// query specifies the type of query - either a prefix or range query.
//
// Types that are assignable to Query:
//
// *ListSupplyRequest_PrefixQuery
// *ListSupplyRequest_RangeQuery_
Query isListSupplyRequest_Query `protobuf_oneof:"query"`
@ -541,6 +543,7 @@ type ListBalanceRequest_IndexKey struct {
// key specifies the index key value.
//
// Types that are assignable to Key:
//
// *ListBalanceRequest_IndexKey_AddressDenom_
// *ListBalanceRequest_IndexKey_Denom_
Key isListBalanceRequest_IndexKey_Key `protobuf_oneof:"key"`
@ -795,6 +798,7 @@ type ListSupplyRequest_IndexKey struct {
// key specifies the index key value.
//
// Types that are assignable to Key:
//
// *ListSupplyRequest_IndexKey_Denom_
Key isListSupplyRequest_IndexKey_Key `protobuf_oneof:"key"`
}

View File

@ -216,6 +216,7 @@ func NewExampleTableTable(db ormtable.Schema) (ExampleTableTable, error) {
type ExampleAutoIncrementTableTable interface {
Insert(ctx context.Context, exampleAutoIncrementTable *ExampleAutoIncrementTable) error
InsertReturningId(ctx context.Context, exampleAutoIncrementTable *ExampleAutoIncrementTable) (uint64, error)
LastInsertedSequence(ctx context.Context) (uint64, error)
Update(ctx context.Context, exampleAutoIncrementTable *ExampleAutoIncrementTable) error
Save(ctx context.Context, exampleAutoIncrementTable *ExampleAutoIncrementTable) error
Delete(ctx context.Context, exampleAutoIncrementTable *ExampleAutoIncrementTable) error
@ -302,6 +303,10 @@ func (this exampleAutoIncrementTableTable) InsertReturningId(ctx context.Context
return this.table.InsertReturningPKey(ctx, exampleAutoIncrementTable)
}
func (this exampleAutoIncrementTableTable) LastInsertedSequence(ctx context.Context) (uint64, error) {
return this.table.LastInsertedSequence(ctx)
}
func (this exampleAutoIncrementTableTable) Has(ctx context.Context, id uint64) (found bool, err error) {
return this.table.PrimaryKey().Has(ctx, id)
}
@ -401,6 +406,7 @@ func NewExampleSingletonTable(db ormtable.Schema) (ExampleSingletonTable, error)
type ExampleTimestampTable interface {
Insert(ctx context.Context, exampleTimestamp *ExampleTimestamp) error
InsertReturningId(ctx context.Context, exampleTimestamp *ExampleTimestamp) (uint64, error)
LastInsertedSequence(ctx context.Context) (uint64, error)
Update(ctx context.Context, exampleTimestamp *ExampleTimestamp) error
Save(ctx context.Context, exampleTimestamp *ExampleTimestamp) error
Delete(ctx context.Context, exampleTimestamp *ExampleTimestamp) error
@ -484,6 +490,10 @@ func (this exampleTimestampTable) InsertReturningId(ctx context.Context, example
return this.table.InsertReturningPKey(ctx, exampleTimestamp)
}
func (this exampleTimestampTable) LastInsertedSequence(ctx context.Context) (uint64, error) {
return this.table.LastInsertedSequence(ctx)
}
func (this exampleTimestampTable) Has(ctx context.Context, id uint64) (found bool, err error) {
return this.table.PrimaryKey().Has(ctx, id)
}
@ -683,6 +693,7 @@ func NewSimpleExampleTable(db ormtable.Schema) (SimpleExampleTable, error) {
type ExampleAutoIncFieldNameTable interface {
Insert(ctx context.Context, exampleAutoIncFieldName *ExampleAutoIncFieldName) error
InsertReturningFoo(ctx context.Context, exampleAutoIncFieldName *ExampleAutoIncFieldName) (uint64, error)
LastInsertedSequence(ctx context.Context) (uint64, error)
Update(ctx context.Context, exampleAutoIncFieldName *ExampleAutoIncFieldName) error
Save(ctx context.Context, exampleAutoIncFieldName *ExampleAutoIncFieldName) error
Delete(ctx context.Context, exampleAutoIncFieldName *ExampleAutoIncFieldName) error
@ -753,6 +764,10 @@ func (this exampleAutoIncFieldNameTable) InsertReturningFoo(ctx context.Context,
return this.table.InsertReturningPKey(ctx, exampleAutoIncFieldName)
}
func (this exampleAutoIncFieldNameTable) LastInsertedSequence(ctx context.Context) (uint64, error) {
return this.table.LastInsertedSequence(ctx)
}
func (this exampleAutoIncFieldNameTable) Has(ctx context.Context, foo uint64) (found bool, err error) {
return this.table.PrimaryKey().Has(ctx, foo)
}

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc-gen-go v1.28.1
// protoc (unknown)
// source: testpb/test_schema.proto
@ -105,6 +105,7 @@ type ExampleTable struct {
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:
//
// *ExampleTable_Oneof
Sum isExampleTable_Sum `protobuf_oneof:"sum"`
}

View File

@ -2,7 +2,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc-gen-go v1.28.1
// protoc (unknown)
// source: testpb/test_schema_query.proto
@ -253,6 +253,7 @@ type ListExampleTableRequest struct {
// query specifies the type of query - either a prefix or range query.
//
// Types that are assignable to Query:
//
// *ListExampleTableRequest_PrefixQuery
// *ListExampleTableRequest_RangeQuery_
Query isListExampleTableRequest_Query `protobuf_oneof:"query"`
@ -599,6 +600,7 @@ type ListExampleAutoIncrementTableRequest struct {
// query specifies the type of query - either a prefix or range query.
//
// Types that are assignable to Query:
//
// *ListExampleAutoIncrementTableRequest_PrefixQuery
// *ListExampleAutoIncrementTableRequest_RangeQuery_
Query isListExampleAutoIncrementTableRequest_Query `protobuf_oneof:"query"`
@ -938,6 +940,7 @@ type ListExampleTimestampRequest struct {
// query specifies the type of query - either a prefix or range query.
//
// Types that are assignable to Query:
//
// *ListExampleTimestampRequest_PrefixQuery
// *ListExampleTimestampRequest_RangeQuery_
Query isListExampleTimestampRequest_Query `protobuf_oneof:"query"`
@ -1284,6 +1287,7 @@ type ListSimpleExampleRequest struct {
// query specifies the type of query - either a prefix or range query.
//
// Types that are assignable to Query:
//
// *ListSimpleExampleRequest_PrefixQuery
// *ListSimpleExampleRequest_RangeQuery_
Query isListSimpleExampleRequest_Query `protobuf_oneof:"query"`
@ -1534,6 +1538,7 @@ type ListExampleAutoIncFieldNameRequest struct {
// query specifies the type of query - either a prefix or range query.
//
// Types that are assignable to Query:
//
// *ListExampleAutoIncFieldNameRequest_PrefixQuery
// *ListExampleAutoIncFieldNameRequest_RangeQuery_
Query isListExampleAutoIncFieldNameRequest_Query `protobuf_oneof:"query"`
@ -1686,6 +1691,7 @@ type ListExampleTableRequest_IndexKey struct {
// key specifies the index key value.
//
// Types that are assignable to Key:
//
// *ListExampleTableRequest_IndexKey_U_32I_64Str
// *ListExampleTableRequest_IndexKey_U_64Str
// *ListExampleTableRequest_IndexKey_StrU_32
@ -2108,6 +2114,7 @@ type ListExampleAutoIncrementTableRequest_IndexKey struct {
// key specifies the index key value.
//
// Types that are assignable to Key:
//
// *ListExampleAutoIncrementTableRequest_IndexKey_Id_
// *ListExampleAutoIncrementTableRequest_IndexKey_X_
Key isListExampleAutoIncrementTableRequest_IndexKey_Key `protobuf_oneof:"key"`
@ -2354,6 +2361,7 @@ type ListExampleTimestampRequest_IndexKey struct {
// key specifies the index key value.
//
// Types that are assignable to Key:
//
// *ListExampleTimestampRequest_IndexKey_Id_
// *ListExampleTimestampRequest_IndexKey_Ts_
Key isListExampleTimestampRequest_IndexKey_Key `protobuf_oneof:"key"`
@ -2598,6 +2606,7 @@ type ListSimpleExampleRequest_IndexKey struct {
// key specifies the index key value.
//
// Types that are assignable to Key:
//
// *ListSimpleExampleRequest_IndexKey_Name_
// *ListSimpleExampleRequest_IndexKey_Unique_
Key isListSimpleExampleRequest_IndexKey_Key `protobuf_oneof:"key"`
@ -2842,6 +2851,7 @@ type ListExampleAutoIncFieldNameRequest_IndexKey struct {
// key specifies the index key value.
//
// Types that are assignable to Key:
//
// *ListExampleAutoIncFieldNameRequest_IndexKey_Foo_
Key isListExampleAutoIncFieldNameRequest_IndexKey_Key `protobuf_oneof:"key"`
}

View File

@ -61,6 +61,15 @@ func (t autoIncrementTable) Update(ctx context.Context, message proto.Message) e
return err
}
func (t autoIncrementTable) LastInsertedSequence(ctx context.Context) (uint64, error) {
backend, err := t.getBackend(ctx)
if err != nil {
return 0, err
}
return t.curSeqValue(backend.IndexStoreReader())
}
func (t *autoIncrementTable) save(ctx context.Context, backend Backend, message proto.Message, mode saveMode) (newPK uint64, err error) {
messageRef := message.ProtoReflect()
val := messageRef.Get(t.autoIncField).Uint()

View File

@ -52,12 +52,18 @@ func runAutoIncrementScenario(t *testing.T, table ormtable.AutoIncrementTable, c
ex1 := &testpb.ExampleAutoIncrementTable{X: "foo", Y: 5}
assert.NilError(t, store.Save(ctx, ex1))
assert.Equal(t, uint64(1), ex1.Id)
curSeq, err := table.LastInsertedSequence(ctx)
assert.NilError(t, err)
assert.Equal(t, curSeq, uint64(1))
ex2 := &testpb.ExampleAutoIncrementTable{X: "bar", Y: 10}
newId, err := table.InsertReturningPKey(ctx, ex2)
assert.NilError(t, err)
assert.Equal(t, uint64(2), ex2.Id)
assert.Equal(t, newId, ex2.Id)
curSeq, err = table.LastInsertedSequence(ctx)
assert.NilError(t, err)
assert.Equal(t, curSeq, uint64(2))
buf := &bytes.Buffer{}
assert.NilError(t, table.ExportJSON(ctx, buf))
@ -78,6 +84,9 @@ func runAutoIncrementScenario(t *testing.T, table ormtable.AutoIncrementTable, c
ex1.Id = 0
assert.NilError(t, table.Insert(store3, ex1))
assert.Equal(t, uint64(3), ex1.Id) // should equal 3 because the sequence number 2 should have been imported from JSON
curSeq, err = table.LastInsertedSequence(store3)
assert.NilError(t, err)
assert.Equal(t, curSeq, uint64(3))
}
func TestBadJSON(t *testing.T) {

View File

@ -3,18 +3,15 @@ package ormtable
import (
"fmt"
"github.com/cosmos/cosmos-sdk/orm/internal/fieldnames"
"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"
"google.golang.org/protobuf/reflect/protoregistry"
ormv1 "cosmossdk.io/api/cosmos/orm/v1"
"github.com/cosmos/cosmos-sdk/orm/encoding/encodeutil"
"github.com/cosmos/cosmos-sdk/orm/encoding/ormkv"
"github.com/cosmos/cosmos-sdk/orm/internal/fieldnames"
"github.com/cosmos/cosmos-sdk/orm/types/ormerrors"
)

View File

@ -143,6 +143,7 @@ type Table interface {
// Schema is an interface for things that contain tables and can encode and
// decode kv-store pairs.
type Schema interface {
ormkv.EntryCodec
@ -156,4 +157,8 @@ type AutoIncrementTable interface {
// InsertReturningPKey inserts the provided entry in the store and returns the newly
// generated primary key for the message or an error.
InsertReturningPKey(ctx context.Context, message proto.Message) (newPK uint64, err error)
// LastInsertedSequence retrieves the sequence number of the last entry inserted into the table.
// The LastInsertedSequence is 0 if no entries have been inserted into the table.
LastInsertedSequence(ctx context.Context) (uint64, error)
}

View File

@ -14,6 +14,8 @@ SET 03808002 01
SET 0301666f6f 0001
UNIQ testpb.ExampleAutoIncrementTable x : foo -> 1
ORM AFTER INSERT testpb.ExampleAutoIncrementTable {"id":1,"x":"foo","y":5}
GET 03808002 01
SEQ testpb.ExampleAutoIncrementTable 1
GET 03808002 01
SEQ testpb.ExampleAutoIncrementTable 1
GET 03000002
@ -28,6 +30,8 @@ SET 03808002 02
SET 0301626172 0002
UNIQ testpb.ExampleAutoIncrementTable x : bar -> 2
ORM AFTER INSERT testpb.ExampleAutoIncrementTable {"id":2,"x":"bar","y":10}
GET 03808002 02
SEQ testpb.ExampleAutoIncrementTable 2
GET 03808002 02
SEQ testpb.ExampleAutoIncrementTable 2
ITERATOR 0300 -> 0301