diff options
author | Ting-Wei Lan <tingwei.lan@cobinhood.com> | 2019-02-01 14:36:49 +0800 |
---|---|---|
committer | Jhih-Ming Huang <jm.huang@cobinhood.com> | 2019-05-06 10:44:04 +0800 |
commit | b414e5491c58bab824d0a6bb9fd94e17b2a9659a (patch) | |
tree | 4b5d4925a8301f1bee8a332e12e76667b8e774dc /core/vm/sqlvm/ast | |
parent | a7ecd58ffb2f4137bb09b084cadbbb90048fb1fe (diff) | |
download | dexon-b414e5491c58bab824d0a6bb9fd94e17b2a9659a.tar dexon-b414e5491c58bab824d0a6bb9fd94e17b2a9659a.tar.gz dexon-b414e5491c58bab824d0a6bb9fd94e17b2a9659a.tar.bz2 dexon-b414e5491c58bab824d0a6bb9fd94e17b2a9659a.tar.lz dexon-b414e5491c58bab824d0a6bb9fd94e17b2a9659a.tar.xz dexon-b414e5491c58bab824d0a6bb9fd94e17b2a9659a.tar.zst dexon-b414e5491c58bab824d0a6bb9fd94e17b2a9659a.zip |
core: vm: sqlvm: introduce interfaces for AST nodes
In order to make our AST easier and safer to use, all declarations with
empty interface type are now removed.
This changes also makes it possible to traverse the AST without using
reflection or understanding what each type means because all AST nodes
have at least one common interface.
Diffstat (limited to 'core/vm/sqlvm/ast')
-rw-r--r-- | core/vm/sqlvm/ast/ast.go | 1068 | ||||
-rw-r--r-- | core/vm/sqlvm/ast/printer.go | 69 | ||||
-rw-r--r-- | core/vm/sqlvm/ast/types.go | 8 |
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 |