github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/order_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 "go/constant" 19 20 "github.com/matrixorigin/matrixone/pkg/common/moerr" 21 "github.com/matrixorigin/matrixone/pkg/pb/plan" 22 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 23 ) 24 25 func NewOrderBinder(projectionBinder *ProjectionBinder, selectList tree.SelectExprs) *OrderBinder { 26 return &OrderBinder{ 27 ProjectionBinder: projectionBinder, 28 selectList: selectList, 29 } 30 } 31 32 func (b *OrderBinder) BindExpr(astExpr tree.Expr) (*plan.Expr, error) { 33 if colRef, ok := astExpr.(*tree.UnresolvedName); ok && colRef.NumParts == 1 { 34 if selectItem, ok := b.ctx.aliasMap[colRef.Parts[0]]; ok { 35 return &plan.Expr{ 36 Typ: b.ctx.projects[selectItem.idx].Typ, 37 Expr: &plan.Expr_Col{ 38 Col: &plan.ColRef{ 39 RelPos: b.ctx.projectTag, 40 ColPos: selectItem.idx, 41 }, 42 }, 43 }, nil 44 } 45 } 46 47 if numVal, ok := astExpr.(*tree.NumVal); ok { 48 switch numVal.Value.Kind() { 49 case constant.Int: 50 colPos, _ := constant.Int64Val(numVal.Value) 51 if numVal.Negative() { 52 colPos = -colPos 53 } 54 if colPos < 1 || int(colPos) > len(b.ctx.projects) { 55 return nil, moerr.NewSyntaxError(b.GetContext(), "ORDER BY position %v is not in select list", colPos) 56 } 57 58 colPos = colPos - 1 59 return &plan.Expr{ 60 Typ: b.ctx.projects[colPos].Typ, 61 Expr: &plan.Expr_Col{ 62 Col: &plan.ColRef{ 63 RelPos: b.ctx.projectTag, 64 ColPos: int32(colPos), 65 }, 66 }, 67 }, nil 68 69 default: 70 return nil, moerr.NewSyntaxError(b.GetContext(), "non-integer constant in ORDER BY") 71 } 72 } 73 74 astExpr, err := b.ctx.qualifyColumnNames(astExpr, AliasBeforeColumn) 75 if err != nil { 76 return nil, err 77 } 78 79 expr, err := b.ProjectionBinder.BindExpr(astExpr, 0, true) 80 if err != nil { 81 return nil, err 82 } 83 84 var colPos int32 85 var ok bool 86 87 exprStr := expr.String() 88 if colPos, ok = b.ctx.projectByExpr[exprStr]; !ok { 89 if b.ctx.isDistinct { 90 return nil, moerr.NewSyntaxError(b.GetContext(), "for SELECT DISTINCT, ORDER BY expressions must appear in select list") 91 } 92 93 colPos = int32(len(b.ctx.projects)) 94 b.ctx.projectByExpr[exprStr] = colPos 95 b.ctx.projects = append(b.ctx.projects, expr) 96 } 97 98 expr = &plan.Expr{ 99 Typ: b.ctx.projects[colPos].Typ, 100 Expr: &plan.Expr_Col{ 101 Col: &plan.ColRef{ 102 RelPos: b.ctx.projectTag, 103 ColPos: colPos, 104 }, 105 }, 106 } 107 108 return expr, err 109 }