github.com/dolthub/go-mysql-server@v0.18.0/sql/types/year.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 "reflect" 19 "strconv" 20 "time" 21 22 "github.com/dolthub/vitess/go/sqltypes" 23 "github.com/dolthub/vitess/go/vt/proto/query" 24 "github.com/shopspring/decimal" 25 "gopkg.in/src-d/go-errors.v1" 26 27 "github.com/dolthub/go-mysql-server/sql" 28 ) 29 30 var ( 31 Year sql.YearType = YearType_{} 32 33 ErrConvertingToYear = errors.NewKind("value %v is not a valid Year") 34 35 yearValueType = reflect.TypeOf(int16(0)) 36 ) 37 38 type YearType_ struct{} 39 40 // Compare implements Type interface. 41 func (t YearType_) Compare(a interface{}, b interface{}) (int, error) { 42 if hasNulls, res := CompareNulls(a, b); hasNulls { 43 return res, nil 44 } 45 46 as, _, err := t.Convert(a) 47 if err != nil { 48 return 0, err 49 } 50 bs, _, err := t.Convert(b) 51 if err != nil { 52 return 0, err 53 } 54 ai := as.(int16) 55 bi := bs.(int16) 56 57 if ai == bi { 58 return 0, nil 59 } 60 if ai < bi { 61 return -1, nil 62 } 63 return 1, nil 64 } 65 66 // Convert implements Type interface. 67 func (t YearType_) Convert(v interface{}) (interface{}, sql.ConvertInRange, error) { 68 if v == nil { 69 return nil, sql.InRange, nil 70 } 71 72 switch value := v.(type) { 73 case int: 74 return t.Convert(int64(value)) 75 case uint: 76 return t.Convert(int64(value)) 77 case int8: 78 return t.Convert(int64(value)) 79 case uint8: 80 return t.Convert(int64(value)) 81 case int16: 82 return t.Convert(int64(value)) 83 case uint16: 84 return t.Convert(int64(value)) 85 case int32: 86 return t.Convert(int64(value)) 87 case uint32: 88 return t.Convert(int64(value)) 89 case int64: 90 if value == 0 { 91 return int16(0), sql.InRange, nil 92 } 93 if value >= 1 && value <= 69 { 94 return int16(value + 2000), sql.InRange, nil 95 } 96 if value >= 70 && value <= 99 { 97 return int16(value + 1900), sql.InRange, nil 98 } 99 if value >= 1901 && value <= 2155 { 100 return int16(value), sql.InRange, nil 101 } 102 case uint64: 103 return t.Convert(int64(value)) 104 case float32: 105 return t.Convert(int64(value)) 106 case float64: 107 return t.Convert(int64(value)) 108 case decimal.Decimal: 109 return t.Convert(value.IntPart()) 110 case decimal.NullDecimal: 111 if !value.Valid { 112 return nil, sql.InRange, nil 113 } 114 return t.Convert(value.Decimal.IntPart()) 115 case string: 116 valueLength := len(value) 117 if valueLength == 1 || valueLength == 2 || valueLength == 4 { 118 i, err := strconv.ParseInt(value, 10, 64) 119 if err != nil { 120 return nil, sql.OutOfRange, err 121 } 122 if i == 0 { 123 return int16(2000), sql.InRange, nil 124 } 125 return t.Convert(i) 126 } 127 case time.Time: 128 year := value.Year() 129 if year == 0 || (year >= 1901 && year <= 2155) { 130 return int16(year), sql.InRange, nil 131 } 132 } 133 134 return nil, sql.InRange, ErrConvertingToYear.New(v) 135 } 136 137 // MustConvert implements the Type interface. 138 func (t YearType_) MustConvert(v interface{}) interface{} { 139 value, _, err := t.Convert(v) 140 if err != nil { 141 panic(err) 142 } 143 return value 144 } 145 146 // Equals implements the Type interface. 147 func (t YearType_) Equals(otherType sql.Type) bool { 148 _, ok := otherType.(YearType_) 149 return ok 150 } 151 152 // MaxTextResponseByteLength implements the Type interface 153 func (t YearType_) MaxTextResponseByteLength(_ *sql.Context) uint32 { 154 return 4 155 } 156 157 // Promote implements the Type interface. 158 func (t YearType_) Promote() sql.Type { 159 return t 160 } 161 162 // SQL implements Type interface. 163 func (t YearType_) SQL(ctx *sql.Context, dest []byte, v interface{}) (sqltypes.Value, error) { 164 if v == nil { 165 return sqltypes.NULL, nil 166 } 167 168 v, _, err := t.Convert(v) 169 if err != nil { 170 return sqltypes.Value{}, err 171 } 172 173 stop := len(dest) 174 dest = strconv.AppendInt(dest, int64(v.(int16)), 10) 175 val := dest[stop:] 176 177 return sqltypes.MakeTrusted(sqltypes.Year, val), nil 178 } 179 180 // String implements Type interface. 181 func (t YearType_) String() string { 182 return "year" 183 } 184 185 // Type implements Type interface. 186 func (t YearType_) Type() query.Type { 187 return sqltypes.Year 188 } 189 190 // ValueType implements Type interface. 191 func (t YearType_) ValueType() reflect.Type { 192 return yearValueType 193 } 194 195 // Zero implements Type interface. 196 func (t YearType_) Zero() interface{} { 197 return int16(0) 198 } 199 200 // CollationCoercibility implements sql.CollationCoercible interface. 201 func (YearType_) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 202 return sql.Collation_binary, 5 203 }