github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/common.go (about) 1 // Copyright 2020-2021 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 expression 16 17 import ( 18 "gopkg.in/src-d/go-errors.v1" 19 20 "github.com/dolthub/go-mysql-server/sql" 21 ) 22 23 var ErrInvalidOffset = errors.NewKind("offset must be a non-negative integer; found: %v") 24 25 // IsUnary returns whether the expression is unary or not. 26 func IsUnary(e sql.Expression) bool { 27 return len(e.Children()) == 1 28 } 29 30 // IsBinary returns whether the expression is binary or not. 31 func IsBinary(e sql.Expression) bool { 32 return len(e.Children()) == 2 33 } 34 35 // UnaryExpression is an expression that has only one child. 36 type UnaryExpression struct { 37 Child sql.Expression 38 } 39 40 // Children implements the Expression interface. 41 func (p *UnaryExpression) Children() []sql.Expression { 42 return []sql.Expression{p.Child} 43 } 44 45 // Resolved implements the Expression interface. 46 func (p *UnaryExpression) Resolved() bool { 47 return p.Child.Resolved() 48 } 49 50 // IsNullable returns whether the expression can be null. 51 func (p *UnaryExpression) IsNullable() bool { 52 return p.Child.IsNullable() 53 } 54 55 // BinaryExpressionStub is an expression that has two children. 56 type BinaryExpressionStub struct { 57 LeftChild sql.Expression 58 RightChild sql.Expression 59 } 60 61 // BinaryExpression is an expression that has two children 62 type BinaryExpression interface { 63 sql.Expression 64 Left() sql.Expression 65 Right() sql.Expression 66 } 67 68 func (p *BinaryExpressionStub) Left() sql.Expression { 69 return p.LeftChild 70 } 71 72 func (p *BinaryExpressionStub) Right() sql.Expression { 73 return p.RightChild 74 } 75 76 // Children implements the Expression interface. 77 func (p *BinaryExpressionStub) Children() []sql.Expression { 78 return []sql.Expression{p.LeftChild, p.RightChild} 79 } 80 81 // Resolved implements the Expression interface. 82 func (p *BinaryExpressionStub) Resolved() bool { 83 return p.LeftChild.Resolved() && p.RightChild.Resolved() 84 } 85 86 // IsNullable returns whether the expression can be null. 87 func (p *BinaryExpressionStub) IsNullable() bool { 88 return p.LeftChild.IsNullable() || p.RightChild.IsNullable() 89 } 90 91 type NaryExpression struct { 92 ChildExpressions []sql.Expression 93 } 94 95 // Children implements the Expression interface. 96 func (n *NaryExpression) Children() []sql.Expression { 97 return n.ChildExpressions 98 } 99 100 // Resolved implements the Expression interface. 101 func (n *NaryExpression) Resolved() bool { 102 for _, child := range n.Children() { 103 if !child.Resolved() { 104 return false 105 } 106 } 107 return true 108 } 109 110 // IsNullable returns whether the expression can be null. 111 func (n *NaryExpression) IsNullable() bool { 112 for _, child := range n.Children() { 113 if child.IsNullable() { 114 return true 115 } 116 } 117 return false 118 } 119 120 // ExpressionsResolved returns whether all the expressions in the slice given are resolved 121 func ExpressionsResolved(exprs ...sql.Expression) bool { 122 for _, e := range exprs { 123 if !e.Resolved() { 124 return false 125 } 126 } 127 128 return true 129 } 130 131 func Dispose(e sql.Expression) { 132 sql.Inspect(e, func(e sql.Expression) bool { 133 sql.Dispose(e) 134 return true 135 }) 136 } 137 138 // LiteralToInt extracts a non-negative integer from an expression.Literal, or errors 139 func LiteralToInt(e sql.Expression) (int, error) { 140 lit, ok := e.(*Literal) 141 if !ok { 142 return 0, ErrInvalidOffset.New(e) 143 } 144 val := lit.Value() 145 var offset int 146 switch e := val.(type) { 147 case int: 148 offset = e 149 case int8: 150 offset = int(e) 151 case int16: 152 offset = int(e) 153 case int32: 154 offset = int(e) 155 case int64: 156 offset = int(e) 157 case uint: 158 offset = int(e) 159 case uint8: 160 offset = int(e) 161 case uint16: 162 offset = int(e) 163 case uint32: 164 offset = int(e) 165 case uint64: 166 offset = int(e) 167 default: 168 return 0, ErrInvalidOffset.New(e) 169 } 170 171 if offset < 0 { 172 return 0, ErrInvalidOffset.New(e) 173 } 174 175 return offset, nil 176 }