github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/expression/cast.go (about) 1 // Copyright 2023 zGraph Authors. All rights reserved. 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 "fmt" 19 20 "github.com/cockroachdb/apd/v3" 21 "github.com/vescale/zgraph/datum" 22 "github.com/vescale/zgraph/stmtctx" 23 "github.com/vescale/zgraph/types" 24 ) 25 26 var _ Expression = &CastExpr{} 27 28 type CastExpr struct { 29 Expr Expression 30 Type types.T 31 } 32 33 func NewCastExpr(expr Expression, typ types.T) *CastExpr { 34 return &CastExpr{ 35 Expr: expr, 36 Type: typ, 37 } 38 } 39 40 func (c *CastExpr) String() string { 41 return fmt.Sprintf("CAST(%s AS %s)", c.Expr, c.Type) 42 } 43 44 func (c *CastExpr) ReturnType() types.T { 45 return c.Type 46 } 47 48 func (c *CastExpr) Eval(stmtCtx *stmtctx.Context, input datum.Row) (datum.Datum, error) { 49 d, err := c.Expr.Eval(stmtCtx, input) 50 if err != nil || d == datum.Null { 51 return d, err 52 } 53 // Cast the datum to the desired type. 54 // See https://pgql-lang.org/spec/1.5/#cast for supported casts. 55 switch c.Type { 56 case types.Bool: 57 v, err := datum.TryAsBool(d) 58 if err != nil { 59 return nil, err 60 } 61 return datum.NewBool(v), nil 62 case types.Int: 63 case types.Float: 64 case types.Decimal: 65 case types.String: 66 case types.Date: 67 case types.Time: 68 case types.TimeTZ: 69 case types.Timestamp: 70 case types.TimestampTZ: 71 case types.Interval: 72 } 73 return nil, fmt.Errorf("unsupported cast: %s -> %s", d.Type(), c.Type) 74 } 75 76 type castFunc func(stmtCtx *stmtctx.Context, input datum.Datum) (datum.Datum, error) 77 78 func castIntAsFloat(_ *stmtctx.Context, input datum.Datum) (datum.Datum, error) { 79 i := datum.AsInt(input) 80 return datum.NewFloat(float64(i)), nil 81 } 82 83 func castIntAsDecimal(_ *stmtctx.Context, input datum.Datum) (datum.Datum, error) { 84 i := datum.AsInt(input) 85 d := &apd.Decimal{} 86 d.SetInt64(i) 87 return datum.NewDecimal(d), nil 88 } 89 90 func castFloatAsDecimal(_ *stmtctx.Context, input datum.Datum) (datum.Datum, error) { 91 f := datum.AsFloat(input) 92 d := &apd.Decimal{} 93 d.SetInt64(int64(f)) 94 return datum.NewDecimal(d), nil 95 } 96 97 func castBytesAsString(_ *stmtctx.Context, input datum.Datum) (datum.Datum, error) { 98 b := datum.AsBytes(input) 99 return datum.NewString(string(b)), nil 100 } 101 102 func castTimeAsTimeTZ(_ *stmtctx.Context, input datum.Datum) (datum.Datum, error) { 103 panic("unimplemented") 104 } 105 106 func castTimestampAsTimestampTZ(_ *stmtctx.Context, input datum.Datum) (datum.Datum, error) { 107 panic("unimplemented") 108 }