aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMeng-Ying Yang <garfield@dexon.org>2019-04-16 17:31:23 +0800
committerMeng-Ying Yang <garfield@dexon.org>2019-05-09 09:29:30 +0800
commit239b0afbe0b092dc1af91d9e90a810da584b4315 (patch)
treee346209b88b9a82e2b7f9b48ccb0a2f46fe633e7
parentf60d57ffc915e9a4131da02a743763603332c8b3 (diff)
downloaddexon-239b0afbe0b092dc1af91d9e90a810da584b4315.tar.gz
dexon-239b0afbe0b092dc1af91d9e90a810da584b4315.tar.zst
dexon-239b0afbe0b092dc1af91d9e90a810da584b4315.zip
core: vm: sqlvm: add built-in function BITNOT()
-rw-r--r--core/vm/sqlvm/runtime/functions.go49
-rw-r--r--core/vm/sqlvm/runtime/instructions_op_test.go53
-rw-r--r--core/vm/sqlvm/runtime/instructions_tmpl_data.go50
3 files changed, 152 insertions, 0 deletions
diff --git a/core/vm/sqlvm/runtime/functions.go b/core/vm/sqlvm/runtime/functions.go
index 7b062fdee..d426c8a77 100644
--- a/core/vm/sqlvm/runtime/functions.go
+++ b/core/vm/sqlvm/runtime/functions.go
@@ -29,6 +29,7 @@ const (
BITAND
BITOR
BITXOR
+ BITNOT
)
type fn func(*common.Context, []*Operand, uint64) (*Operand, error)
@@ -48,6 +49,7 @@ var (
BITAND: fnBitAnd,
BITOR: fnBitOr,
BITXOR: fnBitXor,
+ BITNOT: fnBitNot,
}
)
@@ -356,3 +358,50 @@ func fnBitXor(ctx *common.Context, ops []*Operand, length uint64) (result *Opera
}
return
}
+
+type bitUnFunc func(b byte) byte
+
+func fnBitNot(ctx *common.Context, ops []*Operand, length uint64) (result *Operand, err error) {
+ if len(ops) < 2 {
+ err = se.ErrorCodeInvalidOperandNum
+ return
+ }
+
+ op := ops[1]
+ if !metaAllBitOp(op) {
+ err = se.ErrorCodeInvalidDataType
+ return
+ }
+
+ result = op.clone(true)
+ result.Data = make([]Tuple, len(op.Data))
+ for i := 0; i < len(op.Data); i++ {
+ result.Data[i] = op.Data[i].bitUnOp(
+ op.Meta,
+ func(b byte) byte { return ^b },
+ )
+ }
+ return
+}
+
+func (t Tuple) bitUnOp(meta []ast.DataType, bFn bitUnFunc) (t2 Tuple) {
+ t2 = make(Tuple, len(t))
+ for i := 0; i < len(t); i++ {
+ t2[i] = t[i].bitUnOp(meta[i], bFn)
+ }
+ return
+}
+
+func (r *Raw) bitUnOp(dType ast.DataType, bFn bitUnFunc) (r2 *Raw) {
+ bytes := r.toBytes(dType)
+
+ n := len(bytes)
+ bytes2 := make([]byte, n)
+ for i := 0; i < n; i++ {
+ bytes2[i] = bFn(bytes[i])
+ }
+
+ r2 = &Raw{}
+ r2.fromBytes(bytes2, dType)
+ return
+}
diff --git a/core/vm/sqlvm/runtime/instructions_op_test.go b/core/vm/sqlvm/runtime/instructions_op_test.go
index 42f5074db..088d889fb 100644
--- a/core/vm/sqlvm/runtime/instructions_op_test.go
+++ b/core/vm/sqlvm/runtime/instructions_op_test.go
@@ -3879,3 +3879,56 @@ func (s *instructionSuite) TestOpFuncBitXor() {
s.run(testcases, opFunc)
}
+
+func (s *instructionSuite) TestOpFuncBitNot() {
+ testcases := []opTestcase{
+ {
+ "Func BitNot",
+ Instruction{
+ Op: FUNC,
+ Input: []*Operand{
+ makeOperand(
+ true,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorUint, 0),
+ },
+ []Tuple{
+ {&Raw{Value: decimal.NewFromFloat(2)}},
+ },
+ ),
+ makeOperand(
+ true,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorUint, 1),
+ },
+ []Tuple{
+ {&Raw{Value: decimal.NewFromFloat(13)}},
+ },
+ ),
+ makeOperand(
+ false,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorUint, 0), ast.ComposeDataType(ast.DataTypeMajorUint, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorFixedBytes, 0), ast.ComposeDataType(ast.DataTypeMajorFixedBytes, 0),
+ },
+ []Tuple{
+ {&Raw{Value: decimal.NewFromFloat(128)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-128)}, &Raw{Bytes: []byte{0x12, 0x34}}, &Raw{Bytes: []byte{0xff, 0x00}}},
+ },
+ ),
+ },
+ Output: 0,
+ },
+ makeOperand(
+ false,
+ []ast.DataType{
+ ast.ComposeDataType(ast.DataTypeMajorUint, 0), ast.ComposeDataType(ast.DataTypeMajorUint, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorFixedBytes, 0), ast.ComposeDataType(ast.DataTypeMajorFixedBytes, 0),
+ },
+ []Tuple{
+ {&Raw{Value: decimal.NewFromFloat(127)}, &Raw{Value: decimal.NewFromFloat(255)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(127)}, &Raw{Bytes: []byte{0xed, 0xcb}}, &Raw{Bytes: []byte{0x00, 0xff}}},
+ },
+ ),
+ nil,
+ },
+ }
+
+ s.run(testcases, opFunc)
+}
diff --git a/core/vm/sqlvm/runtime/instructions_tmpl_data.go b/core/vm/sqlvm/runtime/instructions_tmpl_data.go
index c0928615f..6cc1716eb 100644
--- a/core/vm/sqlvm/runtime/instructions_tmpl_data.go
+++ b/core/vm/sqlvm/runtime/instructions_tmpl_data.go
@@ -2784,5 +2784,55 @@ var testData = &tmplData{
},
},
// -- end of FUNC BITXOR
+ {
+ TestName: "OpFuncBitNot", OpFunc: "opFunc",
+ Cases: []*tmplTestCase{
+ {
+ Name: "Func BitNot",
+ Error: "nil", OpCode: "FUNC",
+ Inputs: []*tmplOp{
+ {
+ Im: true,
+ Metas: []*tmplOpMeta{
+ {Major: "Uint", Minor: 0},
+ },
+ Data: []string{`{V: 2}`},
+ },
+ {
+ Im: true,
+ Metas: []*tmplOpMeta{
+ {Major: "Uint", Minor: 1},
+ },
+ Data: []string{`{V: 13}`},
+ },
+ {
+ Im: false,
+ Metas: []*tmplOpMeta{
+ {Major: "Uint", Minor: 0},
+ {Major: "Uint", Minor: 0},
+ {Major: "Int", Minor: 0},
+ {Major: "Int", Minor: 0},
+ {Major: "FixedBytes", Minor: 0},
+ {Major: "FixedBytes", Minor: 0},
+ },
+ Data: []string{"{V: 128, V: 0, V: -1, V: -128, B: {0x12, 0x34}, B: {0xff, 0x00}}"},
+ },
+ },
+ Output: &tmplOp{
+ Im: false,
+ Metas: []*tmplOpMeta{
+ {Major: "Uint", Minor: 0},
+ {Major: "Uint", Minor: 0},
+ {Major: "Int", Minor: 0},
+ {Major: "Int", Minor: 0},
+ {Major: "FixedBytes", Minor: 0},
+ {Major: "FixedBytes", Minor: 0},
+ },
+ Data: []string{`{V: 127, V: 255, V: 0, V: 127, B: {0xed, 0xcb}, B: {0x00, 0xff}}`},
+ },
+ },
+ },
+ },
+ // -- end of FUNC BITNOT
},
}