aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryenlin.lai <yenlin.lai@cobinhood.com>2019-04-18 10:13:29 +0800
committerJhih-Ming Huang <jm.huang@cobinhood.com>2019-05-06 10:44:04 +0800
commit107dbb1954ac76647d4fceab5770285a5f7ecfe1 (patch)
tree333a4e5a2f5713f0c91dd1efa443dff079c77468
parent5b71bbd50a64d3b1576626d4cf0ca22569b57cf8 (diff)
downloaddexon-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.go87
-rw-r--r--core/vm/sqlvm/common/storage_test.go13
-rw-r--r--core/vm/sqlvm/runtime/instructions.go4
-rw-r--r--core/vm/sqlvm/runtime/instructions_test.go9
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)
}