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.