Source File
fuse_sortlimit.go
Belonging Package
github.com/freeeve/gochickpeas/gql/internal/plan
// Sort-limit fusion: a trailing segment that only orders, paginates, and// re-projects the previous segment's columns forces that segment to// materialize every row it produces, even though at most skip+limit can// ever surface. Donating the ORDER BY / OFFSET / LIMIT upstream lets the// producing segment's bounded sink retain skip+limit rows and refuse the// rest before they are built (the NEXT-authored ORDER BY form of the// LDBC IC queries). The donor keeps its projection, now over the already// ordered, already truncated rows.package planimport// DisableSortLimitFusion pins result identity in tests: the unfused// pipeline must produce exactly the rows the fused one does, in the// same order.var DisableSortLimitFusion bool// fuseSortLimit hoists each qualifying segment's ordering and pagination// into its producer, scanning producers first so an aligned chain can// cascade. The donor must be a pure projection (no stages, no// post-where, not distinct, not aggregated) whose ORDER BY keys are bare// references to the producer's output columns and whose LIMIT bounds the// retention; the receiver must not order, paginate, or post-filter on// its own (a receiver post-where runs before the donor's sort-limit in// the unfused pipeline, so hoisting past it would reorder semantics).func fuseSortLimit( []*Segment) {if DisableSortLimitFusion {return}for := len() - 2; >= 0; -- {, := [], [+1]if !sortLimitDonor() || !sortLimitReceiver() {continue}if !orderKeysAreColumns(.Proj.OrderBy, &.Proj) {continue}.Proj.OrderBy = .Proj.OrderBy.Proj.Skip = .Proj.Skip.Proj.Limit = .Proj.Limit.Proj.OrderBy = nil.Proj.Skip = nil.Proj.Limit = nil}}// sortLimitDonor: a stage-less, filter-less, non-distinct,// non-aggregated projection segment carrying both an ORDER BY and a// LIMIT (a bound; ORDER BY alone retains everything and buys nothing).func sortLimitDonor( *Segment) bool {return len(.Stages) == 0 && .PostWhere == nil &&!.Proj.Distinct && !.Proj.Aggregated &&len(.Proj.Post) == 0 && .Proj.NHidden == 0 &&len(.Proj.OrderBy) > 0 && .Proj.Limit != nil}// sortLimitReceiver: no ordering or pagination of its own to compete// with the donated one, and no post-where the donation would leapfrog.func sortLimitReceiver( *Segment) bool {return len(.Proj.OrderBy) == 0 && .Proj.Limit == nil &&.Proj.Skip == nil && .PostWhere == nil}// orderKeysAreColumns reports whether every sort key is a bare variable// naming one of the receiver's output columns -- the only form whose// meaning is unchanged by evaluation in the receiver's scope (an// arbitrary expression could collide with a receiver match variable of// the same name).func orderKeysAreColumns( []ast.SortItem, *ProjPlan) bool {for := range {, := [].Expr.(*ast.Var)if ! {return false}:= falsefor , := range .Columns {if == .Name {= truebreak}}if ! {return false}}return true}
![]() |
The pages are generated with Golds v0.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. |