aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm/sqlvm/runtime/instructions.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/vm/sqlvm/runtime/instructions.go')
-rw-r--r--core/vm/sqlvm/runtime/instructions.go109
1 files changed, 101 insertions, 8 deletions
diff --git a/core/vm/sqlvm/runtime/instructions.go b/core/vm/sqlvm/runtime/instructions.go
index 668da692c..5a61d5f80 100644
--- a/core/vm/sqlvm/runtime/instructions.go
+++ b/core/vm/sqlvm/runtime/instructions.go
@@ -2,11 +2,14 @@ package runtime
import (
"fmt"
- "math/big"
"strings"
+ "github.com/shopspring/decimal"
+
+ dexCommon "github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/core/vm/sqlvm/ast"
"github.com/dexon-foundation/dexon/core/vm/sqlvm/common"
+ "github.com/dexon-foundation/dexon/core/vm/sqlvm/errors"
)
var tupleJoin = "|"
@@ -27,17 +30,12 @@ type Instruction struct {
// Raw with embedded big.Int value or byte slice which represents the real value
// of basic operand unit.
type Raw struct {
- MajorType ast.DataTypeMajor
- MinorType ast.DataTypeMinor
-
- Value *big.Int
+ Value decimal.Decimal
Bytes []byte
}
func (r *Raw) String() string {
- return fmt.Sprintf(
- "MajorType: %v, MinorType: %v, Value: %v, Bytes :%v",
- r.MajorType, r.MinorType, r.Value, r.Bytes)
+ return fmt.Sprintf("Value: %v, Bytes: %v", r.Value, r.Bytes)
}
// Tuple is collection of Raw.
@@ -59,3 +57,98 @@ type Operand struct {
Data []Tuple
RegisterIndex uint
}
+
+func (o *Operand) toUint64() []uint64 {
+ result := make([]uint64, len(o.Data))
+ for i, tuple := range o.Data {
+ result[i] = uint64(tuple[0].Value.IntPart())
+ }
+ return result
+}
+
+func (o *Operand) toUint8() []uint8 {
+ result := make([]uint8, len(o.Data))
+ for i, tuple := range o.Data {
+ result[i] = uint8(tuple[0].Value.IntPart())
+ }
+ return result
+}
+
+func opLoad(ctx *common.Context, input []*Operand, registers []*Operand, output int) error {
+ tableIdx := input[0].Data[0][0].Value.IntPart()
+ if tableIdx >= int64(len(ctx.Storage.Schema)) {
+ return errors.ErrorCodeIndexOutOfRange
+ }
+ table := ctx.Storage.Schema[tableIdx]
+
+ ids := input[1].toUint64()
+ fields := input[2].toUint8()
+ op := Operand{
+ IsImmediate: false,
+ Data: make([]Tuple, len(ids)),
+ RegisterIndex: 0,
+ }
+ for i := range op.Data {
+ op.Data[i] = make([]*Raw, len(fields))
+ }
+ meta, err := table.GetFieldType(fields)
+ if err != nil {
+ return err
+ }
+ op.Meta = meta
+ for i, id := range ids {
+ slotDataCache := make(map[dexCommon.Hash]dexCommon.Hash)
+ head := ctx.Storage.GetPrimaryKeyHash(table.Name, id)
+ for j := range fields {
+ col := table.Columns[int(fields[j])]
+ byteOffset := col.ByteOffset
+ slotOffset := col.SlotOffset
+ dt := meta[j]
+ size := dt.Size()
+ slot := ctx.Storage.ShiftHashUint64(head, uint64(slotOffset))
+ slotData := getSlotData(ctx, slot, slotDataCache)
+ bytes := slotData.Bytes()[byteOffset : byteOffset+size]
+ op.Data[i][j], err = decode(ctx, dt, slot, bytes)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ registers[output] = &op
+ return nil
+}
+
+func getSlotData(ctx *common.Context, slot dexCommon.Hash,
+ cache map[dexCommon.Hash]dexCommon.Hash) dexCommon.Hash {
+ if d, exist := cache[slot]; exist {
+ return d
+ }
+ cache[slot] = ctx.Storage.GetState(ctx.Contract.Address(), slot)
+ return cache[slot]
+}
+
+// decode byte data to Raw format
+func decode(ctx *common.Context, dt ast.DataType, slot dexCommon.Hash, bytes []byte) (*Raw, error) {
+ rVal := &Raw{}
+ major, _ := ast.DecomposeDataType(dt)
+ switch major {
+ case ast.DataTypeMajorDynamicBytes:
+ rVal.Bytes = ctx.Storage.DecodeDByteBySlot(ctx.Contract.Address(), slot)
+ case ast.DataTypeMajorFixedBytes, ast.DataTypeMajorBool,
+ ast.DataTypeMajorAddress, ast.DataTypeMajorInt,
+ ast.DataTypeMajorUint:
+ d, err := ast.DecimalDecode(dt, bytes)
+ if err != nil {
+ return nil, err
+ }
+ rVal.Value = d
+ }
+ if major.IsFixedRange() || major.IsUfixedRange() {
+ d, err := ast.DecimalDecode(dt, bytes)
+ if err != nil {
+ return nil, err
+ }
+ rVal.Value = d
+ }
+ return rVal, nil
+}