github.com/dolthub/go-mysql-server@v0.18.0/sql/analyzer/select_limit.go (about) 1 // Copyright 2022 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package analyzer 16 17 import ( 18 "fmt" 19 20 "github.com/dolthub/go-mysql-server/sql" 21 "github.com/dolthub/go-mysql-server/sql/expression" 22 "github.com/dolthub/go-mysql-server/sql/plan" 23 "github.com/dolthub/go-mysql-server/sql/transform" 24 "github.com/dolthub/go-mysql-server/sql/types" 25 ) 26 27 // applyDefaultSelectLimit wraps the root node in a Limit clause 28 // if 1) `sql_select_limit` is non-default and 2) there is no 29 // user-provided Limit already applied to the root node. 30 func applyDefaultSelectLimit( 31 ctx *sql.Context, 32 a *Analyzer, 33 n sql.Node, 34 scope *plan.Scope, 35 sel RuleSelector, 36 ) (sql.Node, transform.TreeIdentity, error) { 37 if !scope.IsEmpty() || scope.RecursionDepth() > 0 { 38 return n, transform.SameTree, nil 39 } 40 ok, val := sql.HasDefaultValue(ctx, ctx.Session, "sql_select_limit") 41 if ok { 42 // we only apply limit if the default has been modified 43 return n, transform.SameTree, nil 44 } 45 limit := expression.NewLiteral(mustCastNumToInt64(val), types.Int64) 46 ret, same := applyLimit(n, limit) 47 return ret, same, nil 48 } 49 50 func applyLimit(n sql.Node, limit sql.Expression) (sql.Node, transform.TreeIdentity) { 51 var child sql.Node 52 switch n := n.(type) { 53 case *plan.Limit: 54 return n, transform.SameTree 55 case *plan.SetOp: 56 if n.Limit != nil { 57 return n, transform.SameTree 58 } 59 return n.WithLimit(limit), transform.NewTree 60 case *plan.With: 61 child = n.Child 62 case *plan.Describe: 63 child = n.Child 64 case *plan.Sort, *plan.GroupBy, *plan.Project, *plan.SubqueryAlias, 65 *plan.Window: 66 ret := plan.NewLimit(limit, n) 67 return ret, transform.NewTree 68 default: 69 return n, transform.SameTree 70 } 71 c, same := applyLimit(child, limit) 72 if !same { 73 ret, _ := n.WithChildren(c) 74 return ret, transform.NewTree 75 } 76 return n, transform.SameTree 77 } 78 79 func mustCastNumToInt64(x interface{}) int64 { 80 switch v := x.(type) { 81 case int8: 82 return int64(v) 83 case int16: 84 return int64(v) 85 case int32: 86 return int64(v) 87 case uint8: 88 return int64(v) 89 case uint16: 90 return int64(v) 91 case uint32: 92 return int64(v) 93 case int64: 94 return int64(v) 95 case uint64: 96 i64 := int64(v) 97 if v == uint64(i64) { 98 return i64 99 } 100 } 101 102 panic(fmt.Sprintf("failed to convert to int64: %v", x)) 103 }