aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryenlin.lai <yenlin.lai@cobinhood.com>2019-04-01 18:03:23 +0800
committeryenlin.lai <yenlin.lai@cobinhood.com>2019-04-03 16:59:48 +0800
commita1d8558dba947afd56d0cc4a0144537270c1a6fa (patch)
tree1b830f3066a6f6c960e481607d757ebb08269001
parent14a72212c5d80ffdfe1e1a8068779212f5f2057e (diff)
downloaddexon-a1d8558dba947afd56d0cc4a0144537270c1a6fa.tar.gz
dexon-a1d8558dba947afd56d0cc4a0144537270c1a6fa.tar.zst
dexon-a1d8558dba947afd56d0cc4a0144537270c1a6fa.zip
sqlvm: planner: use ColumnDescriptor
-rw-r--r--core/vm/sqlvm/planner/planner.go74
-rw-r--r--core/vm/sqlvm/planner/planner_test.go326
-rw-r--r--core/vm/sqlvm/planner/types.go2
-rw-r--r--core/vm/sqlvm/planner/utils.go62
-rw-r--r--core/vm/sqlvm/planner/utils_test.go89
5 files changed, 386 insertions, 167 deletions
diff --git a/core/vm/sqlvm/planner/planner.go b/core/vm/sqlvm/planner/planner.go
index 5f2f06e25..7b4ba4bb9 100644
--- a/core/vm/sqlvm/planner/planner.go
+++ b/core/vm/sqlvm/planner/planner.go
@@ -1,7 +1,7 @@
package planner
import (
- "github.com/shopspring/decimal"
+ "github.com/dexon-foundation/decimal"
"github.com/dexon-foundation/dexon/core/vm/sqlvm/ast"
"github.com/dexon-foundation/dexon/core/vm/sqlvm/common"
@@ -22,12 +22,9 @@ type planner struct {
}
func (planner *planner) planInsert(stmt *ast.InsertStmtNode) (PlanStep, error) {
- tableIdx, ok := findTableIdxByName(planner.schema, stmt.Table.Name)
- if !ok {
- panic("Invalid table name.")
- }
- planner.tableRef = tableIdx
- planner.table = &planner.schema[tableIdx]
+ tableDesc := stmt.Table.Desc.(*schema.TableDescriptor)
+ planner.tableRef = tableDesc.Table
+ planner.table = &planner.schema[planner.tableRef]
plan := &InsertStep{}
plan.Table = planner.tableRef
@@ -36,11 +33,7 @@ func (planner *planner) planInsert(stmt *ast.InsertStmtNode) (PlanStep, error) {
case *ast.InsertWithColumnOptionNode:
plan.Columns = make([]schema.ColumnRef, len(node.Column))
for i, node := range node.Column {
- columnIdx, ok := findColumnIdxByName(planner.table, node.Name)
- if !ok {
- panic("Invalid column name.")
- }
- plan.Columns[i] = columnIdx
+ plan.Columns[i] = node.Desc.(*schema.ColumnDescriptor).Column
}
plan.Values = node.Value
case *ast.InsertWithDefaultOptionNode:
@@ -67,10 +60,12 @@ func (planner *planner) mergeAndHashKeys(cl *clause) {
rightColMap := make([]int, len(cl.SubCls[1].ColumnSet))
for i, j, k := 0, 0, 0; k < colNum; {
switch {
- case i < len(leftCols) && leftCols[i] == cl.ColumnSet[k]:
+ case i < len(leftCols) &&
+ compareColumn(leftCols[i], cl.ColumnSet[k]) == 0:
leftColMap[i] = k
i++
- case j < len(rightCols) && rightCols[j] == cl.ColumnSet[k]:
+ case j < len(rightCols) &&
+ compareColumn(rightCols[j], cl.ColumnSet[k]) == 0:
rightColMap[j] = k
j++
default:
@@ -138,14 +133,15 @@ func (planner *planner) parseClause(node ast.ExprNode) (*clause, error) {
switch op := node.(type) {
case *ast.IdentifierNode:
// Column.
- // TODO(yenlin): bool column is directly enumerable.
- colIdx, ok := findColumnIdxByName(planner.table, op.Name)
- if !ok {
+ switch desc := op.Desc.(type) {
+ case *schema.ColumnDescriptor:
+ cl.ColumnSet = []*schema.ColumnDescriptor{desc}
+ default:
// This is function name.
// TODO(yenlin): distinguish function name from column names.
break
}
- cl.ColumnSet = []schema.ColumnRef{colIdx}
+ // TODO(yenlin): bool column is directly enumerable.
cl.Attr |= clauseAttrColumn
case ast.Valuer:
// Constant value.
@@ -272,8 +268,14 @@ func (planner *planner) planWhereclause(
for i, index := range planner.table.Indices {
var plan PlanStep
- // NOTICE: we need the index.Columns in ascending order.
- columnSet := (ColumnSet)(index.Columns)
+ var columnSet ColumnSet
+ columnSet = make([]*schema.ColumnDescriptor, len(index.Columns))
+ for i := range columnSet {
+ columnSet[i] = &schema.ColumnDescriptor{
+ Table: planner.tableRef,
+ Column: index.Columns[i],
+ }
+ }
if clause.Attr&clauseAttrEnumerable != 0 &&
columnSet.Equal(clause.ColumnSet) {
// Values are known for hash.
@@ -363,12 +365,9 @@ func (planner *planner) planSelect(stmt *ast.SelectStmtNode) (PlanStep, error) {
if stmt.Table == nil {
return planner.planSelectWithoutTable(stmt)
}
- tableIdx, ok := findTableIdxByName(planner.schema, stmt.Table.Name)
- if !ok {
- panic("Invalid table name.")
- }
- planner.tableRef = tableIdx
- planner.table = &planner.schema[tableIdx]
+ tableDesc := stmt.Table.Desc.(*schema.TableDescriptor)
+ planner.tableRef = tableDesc.Table
+ planner.table = &planner.schema[planner.tableRef]
wherePlan, err := planner.planWhere(stmt.Where)
if err != nil {
@@ -407,12 +406,9 @@ func (planner *planner) planSelect(stmt *ast.SelectStmtNode) (PlanStep, error) {
}
func (planner *planner) planUpdate(stmt *ast.UpdateStmtNode) (PlanStep, error) {
- tableIdx, ok := findTableIdxByName(planner.schema, stmt.Table.Name)
- if !ok {
- panic("Invalid table name.")
- }
- planner.tableRef = tableIdx
- planner.table = &planner.schema[tableIdx]
+ tableDesc := stmt.Table.Desc.(*schema.TableDescriptor)
+ planner.tableRef = tableDesc.Table
+ planner.table = &planner.schema[planner.tableRef]
wherePlan, err := planner.planWhere(stmt.Where)
if err != nil {
@@ -428,10 +424,7 @@ func (planner *planner) planUpdate(stmt *ast.UpdateStmtNode) (PlanStep, error) {
if err != nil {
return nil, err
}
- columnIdx, ok := findColumnIdxByName(planner.table, as.Column.Name)
- if !ok {
- panic("Invalid column name.")
- }
+ columnIdx := as.Column.Desc.(*schema.ColumnDescriptor).Column
plan.Columns[i] = columnIdx
plan.Values[i] = as.Expr
plan.ColumnSet = plan.ColumnSet.Join(cl.ColumnSet)
@@ -441,12 +434,9 @@ func (planner *planner) planUpdate(stmt *ast.UpdateStmtNode) (PlanStep, error) {
}
func (planner *planner) planDelete(stmt *ast.DeleteStmtNode) (PlanStep, error) {
- tableIdx, ok := findTableIdxByName(planner.schema, stmt.Table.Name)
- if !ok {
- panic("Invalid table name.")
- }
- planner.tableRef = tableIdx
- planner.table = &planner.schema[tableIdx]
+ tableDesc := stmt.Table.Desc.(*schema.TableDescriptor)
+ planner.tableRef = tableDesc.Table
+ planner.table = &planner.schema[planner.tableRef]
wherePlan, err := planner.planWhere(stmt.Where)
if err != nil {
diff --git a/core/vm/sqlvm/planner/planner_test.go b/core/vm/sqlvm/planner/planner_test.go
index a1065db1e..a13659a1d 100644
--- a/core/vm/sqlvm/planner/planner_test.go
+++ b/core/vm/sqlvm/planner/planner_test.go
@@ -4,7 +4,7 @@ import (
"fmt"
"testing"
- "github.com/shopspring/decimal"
+ "github.com/dexon-foundation/decimal"
"github.com/stretchr/testify/suite"
"github.com/dexon-foundation/dexon/core/vm/sqlvm/ast"
@@ -77,11 +77,20 @@ func (s *PlannerTestSuite) TestBasic() {
}
{
stmt := &ast.InsertStmtNode{
- Table: &ast.IdentifierNode{Name: []byte("table1")},
+ Table: &ast.IdentifierNode{
+ Name: []byte("table1"),
+ Desc: &schema.TableDescriptor{Table: 0},
+ },
Insert: &ast.InsertWithColumnOptionNode{
Column: []*ast.IdentifierNode{
- &ast.IdentifierNode{Name: []byte("a")},
- &ast.IdentifierNode{Name: []byte("b")},
+ &ast.IdentifierNode{
+ Name: []byte("a"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 0},
+ },
+ &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
},
Value: [][]ast.ExprNode{
[]ast.ExprNode{
@@ -109,24 +118,38 @@ func (s *PlannerTestSuite) TestBasic() {
{
expr := &ast.AddOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("b")},
- Subject: &ast.IdentifierNode{Name: []byte("b")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
+ Subject: &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
},
}
stmt := &ast.UpdateStmtNode{
- Table: &ast.IdentifierNode{Name: []byte("table1")},
+ Table: &ast.IdentifierNode{
+ Name: []byte("table1"),
+ Desc: &schema.TableDescriptor{Table: 0},
+ },
Assignment: []*ast.AssignOperatorNode{
&ast.AssignOperatorNode{
- Column: &ast.IdentifierNode{Name: []byte("a")},
- Expr: expr,
+ Column: &ast.IdentifierNode{
+ Name: []byte("a"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 0},
+ },
+ Expr: expr,
},
},
}
expectedPlan := &UpdateStep{
- Table: 0,
- ColumnSet: ColumnSet{1},
- Columns: []schema.ColumnRef{0},
- Values: []ast.ExprNode{expr},
+ Table: 0,
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
+ Columns: []schema.ColumnRef{0},
+ Values: []ast.ExprNode{expr},
// Children.
PlanStepBase: PlanStepBase{
Operands: []PlanStep{
@@ -149,21 +172,36 @@ func (s *PlannerTestSuite) TestBasic() {
offset := decimal.New(20, 0)
stmt := &ast.SelectStmtNode{
Column: []ast.ExprNode{
- &ast.IdentifierNode{Name: []byte("a")},
- &ast.IdentifierNode{Name: []byte("b")},
+ &ast.IdentifierNode{
+ Name: []byte("a"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 0},
+ },
+ &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
+ },
+ Table: &ast.IdentifierNode{
+ Name: []byte("table1"),
+ Desc: &schema.TableDescriptor{Table: 0},
},
- Table: &ast.IdentifierNode{Name: []byte("table1")},
Where: &ast.WhereOptionNode{
Condition: &ast.EqualOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("b")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
Subject: &ast.BytesValueNode{V: []byte("valB")},
},
},
},
Order: []*ast.OrderOptionNode{
&ast.OrderOptionNode{
- Expr: &ast.IdentifierNode{Name: []byte("c")},
+ Expr: &ast.IdentifierNode{
+ Name: []byte("c"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 2},
+ },
},
},
Limit: &ast.LimitOptionNode{
@@ -178,15 +216,28 @@ func (s *PlannerTestSuite) TestBasic() {
},
}
expectedPlan := &SelectStep{
- Table: 0,
- ColumnSet: ColumnSet{0, 1, 2},
+ Table: 0,
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 1},
+ &schema.ColumnDescriptor{Table: 0, Column: 2},
+ },
Columns: []ast.ExprNode{
- &ast.IdentifierNode{Name: []byte("a")},
- &ast.IdentifierNode{Name: []byte("b")},
+ &ast.IdentifierNode{
+ Name: []byte("a"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 0},
+ },
+ &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
},
Order: []*ast.OrderOptionNode{
&ast.OrderOptionNode{
- Expr: &ast.IdentifierNode{Name: []byte("c")},
+ Expr: &ast.IdentifierNode{
+ Name: []byte("c"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 2},
+ },
},
},
Limit: &limit,
@@ -277,11 +328,17 @@ func (s *PlannerTestSuite) TestBasic() {
}
{
stmt := &ast.DeleteStmtNode{
- Table: &ast.IdentifierNode{Name: []byte("table1")},
+ Table: &ast.IdentifierNode{
+ Name: []byte("table1"),
+ Desc: &schema.TableDescriptor{Table: 0},
+ },
Where: &ast.WhereOptionNode{
Condition: &ast.GreaterOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("b")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
Subject: &ast.BytesValueNode{V: []byte("valB")},
},
},
@@ -297,7 +354,10 @@ func (s *PlannerTestSuite) TestBasic() {
Index: 1,
Condition: &ast.GreaterOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("b")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
Subject: &ast.BytesValueNode{V: []byte("valB")},
},
},
@@ -368,12 +428,19 @@ func (s *PlannerTestSuite) TestHashKeys() {
{
// Test AND merge.
cl := &clause{
- ColumnSet: []schema.ColumnRef{0, 1, 2},
- Attr: clauseAttrAnd | clauseAttrEnumerable,
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 1},
+ &schema.ColumnDescriptor{Table: 0, Column: 2},
+ },
+ Attr: clauseAttrAnd | clauseAttrEnumerable,
SubCls: []*clause{
&clause{
- ColumnSet: []schema.ColumnRef{0, 2},
- Attr: clauseAttrEnumerable,
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 2},
+ },
+ Attr: clauseAttrEnumerable,
HashKeys: [][]ast.Valuer{
genCombination([]schema.ColumnRef{0, 2}, []int{0, 0}),
genCombination([]schema.ColumnRef{0, 2}, []int{1, 1}),
@@ -381,8 +448,10 @@ func (s *PlannerTestSuite) TestHashKeys() {
},
},
&clause{
- ColumnSet: []schema.ColumnRef{1},
- Attr: clauseAttrEnumerable,
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
+ Attr: clauseAttrEnumerable,
HashKeys: [][]ast.Valuer{
genCombination([]schema.ColumnRef{1}, []int{0}),
genCombination([]schema.ColumnRef{1}, []int{1}),
@@ -404,17 +473,26 @@ func (s *PlannerTestSuite) TestHashKeys() {
{
// Test AND merge boundary with one size empty.
cl := &clause{
- ColumnSet: []schema.ColumnRef{0, 1, 2},
- Attr: clauseAttrAnd | clauseAttrEnumerable,
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 1},
+ &schema.ColumnDescriptor{Table: 0, Column: 2},
+ },
+ Attr: clauseAttrAnd | clauseAttrEnumerable,
SubCls: []*clause{
&clause{
- ColumnSet: []schema.ColumnRef{0, 2},
- Attr: clauseAttrEnumerable,
- HashKeys: [][]ast.Valuer{},
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 2},
+ },
+ Attr: clauseAttrEnumerable,
+ HashKeys: [][]ast.Valuer{},
},
&clause{
- ColumnSet: []schema.ColumnRef{1},
- Attr: clauseAttrEnumerable,
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
+ Attr: clauseAttrEnumerable,
HashKeys: [][]ast.Valuer{
genCombination([]schema.ColumnRef{1}, []int{0}),
genCombination([]schema.ColumnRef{1}, []int{1}),
@@ -426,12 +504,19 @@ func (s *PlannerTestSuite) TestHashKeys() {
expectedKeys := [][]ast.Valuer{}
s.Require().Equal(expectedKeys, cl.HashKeys)
cl = &clause{
- ColumnSet: []schema.ColumnRef{0, 1, 2},
- Attr: clauseAttrAnd | clauseAttrEnumerable,
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 1},
+ &schema.ColumnDescriptor{Table: 0, Column: 2},
+ },
+ Attr: clauseAttrAnd | clauseAttrEnumerable,
SubCls: []*clause{
&clause{
- ColumnSet: []schema.ColumnRef{0, 2},
- Attr: clauseAttrEnumerable,
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 2},
+ },
+ Attr: clauseAttrEnumerable,
HashKeys: [][]ast.Valuer{
genCombination([]schema.ColumnRef{0, 2}, []int{0, 0}),
genCombination([]schema.ColumnRef{0, 2}, []int{1, 1}),
@@ -439,9 +524,11 @@ func (s *PlannerTestSuite) TestHashKeys() {
},
},
&clause{
- ColumnSet: []schema.ColumnRef{1},
- Attr: clauseAttrEnumerable,
- HashKeys: [][]ast.Valuer{},
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
+ Attr: clauseAttrEnumerable,
+ HashKeys: [][]ast.Valuer{},
},
},
}
@@ -452,20 +539,29 @@ func (s *PlannerTestSuite) TestHashKeys() {
{
// Test OR merge.
cl := &clause{
- ColumnSet: []schema.ColumnRef{0, 2},
- Attr: clauseAttrOr | clauseAttrEnumerable,
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 2},
+ },
+ Attr: clauseAttrOr | clauseAttrEnumerable,
SubCls: []*clause{
&clause{
- ColumnSet: []schema.ColumnRef{0, 2},
- Attr: clauseAttrEnumerable,
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 2},
+ },
+ Attr: clauseAttrEnumerable,
HashKeys: [][]ast.Valuer{
genCombination([]schema.ColumnRef{0, 2}, []int{0, 0}),
genCombination([]schema.ColumnRef{0, 2}, []int{1, 1}),
},
},
&clause{
- ColumnSet: []schema.ColumnRef{0, 2},
- Attr: clauseAttrEnumerable,
+ ColumnSet: ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 2},
+ },
+ Attr: clauseAttrEnumerable,
HashKeys: [][]ast.Valuer{
genCombination([]schema.ColumnRef{0, 2}, []int{1, 2}),
genCombination([]schema.ColumnRef{0, 2}, []int{2, 1}),
@@ -487,7 +583,7 @@ func (s *PlannerTestSuite) TestHashKeys() {
}
func (s *PlannerTestSuite) TestClauseAttr() {
- var schema schema.Schema = []schema.Table{
+ var dbSchema schema.Schema = []schema.Table{
s.createTable(
[]byte("table1"),
[][]byte{
@@ -503,16 +599,22 @@ func (s *PlannerTestSuite) TestClauseAttr() {
),
}
planner := planner{
- schema: schema,
- table: &schema[0],
+ schema: dbSchema,
+ table: &dbSchema[0],
+ tableRef: 0,
}
{
- node := &ast.IdentifierNode{Name: []byte("a")}
+ node := &ast.IdentifierNode{
+ Name: []byte("a"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 0},
+ }
cl, err := planner.parseClause(node)
s.Require().Nil(err)
s.Require().Equal(clauseAttrColumn, cl.Attr)
- s.Require().Equal(ColumnSet{0}, cl.ColumnSet)
+ s.Require().Equal(ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ }, cl.ColumnSet)
s.Require().Zero(cl.HashKeys)
}
{
@@ -527,27 +629,37 @@ func (s *PlannerTestSuite) TestClauseAttr() {
valA := &ast.BytesValueNode{V: []byte("valA")}
node := &ast.EqualOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("a")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("a"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 0},
+ },
Subject: valA,
},
}
cl, err := planner.parseClause(node)
s.Require().Nil(err)
s.Require().Equal(clauseAttrEnumerable, cl.Attr)
- s.Require().Equal(ColumnSet{0}, cl.ColumnSet)
+ s.Require().Equal(ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ }, cl.ColumnSet)
s.Require().Equal([][]ast.Valuer{[]ast.Valuer{valA}}, cl.HashKeys)
}
{
node := &ast.GreaterOrEqualOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("a")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("a"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 0},
+ },
Subject: &ast.BytesValueNode{V: []byte("valA")},
},
}
cl, err := planner.parseClause(node)
s.Require().Nil(err)
s.Require().Zero(cl.Attr)
- s.Require().Equal(ColumnSet{0}, cl.ColumnSet)
+ s.Require().Equal(ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ }, cl.ColumnSet)
s.Require().Zero(cl.HashKeys)
}
{
@@ -557,13 +669,19 @@ func (s *PlannerTestSuite) TestClauseAttr() {
BinaryOperatorNode: ast.BinaryOperatorNode{
Object: &ast.EqualOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("b")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
Subject: valB,
},
},
Subject: &ast.EqualOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("a")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("a"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 0},
+ },
Subject: valA,
},
},
@@ -572,7 +690,10 @@ func (s *PlannerTestSuite) TestClauseAttr() {
cl, err := planner.parseClause(node)
s.Require().Nil(err)
s.Require().Equal(clauseAttrEnumerable|clauseAttrAnd, cl.Attr)
- s.Require().Equal(ColumnSet{0, 1}, cl.ColumnSet)
+ s.Require().Equal(ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 1},
+ }, cl.ColumnSet)
s.Require().Equal([][]ast.Valuer{
[]ast.Valuer{valA, valB},
}, cl.HashKeys)
@@ -582,13 +703,19 @@ func (s *PlannerTestSuite) TestClauseAttr() {
BinaryOperatorNode: ast.BinaryOperatorNode{
Object: &ast.EqualOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("a")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("a"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 0},
+ },
Subject: &ast.BytesValueNode{V: []byte("valA")},
},
},
Subject: &ast.EqualOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("b")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
Subject: &ast.BytesValueNode{V: []byte("valB")},
},
},
@@ -597,7 +724,10 @@ func (s *PlannerTestSuite) TestClauseAttr() {
cl, err := planner.parseClause(node)
s.Require().Nil(err)
s.Require().Equal(clauseAttrOr, cl.Attr)
- s.Require().Equal(ColumnSet{0, 1}, cl.ColumnSet)
+ s.Require().Equal(ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 1},
+ }, cl.ColumnSet)
s.Require().Zero(cl.HashKeys)
}
{
@@ -607,13 +737,19 @@ func (s *PlannerTestSuite) TestClauseAttr() {
BinaryOperatorNode: ast.BinaryOperatorNode{
Object: &ast.EqualOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("b")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
Subject: valA,
},
},
Subject: &ast.EqualOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("b")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
Subject: valB,
},
},
@@ -622,7 +758,9 @@ func (s *PlannerTestSuite) TestClauseAttr() {
cl, err := planner.parseClause(node)
s.Require().Nil(err)
s.Require().Equal(clauseAttrOr|clauseAttrEnumerable, cl.Attr)
- s.Require().Equal(ColumnSet{1}, cl.ColumnSet)
+ s.Require().Equal(ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 1},
+ }, cl.ColumnSet)
s.Require().Equal([][]ast.Valuer{
[]ast.Valuer{valA},
[]ast.Valuer{valB},
@@ -634,14 +772,20 @@ func (s *PlannerTestSuite) TestClauseAttr() {
node := &ast.InOperatorNode{
Left: &ast.EqualOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("a")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("a"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 0},
+ },
Subject: valA,
},
},
Right: []ast.ExprNode{
&ast.EqualOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("b")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
Subject: valB,
},
},
@@ -650,14 +794,20 @@ func (s *PlannerTestSuite) TestClauseAttr() {
cl, err := planner.parseClause(node)
s.Require().Nil(err)
s.Require().Zero(cl.Attr)
- s.Require().Equal(ColumnSet{0, 1}, cl.ColumnSet)
+ s.Require().Equal(ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 1},
+ }, cl.ColumnSet)
s.Require().Zero(cl.HashKeys)
}
{
valA := &ast.BytesValueNode{V: []byte("valA")}
valB := &ast.BytesValueNode{V: []byte("valB")}
node := &ast.InOperatorNode{
- Left: &ast.IdentifierNode{Name: []byte("a")},
+ Left: &ast.IdentifierNode{
+ Name: []byte("a"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 0},
+ },
Right: []ast.ExprNode{
valA, valB,
},
@@ -665,7 +815,9 @@ func (s *PlannerTestSuite) TestClauseAttr() {
cl, err := planner.parseClause(node)
s.Require().Nil(err)
s.Require().Equal(clauseAttrEnumerable, cl.Attr)
- s.Require().Equal(ColumnSet{0}, cl.ColumnSet)
+ s.Require().Equal(ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ }, cl.ColumnSet)
s.Require().Equal([][]ast.Valuer{
[]ast.Valuer{valA},
[]ast.Valuer{valB},
@@ -675,8 +827,14 @@ func (s *PlannerTestSuite) TestClauseAttr() {
node := &ast.CastOperatorNode{
SourceExpr: &ast.AddOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("a")},
- Subject: &ast.IdentifierNode{Name: []byte("b")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("a"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 0},
+ },
+ Subject: &ast.IdentifierNode{
+ Name: []byte("b"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 1},
+ },
},
},
TargetType: &ast.IntTypeNode{
@@ -687,13 +845,19 @@ func (s *PlannerTestSuite) TestClauseAttr() {
cl, err := planner.parseClause(node)
s.Require().Nil(err)
s.Require().Zero(cl.Attr)
- s.Require().Equal(ColumnSet{0, 1}, cl.ColumnSet)
+ s.Require().Equal(ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ &schema.ColumnDescriptor{Table: 0, Column: 1},
+ }, cl.ColumnSet)
s.Require().Zero(cl.HashKeys)
}
{
node := &ast.EqualOperatorNode{
BinaryOperatorNode: ast.BinaryOperatorNode{
- Object: &ast.IdentifierNode{Name: []byte("a")},
+ Object: &ast.IdentifierNode{
+ Name: []byte("a"),
+ Desc: &schema.ColumnDescriptor{Table: 0, Column: 0},
+ },
Subject: &ast.FunctionOperatorNode{
Name: &ast.IdentifierNode{Name: []byte("RAND")},
},
@@ -702,7 +866,9 @@ func (s *PlannerTestSuite) TestClauseAttr() {
cl, err := planner.parseClause(node)
s.Require().Nil(err)
s.Require().Equal(clauseAttrForceScan, cl.Attr)
- s.Require().Equal(ColumnSet{0}, cl.ColumnSet)
+ s.Require().Equal(ColumnSet{
+ &schema.ColumnDescriptor{Table: 0, Column: 0},
+ }, cl.ColumnSet)
s.Require().Zero(cl.HashKeys)
}
}
diff --git a/core/vm/sqlvm/planner/types.go b/core/vm/sqlvm/planner/types.go
index eb5c4f3a0..d93c3e850 100644
--- a/core/vm/sqlvm/planner/types.go
+++ b/core/vm/sqlvm/planner/types.go
@@ -1,7 +1,7 @@
package planner
import (
- "github.com/shopspring/decimal"
+ "github.com/dexon-foundation/decimal"
"github.com/dexon-foundation/dexon/core/vm/sqlvm/ast"
"github.com/dexon-foundation/dexon/core/vm/sqlvm/schema"
diff --git a/core/vm/sqlvm/planner/utils.go b/core/vm/sqlvm/planner/utils.go
index e1aad047a..912f32346 100644
--- a/core/vm/sqlvm/planner/utils.go
+++ b/core/vm/sqlvm/planner/utils.go
@@ -37,21 +37,55 @@ func findColumnIdxByName(table *schema.Table, name []byte) (
}
// ColumnSet is a sorted slice of column idxs.
-type ColumnSet []schema.ColumnRef
+type ColumnSet []*schema.ColumnDescriptor
+
+func compareTableRef(a, b schema.TableRef) int {
+ switch {
+ case a > b:
+ return 1
+ case a == b:
+ return 0
+ default:
+ return -1
+ }
+}
+
+func compareColumnRef(a, b schema.ColumnRef) int {
+ switch {
+ case a > b:
+ return 1
+ case a == b:
+ return 0
+ default:
+ return -1
+ }
+}
+
+func compareColumn(a, b *schema.ColumnDescriptor) int {
+ comp := compareTableRef(a.Table, b.Table)
+ switch comp {
+ case 0:
+ return compareColumnRef(a.Column, b.Column)
+ default:
+ return comp
+ }
+}
// Join creates a new set which is the union of c and other.
func (c ColumnSet) Join(other ColumnSet) ColumnSet {
- ret := make([]schema.ColumnRef, 0, len(c)+len(other))
+ ret := make([]*schema.ColumnDescriptor, 0, len(c)+len(other))
i, j := 0, 0
for i != len(c) && j != len(other) {
- if c[i] == other[j] {
+ comp := compareColumn(c[i], other[j])
+ switch comp {
+ case 0:
ret = append(ret, c[i])
i++
j++
- } else if c[i] > other[j] {
+ case 1:
ret = append(ret, other[j])
j++
- } else {
+ case -1:
ret = append(ret, c[i])
i++
}
@@ -73,7 +107,7 @@ func (c ColumnSet) Equal(other ColumnSet) bool {
return false
}
for i := range c {
- if c[i] != other[i] {
+ if compareColumn(c[i], other[i]) != 0 {
return false
}
}
@@ -84,12 +118,13 @@ func (c ColumnSet) Equal(other ColumnSet) bool {
func (c ColumnSet) IsDisjoint(other ColumnSet) bool {
i, j := 0, 0
for i != len(c) && j != len(other) {
- if c[i] == other[j] {
+ comp := compareColumn(c[i], other[j])
+ switch comp {
+ case 0:
return false
- }
- if c[i] > other[j] {
+ case 1:
j++
- } else {
+ case -1:
i++
}
}
@@ -100,11 +135,12 @@ func (c ColumnSet) IsDisjoint(other ColumnSet) bool {
func (c ColumnSet) Contains(other ColumnSet) bool {
i, j := 0, 0
for i != len(c) && j != len(other) {
- if c[i] > other[j] {
+ comp := compareColumn(c[i], other[j])
+ switch comp {
+ case 1:
// Found some item not in c.
return false
- }
- if c[i] == other[j] {
+ case 0:
j++
}
i++
diff --git a/core/vm/sqlvm/planner/utils_test.go b/core/vm/sqlvm/planner/utils_test.go
index 3e3d90a8d..6053a3180 100644
--- a/core/vm/sqlvm/planner/utils_test.go
+++ b/core/vm/sqlvm/planner/utils_test.go
@@ -4,28 +4,44 @@ import (
"testing"
"github.com/stretchr/testify/suite"
+
+ "github.com/dexon-foundation/dexon/core/vm/sqlvm/schema"
)
type PlannerUtilsTestSuite struct{ suite.Suite }
+func makeColumnSet(cols []uint8) ColumnSet {
+ var ret ColumnSet = make([]*schema.ColumnDescriptor, len(cols))
+ for i := range ret {
+ ret[i] = &schema.ColumnDescriptor{
+ Table: 0,
+ Column: schema.ColumnRef(cols[i]),
+ }
+ }
+ return ret
+}
+
func (s *PlannerUtilsTestSuite) TestColumnSet() {
{
// Join.
var columns, expected ColumnSet
- columns = ColumnSet{1, 3, 5}.Join(ColumnSet{0, 1, 2, 4, 6})
- expected = ColumnSet{0, 1, 2, 3, 4, 5, 6}
+ columns = makeColumnSet([]uint8{1, 3, 5}).Join(
+ makeColumnSet([]uint8{0, 1, 2, 4, 6}))
+ expected = makeColumnSet([]uint8{0, 1, 2, 3, 4, 5, 6})
s.Require().Equal(expected, columns)
- columns = ColumnSet{1, 3, 5}.Join(ColumnSet{3, 5})
- expected = ColumnSet{1, 3, 5}
+ columns = makeColumnSet([]uint8{1, 3, 5}).Join(
+ makeColumnSet([]uint8{3, 5}))
+ expected = makeColumnSet([]uint8{1, 3, 5})
s.Require().Equal(expected, columns)
- columns = ColumnSet{}.Join(ColumnSet{0})
- expected = ColumnSet{0}
+ columns = ColumnSet{}.Join(makeColumnSet([]uint8{0}))
+ expected = makeColumnSet([]uint8{0})
s.Require().Equal(expected, columns)
- columns = ColumnSet{1}.Join(ColumnSet{1, 3})
- expected = ColumnSet{1, 3}
+ columns = makeColumnSet([]uint8{1}).Join(
+ makeColumnSet([]uint8{1, 3}))
+ expected = makeColumnSet([]uint8{1, 3})
s.Require().Equal(expected, columns)
- columns = ColumnSet{5}.Join(ColumnSet{1, 3})
- expected = ColumnSet{1, 3, 5}
+ columns = makeColumnSet([]uint8{5}).Join(makeColumnSet([]uint8{1, 3}))
+ expected = makeColumnSet([]uint8{1, 3, 5})
s.Require().Equal(expected, columns)
}
{
@@ -34,18 +50,18 @@ func (s *PlannerUtilsTestSuite) TestColumnSet() {
// True cases.
equal = ColumnSet{}.Equal(ColumnSet{})
s.Require().True(equal)
- equal = ColumnSet{1, 2}.Equal(ColumnSet{1, 2})
+ equal = makeColumnSet([]uint8{1, 2}).Equal(makeColumnSet([]uint8{1, 2}))
s.Require().True(equal)
// False cases.
- equal = ColumnSet{}.Equal(ColumnSet{1, 2})
+ equal = ColumnSet{}.Equal(makeColumnSet([]uint8{1, 2}))
s.Require().False(equal)
- equal = ColumnSet{1, 2}.Equal(ColumnSet{})
+ equal = makeColumnSet([]uint8{1, 2}).Equal(ColumnSet{})
s.Require().False(equal)
- equal = ColumnSet{2}.Equal(ColumnSet{1})
+ equal = makeColumnSet([]uint8{2}).Equal(makeColumnSet([]uint8{1}))
s.Require().False(equal)
- equal = ColumnSet{2}.Equal(ColumnSet{1, 3})
+ equal = makeColumnSet([]uint8{2}).Equal(makeColumnSet([]uint8{1, 3}))
s.Require().False(equal)
- equal = ColumnSet{1, 3}.Equal(ColumnSet{2})
+ equal = makeColumnSet([]uint8{1, 3}).Equal(makeColumnSet([]uint8{2}))
s.Require().False(equal)
}
{
@@ -54,22 +70,28 @@ func (s *PlannerUtilsTestSuite) TestColumnSet() {
// True cases.
contains = ColumnSet{}.Contains(ColumnSet{})
s.Require().True(contains)
- contains = ColumnSet{1, 2}.Contains(ColumnSet{})
+ contains = makeColumnSet([]uint8{1, 2}).Contains(ColumnSet{})
s.Require().True(contains)
- contains = ColumnSet{1, 2}.Contains(ColumnSet{2})
+ contains = makeColumnSet([]uint8{1, 2}).Contains(
+ makeColumnSet([]uint8{2}))
s.Require().True(contains)
- contains = ColumnSet{1, 2}.Contains(ColumnSet{1})
+ contains = makeColumnSet([]uint8{1, 2}).Contains(
+ makeColumnSet([]uint8{1}))
s.Require().True(contains)
- contains = ColumnSet{1, 2, 3}.Contains(ColumnSet{1, 2})
+ contains = makeColumnSet([]uint8{1, 2, 3}).Contains(
+ makeColumnSet([]uint8{1, 2}))
s.Require().True(contains)
// False cases.
- contains = ColumnSet{1}.Contains(ColumnSet{2})
+ contains = makeColumnSet([]uint8{1}).Contains(makeColumnSet([]uint8{2}))
s.Require().False(contains)
- contains = ColumnSet{2}.Contains(ColumnSet{1, 2})
+ contains = makeColumnSet([]uint8{2}).Contains(
+ makeColumnSet([]uint8{1, 2}))
s.Require().False(contains)
- contains = ColumnSet{1}.Contains(ColumnSet{1, 2})
+ contains = makeColumnSet([]uint8{1}).Contains(
+ makeColumnSet([]uint8{1, 2}))
s.Require().False(contains)
- contains = ColumnSet{1, 3, 5}.Contains(ColumnSet{4})
+ contains = makeColumnSet([]uint8{1, 3, 5}).Contains(
+ makeColumnSet([]uint8{4}))
s.Require().False(contains)
}
{
@@ -78,20 +100,25 @@ func (s *PlannerUtilsTestSuite) TestColumnSet() {
// True cases.
disjoin = ColumnSet{}.IsDisjoint(ColumnSet{})
s.Require().True(disjoin)
- disjoin = ColumnSet{}.IsDisjoint(ColumnSet{1})
+ disjoin = ColumnSet{}.IsDisjoint(makeColumnSet([]uint8{1}))
s.Require().True(disjoin)
- disjoin = ColumnSet{1}.IsDisjoint(ColumnSet{})
+ disjoin = makeColumnSet([]uint8{1}).IsDisjoint(ColumnSet{})
s.Require().True(disjoin)
- disjoin = ColumnSet{1}.IsDisjoint(ColumnSet{2})
+ disjoin = makeColumnSet([]uint8{1}).IsDisjoint(
+ makeColumnSet([]uint8{2}))
s.Require().True(disjoin)
// False cases.
- disjoin = ColumnSet{1, 2}.IsDisjoint(ColumnSet{2})
+ disjoin = makeColumnSet([]uint8{1, 2}).IsDisjoint(
+ makeColumnSet([]uint8{2}))
s.Require().False(disjoin)
- disjoin = ColumnSet{1, 2}.IsDisjoint(ColumnSet{1})
+ disjoin = makeColumnSet([]uint8{1, 2}).IsDisjoint(
+ makeColumnSet([]uint8{1}))
s.Require().False(disjoin)
- disjoin = ColumnSet{1, 2}.IsDisjoint(ColumnSet{0, 2})
+ disjoin = makeColumnSet([]uint8{1, 2}).IsDisjoint(
+ makeColumnSet([]uint8{0, 2}))
s.Require().False(disjoin)
- disjoin = ColumnSet{1, 7}.IsDisjoint(ColumnSet{5, 6, 7})
+ disjoin = makeColumnSet([]uint8{1, 7}).IsDisjoint(
+ makeColumnSet([]uint8{5, 6, 7}))
s.Require().False(disjoin)
}
}