github.com/dolthub/go-mysql-server@v0.18.0/sql/types/tuple.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 types
    16  
    17  import (
    18  	"fmt"
    19  	"reflect"
    20  	"strings"
    21  
    22  	"github.com/dolthub/vitess/go/sqltypes"
    23  	"github.com/dolthub/vitess/go/vt/proto/query"
    24  
    25  	"github.com/dolthub/go-mysql-server/sql"
    26  )
    27  
    28  var tupleValueType = reflect.TypeOf((*[]interface{})(nil)).Elem()
    29  
    30  type TupleType []sql.Type
    31  
    32  var _ sql.Type = TupleType{nil}
    33  var _ sql.CollationCoercible = TupleType{nil}
    34  
    35  // CreateTuple returns a new tuple type with the given element types.
    36  func CreateTuple(types ...sql.Type) sql.Type {
    37  	return TupleType(types)
    38  }
    39  
    40  func (t TupleType) Compare(a, b interface{}) (int, error) {
    41  	if hasNulls, res := CompareNulls(a, b); hasNulls {
    42  		return res, nil
    43  	}
    44  
    45  	a, _, err := t.Convert(a)
    46  	if err != nil {
    47  		return 0, err
    48  	}
    49  
    50  	b, _, err = t.Convert(b)
    51  	if err != nil {
    52  		return 0, err
    53  	}
    54  
    55  	left := a.([]interface{})
    56  	right := b.([]interface{})
    57  	for i := range left {
    58  		cmp, err := t[i].Compare(left[i], right[i])
    59  		if err != nil {
    60  			return 0, err
    61  		}
    62  
    63  		if cmp != 0 {
    64  			return cmp, nil
    65  		}
    66  	}
    67  
    68  	return 0, nil
    69  }
    70  
    71  func (t TupleType) Convert(v interface{}) (interface{}, sql.ConvertInRange, error) {
    72  	if v == nil {
    73  		return nil, sql.InRange, nil
    74  	}
    75  	if vals, ok := v.([]interface{}); ok {
    76  		if len(vals) != len(t) {
    77  			return nil, sql.OutOfRange, sql.ErrInvalidColumnNumber.New(len(t), len(vals))
    78  		}
    79  
    80  		var result = make([]interface{}, len(t))
    81  		for i, typ := range t {
    82  			var err error
    83  			result[i], _, err = typ.Convert(vals[i])
    84  			if err != nil {
    85  				return nil, sql.OutOfRange, err
    86  			}
    87  		}
    88  
    89  		return result, sql.InRange, nil
    90  	}
    91  	return nil, sql.OutOfRange, sql.ErrNotTuple.New(v)
    92  }
    93  
    94  func (t TupleType) MustConvert(v interface{}) interface{} {
    95  	value, _, err := t.Convert(v)
    96  	if err != nil {
    97  		panic(err)
    98  	}
    99  	return value
   100  }
   101  
   102  // Equals implements the Type interface.
   103  func (t TupleType) Equals(otherType sql.Type) bool {
   104  	if ot, ok := otherType.(TupleType); ok && len(t) == len(ot) {
   105  		for i, tupType := range t {
   106  			if !tupType.Equals(ot[i]) {
   107  				return false
   108  			}
   109  		}
   110  		return true
   111  	}
   112  	return false
   113  }
   114  
   115  // MaxTextResponseByteLength implements the Type interface
   116  func (t TupleType) MaxTextResponseByteLength(_ *sql.Context) uint32 {
   117  	// TupleTypes are never actually sent over the wire directly
   118  	return 0
   119  }
   120  
   121  func (t TupleType) Promote() sql.Type {
   122  	return t
   123  }
   124  
   125  func (t TupleType) SQL(*sql.Context, []byte, interface{}) (sqltypes.Value, error) {
   126  	return sqltypes.Value{}, fmt.Errorf("unable to convert tuple type to SQL")
   127  }
   128  
   129  func (t TupleType) String() string {
   130  	var elems = make([]string, len(t))
   131  	for i, el := range t {
   132  		elems[i] = el.String()
   133  	}
   134  	return fmt.Sprintf("tuple(%s)", strings.Join(elems, ", "))
   135  }
   136  
   137  func (t TupleType) Type() query.Type {
   138  	return sqltypes.Expression
   139  }
   140  
   141  // ValueType implements Type interface.
   142  func (t TupleType) ValueType() reflect.Type {
   143  	return tupleValueType
   144  }
   145  
   146  func (t TupleType) Zero() interface{} {
   147  	zeroes := make([]interface{}, len(t))
   148  	for i, tt := range t {
   149  		zeroes[i] = tt.Zero()
   150  	}
   151  	return zeroes
   152  }
   153  
   154  // CollationCoercibility implements sql.CollationCoercible interface.
   155  func (TupleType) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) {
   156  	return sql.Collation_binary, 7
   157  }