aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMeng-Ying Yang <garfield@dexon.org>2019-04-08 10:20:21 +0800
committerJhih-Ming Huang <jm.huang@cobinhood.com>2019-05-06 10:44:04 +0800
commit7fa7af1678bcca79484b7e1b11bf9efdb3ae999c (patch)
treefd003a777518f6e9478cc3639a13255ef4ac93af
parentb35152c24e637d0e26b6a061466999faadcaa7e4 (diff)
downloaddexon-7fa7af1678bcca79484b7e1b11bf9efdb3ae999c.tar.gz
dexon-7fa7af1678bcca79484b7e1b11bf9efdb3ae999c.tar.zst
dexon-7fa7af1678bcca79484b7e1b11bf9efdb3ae999c.zip
core: vm: sqlvm: add opCut
Add `opCut` which supports slice cutting.
-rw-r--r--core/vm/sqlvm/runtime/instructions.go29
-rw-r--r--core/vm/sqlvm/runtime/instructions_op_test.go229
-rw-r--r--core/vm/sqlvm/runtime/instructions_tmpl_data.go202
-rw-r--r--core/vm/sqlvm/runtime/jumptable.go1
-rw-r--r--core/vm/sqlvm/runtime/opcodes.go1
5 files changed, 462 insertions, 0 deletions
diff --git a/core/vm/sqlvm/runtime/instructions.go b/core/vm/sqlvm/runtime/instructions.go
index e3a414123..cc00f741e 100644
--- a/core/vm/sqlvm/runtime/instructions.go
+++ b/core/vm/sqlvm/runtime/instructions.go
@@ -1369,6 +1369,35 @@ func pruneTuple(t Tuple, prune []int) Tuple {
}
// in-place Op
+func opCut(ctx *common.Context, ops, registers []*Operand, output uint) (err error) {
+ if len(ops) != 2 {
+ err = se.ErrorCodeInvalidOperandNum
+ return
+ }
+ op, slice := ops[0], ops[1].Data[0]
+
+ maxL := uint16(len(op.Meta))
+ start, end := value2ColIdx(slice[0].Value), maxL
+ if len(slice) > 1 {
+ end = value2ColIdx(slice[1].Value) + 1
+ }
+
+ if start > maxL || end > maxL || start > end {
+ err = se.ErrorCodeIndexOutOfRange
+ return
+ }
+
+ op.Meta = append(op.Meta[:start], op.Meta[end:]...)
+
+ for i := 0; i < len(op.Data); i++ {
+ op.Data[i] = append(op.Data[i][:start], op.Data[i][end:]...)
+ }
+
+ registers[output] = op
+ return
+}
+
+// in-place Op
func opSort(ctx *common.Context, ops, registers []*Operand, output uint) (err error) {
if len(ops) != 2 {
err = se.ErrorCodeInvalidOperandNum
diff --git a/core/vm/sqlvm/runtime/instructions_op_test.go b/core/vm/sqlvm/runtime/instructions_op_test.go
index a3f84037b..0255e74cf 100644
--- a/core/vm/sqlvm/runtime/instructions_op_test.go
+++ b/core/vm/sqlvm/runtime/instructions_op_test.go
@@ -2448,6 +2448,235 @@ func (s *instructionSuite) TestOpPrune() {
s.run(testcases, opPrune)
}
+func (s *instructionSuite) TestOpCut() {
+ testcases := []opTestcase{
+ {
+ "Cut 2nd to 4th columns",
+ Instruction{
+ Op: CUT,
+ Input: []*Operand{
+ makeOperand(
+ false,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorBool, 0), ast.ComposeDataType(ast.DataTypeMajorBool, 0),
+ },
+ []Tuple{
+ {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawFalse, rawTrue},
+ {&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}, rawTrue, rawFalse},
+ },
+ ),
+ makeOperand(
+ true,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0),
+ },
+ []Tuple{
+ {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(3)}},
+ },
+ ),
+ },
+ Output: 0,
+ },
+ makeOperand(
+ false,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorBool, 0),
+ },
+ []Tuple{
+ {&Raw{Bytes: []byte("abcdefg-1")}, rawTrue},
+ {&Raw{Bytes: []byte("abcdefg-2")}, rawFalse},
+ },
+ ),
+ nil,
+ },
+ {
+ "Cut 1st column",
+ Instruction{
+ Op: CUT,
+ Input: []*Operand{
+ makeOperand(
+ false,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorBool, 0), ast.ComposeDataType(ast.DataTypeMajorBool, 0),
+ },
+ []Tuple{
+ {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawFalse, rawTrue},
+ {&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}, rawTrue, rawFalse},
+ },
+ ),
+ makeOperand(
+ true,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0),
+ },
+ []Tuple{
+ {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}},
+ },
+ ),
+ },
+ Output: 0,
+ },
+ makeOperand(
+ false,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorBool, 0), ast.ComposeDataType(ast.DataTypeMajorBool, 0),
+ },
+ []Tuple{
+ {&Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawFalse, rawTrue},
+ {&Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}, rawTrue, rawFalse},
+ },
+ ),
+ nil,
+ },
+ {
+ "Cut since 2nd column",
+ Instruction{
+ Op: CUT,
+ Input: []*Operand{
+ makeOperand(
+ false,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorBool, 0),
+ },
+ []Tuple{
+ {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue},
+ {&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse},
+ },
+ ),
+ makeOperand(
+ true,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorInt, 0),
+ },
+ []Tuple{
+ {&Raw{Value: decimal.NewFromFloat(1)}},
+ },
+ ),
+ },
+ Output: 0,
+ },
+ makeOperand(
+ false,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0),
+ },
+ []Tuple{
+ {&Raw{Bytes: []byte("abcdefg-1")}},
+ {&Raw{Bytes: []byte("abcdefg-2")}},
+ },
+ ),
+ nil,
+ },
+ {
+ "Cut all columns",
+ Instruction{
+ Op: CUT,
+ Input: []*Operand{
+ makeOperand(
+ false,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorBool, 0),
+ },
+ []Tuple{
+ {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue},
+ {&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse},
+ },
+ ),
+ makeOperand(
+ true,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorInt, 0),
+ },
+ []Tuple{
+ {&Raw{Value: decimal.NewFromFloat(0)}},
+ },
+ ),
+ },
+ Output: 0,
+ },
+ makeOperand(
+ false,
+ []ast.DataType{},
+ []Tuple{
+ {},
+ {},
+ },
+ ),
+ nil,
+ },
+ {
+ "Cut error range - 1",
+ Instruction{
+ Op: CUT,
+ Input: []*Operand{
+ makeOperand(
+ false,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorBool, 0),
+ },
+ []Tuple{
+ {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue},
+ {&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse},
+ },
+ ),
+ makeOperand(
+ true,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorInt, 0),
+ },
+ []Tuple{
+ {&Raw{Value: decimal.NewFromFloat(5)}},
+ },
+ ),
+ },
+ Output: 0,
+ },
+ makeOperand(
+ false,
+ []ast.DataType{},
+ []Tuple{},
+ ),
+ errors.ErrorCodeIndexOutOfRange,
+ },
+ {
+ "Cut error range - 2",
+ Instruction{
+ Op: CUT,
+ Input: []*Operand{
+ makeOperand(
+ false,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorDynamicBytes, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorBool, 0),
+ },
+ []Tuple{
+ {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue},
+ {&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse},
+ },
+ ),
+ makeOperand(
+ true,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0),
+ },
+ []Tuple{
+ {&Raw{Value: decimal.NewFromFloat(15)}, &Raw{Value: decimal.NewFromFloat(17)}},
+ },
+ ),
+ },
+ Output: 0,
+ },
+ makeOperand(
+ false,
+ []ast.DataType{},
+ []Tuple{},
+ ),
+ errors.ErrorCodeIndexOutOfRange,
+ },
+ }
+
+ s.run(testcases, opCut)
+}
+
func (s *instructionSuite) TestOpFilter() {
testcases := []opTestcase{
{
diff --git a/core/vm/sqlvm/runtime/instructions_tmpl_data.go b/core/vm/sqlvm/runtime/instructions_tmpl_data.go
index 210adafed..c4a7ac4a7 100644
--- a/core/vm/sqlvm/runtime/instructions_tmpl_data.go
+++ b/core/vm/sqlvm/runtime/instructions_tmpl_data.go
@@ -1543,6 +1543,208 @@ var testData = &tmplData{
},
// -- end of PRUNE
{
+ TestName: "OpCut", OpFunc: "opCut",
+ Cases: []*tmplTestCase{
+ {
+ Name: "Cut 2nd to 4th columns",
+ Error: "nil", OpCode: "CUT",
+ Inputs: []*tmplOp{
+ {
+ Im: false,
+ Metas: []*tmplOpMeta{
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "Int", Minor: 0},
+ {Major: "Bool", Minor: 0},
+ {Major: "Bool", Minor: 0},
+ },
+ Data: []string{
+ `{B: "abcdefg-1", B: "gfedcba-1", V: 1, F, T}`,
+ `{B: "abcdefg-2", B: "gfedcba-2", V: 2, T, F}`,
+ },
+ },
+ {
+ Im: true,
+ Metas: []*tmplOpMeta{
+ {Major: "Int", Minor: 0},
+ {Major: "Int", Minor: 0},
+ },
+ Data: []string{"{V: 1, V: 3}"},
+ },
+ },
+ Output: &tmplOp{
+ Im: false,
+ Metas: []*tmplOpMeta{
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "Bool", Minor: 0},
+ },
+ Data: []string{
+ `{B: "abcdefg-1", T}`,
+ `{B: "abcdefg-2", F}`,
+ },
+ },
+ },
+ {
+ Name: "Cut 1st column",
+ Error: "nil", OpCode: "CUT",
+ Inputs: []*tmplOp{
+ {
+ Im: false,
+ Metas: []*tmplOpMeta{
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "Int", Minor: 0},
+ {Major: "Bool", Minor: 0},
+ {Major: "Bool", Minor: 0},
+ },
+ Data: []string{
+ `{B: "abcdefg-1", B: "gfedcba-1", V: 1, F, T}`,
+ `{B: "abcdefg-2", B: "gfedcba-2", V: 2, T, F}`,
+ },
+ },
+ {
+ Im: true,
+ Metas: []*tmplOpMeta{
+ {Major: "Int", Minor: 0},
+ {Major: "Int", Minor: 0},
+ },
+ Data: []string{"{V: 0, V: 0}"},
+ },
+ },
+ Output: &tmplOp{
+ Im: false,
+ Metas: []*tmplOpMeta{
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "Int", Minor: 0},
+ {Major: "Bool", Minor: 0},
+ {Major: "Bool", Minor: 0},
+ },
+ Data: []string{
+ `{B: "gfedcba-1", V: 1, F, T}`,
+ `{B: "gfedcba-2", V: 2, T, F}`,
+ },
+ },
+ },
+ {
+ Name: "Cut since 2nd column",
+ Error: "nil", OpCode: "CUT",
+ Inputs: []*tmplOp{
+ {
+ Im: false,
+ Metas: []*tmplOpMeta{
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "Int", Minor: 0},
+ {Major: "Bool", Minor: 0},
+ },
+ Data: []string{
+ `{B: "abcdefg-1", B: "gfedcba-1", V: 1, T}`,
+ `{B: "abcdefg-2", B: "gfedcba-2", V: 2, F}`,
+ },
+ },
+ {
+ Im: true,
+ Metas: []*tmplOpMeta{{Major: "Int", Minor: 0}},
+ Data: []string{"{V: 1}"},
+ },
+ },
+ Output: &tmplOp{
+ Im: false,
+ Metas: []*tmplOpMeta{
+ {Major: "DynamicBytes", Minor: 0},
+ },
+ Data: []string{
+ `{B: "abcdefg-1"}`,
+ `{B: "abcdefg-2"}`,
+ },
+ },
+ },
+ {
+ Name: "Cut all columns",
+ Error: "nil", OpCode: "CUT",
+ Inputs: []*tmplOp{
+ {
+ Im: false,
+ Metas: []*tmplOpMeta{
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "Int", Minor: 0},
+ {Major: "Bool", Minor: 0},
+ },
+ Data: []string{
+ `{B: "abcdefg-1", B: "gfedcba-1", V: 1, T}`,
+ `{B: "abcdefg-2", B: "gfedcba-2", V: 2, F}`,
+ },
+ },
+ {
+ Im: true,
+ Metas: []*tmplOpMeta{{Major: "Int", Minor: 0}},
+ Data: []string{"{V: 0}"},
+ },
+ },
+ Output: &tmplOp{
+ Im: false,
+ Metas: []*tmplOpMeta{},
+ Data: []string{"{}", "{}"},
+ },
+ },
+ {
+ Name: "Cut error range - 1",
+ Error: "errors.ErrorCodeIndexOutOfRange", OpCode: "CUT",
+ Inputs: []*tmplOp{
+ {
+ Im: false,
+ Metas: []*tmplOpMeta{
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "Int", Minor: 0},
+ {Major: "Bool", Minor: 0},
+ },
+ Data: []string{
+ `{B: "abcdefg-1", B: "gfedcba-1", V: 1, T}`,
+ `{B: "abcdefg-2", B: "gfedcba-2", V: 2, F}`,
+ },
+ },
+ {
+ Im: true,
+ Metas: []*tmplOpMeta{{Major: "Int", Minor: 0}},
+ Data: []string{"{V: 5}"},
+ },
+ },
+ Output: &tmplOp{},
+ },
+ {
+ Name: "Cut error range - 2",
+ Error: "errors.ErrorCodeIndexOutOfRange", OpCode: "CUT",
+ Inputs: []*tmplOp{
+ {
+ Im: false,
+ Metas: []*tmplOpMeta{
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "DynamicBytes", Minor: 0},
+ {Major: "Int", Minor: 0},
+ {Major: "Bool", Minor: 0},
+ },
+ Data: []string{
+ `{B: "abcdefg-1", B: "gfedcba-1", V: 1, T}`,
+ `{B: "abcdefg-2", B: "gfedcba-2", V: 2, F}`,
+ },
+ },
+ {
+ Im: true,
+ Metas: []*tmplOpMeta{
+ {Major: "Int", Minor: 0},
+ {Major: "Int", Minor: 0},
+ },
+ Data: []string{"{V: 15, V: 17}"},
+ },
+ },
+ Output: &tmplOp{},
+ },
+ },
+ },
+ // -- end of CUT
+ {
TestName: "OpFilter", OpFunc: "opFilter",
Cases: []*tmplTestCase{
{
diff --git a/core/vm/sqlvm/runtime/jumptable.go b/core/vm/sqlvm/runtime/jumptable.go
index 415a4e62b..2408ee0f4 100644
--- a/core/vm/sqlvm/runtime/jumptable.go
+++ b/core/vm/sqlvm/runtime/jumptable.go
@@ -26,6 +26,7 @@ var jumpTable = [256]OpFunction{
SORT: opSort,
FILTER: opFilter,
CAST: opCast,
+ CUT: opCut,
// 0x60
LOAD: opLoad,
diff --git a/core/vm/sqlvm/runtime/opcodes.go b/core/vm/sqlvm/runtime/opcodes.go
index 88bc039e1..07b30bdc3 100644
--- a/core/vm/sqlvm/runtime/opcodes.go
+++ b/core/vm/sqlvm/runtime/opcodes.go
@@ -45,6 +45,7 @@ const (
SORT
FILTER
CAST
+ CUT
)
// 0x60 range - storage ops