Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 32 additions & 117 deletions compiler/semantic/projection.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,7 @@ func (p projection) aggCols() []column {
func newColumn(name string, loc ast.Expr, e sem.Expr, funcs *aggfuncs) (*column, error) {
c := &column{name: name, loc: loc}
cnt := len(*funcs)
var err error
c.expr, err = funcs.subst(e)
if err != nil {
return nil, err
}
c.expr = funcs.subst(e)
c.isAgg = cnt != len(*funcs)
return c, nil
}
Expand All @@ -76,169 +72,88 @@ func (a aggfuncs) tmp() string {
return fmt.Sprintf("t%d", len(a))
}

func (a *aggfuncs) subst(e sem.Expr) (sem.Expr, error) {
var err error
func (a *aggfuncs) subst(e sem.Expr) sem.Expr {
switch e := e.(type) {
case nil:
return e, nil
return e
case *sem.AggFunc:
// swap in a temp column for each agg function found, which
// will then be referred to by the containing expression.
// The agg function is computed into the tmp value with
// the generated aggregate operator.
tmp := a.tmp()
*a = append(*a, namedAgg{name: tmp, agg: e})
return sem.NewThis(e, []string{"in", tmp}), nil
return sem.NewThis(e, []string{"in", tmp})
case *sem.ArrayExpr:
elems, err := a.substArrayElems(e.Elems)
if err != nil {
return nil, err
}
e.Elems = elems
e.Elems = a.substArrayElems(e.Elems)
case *sem.BinaryExpr:
e.LHS, err = a.subst(e.LHS)
if err != nil {
return nil, err
}
e.RHS, err = a.subst(e.RHS)
if err != nil {
return nil, err
}
e.LHS = a.subst(e.LHS)
e.RHS = a.subst(e.RHS)
case *sem.CallExpr:
for k, arg := range e.Args {
e.Args[k], err = a.subst(arg)
if err != nil {
return nil, err
}
e.Args[k] = a.subst(arg)
}
case *sem.CondExpr:
e.Cond, err = a.subst(e.Cond)
if err != nil {
return nil, err
}
e.Then, err = a.subst(e.Then)
if err != nil {
return nil, err
}
e.Else, err = a.subst(e.Else)
if err != nil {
return nil, err
}
e.Cond = a.subst(e.Cond)
e.Then = a.subst(e.Then)
e.Else = a.subst(e.Else)
case *sem.DotExpr:
e.LHS, err = a.subst(e.LHS)
if err != nil {
return nil, err
}
e.LHS = a.subst(e.LHS)
case *sem.IndexExpr:
e.Expr, err = a.subst(e.Expr)
if err != nil {
return nil, err
}
e.Index, err = a.subst(e.Index)
if err != nil {
return nil, err
}
e.Expr = a.subst(e.Expr)
e.Index = a.subst(e.Index)
case *sem.IsNullExpr:
e.Expr, err = a.subst(e.Expr)
if err != nil {
return nil, err
}
e.Expr = a.subst(e.Expr)
case *sem.LiteralExpr:
case *sem.MapExpr:
for _, ent := range e.Entries {
ent.Key, err = a.subst(ent.Key)
if err != nil {
return nil, err
}
ent.Value, err = a.subst(ent.Value)
if err != nil {
return nil, err
}
ent.Key = a.subst(ent.Key)
ent.Value = a.subst(ent.Value)
}
case *sem.RecordExpr:
var elems []sem.RecordElem
for _, elem := range e.Elems {
switch elem := elem.(type) {
case *sem.FieldElem:
sub, err := a.subst(elem.Value)
if err != nil {
return nil, err
}
sub := a.subst(elem.Value)
elems = append(elems, &sem.FieldElem{Node: elem, Name: elem.Name, Value: sub})
case *sem.SpreadElem:
sub, err := a.subst(elem.Expr)
if err != nil {
return nil, err
}
elems = append(elems, &sem.SpreadElem{Node: elem, Expr: sub})
elems = append(elems, &sem.SpreadElem{Node: elem, Expr: a.subst(elem.Expr)})
default:
panic(elem)
}
}
e.Elems = elems
case *sem.RegexpMatchExpr:
e.Expr, err = a.subst(e.Expr)
if err != nil {
return nil, err
}
e.Expr = a.subst(e.Expr)
case *sem.RegexpSearchExpr:
e.Expr, err = a.subst(e.Expr)
if err != nil {
return nil, err
}
e.Expr = a.subst(e.Expr)
case *sem.SearchTermExpr:
e.Expr, err = a.subst(e.Expr)
if err != nil {
return nil, err
}
e.Expr = a.subst(e.Expr)
case *sem.SetExpr:
elems, err := a.substArrayElems(e.Elems)
if err != nil {
return nil, err
}
e.Elems = elems
e.Elems = a.substArrayElems(e.Elems)
case *sem.SliceExpr:
e.Expr, err = a.subst(e.Expr)
if err != nil {
return nil, err
}
e.From, err = a.subst(e.From)
if err != nil {
return nil, err
}
e.To, err = a.subst(e.To)
if err != nil {
return nil, err
}
e.Expr = a.subst(e.Expr)
e.From = a.subst(e.From)
e.To = a.subst(e.To)
case *sem.ThisExpr:
case *sem.UnaryExpr:
e.Operand, err = a.subst(e.Operand)
if err != nil {
return nil, err
}
e.Operand = a.subst(e.Operand)
}
return e, nil
return e
}

func (a *aggfuncs) substArrayElems(elems []sem.ArrayElem) ([]sem.ArrayElem, error) {
func (a *aggfuncs) substArrayElems(elems []sem.ArrayElem) []sem.ArrayElem {
var out []sem.ArrayElem
for _, e := range elems {
switch e := e.(type) {
case *sem.SpreadElem:
sub, err := a.subst(e.Expr)
if err != nil {
return nil, err
}
out = append(out, &sem.SpreadElem{Node: e, Expr: sub})
out = append(out, &sem.SpreadElem{Node: e, Expr: a.subst(e.Expr)})
case *sem.ExprElem:
sub, err := a.subst(e.Expr)
if err != nil {
return nil, err
}
out = append(out, &sem.ExprElem{Node: e, Expr: sub})
out = append(out, &sem.ExprElem{Node: e, Expr: a.subst(e.Expr)})
default:
panic(e)
}
}
return out, nil
return out
}
10 changes: 3 additions & 7 deletions compiler/semantic/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,7 @@ func (t *translator) sqlSelect(sel *ast.SQLSelect, seq sem.Seq) (sem.Seq, schema
where = t.exprSchema(sch, sel.Where)
}
keyExprs := t.groupBy(sch, sel.GroupBy)
having, err := t.having(sch, sel.Having, &funcs)
if err != nil {
t.error(sel.Having, err)
return seq, badSchema()
}
having := t.having(sch, sel.Having, &funcs)
// Now that all the pieces have been converted to sem tree fragments,
// we stitch together the fragments into pipeline operators depending
// on whether its an aggregation or a selection of scalar expressions.
Expand All @@ -72,9 +68,9 @@ func (t *translator) sqlSelect(sel *ast.SQLSelect, seq sem.Seq) (sem.Seq, schema
return seq, sch
}

func (t *translator) having(sch *selectSchema, e ast.Expr, funcs *aggfuncs) (sem.Expr, error) {
func (t *translator) having(sch *selectSchema, e ast.Expr, funcs *aggfuncs) sem.Expr {
if e == nil {
return nil, nil
return nil
}
return funcs.subst(t.exprSchema(&havingSchema{sch}, e))
}
Expand Down