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  }