github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/limit_binder.go (about) 1 // Copyright 2022 Matrix Origin 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 plan 16 17 import ( 18 "github.com/matrixorigin/matrixone/pkg/common/moerr" 19 "github.com/matrixorigin/matrixone/pkg/container/types" 20 "github.com/matrixorigin/matrixone/pkg/pb/plan" 21 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 22 ) 23 24 func NewLimitBinder(builder *QueryBuilder, ctx *BindContext) *LimitBinder { 25 lb := &LimitBinder{} 26 lb.sysCtx = builder.GetContext() 27 lb.builder = builder 28 lb.ctx = ctx 29 lb.impl = lb 30 return lb 31 } 32 33 func (b *LimitBinder) BindExpr(astExpr tree.Expr, depth int32, isRoot bool) (*plan.Expr, error) { 34 switch astExpr.(type) { 35 case *tree.UnqualifiedStar: 36 // need check other expr 37 return nil, moerr.NewSyntaxError(b.GetContext(), "unsupported expr in limit clause") 38 } 39 40 expr, err := b.baseBindExpr(astExpr, depth, isRoot) 41 if err != nil { 42 return nil, err 43 } 44 45 if expr.Typ.Id != int32(types.T_int64) { 46 // limit '10' / offset '2' 47 // the valid string should be cast to int64 48 if expr.Typ.Id == int32(types.T_varchar) { 49 targetType := types.T_int64.ToType() 50 planTargetType := makePlan2Type(&targetType) 51 var err error 52 expr, err = appendCastBeforeExpr(b.GetContext(), expr, planTargetType) 53 if err != nil { 54 return nil, err 55 } 56 } else if expr.GetP() != nil { 57 targetType := types.T_int64.ToType() 58 planTargetType := makePlan2Type(&targetType) 59 return appendCastBeforeExpr(b.GetContext(), expr, planTargetType) 60 } else if expr.GetV() != nil { 61 // SELECT IFNULL(CAST(@var AS BIGINT), 1) => CASE( ISNULL(@var), 1, CAST(@var AS BIGINT)) 62 63 //ISNULL(@var) 64 arg0, err := BindFuncExprImplByPlanExpr(b.GetContext(), "isnull", []*plan.Expr{ 65 expr, 66 }) 67 if err != nil { 68 return nil, err 69 } 70 71 // CAST( 1 AS BIGINT) 72 arg1 := makePlan2Int64ConstExprWithType(1) 73 74 // CAST(@var AS BIGINT) 75 targetType := types.T_int64.ToType() 76 planTargetType := makePlan2Type(&targetType) 77 arg2, err := appendCastBeforeExpr(b.GetContext(), expr, planTargetType) 78 if err != nil { 79 return nil, err 80 } 81 82 return BindFuncExprImplByPlanExpr(b.GetContext(), "case", []*plan.Expr{ 83 arg0, 84 arg1, 85 arg2, 86 }) 87 } else { 88 return nil, moerr.NewSyntaxError(b.GetContext(), "only int64 support in limit/offset clause") 89 } 90 } 91 92 return expr, nil 93 } 94 95 func (b *LimitBinder) BindColRef(astExpr *tree.UnresolvedName, depth int32, isRoot bool) (*plan.Expr, error) { 96 return nil, moerr.NewSyntaxError(b.GetContext(), "column not allowed in limit clause") 97 } 98 99 func (b *LimitBinder) BindAggFunc(funcName string, astExpr *tree.FuncExpr, depth int32, isRoot bool) (*plan.Expr, error) { 100 return nil, moerr.NewSyntaxError(b.GetContext(), "aggregate function not allowed in limit clause") 101 } 102 103 func (b *LimitBinder) BindWinFunc(funcName string, astExpr *tree.FuncExpr, depth int32, isRoot bool) (*plan.Expr, error) { 104 return nil, moerr.NewSyntaxError(b.GetContext(), "window function not allowed in limit clause") 105 } 106 107 func (b *LimitBinder) BindSubquery(astExpr *tree.Subquery, isRoot bool) (*plan.Expr, error) { 108 return nil, moerr.NewSyntaxError(b.GetContext(), "subquery not allowed in limit clause") 109 } 110 111 func (b *LimitBinder) BindTimeWindowFunc(funcName string, astExpr *tree.FuncExpr, depth int32, isRoot bool) (*plan.Expr, error) { 112 return nil, moerr.NewInvalidInput(b.GetContext(), "cannot bind time window functions '%s'", funcName) 113 }