diff --git a/sql/aggregates.go b/sql/aggregates.go index ab09f44afe..ad793348e3 100644 --- a/sql/aggregates.go +++ b/sql/aggregates.go @@ -109,7 +109,7 @@ type WindowFrame interface { StartCurrentRow() bool // EndCurrentRow returns whether a frame end is CURRENT ROW EndCurrentRow() bool - // StartNFollowing returns a frame's start preceding Expression or nil + // StartNPreceding returns a frame's start preceding Expression or nil StartNPreceding() Expression // StartNFollowing returns a frame's start following Expression or nil StartNFollowing() Expression diff --git a/sql/rowexec/agg.go b/sql/rowexec/agg.go index 384e8efe91..548c27a9a8 100644 --- a/sql/rowexec/agg.go +++ b/sql/rowexec/agg.go @@ -238,8 +238,9 @@ func (i *groupByGroupingIter) Dispose() { } func groupingKey(ctx *sql.Context, exprs []sql.Expression, row sql.Row) (uint64, error) { - var keyRow = make(sql.Row, len(exprs)) var keySch = make(sql.Schema, len(exprs)) + keyRow := sql.GetRow(len(exprs)) + defer sql.PutRow(keyRow) for i, expr := range exprs { v, err := expr.Eval(ctx, row) if err != nil { diff --git a/sql/rowexec/merge_join.go b/sql/rowexec/merge_join.go index 5a92bcd9f2..cc63b7c8e4 100644 --- a/sql/rowexec/merge_join.go +++ b/sql/rowexec/merge_join.go @@ -47,7 +47,6 @@ func newMergeJoinIter(ctx *sql.Context, b sql.NodeExecBuilder, j *plan.JoinNode, } fullRow := make(sql.Row, len(row)+len(j.Left().Schema())+len(j.Right().Schema())) - fullRow[0] = row if len(row) > 0 { copy(fullRow[0:], row[:]) } @@ -376,7 +375,7 @@ func (i *mergeJoinIter) incMatch(ctx *sql.Context) error { if !i.leftDone { // rightBuf has already been validated, we don't need compare - copySubslice(i.fullRow, i.rightBuf[i.bufI], i.scopeLen+i.parentLen+i.leftRowLen) + copy(i.fullRow[i.scopeLen+i.parentLen+i.leftRowLen:], i.rightBuf[i.bufI]) i.bufI++ return nil } @@ -394,7 +393,7 @@ func (i *mergeJoinIter) incMatch(ctx *sql.Context) error { if i.lojFinalize() { // left joins expect the left row in |i.fullRow| as long // as the left iter is not exhausted. - copySubslice(i.fullRow, i.leftPeek, i.scopeLen+i.parentLen) + copy(i.fullRow[i.scopeLen+i.parentLen:], i.leftPeek) } return nil } @@ -402,8 +401,8 @@ func (i *mergeJoinIter) incMatch(ctx *sql.Context) error { // both lookaheads fail the join condition. Drain // lookahead rows / increment both iterators. i.matchIncLeft = true - copySubslice(i.fullRow, i.leftPeek, i.scopeLen+i.parentLen) - copySubslice(i.fullRow, i.rightPeek, i.scopeLen+i.parentLen+i.leftRowLen) + copy(i.fullRow[i.scopeLen+i.parentLen:], i.leftPeek) + copy(i.fullRow[i.scopeLen+i.parentLen+i.leftRowLen:], i.rightPeek) return nil } @@ -454,7 +453,7 @@ func (i *mergeJoinIter) resetMatchState() { // no match, no lookahead row, and no error. func (i *mergeJoinIter) peekMatch(ctx *sql.Context, iter sql.RowIter) (bool, sql.Row, error) { var off int - var restore sql.Row + var restore sql.Row // TODO: rowBuffer? switch iter { case i.left: off = i.scopeLen + i.parentLen @@ -477,17 +476,17 @@ func (i *mergeJoinIter) peekMatch(ctx *sql.Context, iter sql.RowIter) (bool, sql } // check if lookahead valid - copySubslice(i.fullRow, peek, off) + copy(i.fullRow[off:], peek) res, err := i.cmp.Compare(ctx, i.fullRow) if expression.ErrNilOperand.Is(err) { // revert change to output row if no match - copySubslice(i.fullRow, restore, off) + copy(i.fullRow[off:], restore) } else if err != nil { return false, nil, err } if res != 0 { // revert change to output row if no match - copySubslice(i.fullRow, restore, off) + copy(i.fullRow[off:], restore) } return res == 0, peek, nil } diff --git a/sql/rows.go b/sql/rows.go index faf3a738bf..3c5c5e4746 100644 --- a/sql/rows.go +++ b/sql/rows.go @@ -18,6 +18,7 @@ import ( "fmt" "io" "strings" + "sync" "github.com/dolthub/vitess/go/vt/proto/query" @@ -69,6 +70,22 @@ func (r Row) Equals(ctx *Context, row Row, schema Schema) (bool, error) { return true, nil } +// TODO: find a proper place for this +var rowBuffers = sync.Pool{ + New: func() interface{} { + return make(Row, 0, 4096) // max number of columns for a table + }, +} + +func GetRow(length int) Row { + row := rowBuffers.Get().(Row) + return row[:length] +} + +func PutRow(row Row) { + rowBuffers.Put(row[:0]) +} + // FormatRow returns a formatted string representing this row's values func FormatRow(row Row) string { var sb strings.Builder