sq/libsq/ast/join.go

196 lines
3.8 KiB
Go
Raw Normal View History

2016-10-17 07:14:01 +03:00
package ast
import (
"fmt"
2020-08-06 20:58:47 +03:00
"github.com/antlr/antlr4/runtime/Go/antlr"
2016-10-17 07:14:01 +03:00
)
2020-08-06 20:58:47 +03:00
var _ Node = (*Join)(nil)
2016-10-17 07:14:01 +03:00
2020-08-06 20:58:47 +03:00
// Join models a SQL JOIN node. It has a child of type JoinConstraint.
2016-10-31 01:35:56 +03:00
type Join struct {
seg *Segment
ctx antlr.ParseTree
constraint *JoinConstraint
leftTbl *TblSelector
rightTbl *TblSelector
2016-10-17 07:14:01 +03:00
}
2020-08-06 20:58:47 +03:00
// LeftTbl is the selector for the left table of the join.
2016-10-31 01:35:56 +03:00
func (jn *Join) LeftTbl() *TblSelector {
return jn.leftTbl
2016-10-17 07:14:01 +03:00
}
2020-08-06 20:58:47 +03:00
// RightTbl is the selector for the right table of the join.
2016-10-31 01:35:56 +03:00
func (jn *Join) RightTbl() *TblSelector {
return jn.rightTbl
2016-10-17 07:14:01 +03:00
}
2020-08-06 20:58:47 +03:00
// Selectable implements the Selectable marker interface.
2016-10-31 01:35:56 +03:00
func (jn *Join) Selectable() {
2016-10-17 07:14:01 +03:00
// no-op
}
2016-10-31 01:35:56 +03:00
func (jn *Join) Parent() Node {
return jn.seg
2016-10-17 07:14:01 +03:00
}
2016-10-31 01:35:56 +03:00
func (jn *Join) SetParent(parent Node) error {
2016-10-17 07:14:01 +03:00
seg, ok := parent.(*Segment)
if !ok {
2020-08-06 20:58:47 +03:00
return errorf("%T requires parent of type %s", jn, typeSegment)
2016-10-17 07:14:01 +03:00
}
2016-10-31 01:35:56 +03:00
jn.seg = seg
2016-10-17 07:14:01 +03:00
return nil
}
2016-10-31 01:35:56 +03:00
func (jn *Join) Children() []Node {
if jn.constraint == nil {
2016-10-17 07:14:01 +03:00
return []Node{}
}
2016-10-31 01:35:56 +03:00
return []Node{jn.constraint}
2016-10-17 07:14:01 +03:00
}
2016-10-31 01:35:56 +03:00
func (jn *Join) AddChild(node Node) error {
2020-08-06 20:58:47 +03:00
jc, ok := node.(*JoinConstraint)
2016-10-17 07:14:01 +03:00
if !ok {
2020-08-06 20:58:47 +03:00
return errorf("JOIN() child must be *JoinConstraint, but got: %T", node)
2016-10-17 07:14:01 +03:00
}
2016-10-31 01:35:56 +03:00
if jn.constraint != nil {
2016-10-17 07:14:01 +03:00
return errorf("JOIN() has max 1 child: failed to add: %T", node)
}
2020-08-06 20:58:47 +03:00
jn.constraint = jc
2016-10-17 07:14:01 +03:00
return nil
}
2016-10-31 01:35:56 +03:00
func (jn *Join) SetChildren(children []Node) error {
2016-10-17 07:14:01 +03:00
if len(children) == 0 {
2016-10-31 01:35:56 +03:00
jn.constraint = nil
2016-10-17 07:14:01 +03:00
return nil
}
if len(children) > 1 {
return errorf("JOIN() can have only one child: failed to add %d children", len(children))
}
2016-10-31 01:35:56 +03:00
expr, ok := children[0].(*JoinConstraint)
2016-10-17 07:14:01 +03:00
if !ok {
return errorf("JOIN() child must be *FnJoinExpr, but got: %T", children[0])
}
2016-10-31 01:35:56 +03:00
jn.constraint = expr
2016-10-17 07:14:01 +03:00
return nil
}
2016-10-31 01:35:56 +03:00
func (jn *Join) Context() antlr.ParseTree {
return jn.ctx
2016-10-17 07:14:01 +03:00
}
2016-10-31 01:35:56 +03:00
func (jn *Join) SetContext(ctx antlr.ParseTree) error {
jn.ctx = ctx
2016-10-17 07:14:01 +03:00
return nil
}
2016-10-31 01:35:56 +03:00
func (jn *Join) Text() string {
return jn.ctx.GetText()
2016-10-17 07:14:01 +03:00
}
2016-10-31 01:35:56 +03:00
func (jn *Join) Segment() *Segment {
return jn.seg
2016-10-17 07:14:01 +03:00
}
2016-10-31 01:35:56 +03:00
func (jn *Join) String() string {
text := nodeString(jn)
2016-10-17 07:14:01 +03:00
leftTblName := ""
rightTblName := ""
2016-10-31 01:35:56 +03:00
if jn.leftTbl != nil {
leftTblName = jn.leftTbl.SelValue()
2016-10-17 07:14:01 +03:00
}
2016-10-31 01:35:56 +03:00
if jn.rightTbl != nil {
rightTblName = jn.rightTbl.SelValue()
2016-10-17 07:14:01 +03:00
}
2020-08-06 20:58:47 +03:00
text += fmt.Sprintf(" | left_table: %q | right_table: %q", leftTblName, rightTblName)
2016-10-17 07:14:01 +03:00
return text
}
2020-08-06 20:58:47 +03:00
var _ Node = (*JoinConstraint)(nil)
2016-10-17 07:14:01 +03:00
2020-08-06 20:58:47 +03:00
// JoinConstraint models a join's constraint.
// For example the elements inside the parentheses
// in "join(.uid == .user_id)".
2016-10-31 01:35:56 +03:00
type JoinConstraint struct {
2020-08-06 20:58:47 +03:00
// join is the parent node
2016-10-31 01:35:56 +03:00
join *Join
2016-10-17 07:14:01 +03:00
ctx antlr.ParseTree
children []Node
}
2016-10-31 01:35:56 +03:00
func (jc *JoinConstraint) Parent() Node {
return jc.join
2016-10-17 07:14:01 +03:00
}
2016-10-31 01:35:56 +03:00
func (jc *JoinConstraint) SetParent(parent Node) error {
join, ok := parent.(*Join)
2016-10-17 07:14:01 +03:00
if !ok {
2020-08-06 20:58:47 +03:00
return errorf("%T requires parent of type %s", jc, typeJoin)
2016-10-17 07:14:01 +03:00
}
2016-10-31 01:35:56 +03:00
jc.join = join
2016-10-17 07:14:01 +03:00
return nil
}
2016-10-31 01:35:56 +03:00
func (jc *JoinConstraint) Children() []Node {
return jc.children
2016-10-17 07:14:01 +03:00
}
2016-10-31 01:35:56 +03:00
func (jc *JoinConstraint) AddChild(child Node) error {
2016-10-17 07:14:01 +03:00
nodeCtx := child.Context()
_, ok := nodeCtx.(*antlr.TerminalNodeImpl)
if !ok {
return errorf("expected leaf node, but got: %T", nodeCtx)
}
2016-10-31 01:35:56 +03:00
jc.children = append(jc.children, child)
2016-10-17 07:14:01 +03:00
return nil
}
2016-10-31 01:35:56 +03:00
func (jc *JoinConstraint) SetChildren(children []Node) error {
2016-10-17 07:14:01 +03:00
for _, child := range children {
nodeCtx := child.Context()
2020-08-06 20:58:47 +03:00
if _, ok := nodeCtx.(*antlr.TerminalNodeImpl); !ok {
2016-10-17 07:14:01 +03:00
return errorf("expected leaf node, but got: %T", nodeCtx)
}
}
2020-08-06 20:58:47 +03:00
if len(children) == 0 {
jc.children = children
return nil
}
2016-10-31 01:35:56 +03:00
jc.children = children
2016-10-17 07:14:01 +03:00
return nil
}
2016-10-31 01:35:56 +03:00
func (jc *JoinConstraint) Context() antlr.ParseTree {
return jc.ctx
2016-10-17 07:14:01 +03:00
}
2016-10-31 01:35:56 +03:00
func (jc *JoinConstraint) SetContext(ctx antlr.ParseTree) error {
jc.ctx = ctx // TODO: check for correct type
2016-10-17 07:14:01 +03:00
return nil
}
2016-10-31 01:35:56 +03:00
func (jc *JoinConstraint) Text() string {
return jc.ctx.GetText()
2016-10-17 07:14:01 +03:00
}
2016-10-31 01:35:56 +03:00
func (jc *JoinConstraint) String() string {
return nodeString(jc)
2016-10-17 07:14:01 +03:00
}