// Execute: run a plan's UNION branches and combine their rows (port of// the Rust exec.rs entry points, minus the recognizer kernel dispatch).
package execimport ()// Execute runs a plan and returns its rows in output-column order. Every// plan construct the planner produces is executable as of M19, so// execution is infallible once a plan builds.func ( *eval.Ctx, *plan.Plan) ([][]value.Value, error) {installCompileWhere() := runBranch(, .Branches[0])for , := range .Union {combineUnion(&, runBranch(, .Branches[+1]), ) }return , nil}// installCompileWhere hands the eval-side subquery walk a compiler for// its WHERE filters: eval cannot import compile (compile imports eval),// so the executor -- which reaches both -- bridges them. Idempotent; the// interpreted path stays authoritative under ForceInterp and on// non-native graphs, mirroring compileEval's own gate.func installCompileWhere( *eval.Ctx) {if .CompileWhere != nil || .ForceInterp {return } , := .G.(graph.Native)if ! {return } := .Snapshot() .CompileWhere = func( ast.Expr, map[string]int) func(*eval.Ctx, []value.Value) value.Value { := compile.New(, , , )returnfunc( *eval.Ctx, []value.Value) value.Value {return .Eval(, , ) } }}// ExecuteProfiled runs the plan while recording how many rows each// operator produces. Segment profiles are pushed branch-major,// segment-minor -- the order the explain renderer walks. PROFILE reports// operator cardinalities, not the result set; each branch's final rows// are discarded (the union combine is not a profiled operator).func ( *eval.Ctx, *plan.Plan) *explain.Profile {installCompileWhere() := &explain.Profile{}for , := range .Branches { := [][]value.Value{nil}for , := range { := explain.SegProf{} = runSegment(, , , &) .Segs = append(.Segs, ) } }return}// runBranch runs one branch's segment pipeline from a single empty seed// row, streaming across every run of boundaries whose upstream projection// is per-row passthrough (rows cross a NEXT without materializing; the// run's final segment materializes as before).func runBranch( *eval.Ctx, []*plan.Segment) [][]value.Value { := [][]value.Value{nil}for := 0; < len(); {// A columnar-aggregate chain fuses whole: the scan segment, its // LET boundaries, and the aggregated boundary run as one typed // pass; a declined chain falls through to the general runs.if [].ColAgg {if , , := tryColumnarAggChain(, , , ); { = += continue } }// An aggregate whose ordering and DISTINCT+LIMIT live on the two // following boundaries fuses to a streamed argmin selection.if , , := tryOrderedDistinctTopK(, , , ); { = += continue } := // Runs never stream INTO a chain head: the fused pass needs its // materialized seed rows.for +1 < len() && streamableBoundary([]) && ![+1].ColAgg { ++ } = runSegmentRun(, [:+1], ) = + 1 }return}// combineUnion folds a later branch's rows into the accumulator. UNION ALL// concatenates; UNION concatenates then dedups the whole accumulated set// keeping first-occurrence order (left-associative). The dedup key matches// DISTINCT's group key, so UNION and RETURN DISTINCT agree on row// identity.func combineUnion( *[][]value.Value, [][]value.Value, ast.UnionKind) {// EXCEPT / INTERSECT: distinct-set semantics (ISO) -- dedup the left // side, then keep rows absent from / present in the right side.if == ast.UnionExcept || == ast.UnionIntersect { := make(map[string]struct{}, len())var []bytefor , := range { = [:0]for , := range { = value.AppendKey(, ) } [string()] = struct{}{} } := make(map[string]struct{}, len(*)) := (*)[:0]for , := range * { = [:0]for , := range { = value.AppendKey(, ) }if , := [string()]; {continue } [string()] = struct{}{} , := [string()]if ( == ast.UnionExcept) != { = append(, ) } } * = return } * = append(*, ...)if != ast.UnionDistinct {return } := make(map[string]struct{}, len(*)) := (*)[:0]var []bytefor , := range * { = [:0]for , := range { = value.AppendKey(, ) }if , := [string()]; ! { [string()] = struct{}{} = append(, ) } } * = }
The pages are generated with Goldsv0.8.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.