diff options
author | yenlin.lai <yenlin.lai@cobinhood.com> | 2019-04-18 10:13:29 +0800 |
---|---|---|
committer | Jhih-Ming Huang <jm.huang@cobinhood.com> | 2019-05-06 10:44:04 +0800 |
commit | 107dbb1954ac76647d4fceab5770285a5f7ecfe1 (patch) | |
tree | 333a4e5a2f5713f0c91dd1efa443dff079c77468 | |
parent | 5b71bbd50a64d3b1576626d4cf0ca22569b57cf8 (diff) | |
download | dexon-107dbb1954ac76647d4fceab5770285a5f7ecfe1.tar.gz dexon-107dbb1954ac76647d4fceab5770285a5f7ecfe1.tar.zst dexon-107dbb1954ac76647d4fceab5770285a5f7ecfe1.zip |
sqlvm: common: replace table/index name with TableRef/IndexRef
Names will be mapped to references after parsing. Use references in hash
will have better performance.
-rw-r--r-- | core/vm/sqlvm/common/storage.go | 87 | ||||
-rw-r--r-- | core/vm/sqlvm/common/storage_test.go | 13 | ||||
-rw-r--r-- | core/vm/sqlvm/runtime/instructions.go | 4 | ||||
-rw-r--r-- | core/vm/sqlvm/runtime/instructions_test.go | 9 |
4 files changed, 69 insertions, 44 deletions
diff --git a/core/vm/sqlvm/common/storage.go b/core/vm/sqlvm/common/storage.go index 6ed7c2525..0244877a2 100644 --- a/core/vm/sqlvm/common/storage.go +++ b/core/vm/sqlvm/common/storage.go @@ -54,6 +54,22 @@ func bytesToUint64(b []byte) uint64 { return bigInt.Uint64() } +func uint8ToBytes(i uint8) []byte { + return []byte{i} +} + +func tableRefToBytes(t schema.TableRef) []byte { + return uint8ToBytes(uint8(t)) +} + +func columnRefToBytes(c schema.ColumnRef) []byte { + return uint8ToBytes(uint8(c)) +} + +func indexRefToBytes(i schema.IndexRef) []byte { + return uint8ToBytes(uint8(i)) +} + func hashToAddress(hash common.Hash) common.Address { return common.BytesToAddress(hash.Bytes()) } @@ -72,11 +88,11 @@ func (s *Storage) hashPathKey(key [][]byte) (h common.Hash) { } // GetRowPathHash return primary key hash which points to row data. -func (s *Storage) GetRowPathHash(tableName []byte, rowID uint64) common.Hash { +func (s *Storage) GetRowPathHash(tableRef schema.TableRef, rowID uint64) common.Hash { // PathKey(["tables", "{table_name}", "primary", uint64({row_id})]) key := [][]byte{ pathCompTables, - tableName, + tableRefToBytes(tableRef), pathCompPrimary, uint64ToBytes(rowID), } @@ -86,14 +102,15 @@ func (s *Storage) GetRowPathHash(tableName []byte, rowID uint64) common.Hash { // GetIndexValuesPathHash return the hash address to IndexValues structure // which contains all possible values. func (s *Storage) GetIndexValuesPathHash( - tableName, indexName []byte, + tableRef schema.TableRef, + indexRef schema.IndexRef, ) common.Hash { // PathKey(["tables", "{table_name}", "indices", "{index_name}"]) key := [][]byte{ pathCompTables, - tableName, + tableRefToBytes(tableRef), pathCompIndices, - indexName, + indexRefToBytes(indexRef), } return s.hashPathKey(key) } @@ -101,12 +118,14 @@ func (s *Storage) GetIndexValuesPathHash( // GetIndexEntryPathHash return the hash address to IndexEntry structure for a // given value. func (s *Storage) GetIndexEntryPathHash( - tableName, indexName []byte, + tableRef schema.TableRef, + indexRef schema.IndexRef, values ...[]byte, ) common.Hash { // PathKey(["tables", "{table_name}", "indices", "{index_name}", field_1, field_2, field_3, ...]) key := make([][]byte, 0, 4+len(values)) - key = append(key, pathCompTables, tableName, pathCompIndices, indexName) + key = append(key, pathCompTables, tableRefToBytes(tableRef)) + key = append(key, pathCompIndices, indexRefToBytes(indexRef)) key = append(key, values...) return s.hashPathKey(key) } @@ -114,13 +133,13 @@ func (s *Storage) GetIndexEntryPathHash( // GetReverseIndexPathHash return the hash address to IndexRev structure for a // row in a table. func (s *Storage) GetReverseIndexPathHash( - tableName []byte, + tableRef schema.TableRef, rowID uint64, ) common.Hash { // PathKey(["tables", "{table_name}", "reverse_indices", "{RowID}"]) key := [][]byte{ pathCompTables, - tableName, + tableRefToBytes(tableRef), pathCompReverseIndices, uint64ToBytes(rowID), } @@ -129,14 +148,14 @@ func (s *Storage) GetReverseIndexPathHash( // getSequencePathHash return the hash address of a sequence. func (s *Storage) getSequencePathHash( - tableName []byte, seqIdx uint8, + tableRef schema.TableRef, seqIdx uint8, ) common.Hash { // PathKey(["tables", "{table_name}", "sequence", uint8(sequence_idx)]) key := [][]byte{ pathCompTables, - tableName, + tableRefToBytes(tableRef), pathCompSequence, - {seqIdx}, // TODO(yenlin): use some other encode method on uint8? + uint8ToBytes(seqIdx), } return s.hashPathKey(key) } @@ -147,24 +166,24 @@ func (s *Storage) getOwnerPathHash() common.Hash { return s.hashPathKey(key) } -func (s *Storage) getTableWritersPathHash(tableName []byte) common.Hash { +func (s *Storage) getTableWritersPathHash(tableRef schema.TableRef) common.Hash { // PathKey(["tables", "{table_name}", "writers"]) key := [][]byte{ pathCompTables, - tableName, + tableRefToBytes(tableRef), pathCompWriters, } return s.hashPathKey(key) } func (s *Storage) getTableWriterRevIdxPathHash( - tableName []byte, + tableRef schema.TableRef, account common.Address, ) common.Hash { // PathKey(["tables", "{table_name}", "writers", "{addr}"]) key := [][]byte{ pathCompTables, - tableName, + tableRefToBytes(tableRef), pathCompWriters, account.Bytes(), } @@ -257,11 +276,12 @@ type IndexEntry struct { // LoadIndexValues load IndexValues struct of a given index. func (s *Storage) LoadIndexValues( contract common.Address, - tableName, indexName []byte, + tableRef schema.TableRef, + indexRef schema.IndexRef, onlyHeader bool, ) *IndexValues { ret := &IndexValues{} - slot := s.GetIndexValuesPathHash(tableName, indexName) + slot := s.GetIndexValuesPathHash(tableRef, indexRef) data := s.GetState(contract, slot) ret.Length = bytesToUint64(data[:8]) if onlyHeader { @@ -279,12 +299,13 @@ func (s *Storage) LoadIndexValues( // LoadIndexEntry load IndexEntry struct of a given value key on an index. func (s *Storage) LoadIndexEntry( contract common.Address, - tableName, indexName []byte, + tableRef schema.TableRef, + indexRef schema.IndexRef, onlyHeader bool, values ...[]byte, ) *IndexEntry { ret := &IndexEntry{} - slot := s.GetIndexEntryPathHash(tableName, indexName, values...) + slot := s.GetIndexEntryPathHash(tableRef, indexRef, values...) data := s.GetState(contract, slot) ret.Length = bytesToUint64(data[:8]) ret.IndexToValuesOffset = bytesToUint64(data[8:16]) @@ -415,10 +436,10 @@ func (s *Storage) storeSingleTableWriter( // IsTableWriter check if an account is writer to the table. func (s *Storage) IsTableWriter( contract common.Address, - tableName []byte, + tableRef schema.TableRef, account common.Address, ) bool { - path := s.getTableWriterRevIdxPathHash(tableName, account) + path := s.getTableWriterRevIdxPathHash(tableRef, account) rev := s.loadTableWriterRevIdx(contract, path) return rev.Valid() } @@ -426,9 +447,9 @@ func (s *Storage) IsTableWriter( // LoadTableWriters load writers of a table. func (s *Storage) LoadTableWriters( contract common.Address, - tableName []byte, + tableRef schema.TableRef, ) (ret []common.Address) { - path := s.getTableWritersPathHash(tableName) + path := s.getTableWritersPathHash(tableRef) writers := s.loadTableWriters(contract, path, false) return writers.Writers } @@ -436,15 +457,15 @@ func (s *Storage) LoadTableWriters( // InsertTableWriter insert an account into writer list of the table. func (s *Storage) InsertTableWriter( contract common.Address, - tableName []byte, + tableRef schema.TableRef, account common.Address, ) { - revPath := s.getTableWriterRevIdxPathHash(tableName, account) + revPath := s.getTableWriterRevIdxPathHash(tableRef, account) rev := s.loadTableWriterRevIdx(contract, revPath) if rev.Valid() { return } - path := s.getTableWritersPathHash(tableName) + path := s.getTableWritersPathHash(tableRef) writers := s.loadTableWriters(contract, path, true) // Store modification. s.storeSingleTableWriter(contract, path, writers.Length, account) @@ -459,15 +480,15 @@ func (s *Storage) InsertTableWriter( // DeleteTableWriter delete an account from writer list of the table. func (s *Storage) DeleteTableWriter( contract common.Address, - tableName []byte, + tableRef schema.TableRef, account common.Address, ) { - revPath := s.getTableWriterRevIdxPathHash(tableName, account) + revPath := s.getTableWriterRevIdxPathHash(tableRef, account) rev := s.loadTableWriterRevIdx(contract, revPath) if !rev.Valid() { return } - path := s.getTableWritersPathHash(tableName) + path := s.getTableWritersPathHash(tableRef) writers := s.loadTableWriters(contract, path, true) // Store modification. @@ -477,7 +498,7 @@ func (s *Storage) DeleteTableWriter( s.storeSingleTableWriter(contract, path, rev.IndexToValuesOffset-1, lastAcc) s.storeTableWriterRevIdx(contract, s.getTableWriterRevIdxPathHash( - tableName, lastAcc), rev) + tableRef, lastAcc), rev) } // Delete last. writers.Length-- @@ -489,11 +510,11 @@ func (s *Storage) DeleteTableWriter( // IncSequence increment value of sequence by inc and return the old value. func (s *Storage) IncSequence( contract common.Address, - tableName []byte, + tableRef schema.TableRef, seqIdx uint8, inc uint64, ) uint64 { - seqPath := s.getSequencePathHash(tableName, seqIdx) + seqPath := s.getSequencePathHash(tableRef, seqIdx) slot := s.GetState(contract, seqPath) val := bytesToUint64(slot.Bytes()) // TODO(yenlin): Check overflow? diff --git a/core/vm/sqlvm/common/storage_test.go b/core/vm/sqlvm/common/storage_test.go index aed07b4a8..44aff12f7 100644 --- a/core/vm/sqlvm/common/storage_test.go +++ b/core/vm/sqlvm/common/storage_test.go @@ -11,6 +11,7 @@ import ( "github.com/dexon-foundation/dexon/common" "github.com/dexon-foundation/dexon/core/state" + "github.com/dexon-foundation/dexon/core/vm/sqlvm/schema" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/rlp" @@ -27,10 +28,10 @@ func (s *StorageTestSuite) TestUint64ToBytes() { func (s *StorageTestSuite) TestGetRowAddress() { id := uint64(555666) - table := []byte("TABLE_A") + table := schema.TableRef(1) key := [][]byte{ []byte("tables"), - table, + {uint8(table)}, []byte("primary"), uint64ToBytes(id), } @@ -133,8 +134,8 @@ func (s *StorageTestSuite) TestTableWriter() { state, _ := state.New(common.Hash{}, state.NewDatabase(db)) storage := NewStorage(state) - table1 := []byte("table1") - table2 := []byte("table2") + table1 := schema.TableRef(0) + table2 := schema.TableRef(1) contractA := common.BytesToAddress([]byte("A")) contractB := common.BytesToAddress([]byte("B")) addrs := []common.Address{ @@ -192,8 +193,8 @@ func (s *StorageTestSuite) TestSequence() { state, _ := state.New(common.Hash{}, state.NewDatabase(db)) storage := NewStorage(state) - table1 := []byte("table1") - table2 := []byte("table2") + table1 := schema.TableRef(0) + table2 := schema.TableRef(1) contract := common.BytesToAddress([]byte("A")) s.Require().Equal(uint64(0), storage.IncSequence(contract, table1, 0, 2)) diff --git a/core/vm/sqlvm/runtime/instructions.go b/core/vm/sqlvm/runtime/instructions.go index 92d5753f5..e3a414123 100644 --- a/core/vm/sqlvm/runtime/instructions.go +++ b/core/vm/sqlvm/runtime/instructions.go @@ -15,6 +15,7 @@ import ( "github.com/dexon-foundation/dexon/core/vm/sqlvm/common" dec "github.com/dexon-foundation/dexon/core/vm/sqlvm/common/decimal" se "github.com/dexon-foundation/dexon/core/vm/sqlvm/errors" + "github.com/dexon-foundation/dexon/core/vm/sqlvm/schema" ) var ( @@ -104,6 +105,7 @@ func opLoad(ctx *common.Context, input []*Operand, registers []*Operand, output return se.ErrorCodeIndexOutOfRange } table := ctx.Storage.Schema[tableIdx] + tableRef := schema.TableRef(tableIdx) ids, err := input[1].toUint64() if err != nil { @@ -127,7 +129,7 @@ func opLoad(ctx *common.Context, input []*Operand, registers []*Operand, output } for i, id := range ids { slotDataCache := make(map[dexCommon.Hash]dexCommon.Hash) - head := ctx.Storage.GetRowPathHash(table.Name, id) + head := ctx.Storage.GetRowPathHash(tableRef, id) for j := range fields { col := table.Columns[int(fields[j])] byteOffset := col.ByteOffset diff --git a/core/vm/sqlvm/runtime/instructions_test.go b/core/vm/sqlvm/runtime/instructions_test.go index 7cf05c9f5..c071045e6 100644 --- a/core/vm/sqlvm/runtime/instructions_test.go +++ b/core/vm/sqlvm/runtime/instructions_test.go @@ -211,18 +211,19 @@ type opLoadTestCase struct { func (s *opLoadSuite) SetupTest() { s.ctx = &common.Context{} s.ctx.Storage = s.newStorage() - s.headHash = s.ctx.Storage.GetRowPathHash([]byte("Table_B"), uint64(123456)) + targetTableRef := schema.TableRef(1) + s.headHash = s.ctx.Storage.GetRowPathHash(targetTableRef, uint64(123456)) s.address = dexCommon.HexToAddress("0x6655") s.ctx.Storage.CreateAccount(s.address) s.ctx.Contract = vm.NewContract(vm.AccountRef(s.address), vm.AccountRef(s.address), new(big.Int), 0) s.slotHash, s.raws = setSlotDataInStateDB(s.headHash, s.address, s.ctx.Storage) createSchema(s.ctx.Storage, s.raws) - s.setColData("Table_B", 654321) + s.setColData(targetTableRef, 654321) } -func (s *opLoadSuite) setColData(tableName string, id uint64) { - h := s.ctx.Storage.GetRowPathHash([]byte(tableName), id) +func (s *opLoadSuite) setColData(tableRef schema.TableRef, id uint64) { + h := s.ctx.Storage.GetRowPathHash(tableRef, id) setSlotDataInStateDB(h, s.address, s.ctx.Storage) } |