MCPcopy Create free account
hub / github.com/brimdata/super / sqlSelect

Method sqlSelect

compiler/semantic/sql.go:25–129  ·  view source on GitHub ↗

Analyze a SQL select expression which may have arbitrary nested subqueries and may or may not have its sources embedded. The output of a select expression is a record that wraps its input and selected columns in a record {in:any,out:any}. The schema returned represents the observable scope of the s

(sel *ast.SQLSelect, demand []ast.Expr, seq sem.Seq, parentType super.Type)

Source from the content-addressed store, hash-verified

23// and also sort by the out elements. It's up to the caller to unwrap the in/out
24// record when returning to pipeline context.
25func (t *translator) sqlSelect(sel *ast.SQLSelect, demand []ast.Expr, seq sem.Seq, parentType super.Type) (sem.Seq, tableScope) {
26 if len(sel.Selection.Args) == 0 {
27 t.error(sel, errors.New("SELECT clause has no selection"))
28 return seq, badTable
29 }
30 seq, fromScope := t.selectFrom(sel.Loc, sel.From, seq, parentType)
31 if fromScope == nil || fromScope == badTable {
32 return seq, badTable
33 }
34 if t.scope.sql != nil {
35 fromScope = &subqueryScope{
36 outer: t.scope.sql,
37 inner: fromScope,
38 }
39 }
40 save := t.scope.sql
41 scope := &selectScope{
42 in: fromScope,
43 }
44 t.scope.sql = scope
45 defer func() {
46 t.scope.sql = save
47 }()
48 // We first form column slots (and expand *'s) but delay analysis of expressions.
49 // This will let us properly resolve lateral column aliases from any
50 // GROUP BY expressions that reference them.
51 fromType := fromScope.superType(t.sctx, t.checker.unknown)
52 inType := t.sctx.MustLookupTypeRecord([]super.Field{super.NewField("in", fromType)})
53 scope.columns = t.formProjection(scope, sel.Selection.Args, inType)
54 var where sem.Expr
55 if sel.Where != nil {
56 var typ super.Type
57 where, typ = t.expr(sel.Where, inType)
58 t.checker.boolean(sel.Where, typ)
59 }
60 scope.lateral = true
61 scope.groupings = t.groupBy(scope, sel.GroupBy, inType)
62 scope.aggOk = true
63 // Make sure any aggs needed by ORDER BY and HAVING are computed and
64 // placed into the scope.aggs table.
65 // This is a little tricky because we need to find the agg functions
66 // and type check their args against the input table, but we can't
67 // type check the outer parts of the expression yet because the output
68 // scope is not available. So we just call expr() here and ignore
69 // any type errors. This will work out ok because we descend into
70 // expressions before type checking them so all agg funcs will be
71 // encountered and entered into the scope.aggs table and the real
72 // type checking will be handled above by the ORDER BY logic.
73 t.checker.pushErrs()
74 for _, e := range demand {
75 t.expr(e, inType)
76 }
77 if sel.Having != nil {
78 scope.lateral = false
79 t.expr(sel.Having, inType)
80 scope.lateral = true
81 }
82 t.checker.popErrs()

Callers 1

sqlQueryBodyMethod · 0.95

Calls 15

selectFromMethod · 0.95
formProjectionMethod · 0.95
exprMethod · 0.95
groupByMethod · 0.95
projectionMethod · 0.95
isGroupedMethod · 0.95
replaceGroupingsMethod · 0.95
genAggregateMethod · 0.95
emitProjectionMethod · 0.95
superTypeMethod · 0.95
groupedExprMethod · 0.95
genDistinctMethod · 0.95

Tested by

no test coverage detected