aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm/sqlvm/ast
diff options
context:
space:
mode:
Diffstat (limited to 'core/vm/sqlvm/ast')
-rw-r--r--core/vm/sqlvm/ast/ast.go1068
-rw-r--r--core/vm/sqlvm/ast/printer.go69
-rw-r--r--core/vm/sqlvm/ast/types.go8
3 files changed, 992 insertions, 153 deletions
diff --git a/core/vm/sqlvm/ast/ast.go b/core/vm/sqlvm/ast/ast.go
index 654e778e4..ffd4a1011 100644
--- a/core/vm/sqlvm/ast/ast.go
+++ b/core/vm/sqlvm/ast/ast.go
@@ -1,18 +1,110 @@
package ast
import (
+ "strconv"
+
+ "github.com/dexon-foundation/dexon/core/vm/sqlvm/errors"
"github.com/shopspring/decimal"
)
// ---------------------------------------------------------------------------
+// Base
+// ---------------------------------------------------------------------------
+
+// Node is an interface which should be satisfied by all nodes in AST.
+type Node interface {
+ GetPosition() uint32
+ SetPosition(uint32)
+ GetLength() uint32
+ SetLength(uint32)
+ GetChildren() []Node
+}
+
+// NodeBase is a base struct embedded by structs implementing Node interface.
+type NodeBase struct {
+ Position uint32 `print:"-"`
+ Length uint32 `print:"-"`
+}
+
+// GetPosition returns the offset in bytes where the corresponding token starts.
+func (n NodeBase) GetPosition() uint32 {
+ return n.Position
+}
+
+// SetPosition sets the offset in bytes where the corresponding token starts.
+func (n *NodeBase) SetPosition(position uint32) {
+ n.Position = position
+}
+
+// GetLength returns the length in bytes of the corresponding token.
+func (n NodeBase) GetLength() uint32 {
+ return n.Length
+}
+
+// SetLength sets the length in bytes of the corresponding token.
+func (n *NodeBase) SetLength(length uint32) {
+ n.Length = length
+}
+
+// ---------------------------------------------------------------------------
// Identifiers
// ---------------------------------------------------------------------------
+// ExprNode is an interface which should be satisfied all nodes in expressions.
+type ExprNode interface {
+ Node
+ IsConstant() bool
+ GetType() DataType
+ SetType(DataType)
+}
+
+// UntaggedExprNodeBase is a base struct embedded by nodes whose types can be
+// decided without any context and database schema.
+type UntaggedExprNodeBase struct {
+ NodeBase
+}
+
+// SetType always panics because it is not reasonable to set data type on nodes
+// whose types are already decided.
+func (n *UntaggedExprNodeBase) SetType(t DataType) {
+ panic("setting type on untagged expression node")
+}
+
+// TaggedExprNodeBase is a base struct embedded by nodes whose types depend on
+// the context and can only be decided after loading database schemas.
+type TaggedExprNodeBase struct {
+ NodeBase
+ Type DataType `print:"-"`
+}
+
+// GetType gets the data type of the node.
+func (n TaggedExprNodeBase) GetType() DataType {
+ return n.Type
+}
+
+// SetType sets the data type of the node.
+func (n *TaggedExprNodeBase) SetType(t DataType) {
+ n.Type = t
+}
+
// IdentifierNode references table, column, or function.
type IdentifierNode struct {
+ TaggedExprNodeBase
Name []byte
}
+var _ ExprNode = (*IdentifierNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n IdentifierNode) GetChildren() []Node {
+ return nil
+}
+
+// IsConstant returns whether a node is a constant.
+func (n IdentifierNode) IsConstant() bool {
+ return false
+}
+
// ---------------------------------------------------------------------------
// Values
// ---------------------------------------------------------------------------
@@ -24,54 +116,192 @@ type Valuer interface {
// BoolValueNode is a boolean constant.
type BoolValueNode struct {
+ UntaggedExprNodeBase
V bool
}
+var _ ExprNode = (*BoolValueNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n BoolValueNode) GetChildren() []Node {
+ return nil
+}
+
+// IsConstant returns whether a node is a constant.
+func (n BoolValueNode) IsConstant() bool {
+ return true
+}
+
+// GetType returns the type of 'bool'.
+func (n BoolValueNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare)
+}
+
// Value returns the value of BoolValueNode.
-func (n BoolValueNode) Value() interface{} { return n.V }
+func (n BoolValueNode) Value() interface{} {
+ return n.V
+}
+
+// String is used for printing AST.
+func (n BoolValueNode) String() string {
+ return strconv.FormatBool(n.V)
+}
// IntegerValueNode is an integer constant.
type IntegerValueNode struct {
+ TaggedExprNodeBase
IsAddress bool
V decimal.Decimal
}
+var _ ExprNode = (*IntegerValueNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n IntegerValueNode) GetChildren() []Node {
+ return nil
+}
+
+// IsConstant returns whether a node is a constant.
+func (n IntegerValueNode) IsConstant() bool {
+ return true
+}
+
// Value returns the value of IntegerValueNode.
-func (n IntegerValueNode) Value() interface{} { return n.V }
-func (n IntegerValueNode) String() string { return n.V.String() }
+func (n IntegerValueNode) Value() interface{} {
+ return n.V
+}
+
+// String is used for printing AST.
+func (n IntegerValueNode) String() string {
+ return n.V.String()
+}
// DecimalValueNode is a number constant.
type DecimalValueNode struct {
+ TaggedExprNodeBase
V decimal.Decimal
}
+var _ ExprNode = (*DecimalValueNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n DecimalValueNode) GetChildren() []Node {
+ return nil
+}
+
+// IsConstant returns whether a node is a constant.
+func (n DecimalValueNode) IsConstant() bool {
+ return true
+}
+
// Value returns the value of DecimalValueNode.
-func (n DecimalValueNode) Value() interface{} { return n.V }
-func (n DecimalValueNode) String() string { return n.V.String() }
+func (n DecimalValueNode) Value() interface{} {
+ return n.V
+}
+
+// String is used for printing AST.
+func (n DecimalValueNode) String() string {
+ return n.V.String()
+}
// BytesValueNode is a dynamic or fixed bytes constant.
type BytesValueNode struct {
+ TaggedExprNodeBase
V []byte
}
+var _ ExprNode = (*BytesValueNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n BytesValueNode) GetChildren() []Node {
+ return nil
+}
+
+// IsConstant returns whether a node is a constant.
+func (n BytesValueNode) IsConstant() bool {
+ return true
+}
+
// Value returns the value of BytesValueNode.
-func (n BytesValueNode) Value() interface{} { return n.V }
-func (n BytesValueNode) String() string { return string(n.V) }
+func (n BytesValueNode) Value() interface{} {
+ return n.V
+}
+
+// String is used for printing AST.
+func (n BytesValueNode) String() string {
+ return string(n.V)
+}
// AnyValueNode is '*' used in SELECT and function call.
-type AnyValueNode struct{}
+type AnyValueNode struct {
+ UntaggedExprNodeBase
+}
+
+var _ ExprNode = (*AnyValueNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n AnyValueNode) GetChildren() []Node {
+ return nil
+}
+
+// IsConstant returns whether a node is a constant.
+func (n AnyValueNode) IsConstant() bool {
+ return false
+}
+
+// GetType returns the type of '*'.
+func (n AnyValueNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorSpecial, DataTypeMinorSpecialAny)
+}
// Value returns itself.
-func (n AnyValueNode) Value() interface{} { return n }
+func (n AnyValueNode) Value() interface{} {
+ return n
+}
// DefaultValueNode represents the default value used in INSERT and UPDATE.
-type DefaultValueNode struct{}
+type DefaultValueNode struct {
+ UntaggedExprNodeBase
+}
+
+var _ ExprNode = (*DefaultValueNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n DefaultValueNode) GetChildren() []Node {
+ return nil
+}
+
+// IsConstant returns whether a node is a constant.
+func (n DefaultValueNode) IsConstant() bool {
+ return true
+}
+
+// GetType returns the type of 'DEFAULT'.
+func (n DefaultValueNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorSpecial, DataTypeMinorSpecialDefault)
+}
// Value returns itself.
-func (n DefaultValueNode) Value() interface{} { return n }
+func (n DefaultValueNode) Value() interface{} {
+ return n
+}
// NullValueNode is NULL.
-type NullValueNode struct{}
+type NullValueNode struct {
+ TaggedExprNodeBase
+}
+
+var _ ExprNode = (*NullValueNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n NullValueNode) GetChildren() []Node {
+ return nil
+}
+
+// IsConstant returns whether a node is a constant.
+func (n NullValueNode) IsConstant() bool {
+ return true
+}
// Value returns itself.
func (n NullValueNode) Value() interface{} { return n }
@@ -80,32 +310,162 @@ func (n NullValueNode) Value() interface{} { return n }
// Types
// ---------------------------------------------------------------------------
+// TypeNode is an interface which should be satisfied nodes representing types.
+type TypeNode interface {
+ Node
+ GetType() (DataType, errors.ErrorCode)
+}
+
// IntTypeNode represents solidity int{X} and uint{X} types.
type IntTypeNode struct {
+ NodeBase
Unsigned bool
Size uint32
}
+var _ TypeNode = (*IntTypeNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n IntTypeNode) GetChildren() []Node {
+ return nil
+}
+
+// GetType returns the type represented by the node.
+func (n IntTypeNode) GetType() (DataType, errors.ErrorCode) {
+ if n.Size%8 != 0 || n.Size == 0 || n.Size > 256 {
+ if n.Unsigned {
+ return DataTypeUnknown, errors.ErrorCodeInvalidUintSize
+ }
+ return DataTypeUnknown, errors.ErrorCodeInvalidIntSize
+ }
+ var major DataTypeMajor
+ var minor DataTypeMinor
+ if n.Unsigned {
+ major = DataTypeMajorUint
+ } else {
+ major = DataTypeMajorInt
+ }
+ minor = DataTypeMinor(n.Size/8 - 1)
+ return ComposeDataType(major, minor), errors.ErrorCodeNil
+}
+
// FixedTypeNode represents solidity fixed{M}x{N} and ufixed{M}x{N} types.
type FixedTypeNode struct {
+ NodeBase
Unsigned bool
Size uint32
FractionalDigits uint32
}
+var _ TypeNode = (*FixedTypeNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n FixedTypeNode) GetChildren() []Node {
+ return nil
+}
+
+// GetType returns the type represented by the node.
+func (n FixedTypeNode) GetType() (DataType, errors.ErrorCode) {
+ if n.Size%8 != 0 || n.Size == 0 || n.Size > 256 {
+ if n.Unsigned {
+ return DataTypeUnknown, errors.ErrorCodeInvalidUfixedSize
+ }
+ return DataTypeUnknown, errors.ErrorCodeInvalidFixedSize
+ }
+ if n.FractionalDigits > 80 {
+ if n.Unsigned {
+ return DataTypeUnknown, errors.ErrorCodeInvalidUfixedFractionalDigits
+ }
+ return DataTypeUnknown, errors.ErrorCodeInvalidFixedFractionalDigits
+ }
+ var major DataTypeMajor
+ var minor DataTypeMinor
+ if n.Unsigned {
+ major = DataTypeMajorUfixed
+ } else {
+ major = DataTypeMajorFixed
+ }
+ major += DataTypeMajor(n.Size/8 - 1)
+ minor = DataTypeMinor(n.FractionalDigits)
+ return ComposeDataType(major, minor), errors.ErrorCodeNil
+}
+
// DynamicBytesTypeNode represents solidity bytes type.
-type DynamicBytesTypeNode struct{}
+type DynamicBytesTypeNode struct {
+ NodeBase
+}
+
+var _ TypeNode = (*DynamicBytesTypeNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n DynamicBytesTypeNode) GetChildren() []Node {
+ return nil
+}
+
+// GetType returns the type represented by the node.
+func (n DynamicBytesTypeNode) GetType() (DataType, errors.ErrorCode) {
+ return ComposeDataType(DataTypeMajorDynamicBytes, DataTypeMinorDontCare),
+ errors.ErrorCodeNil
+}
// FixedBytesTypeNode represents solidity bytes{X} type.
type FixedBytesTypeNode struct {
+ NodeBase
Size uint32
}
+var _ TypeNode = (*FixedBytesTypeNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n FixedBytesTypeNode) GetChildren() []Node {
+ return nil
+}
+
+// GetType returns the type represented by the node.
+func (n FixedBytesTypeNode) GetType() (DataType, errors.ErrorCode) {
+ if n.Size == 0 || n.Size > 32 {
+ return DataTypeUnknown, errors.ErrorCodeInvalidBytesSize
+ }
+ major := DataTypeMajorFixedBytes
+ minor := DataTypeMinor(n.Size - 1)
+ return ComposeDataType(major, minor), errors.ErrorCodeNil
+}
+
// AddressTypeNode represents solidity address type.
-type AddressTypeNode struct{}
+type AddressTypeNode struct {
+ NodeBase
+}
+
+var _ TypeNode = (*AddressTypeNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n AddressTypeNode) GetChildren() []Node {
+ return nil
+}
+
+// GetType returns the type represented by the node.
+func (n AddressTypeNode) GetType() (DataType, errors.ErrorCode) {
+ return ComposeDataType(DataTypeMajorAddress, DataTypeMinorDontCare),
+ errors.ErrorCodeNil
+}
// BoolTypeNode represents solidity bool type.
-type BoolTypeNode struct{}
+type BoolTypeNode struct {
+ NodeBase
+}
+
+var _ TypeNode = (*BoolTypeNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n BoolTypeNode) GetChildren() []Node {
+ return nil
+}
+
+// GetType returns the type represented by the node.
+func (n BoolTypeNode) GetType() (DataType, errors.ErrorCode) {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare),
+ errors.ErrorCodeNil
+}
// ---------------------------------------------------------------------------
// Operators
@@ -113,127 +473,410 @@ type BoolTypeNode struct{}
// UnaryOperator defines the interface of a unary operator.
type UnaryOperator interface {
- GetTarget() interface{}
- SetTarget(interface{})
+ ExprNode
+ GetTarget() ExprNode
+ SetTarget(ExprNode)
}
// BinaryOperator defines the interface of a binary operator.
type BinaryOperator interface {
- GetObject() interface{}
- GetSubject() interface{}
- SetObject(interface{})
- SetSubject(interface{})
+ ExprNode
+ GetObject() ExprNode
+ GetSubject() ExprNode
+ SetObject(ExprNode)
+ SetSubject(ExprNode)
}
// UnaryOperatorNode is a base struct of unary operators.
type UnaryOperatorNode struct {
- Target interface{}
+ Target ExprNode
+}
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n UnaryOperatorNode) GetChildren() []Node {
+ return []Node{n.Target}
+}
+
+// IsConstant returns whether a node is a constant.
+func (n UnaryOperatorNode) IsConstant() bool {
+ return n.Target.IsConstant()
}
// GetTarget gets the target of the operation.
-func (n UnaryOperatorNode) GetTarget() interface{} {
+func (n UnaryOperatorNode) GetTarget() ExprNode {
return n.Target
}
// SetTarget sets the target of the operation.
-func (n *UnaryOperatorNode) SetTarget(t interface{}) {
+func (n *UnaryOperatorNode) SetTarget(t ExprNode) {
n.Target = t
}
// BinaryOperatorNode is a base struct of binary operators.
type BinaryOperatorNode struct {
- Object interface{}
- Subject interface{}
+ Object ExprNode
+ Subject ExprNode
+}
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n BinaryOperatorNode) GetChildren() []Node {
+ return []Node{n.Object, n.Subject}
+}
+
+// IsConstant returns whether a node is a constant.
+func (n BinaryOperatorNode) IsConstant() bool {
+ return n.Object.IsConstant() && n.Subject.IsConstant()
}
// GetObject gets the node on which the operation is applied.
-func (n BinaryOperatorNode) GetObject() interface{} {
+func (n BinaryOperatorNode) GetObject() ExprNode {
return n.Object
}
// GetSubject gets the node whose value is applied on the object.
-func (n BinaryOperatorNode) GetSubject() interface{} {
+func (n BinaryOperatorNode) GetSubject() ExprNode {
return n.Subject
}
// SetObject sets the object of the operation.
-func (n *BinaryOperatorNode) SetObject(o interface{}) {
+func (n *BinaryOperatorNode) SetObject(o ExprNode) {
n.Object = o
}
// SetSubject sets the subject of the operation.
-func (n *BinaryOperatorNode) SetSubject(s interface{}) {
+func (n *BinaryOperatorNode) SetSubject(s ExprNode) {
n.Subject = s
}
// PosOperatorNode is '+'.
-type PosOperatorNode struct{ UnaryOperatorNode }
+type PosOperatorNode struct {
+ TaggedExprNodeBase
+ UnaryOperatorNode
+}
+
+var _ UnaryOperator = (*PosOperatorNode)(nil)
// NegOperatorNode is '-'.
-type NegOperatorNode struct{ UnaryOperatorNode }
+type NegOperatorNode struct {
+ TaggedExprNodeBase
+ UnaryOperatorNode
+}
+
+var _ UnaryOperator = (*NegOperatorNode)(nil)
// NotOperatorNode is 'NOT'.
-type NotOperatorNode struct{ UnaryOperatorNode }
+type NotOperatorNode struct {
+ UntaggedExprNodeBase
+ UnaryOperatorNode
+}
+
+var _ UnaryOperator = (*NotOperatorNode)(nil)
+
+// GetType returns the type of 'bool'.
+func (n NotOperatorNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare)
+}
// AndOperatorNode is 'AND'.
-type AndOperatorNode struct{ BinaryOperatorNode }
+type AndOperatorNode struct {
+ UntaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*AndOperatorNode)(nil)
+
+// GetType returns the type of 'bool'.
+func (n AndOperatorNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare)
+}
// OrOperatorNode is 'OR'.
-type OrOperatorNode struct{ BinaryOperatorNode }
+type OrOperatorNode struct {
+ UntaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*OrOperatorNode)(nil)
+
+// GetType returns the type of 'bool'.
+func (n OrOperatorNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare)
+}
// GreaterOrEqualOperatorNode is '>='.
-type GreaterOrEqualOperatorNode struct{ BinaryOperatorNode }
+type GreaterOrEqualOperatorNode struct {
+ UntaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*GreaterOrEqualOperatorNode)(nil)
+
+// GetType returns the type of 'bool'.
+func (n GreaterOrEqualOperatorNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare)
+}
// LessOrEqualOperatorNode is '<='.
-type LessOrEqualOperatorNode struct{ BinaryOperatorNode }
+type LessOrEqualOperatorNode struct {
+ UntaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*LessOrEqualOperatorNode)(nil)
+
+// GetType returns the type of 'bool'.
+func (n LessOrEqualOperatorNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare)
+}
// NotEqualOperatorNode is '<>'.
-type NotEqualOperatorNode struct{ BinaryOperatorNode }
+type NotEqualOperatorNode struct {
+ UntaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*NotEqualOperatorNode)(nil)
+
+// GetType returns the type of 'bool'.
+func (n NotEqualOperatorNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare)
+}
// EqualOperatorNode is '=' used in expressions.
-type EqualOperatorNode struct{ BinaryOperatorNode }
+type EqualOperatorNode struct {
+ UntaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*EqualOperatorNode)(nil)
+
+// GetType returns the type of 'bool'.
+func (n EqualOperatorNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare)
+}
// GreaterOperatorNode is '>'.
-type GreaterOperatorNode struct{ BinaryOperatorNode }
+type GreaterOperatorNode struct {
+ UntaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*GreaterOperatorNode)(nil)
+
+// GetType returns the type of 'bool'.
+func (n GreaterOperatorNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare)
+}
// LessOperatorNode is '<'.
-type LessOperatorNode struct{ BinaryOperatorNode }
+type LessOperatorNode struct {
+ UntaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*LessOperatorNode)(nil)
+
+// GetType returns the type of 'bool'.
+func (n LessOperatorNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare)
+}
// ConcatOperatorNode is '||'.
-type ConcatOperatorNode struct{ BinaryOperatorNode }
+type ConcatOperatorNode struct {
+ UntaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*ConcatOperatorNode)(nil)
+
+// GetType returns the type of 'bytes'.
+func (n ConcatOperatorNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorDynamicBytes, DataTypeMinorDontCare)
+}
// AddOperatorNode is '+'.
-type AddOperatorNode struct{ BinaryOperatorNode }
+type AddOperatorNode struct {
+ TaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*AddOperatorNode)(nil)
// SubOperatorNode is '-'.
-type SubOperatorNode struct{ BinaryOperatorNode }
+type SubOperatorNode struct {
+ TaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*SubOperatorNode)(nil)
// MulOperatorNode is '*'.
-type MulOperatorNode struct{ BinaryOperatorNode }
+type MulOperatorNode struct {
+ TaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*MulOperatorNode)(nil)
// DivOperatorNode is '/'.
-type DivOperatorNode struct{ BinaryOperatorNode }
+type DivOperatorNode struct {
+ TaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*DivOperatorNode)(nil)
// ModOperatorNode is '%'.
-type ModOperatorNode struct{ BinaryOperatorNode }
+type ModOperatorNode struct {
+ TaggedExprNodeBase
+ BinaryOperatorNode
+}
-// InOperatorNode is 'IN'.
-type InOperatorNode struct{ BinaryOperatorNode }
+var _ BinaryOperator = (*ModOperatorNode)(nil)
// IsOperatorNode is 'IS NULL'.
-type IsOperatorNode struct{ BinaryOperatorNode }
+type IsOperatorNode struct {
+ UntaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*IsOperatorNode)(nil)
+
+// GetType returns the type of 'bool'.
+func (n IsOperatorNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare)
+}
// LikeOperatorNode is 'LIKE'.
-type LikeOperatorNode struct{ BinaryOperatorNode }
+type LikeOperatorNode struct {
+ UntaggedExprNodeBase
+ BinaryOperatorNode
+}
+
+var _ BinaryOperator = (*LikeOperatorNode)(nil)
+
+// GetType returns the type of 'bool'.
+func (n LikeOperatorNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare)
+}
+
+// ---------------------------------------------------------------------------
+// Cast
+// ---------------------------------------------------------------------------
// CastOperatorNode is 'CAST(expr AS type)'.
-type CastOperatorNode struct{ BinaryOperatorNode }
+type CastOperatorNode struct {
+ UntaggedExprNodeBase
+ SourceExpr ExprNode
+ TargetType TypeNode
+}
+
+var _ ExprNode = (*CastOperatorNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n CastOperatorNode) GetChildren() []Node {
+ return []Node{n.SourceExpr, n.TargetType}
+}
+
+// IsConstant returns whether a node is a constant.
+func (n CastOperatorNode) IsConstant() bool {
+ return n.SourceExpr.IsConstant()
+}
+
+// GetType returns the type of CAST expression, which is always the target type.
+func (n CastOperatorNode) GetType() DataType {
+ if dt, code := n.TargetType.GetType(); code == errors.ErrorCodeNil {
+ return dt
+ }
+ return DataTypeUnknown
+}
+
+// ---------------------------------------------------------------------------
+// Assignment
+// ---------------------------------------------------------------------------
// AssignOperatorNode is '=' used in UPDATE to set values.
-type AssignOperatorNode struct{ BinaryOperatorNode }
+type AssignOperatorNode struct {
+ NodeBase
+ Column *IdentifierNode
+ Expr ExprNode
+}
+
+var _ Node = (*AssignOperatorNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n AssignOperatorNode) GetChildren() []Node {
+ return []Node{n.Column, n.Expr}
+}
+
+// ---------------------------------------------------------------------------
+// In
+// ---------------------------------------------------------------------------
+
+// InOperatorNode is 'IN'.
+type InOperatorNode struct {
+ UntaggedExprNodeBase
+ Left ExprNode
+ Right []ExprNode
+}
+
+var _ ExprNode = (*InOperatorNode)(nil)
+
+// GetType returns the type of 'bool'.
+func (n InOperatorNode) GetType() DataType {
+ return ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare)
+}
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n InOperatorNode) GetChildren() []Node {
+ nodes := make([]Node, 1+len(n.Right))
+ nodes[0] = n.Left
+ for i := 0; i < len(n.Right); i++ {
+ nodes[i+1] = n.Right[i]
+ }
+ return nodes
+}
+
+// IsConstant returns whether a node is a constant.
+func (n InOperatorNode) IsConstant() bool {
+ if !n.Left.IsConstant() {
+ return false
+ }
+ for i := 0; i < len(n.Right); i++ {
+ if !n.Right[i].IsConstant() {
+ return false
+ }
+ }
+ return true
+}
+
+// ---------------------------------------------------------------------------
+// Function
+// ---------------------------------------------------------------------------
// FunctionOperatorNode is a function call.
-type FunctionOperatorNode struct{ BinaryOperatorNode }
+type FunctionOperatorNode struct {
+ TaggedExprNodeBase
+ Name *IdentifierNode
+ Args []ExprNode
+}
+
+var _ ExprNode = (*FunctionOperatorNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n FunctionOperatorNode) GetChildren() []Node {
+ nodes := make([]Node, 1+len(n.Args))
+ nodes[0] = n.Name
+ for i := 0; i < len(n.Args); i++ {
+ nodes[i+1] = n.Args[i]
+ }
+ return nodes
+}
+
+// IsConstant returns whether a node is a constant.
+func (n FunctionOperatorNode) IsConstant() bool {
+ return false
+}
// ---------------------------------------------------------------------------
// Options
@@ -241,61 +884,184 @@ type FunctionOperatorNode struct{ BinaryOperatorNode }
// WhereOptionNode is 'WHERE' used in SELECT, UPDATE, DELETE.
type WhereOptionNode struct {
- Condition interface{}
+ NodeBase
+ Condition ExprNode
+}
+
+var _ Node = (*WhereOptionNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n WhereOptionNode) GetChildren() []Node {
+ return []Node{n.Condition}
}
// OrderOptionNode is an expression in 'ORDER BY' used in SELECT.
type OrderOptionNode struct {
- Expr interface{}
+ NodeBase
+ Expr ExprNode
Desc bool
NullsFirst bool
}
+var _ Node = (*OrderOptionNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n OrderOptionNode) GetChildren() []Node {
+ return []Node{n.Expr}
+}
+
// GroupOptionNode is 'GROUP BY' used in SELECT.
type GroupOptionNode struct {
- Expr interface{}
+ NodeBase
+ Expr ExprNode
+}
+
+var _ Node = (*GroupOptionNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n GroupOptionNode) GetChildren() []Node {
+ return []Node{n.Expr}
}
// OffsetOptionNode is 'OFFSET' used in SELECT.
type OffsetOptionNode struct {
- Value IntegerValueNode
+ NodeBase
+ Value *IntegerValueNode
+}
+
+var _ Node = (*OffsetOptionNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n OffsetOptionNode) GetChildren() []Node {
+ return []Node{n.Value}
}
// LimitOptionNode is 'LIMIT' used in SELECT.
type LimitOptionNode struct {
- Value IntegerValueNode
+ NodeBase
+ Value *IntegerValueNode
+}
+
+var _ Node = (*LimitOptionNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n LimitOptionNode) GetChildren() []Node {
+ return []Node{n.Value}
}
// InsertWithColumnOptionNode stores columns and values used in INSERT.
type InsertWithColumnOptionNode struct {
- Column []interface{}
- Value []interface{}
+ NodeBase
+ Column []*IdentifierNode
+ Value [][]ExprNode
+}
+
+var _ Node = (*InsertWithColumnOptionNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n InsertWithColumnOptionNode) GetChildren() []Node {
+ size := len(n.Column)
+ for i := 0; i < len(n.Value); i++ {
+ size += len(n.Value[i])
+ }
+ nodes := make([]Node, size)
+ idx := 0
+ for i := 0; i < len(n.Column); i, idx = i+1, idx+1 {
+ nodes[idx] = n.Column[i]
+ }
+ for i := 0; i < len(n.Value); i++ {
+ for j := 0; j < len(n.Value[i]); j, idx = j+1, idx+1 {
+ nodes[idx] = n.Value[i][j]
+ }
+ }
+ return nodes
}
// InsertWithDefaultOptionNode is 'DEFAULT VALUES' used in INSERT.
-type InsertWithDefaultOptionNode struct{}
+type InsertWithDefaultOptionNode struct {
+ NodeBase
+}
+
+var _ Node = (*InsertWithDefaultOptionNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n InsertWithDefaultOptionNode) GetChildren() []Node {
+ return nil
+}
// PrimaryOptionNode is 'PRIMARY KEY' used in CREATE TABLE.
-type PrimaryOptionNode struct{}
+type PrimaryOptionNode struct {
+ NodeBase
+}
+
+var _ Node = (*PrimaryOptionNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n PrimaryOptionNode) GetChildren() []Node {
+ return nil
+}
// NotNullOptionNode is 'NOT NULL' used in CREATE TABLE.
-type NotNullOptionNode struct{}
+type NotNullOptionNode struct {
+ NodeBase
+}
+
+var _ Node = (*NotNullOptionNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n NotNullOptionNode) GetChildren() []Node {
+ return nil
+}
// UniqueOptionNode is 'UNIQUE' used in CREATE TABLE and CREATE INDEX.
-type UniqueOptionNode struct{}
+type UniqueOptionNode struct {
+ NodeBase
+}
+
+var _ Node = (*UniqueOptionNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n UniqueOptionNode) GetChildren() []Node {
+ return nil
+}
// AutoIncrementOptionNode is 'AUTOINCREMENT' used in CREATE TABLE.
-type AutoIncrementOptionNode struct{}
+type AutoIncrementOptionNode struct {
+ NodeBase
+}
+
+var _ Node = (*AutoIncrementOptionNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n AutoIncrementOptionNode) GetChildren() []Node {
+ return nil
+}
// DefaultOptionNode is 'DEFAULT' used in CREATE TABLE.
type DefaultOptionNode struct {
- Value interface{}
+ NodeBase
+ Value ExprNode
+}
+
+var _ Node = (*DefaultValueNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n DefaultOptionNode) GetChildren() []Node {
+ return []Node{n.Value}
}
// ForeignOptionNode is 'REFERENCES' used in CREATE TABLE.
type ForeignOptionNode struct {
- Table IdentifierNode
- Column IdentifierNode
+ NodeBase
+ Table *IdentifierNode
+ Column *IdentifierNode
+}
+
+var _ Node = (*ForeignOptionNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n ForeignOptionNode) GetChildren() []Node {
+ return []Node{n.Table, n.Column}
}
// ---------------------------------------------------------------------------
@@ -304,116 +1070,156 @@ type ForeignOptionNode struct {
// SelectStmtNode is SELECT.
type SelectStmtNode struct {
- Column []interface{}
+ NodeBase
+ Column []ExprNode
Table *IdentifierNode
Where *WhereOptionNode
- Group []interface{}
- Order []interface{}
+ Group []*GroupOptionNode
+ Order []*OrderOptionNode
Limit *LimitOptionNode
Offset *OffsetOptionNode
}
-// GetOption returns a value for printing AST.
-func (n SelectStmtNode) GetOption() map[string]interface{} {
- return map[string]interface{}{
- "Column": n.Column,
- "Table": n.Table,
- "Where": n.Where,
- "Group": n.Group,
- "Order": n.Order,
- "Limit": n.Limit,
- "Offset": n.Offset,
+var _ Node = (*SelectStmtNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n SelectStmtNode) GetChildren() []Node {
+ nodes := make([]Node, len(n.Column)+2+len(n.Group)+len(n.Order)+2)
+ idx := 0
+ for i := 0; i < len(n.Column); i, idx = i+1, idx+1 {
+ nodes[idx] = n.Column[i]
+ }
+ nodes[idx] = n.Table
+ idx++
+ nodes[idx] = n.Where
+ idx++
+ for i := 0; i < len(n.Group); i, idx = i+1, idx+1 {
+ nodes[idx] = n.Group[i]
}
+ for i := 0; i < len(n.Order); i, idx = i+1, idx+1 {
+ nodes[idx] = n.Order[i]
+ }
+ nodes[idx] = n.Limit
+ idx++
+ nodes[idx] = n.Offset
+ idx++
+ return nodes
}
// UpdateStmtNode is UPDATE.
type UpdateStmtNode struct {
- Table IdentifierNode
- Assignment []interface{}
+ NodeBase
+ Table *IdentifierNode
+ Assignment []*AssignOperatorNode
Where *WhereOptionNode
}
-// GetOption returns a value for printing AST.
-func (n UpdateStmtNode) GetOption() map[string]interface{} {
- return map[string]interface{}{
- "Table": n.Table,
- "Assignment": n.Assignment,
- "Where": n.Where,
+var _ Node = (*UpdateStmtNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n UpdateStmtNode) GetChildren() []Node {
+ nodes := make([]Node, 1+len(n.Assignment)+1)
+ idx := 0
+ nodes[idx] = n.Table
+ for i := 0; i < len(n.Assignment); i, idx = i+1, idx+1 {
+ nodes[idx] = n.Assignment[i]
}
+ nodes[idx] = n.Where
+ idx++
+ return nodes
}
// DeleteStmtNode is DELETE.
type DeleteStmtNode struct {
- Table IdentifierNode
+ NodeBase
+ Table *IdentifierNode
Where *WhereOptionNode
}
-// GetOption returns a value for printing AST.
-func (n DeleteStmtNode) GetOption() map[string]interface{} {
- return map[string]interface{}{
- "Table": n.Table,
- "Where": n.Where,
- }
+var _ Node = (*DeleteStmtNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n DeleteStmtNode) GetChildren() []Node {
+ return []Node{n.Table, n.Where}
}
// InsertStmtNode is INSERT.
type InsertStmtNode struct {
- Table IdentifierNode
- Insert interface{}
+ NodeBase
+ Table *IdentifierNode
+ Insert Node
}
-// GetOption returns a value for printing AST.
-func (n InsertStmtNode) GetOption() map[string]interface{} {
- return map[string]interface{}{
- "Table": n.Table,
- "Insert": n.Insert,
- }
+var _ Node = (*InsertStmtNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n InsertStmtNode) GetChildren() []Node {
+ return []Node{n.Table, n.Insert}
}
// CreateTableStmtNode is CREATE TABLE.
type CreateTableStmtNode struct {
- Table IdentifierNode
- Column []interface{}
+ NodeBase
+ Table *IdentifierNode
+ Column []*ColumnSchemaNode
}
-// GetOption returns a value for printing AST.
-func (n CreateTableStmtNode) GetOption() map[string]interface{} {
- return map[string]interface{}{
- "Table": n.Table,
- "Column": n.Column,
+var _ Node = (*CreateTableStmtNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n CreateTableStmtNode) GetChildren() []Node {
+ nodes := make([]Node, 1+len(n.Column))
+ nodes[0] = n.Table
+ for i := 0; i < len(n.Column); i++ {
+ nodes[i+1] = n.Column[i]
}
+ return nodes
}
// ColumnSchemaNode specifies a column in CREATE TABLE.
type ColumnSchemaNode struct {
- Column IdentifierNode
- DataType interface{}
- Constraint []interface{}
+ NodeBase
+ Column *IdentifierNode
+ DataType TypeNode
+ Constraint []Node
}
-// GetOption returns a value for printing AST.
-func (n ColumnSchemaNode) GetOption() map[string]interface{} {
- return map[string]interface{}{
- "Column": n.Column,
- "DataYype": n.DataType,
- "Constraint": n.Constraint,
+var _ Node = (*ColumnSchemaNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n ColumnSchemaNode) GetChildren() []Node {
+ nodes := make([]Node, 2+len(n.Constraint))
+ nodes[0] = n.Column
+ nodes[1] = n.DataType
+ for i := 0; i < len(n.Constraint); i++ {
+ nodes[i+2] = n.Constraint[i]
}
+ return nodes
}
// CreateIndexStmtNode is CREATE INDEX.
type CreateIndexStmtNode struct {
- Index IdentifierNode
- Table IdentifierNode
- Column []interface{}
+ NodeBase
+ Index *IdentifierNode
+ Table *IdentifierNode
+ Column []*IdentifierNode
Unique *UniqueOptionNode
}
-// GetOption returns a value for printing AST.
-func (n CreateIndexStmtNode) GetOption() map[string]interface{} {
- return map[string]interface{}{
- "Index": n.Index,
- "Table": n.Table,
- "Column": n.Column,
- "Unique": n.Unique,
+var _ Node = (*CreateIndexStmtNode)(nil)
+
+// GetChildren returns a list of child nodes used for traversing.
+func (n CreateIndexStmtNode) GetChildren() []Node {
+ nodes := make([]Node, 2+len(n.Column)+1)
+ idx := 0
+ nodes[idx] = n.Index
+ idx++
+ nodes[idx] = n.Table
+ idx++
+ for i := 0; i < len(n.Column); i, idx = i+1, idx+1 {
+ nodes[idx] = n.Column[i]
}
+ nodes[idx] = n.Unique
+ idx++
+ return nodes
}
diff --git a/core/vm/sqlvm/ast/printer.go b/core/vm/sqlvm/ast/printer.go
index 32da47859..a3dd1ba07 100644
--- a/core/vm/sqlvm/ast/printer.go
+++ b/core/vm/sqlvm/ast/printer.go
@@ -54,6 +54,7 @@ func printAST(w io.Writer, n interface{}, depth int, base string, detail bool) {
valueOf = valueOf.Elem()
typeOf = typeOf.Elem()
}
+ kind := typeOf.Kind()
name = name + typeOf.Name()
if op, ok := n.(UnaryOperator); ok {
@@ -70,45 +71,69 @@ func printAST(w io.Writer, n interface{}, depth int, base string, detail bool) {
printAST(w, op.GetSubject(), depth+2, base, detail)
return
}
- if arr, ok := n.([]interface{}); ok {
- if len(arr) == 0 {
+ if stringer, ok := n.(fmt.Stringer); ok {
+ s := stringer.String()
+ fmt.Fprintf(w, "%s%s: %s\n", indent, name, formatString(s))
+ return
+ }
+ if bs, ok := n.([]byte); ok {
+ fmt.Fprintf(w, "%s%s\n", indent, formatBytes(bs))
+ return
+ }
+ if kind == reflect.Slice {
+ l := valueOf.Len()
+ if l == 0 {
fmt.Fprintf(w, "%s[]\n", indent)
return
}
fmt.Fprintf(w, "%s[\n", indent)
- for idx := range arr {
- printAST(w, arr[idx], depth+1, base, detail)
+ for i := 0; i < l; i++ {
+ v := valueOf.Index(i)
+ printAST(w, v.Interface(), depth+1, base, detail)
}
fmt.Fprintf(w, "%s]\n", indent)
return
}
- if stringer, ok := n.(fmt.Stringer); ok {
- s := stringer.String()
- fmt.Fprintf(w, "%s%s: %s\n", indent, name, formatString(s))
- return
- }
- if typeOf.Kind() == reflect.Struct {
+ if kind == reflect.Struct {
+ type field struct {
+ name string
+ value interface{}
+ }
+ var fields []field
+ var collect func(reflect.Type, reflect.Value)
+ collect = func(typeOf reflect.Type, valueOf reflect.Value) {
+ l := typeOf.NumField()
+ for i := 0; i < l; i++ {
+ if !detail && typeOf.Field(i).Tag.Get("print") == "-" {
+ continue
+ }
+ if typeOf.Field(i).Anonymous {
+ embeddedInterface := valueOf.Field(i).Interface()
+ embeddedTypeOf := reflect.TypeOf(embeddedInterface)
+ embeddedValueOf := reflect.ValueOf(embeddedInterface)
+ collect(embeddedTypeOf, embeddedValueOf)
+ continue
+ }
+ fields = append(fields, field{
+ name: typeOf.Field(i).Name,
+ value: valueOf.Field(i).Interface(),
+ })
+ }
+ }
+ collect(typeOf, valueOf)
fmt.Fprintf(w, "%s%s", indent, name)
- l := typeOf.NumField()
- if l == 0 {
+ if len(fields) == 0 {
fmt.Fprintf(w, " {}\n")
return
}
fmt.Fprintf(w, " {\n")
- for i := 0; i < l; i++ {
- if !detail && typeOf.Field(i).Tag.Get("print") == "-" {
- continue
- }
- fmt.Fprintf(w, "%s%s:\n", indentLong, typeOf.Field(i).Name)
- printAST(w, valueOf.Field(i).Interface(), depth+2, base, detail)
+ for i := 0; i < len(fields); i++ {
+ fmt.Fprintf(w, "%s%s:\n", indentLong, fields[i].name)
+ printAST(w, fields[i].value, depth+2, base, detail)
}
fmt.Fprintf(w, "%s}\n", indent)
return
}
- if bs, ok := n.([]byte); ok {
- fmt.Fprintf(w, "%s%s\n", indent, formatBytes(bs))
- return
- }
fmt.Fprintf(w, "%s%+v\n", indent, valueOf.Interface())
}
diff --git a/core/vm/sqlvm/ast/types.go b/core/vm/sqlvm/ast/types.go
index cb8c62c04..0742bbc14 100644
--- a/core/vm/sqlvm/ast/types.go
+++ b/core/vm/sqlvm/ast/types.go
@@ -60,6 +60,14 @@ const (
DataTypeMajorUfixed DataTypeMajor = 0x30
)
+// DataTypeMinor enums.
+const (
+ DataTypeMinorDontCare DataTypeMinor = 0x00
+ DataTypeMinorSpecialNull DataTypeMinor = 0x00
+ DataTypeMinorSpecialAny DataTypeMinor = 0x01
+ DataTypeMinorSpecialDefault DataTypeMinor = 0x02
+)
+
// DataTypeUnknown for unknown data type.
const DataTypeUnknown DataType = 0