Documentation ¶
Index ¶
- Variables
- func CountFunc(ctx EvalContext, val value.Value) (value.IntValue, bool)
- func FindAllIdentityField(node Node) []string
- func FindIdentityField(node Node) string
- func FindIdentityName(depth int, node Node, prefix string) string
- func FuncAdd(name string, fn interface{})
- func FuncsGet() map[string]Func
- func PowFunc(ctx EvalContext, val, toPower value.Value) (value.NumberValue, bool)
- func SqrtFunc(ctx EvalContext, val value.Value) (value.NumberValue, bool)
- func ValueTypeFromNode(n Node) value.ValueType
- type BinaryNode
- type Column
- type Columns
- type ContextReader
- type ContextWriter
- type EvalContext
- type Func
- type FuncNode
- type IdentityNode
- func (m *IdentityNode) Bool() bool
- func (m *IdentityNode) Check() error
- func (m *IdentityNode) IsBooleanIdentity() bool
- func (m *IdentityNode) LeftRight() (string, string, bool)
- func (m *IdentityNode) NodeType() NodeType
- func (m *IdentityNode) String() string
- func (m *IdentityNode) StringAST() string
- func (m *IdentityNode) Type() reflect.Value
- type LexTokenPager
- func (m *LexTokenPager) Backup()
- func (m *LexTokenPager) ClauseEnd() bool
- func (m *LexTokenPager) Cur() lex.Token
- func (m *LexTokenPager) IsEnd() bool
- func (m *LexTokenPager) Last() lex.TokenType
- func (m *LexTokenPager) Lexer() *lex.Lexer
- func (m *LexTokenPager) Next() lex.Token
- func (m *LexTokenPager) Peek() lex.Token
- type MultiArgNode
- type Node
- type NodeType
- type NodeValueType
- type NullNode
- type NumberNode
- type ParsedNode
- type Pos
- type PreparedStatement
- func (m *PreparedStatement) Accept(visitor Visitor) (interface{}, error)
- func (m *PreparedStatement) Check() error
- func (m *PreparedStatement) Keyword() lex.TokenType
- func (m *PreparedStatement) NodeType() NodeType
- func (m *PreparedStatement) String() string
- func (m *PreparedStatement) StringAST() string
- func (m *PreparedStatement) Type() reflect.Value
- type Projection
- type ResultColumn
- type ResultColumns
- type RowWriter
- type SchemaInfo
- type SqlDelete
- type SqlDescribe
- func (m *SqlDescribe) Accept(visitor Visitor) (interface{}, error)
- func (m *SqlDescribe) Check() error
- func (m *SqlDescribe) Keyword() lex.TokenType
- func (m *SqlDescribe) NodeType() NodeType
- func (m *SqlDescribe) String() string
- func (m *SqlDescribe) StringAST() string
- func (m *SqlDescribe) Type() reflect.Value
- type SqlInsert
- type SqlInto
- type SqlSelect
- func (m *SqlSelect) Accept(visitor Visitor) (interface{}, error)
- func (m *SqlSelect) AddColumn(colArg Column) error
- func (m *SqlSelect) Check() error
- func (m *SqlSelect) CountStar() bool
- func (m *SqlSelect) Finalize() error
- func (m *SqlSelect) Keyword() lex.TokenType
- func (m *SqlSelect) NodeType() NodeType
- func (m *SqlSelect) Projection(p *Projection) *Projection
- func (m *SqlSelect) String() string
- func (m *SqlSelect) StringAST() string
- func (m *SqlSelect) SysVariable() string
- func (m *SqlSelect) Type() reflect.Value
- func (m *SqlSelect) UnAliasedColumns() map[string]*Column
- type SqlShow
- type SqlSource
- func (m *SqlSource) Accept(visitor SubVisitor) (interface{}, error)
- func (m *SqlSource) Check() error
- func (m *SqlSource) Finalize() error
- func (m *SqlSource) JoinValueExpr() (Node, error)
- func (m *SqlSource) Keyword() lex.TokenType
- func (m *SqlSource) NodeType() NodeType
- func (m *SqlSource) Rewrite(isLeft bool, fullStmt *SqlSelect) *SqlSelect
- func (m *SqlSource) String() string
- func (m *SqlSource) StringAST() string
- func (m *SqlSource) Type() reflect.Value
- func (m *SqlSource) UnAliasedColumns() map[string]*Column
- type SqlStatement
- type SqlSubStatement
- type SqlTokenPager
- type SqlUpdate
- type SqlUpsert
- type SqlWhere
- type Sqlbridge
- type StringNode
- type SubVisitor
- type TokenPager
- type Tree
- func (t *Tree) A(depth int) Node
- func (t *Tree) BuildTree(runCheck bool) error
- func (t *Tree) C(depth int) Node
- func (t *Tree) F(depth int) Node
- func (t *Tree) Func(depth int, funcTok lex.Token) (fn *FuncNode)
- func (t *Tree) M(depth int) Node
- func (t *Tree) MultiArg(first Node, op lex.Token, depth int) Node
- func (t *Tree) O(depth int) Node
- func (t *Tree) P(depth int) Node
- func (t *Tree) String() string
- type TriNode
- type UnaryNode
- type Visitor
Constants ¶
This section is empty.
Variables ¶
var ( // Standard errors ErrNotSupported = fmt.Errorf("QLB: Not supported") ErrNotImplemented = fmt.Errorf("QLB: Not implemented") ErrUnknownCommand = fmt.Errorf("QLB: Unknown Command") ErrInternalError = fmt.Errorf("QLB: Internal Error") )
var DefaultDialect *lex.Dialect = lex.LogicalExpressionDialect
We have a default Dialect, which is the "Language" or rule-set of ql
Functions ¶
func FindAllIdentityField ¶
Recursively descend down a node looking for all Identity Fields
min(year) == {year} eq(min(item), max(month)) == {item, month}
func FindIdentityField ¶
Recursively descend down a node looking for first Identity Field
min(year) == year eq(min(item), max(month)) == item
func FindIdentityName ¶
Recursively descend down a node looking for first Identity Field
and combine with outermost expression to create an alias min(year) == min_year eq(min(year), max(month)) == eq_year
func PowFunc ¶
func PowFunc(ctx EvalContext, val, toPower value.Value) (value.NumberValue, bool)
Pow
Types ¶
type BinaryNode ¶
Binary node is x op y, two nodes (left, right) and an operator operators can be a variety of:
+, -, *, %, /,
Also, parenthesis may wrap these
func NewBinaryNode ¶
func NewBinaryNode(operator lex.Token, lhArg, rhArg Node) *BinaryNode
Create a Binary node
@operator = * + - %/ / && || = == @operator = and, or, "is not" @lhArg, rhArg the left, right side of binary
func (*BinaryNode) Check ¶
func (m *BinaryNode) Check() error
func (*BinaryNode) IsSimple ¶
func (m *BinaryNode) IsSimple() bool
A simple binary function is one who does not have nested expressions
underneath it, ie just value = y
func (*BinaryNode) NodeType ¶
func (m *BinaryNode) NodeType() NodeType
func (*BinaryNode) String ¶
func (m *BinaryNode) String() string
func (*BinaryNode) StringAST ¶
func (m *BinaryNode) StringAST() string
func (*BinaryNode) Type ¶
func (m *BinaryNode) Type() reflect.Value
type Column ¶
type Column struct { Index int // Field Position Order in original query SourceField string // field name of underlying field As string // As field, auto-populate the Field Name if exists Comment string // optional in-line comments Order string // (ASC | DESC) Star bool // If just * Expr Node // Expression, optional, often Identity.Node Guard Node // If // contains filtered or unexported fields }
Column represents the Column as expressed in a [SELECT] expression
func (*Column) LeftRight ¶
Return left, right values if is of form `table.column` and also return true/false for if it even has left/right
func (*Column) RewriteFor ¶
type Columns ¶
type Columns []*Column
Array of Columns
func (*Columns) FieldNames ¶
func (*Columns) UnAliasedFieldNames ¶
type ContextReader ¶
type ContextReader interface { Get(key string) (value.Value, bool) Row() map[string]value.Value Ts() time.Time }
Context Reader is interface to read the context of message/row/command
being evaluated
type ContextWriter ¶
type ContextWriter interface { Put(col SchemaInfo, readCtx ContextReader, v value.Value) error Delete(row map[string]value.Value) error }
For evaluation storage
type EvalContext ¶
type EvalContext interface { ContextReader }
Eval context, used to contain info for usage/lookup at runtime evaluation
type Func ¶
type Func struct { Name string // The arguments we expect Args []reflect.Value VariadicArgs bool Return reflect.Value ReturnValueType value.ValueType // The actual Go Function F reflect.Value }
Describes a function which wraps and allows native go functions
to be called (via reflection) via scripting
type FuncNode ¶
type FuncNode struct { Pos Name string // Name of func F Func // The actual function that this AST maps to Args []Node // Arguments are them-selves nodes }
FuncNode holds a Func, which desribes a go Function as well as fulfilling the Pos, String() etc for a Node
interfaces: Node
type IdentityNode ¶
IdentityNode will look up a value out of a env bag
also identities of sql objects (tables, columns, etc) we often need to rewrite these as in sql it is `table.column`
func NewIdentityNode ¶
func NewIdentityNode(tok *lex.Token) *IdentityNode
func (*IdentityNode) Bool ¶
func (m *IdentityNode) Bool() bool
func (*IdentityNode) Check ¶
func (m *IdentityNode) Check() error
func (*IdentityNode) IsBooleanIdentity ¶
func (m *IdentityNode) IsBooleanIdentity() bool
func (*IdentityNode) LeftRight ¶
func (m *IdentityNode) LeftRight() (string, string, bool)
Return left, right values if is of form `table.column` and also return true/false for if it even has left/right
func (*IdentityNode) NodeType ¶
func (m *IdentityNode) NodeType() NodeType
func (*IdentityNode) String ¶
func (m *IdentityNode) String() string
func (*IdentityNode) StringAST ¶
func (m *IdentityNode) StringAST() string
func (*IdentityNode) Type ¶
func (m *IdentityNode) Type() reflect.Value
type LexTokenPager ¶
type LexTokenPager struct {
// contains filtered or unexported fields
}
TokenPager is responsible for determining end of current tree (column, etc)
func NewLexTokenPager ¶
func NewLexTokenPager(lex *lex.Lexer) *LexTokenPager
func (*LexTokenPager) Backup ¶
func (m *LexTokenPager) Backup()
backup backs the input stream up one token.
func (*LexTokenPager) ClauseEnd ¶
func (m *LexTokenPager) ClauseEnd() bool
func (*LexTokenPager) Cur ¶
func (m *LexTokenPager) Cur() lex.Token
func (*LexTokenPager) IsEnd ¶
func (m *LexTokenPager) IsEnd() bool
func (*LexTokenPager) Last ¶
func (m *LexTokenPager) Last() lex.TokenType
func (*LexTokenPager) Lexer ¶
func (m *LexTokenPager) Lexer() *lex.Lexer
func (*LexTokenPager) Peek ¶
func (m *LexTokenPager) Peek() lex.Token
peek returns but does not consume the next token.
type MultiArgNode ¶
Multi Arg Node
arg0 IN (arg1,arg2.....) 5 in (1,2,3,4) => false
func NewMultiArgNode ¶
func NewMultiArgNode(operator lex.Token) *MultiArgNode
Create a Multi Arg node
@operator = In @args ....
func NewMultiArgNodeArgs ¶
func NewMultiArgNodeArgs(operator lex.Token, args []Node) *MultiArgNode
func (*MultiArgNode) Append ¶
func (m *MultiArgNode) Append(n Node)
func (*MultiArgNode) Check ¶
func (m *MultiArgNode) Check() error
func (*MultiArgNode) NodeType ¶
func (m *MultiArgNode) NodeType() NodeType
func (*MultiArgNode) String ¶
func (m *MultiArgNode) String() string
func (*MultiArgNode) StringAST ¶
func (m *MultiArgNode) StringAST() string
func (*MultiArgNode) Type ¶
func (m *MultiArgNode) Type() reflect.Value
type Node ¶
type Node interface { // string representation of internals String() string // string representation matches original statement StringAST() string // byte position of start of node in full original input string Position() Pos // performs type checking for itself and sub-nodes, evaluates // validity of the expression/node in advance of evaluation Check() error // describes the Node type, faster than interface casting NodeType() NodeType }
A Node is an element in the expression tree, implemented by different types (string, binary, urnary, func, case, etc)
type NodeType ¶
type NodeType uint8
const ( NodeNodeType NodeType = 1 FuncNodeType NodeType = 2 IdentityNodeType NodeType = 3 StringNodeType NodeType = 4 NumberNodeType NodeType = 5 BinaryNodeType NodeType = 10 UnaryNodeType NodeType = 11 TriNodeType NodeType = 13 MultiArgNodeType NodeType = 14 NullNodeType NodeType = 15 SqlPreparedType NodeType = 29 SqlSelectNodeType NodeType = 30 SqlInsertNodeType NodeType = 31 SqlUpdateNodeType NodeType = 32 SqlUpsertNodeType NodeType = 33 SqlDeleteNodeType NodeType = 35 SqlDescribeNodeType NodeType = 40 SqlShowNodeType NodeType = 41 SqlCreateNodeType NodeType = 50 SqlSourceNodeType NodeType = 55 SqlWhereNodeType NodeType = 56 SqlIntoNodeType NodeType = 57 SqlJoinNodeType NodeType = 58 )
type NodeValueType ¶
Node that has a Type Value
type NumberNode ¶
type NumberNode struct { Pos IsInt bool // Number has an integer value. IsFloat bool // Number has a floating-point value. Int64 int64 // The integer value. Float64 float64 // The floating-point value. Text string // The original textual representation from the input. }
NumberNode holds a number: signed or unsigned integer or float. The value is parsed and stored under all the types that can represent the value. This simulates in a small amount of code the behavior of Go's ideal constants.
func NewNumber ¶
func NewNumber(pos Pos, text string) (*NumberNode, error)
NewNumber is a little weird in that this Node accepts string @text and uses go to parse into Int, AND Float.
func (*NumberNode) Check ¶
func (n *NumberNode) Check() error
func (*NumberNode) NodeType ¶
func (m *NumberNode) NodeType() NodeType
func (*NumberNode) String ¶
func (n *NumberNode) String() string
func (*NumberNode) StringAST ¶
func (n *NumberNode) StringAST() string
func (*NumberNode) Type ¶
func (n *NumberNode) Type() reflect.Value
type ParsedNode ¶
type ParsedNode interface {
Finalize() error
}
type PreparedStatement ¶
type PreparedStatement struct { Pos Alias string Statement SqlStatement }
func NewPreparedStatement ¶
func NewPreparedStatement() *PreparedStatement
func (*PreparedStatement) Accept ¶
func (m *PreparedStatement) Accept(visitor Visitor) (interface{}, error)
func (*PreparedStatement) Check ¶
func (m *PreparedStatement) Check() error
func (*PreparedStatement) Keyword ¶
func (m *PreparedStatement) Keyword() lex.TokenType
func (*PreparedStatement) NodeType ¶
func (m *PreparedStatement) NodeType() NodeType
func (*PreparedStatement) String ¶
func (m *PreparedStatement) String() string
func (*PreparedStatement) StringAST ¶
func (m *PreparedStatement) StringAST() string
func (*PreparedStatement) Type ¶
func (m *PreparedStatement) Type() reflect.Value
type Projection ¶
type Projection struct { Distinct bool Columns ResultColumns }
Projection is just the ResultColumns for a result-set
func NewProjection ¶
func NewProjection() *Projection
func (*Projection) AddColumnShort ¶
func (m *Projection) AddColumnShort(name string, vt value.ValueType)
type ResultColumn ¶
type ResultColumn struct { //Expr Node // If expression, is here Name string // Original path/name for query field ColPos int // Ordinal position in sql statement Col *Column // the original sql column Star bool // Was this a select * ?? As string // aliased Type value.ValueType // Data Type }
func NewResultColumn ¶
type ResultColumns ¶
type ResultColumns []*ResultColumn
type RowWriter ¶
type RowWriter interface { Commit(rowInfo []SchemaInfo, row RowWriter) error Put(col SchemaInfo, readCtx ContextReader, v value.Value) error }
for commiting row ops (insert, update)
type SchemaInfo ¶
type SchemaInfo interface {
Key() string
}
SchemaInfo is interface for a Column type
type SqlDelete ¶
func NewSqlDelete ¶
func NewSqlDelete() *SqlDelete
type SqlDescribe ¶
type SqlDescribe struct { Pos Identity string Tok lex.Token // Explain, Describe, Desc Stmt SqlStatement }
func (*SqlDescribe) Accept ¶
func (m *SqlDescribe) Accept(visitor Visitor) (interface{}, error)
func (*SqlDescribe) Check ¶
func (m *SqlDescribe) Check() error
func (*SqlDescribe) Keyword ¶
func (m *SqlDescribe) Keyword() lex.TokenType
func (*SqlDescribe) NodeType ¶
func (m *SqlDescribe) NodeType() NodeType
func (*SqlDescribe) String ¶
func (m *SqlDescribe) String() string
func (*SqlDescribe) StringAST ¶
func (m *SqlDescribe) StringAST() string
func (*SqlDescribe) Type ¶
func (m *SqlDescribe) Type() reflect.Value
type SqlInsert ¶
func NewSqlInsert ¶
func NewSqlInsert() *SqlInsert
func (*SqlInsert) Keyword ¶
func (m *Join) Accept(visitor SubVisitor) (interface{}, error) { return visitor.VisitSubselect(m) } func (m *Join) Keyword() lex.TokenType { return lex.TokenJoin } func (m *Join) Check() error { return nil } func (m *Join) Type() reflect.Value { return nilRv } func (m *Join) NodeType() NodeType { return SqlJoinNodeType } func (m *Join) StringAST() string { return m.String() } func (m *Join) String() string { return fmt.Sprintf("%s", m.Table) }
type SqlInto ¶
func NewSqlInto ¶
type SqlSelect ¶
type SqlSelect struct { Pos Db string // If provided a use "dbname" Raw string // full original raw statement Star bool // for select * from ... Columns Columns // An array (ordered) list of columns From []*SqlSource // From, Join Into *SqlInto // Into "table" Where *SqlWhere // Expr Node, or *SqlSelect Having Node // Filter results GroupBy Columns OrderBy Columns Limit int Offset int // contains filtered or unexported fields }
func NewSqlSelect ¶
func NewSqlSelect() *SqlSelect
func (*SqlSelect) Finalize ¶
Finalize this Query plan by preparing sub-sources
ie we need to rewrite some things into sub-statements - we need to share the join expression across sources
func (*SqlSelect) Projection ¶
func (m *SqlSelect) Projection(p *Projection) *Projection
func (*SqlSelect) UnAliasedColumns ¶
type SqlSource ¶
type SqlSource struct { Pos Raw string // Raw Partial Name string // From Name (optional, empty if join, subselect) Alias string // From name aliased Op lex.TokenType // In, =, ON LeftOrRight lex.TokenType // Left, Right JoinType lex.TokenType // INNER, OUTER Source *SqlSelect // optional, Join or SubSelect statement JoinExpr Node // Join expression x.y = q.y // If we do have to rewrite statement Into string Star bool // all ? Columns Columns // cols Where *SqlWhere // Expr Node, or *SqlSelect // contains filtered or unexported fields }
Source is a table name, sub-query, or join
func (*SqlSource) Accept ¶
func (m *SqlSource) Accept(visitor SubVisitor) (interface{}, error)
func (*SqlSource) JoinValueExpr ¶
We need to be able to rewrite statements to convert a stmt such as:
FROM users AS u INNER JOIN orders AS o ON u.user_id = o.user_id So that we can evaluate the Join Key on left/right in this case, it is simple, just => user_id or this one: FROM users AS u INNER JOIN orders AS o ON LOWER(u.email) = LOWER(o.email) => LOWER(user_id)
func (*SqlSource) Rewrite ¶
Rewrite this Source to act as a stand-alone query to backend
@fullStmt = the full statement that this a partial source to @isLeft = ??? todo doc
func (*SqlSource) UnAliasedColumns ¶
Get a list of Columns
type SqlStatement ¶
type SqlStatement interface { Node Accept(visitor Visitor) (interface{}, error) Keyword() lex.TokenType }
The sqlStatement interface, to define the sql-types
Select, Insert, Delete etc
func ParseSql ¶
func ParseSql(sqlQuery string) (SqlStatement, error)
Parses Tokens and returns an request.
func ParseSqlVm ¶
func ParseSqlVm(sqlQuery string) (SqlStatement, error)
type SqlSubStatement ¶
type SqlSubStatement interface { Node Accept(visitor SubVisitor) (interface{}, error) Keyword() lex.TokenType }
The sqlStatement interface, to define the subselect/join-types
Join, SubSelect, From
type SqlTokenPager ¶
type SqlTokenPager struct { *LexTokenPager // contains filtered or unexported fields }
TokenPager is responsible for determining end of current tree (column, etc)
func NewSqlTokenPager ¶
func NewSqlTokenPager(lex *lex.Lexer) *SqlTokenPager
func (*SqlTokenPager) ClauseEnd ¶
func (m *SqlTokenPager) ClauseEnd() bool
func (*SqlTokenPager) IsEnd ¶
func (m *SqlTokenPager) IsEnd() bool
type SqlUpdate ¶
type SqlUpdate struct { Pos Columns Columns Where Node From string // contains filtered or unexported fields }
func NewSqlUpdate ¶
func NewSqlUpdate() *SqlUpdate
type SqlWhere ¶
WHERE is select stmt, or set of expressions - WHERE x in (select *) - WHERE x = y - WHERE x = y AND z = q
type Sqlbridge ¶
type Sqlbridge struct { *SqlTokenPager // contains filtered or unexported fields }
generic SQL parser evaluates should be sufficient for most
sql compatible languages
type StringNode ¶
StringNode holds a value literal, quotes not included
func NewStringNode ¶
func NewStringNode(pos Pos, text string) *StringNode
func (*StringNode) Check ¶
func (m *StringNode) Check() error
func (*StringNode) NodeType ¶
func (m *StringNode) NodeType() NodeType
func (*StringNode) String ¶
func (m *StringNode) String() string
func (*StringNode) StringAST ¶
func (m *StringNode) StringAST() string
func (*StringNode) Type ¶
func (m *StringNode) Type() reflect.Value
type SubVisitor ¶
type SubVisitor interface { VisitSubselect(stmt *SqlSource) (interface{}, error) VisitJoin(stmt *SqlSource) (interface{}, error) }
Interface for sub-Tasks of the Select Statement, joins, sub-selects
type TokenPager ¶
type TokenPager interface { Peek() lex.Token Next() lex.Token Cur() lex.Token Last() lex.TokenType Backup() IsEnd() bool ClauseEnd() bool Lexer() *lex.Lexer }
TokenPager wraps a Lexer, and implements the Logic to determine what is the end of this particular clause. Lexer's are stateless, while tokenpager implements state ontop of pager and allows forward/back etc
type Tree ¶
type Tree struct { Root Node // top-level root node of the tree TokenPager // pager for grabbing next tokens, backup(), recognizing end // contains filtered or unexported fields }
Tree is the representation of a single parsed expression
func NewTree ¶
func NewTree(pager TokenPager) *Tree
func ParseExpression ¶
Parse a single Expression, returning a Tree
ParseExpression("5 * toint(item_name)")
type TriNode ¶
Tri Node
ARG1 Between ARG2 AND ARG3
type UnaryNode ¶
UnaryNode holds one argument and an operator
!eq(5,6) !true !(true OR false) !toint(now())
type Visitor ¶
type Visitor interface { VisitPreparedStmt(stmt *PreparedStatement) (interface{}, error) VisitSelect(stmt *SqlSelect) (interface{}, error) VisitInsert(stmt *SqlInsert) (interface{}, error) VisitUpsert(stmt *SqlUpsert) (interface{}, error) VisitUpdate(stmt *SqlUpdate) (interface{}, error) VisitDelete(stmt *SqlDelete) (interface{}, error) VisitShow(stmt *SqlShow) (interface{}, error) VisitDescribe(stmt *SqlDescribe) (interface{}, error) }
Visitor defines the Visit Pattern, so our expr package can
expect implementations from downstream packages in our case, a planner.