// Do implements plan.Plan Do interface, all records are added into an // in-memory array, and sorted in ASC/DESC order. func (r *OrderByDefaultPlan) Do(ctx context.Context, f plan.RowIterFunc) error { t := &orderByTable{Ascs: r.Ascs} m := map[interface{}]interface{}{} err := r.Src.Do(ctx, func(rid interface{}, in []interface{}) (bool, error) { m[expressions.ExprEvalIdentFunc] = func(name string) (interface{}, error) { return getIdentValue(name, r.ResultFields, in, field.CheckFieldFlag) } m[expressions.ExprEvalPositionFunc] = func(position int) (interface{}, error) { // position is in [1, len(fields)], so we must decrease 1 to get correct index // TODO: check position invalidation return in[position-1], nil } row := &orderByRow{ Row: in, Key: make([]interface{}, 0, len(r.By)), } for _, by := range r.By { // err1 is used for passing `go tool vet --shadow` check. val, err1 := by.Eval(ctx, m) if err1 != nil { return false, err1 } if val != nil { var ordered bool val, ordered, err1 = types.IsOrderedType(val) if err1 != nil { return false, err1 } if !ordered { return false, errors.Errorf("cannot order by %v (type %T)", val, val) } } row.Key = append(row.Key, val) } t.Rows = append(t.Rows, row) return true, nil }) if err != nil { return err } sort.Sort(t) var more bool for _, row := range t.Rows { if more, err = f(nil, row.Row); !more || err != nil { break } } return types.EOFAsNil(err) }
func (r *OrderByDefaultPlan) fetchAll(ctx context.Context) error { evalArgs := map[interface{}]interface{}{} for { row, err := r.Src.Next(ctx) if err != nil { return errors.Trace(err) } if row == nil { break } evalArgs[expression.ExprEvalIdentReferFunc] = func(name string, scope int, index int) (interface{}, error) { if scope == expression.IdentReferFromTable { return row.FromData[index], nil } else if scope == expression.IdentReferSelectList { return row.Data[index], nil } // try to find in outer query return getIdentValueFromOuterQuery(ctx, name) } evalArgs[expression.ExprEvalPositionFunc] = func(position int) (interface{}, error) { // position is in [1, len(fields)], so we must decrease 1 to get correct index // TODO: check position invalidation return row.Data[position-1], nil } ordRow := &orderByRow{ Row: row, Key: make([]interface{}, 0, len(r.By)), } for _, by := range r.By { // err1 is used for passing `go tool vet --shadow` check. val, err1 := by.Eval(ctx, evalArgs) if err1 != nil { return err1 } if val != nil { if !types.IsOrderedType(val) { return errors.Errorf("cannot order by %v (type %T)", val, val) } } ordRow.Key = append(ordRow.Key, val) } r.ordTable.Rows = append(r.ordTable.Rows, ordRow) } sort.Sort(r.ordTable) return nil }
func (r *OrderByDefaultPlan) fetchAll(ctx context.Context) error { evalArgs := map[interface{}]interface{}{} for { row, err := r.Src.Next(ctx) if err != nil { return errors.Trace(err) } if row == nil { break } evalArgs[expressions.ExprEvalIdentFunc] = func(name string) (interface{}, error) { return getIdentValue(name, r.ResultFields, row.Data, field.CheckFieldFlag) } evalArgs[expressions.ExprEvalPositionFunc] = func(position int) (interface{}, error) { // position is in [1, len(fields)], so we must decrease 1 to get correct index // TODO: check position invalidation return row.Data[position-1], nil } ordRow := &orderByRow{ Row: row, Key: make([]interface{}, 0, len(r.By)), } for _, by := range r.By { // err1 is used for passing `go tool vet --shadow` check. val, err1 := by.Eval(ctx, evalArgs) if err1 != nil { return err1 } if val != nil { var ordered bool val, ordered, err1 = types.IsOrderedType(val) if err1 != nil { return err1 } if !ordered { return errors.Errorf("cannot order by %v (type %T)", val, val) } } ordRow.Key = append(ordRow.Key, val) } r.ordTable.Rows = append(r.ordTable.Rows, ordRow) } sort.Sort(r.ordTable) return nil }