github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/limit.go (about) 1 // Copyright 2015 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package sql 12 13 import ( 14 "context" 15 "fmt" 16 "math" 17 18 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 19 ) 20 21 // limitNode represents a node that limits the number of rows 22 // returned or only return them past a given number (offset). 23 type limitNode struct { 24 plan planNode 25 countExpr tree.TypedExpr 26 offsetExpr tree.TypedExpr 27 evaluated bool 28 count int64 29 offset int64 30 } 31 32 func (n *limitNode) startExec(params runParams) error { 33 panic("limitNode cannot be run in local mode") 34 } 35 36 func (n *limitNode) Next(params runParams) (bool, error) { 37 panic("limitNode cannot be run in local mode") 38 } 39 40 func (n *limitNode) Values() tree.Datums { 41 panic("limitNode cannot be run in local mode") 42 } 43 44 func (n *limitNode) Close(ctx context.Context) { 45 n.plan.Close(ctx) 46 } 47 48 // evalLimit evaluates the Count and Offset fields. If Count is missing, the 49 // value is MaxInt64. If Offset is missing, the value is 0 50 func (n *limitNode) evalLimit(evalCtx *tree.EvalContext) error { 51 n.count = math.MaxInt64 52 n.offset = 0 53 54 data := []struct { 55 name string 56 src tree.TypedExpr 57 dst *int64 58 }{ 59 {"LIMIT", n.countExpr, &n.count}, 60 {"OFFSET", n.offsetExpr, &n.offset}, 61 } 62 63 for _, datum := range data { 64 if datum.src != nil { 65 dstDatum, err := datum.src.Eval(evalCtx) 66 if err != nil { 67 return err 68 } 69 70 if dstDatum == tree.DNull { 71 // Use the default value. 72 continue 73 } 74 75 dstDInt := tree.MustBeDInt(dstDatum) 76 val := int64(dstDInt) 77 if val < 0 { 78 return fmt.Errorf("negative value for %s", datum.name) 79 } 80 *datum.dst = val 81 } 82 } 83 n.evaluated = true 84 return nil 85 }