// The return type of a CASE expression is the compatible aggregated type of all return values, // but also depends on the context in which it is used. // If used in a string context, the result is returned as a string. // If used in a numeric context, the result is returned as a decimal, real, or integer value. func (v *typeInferrer) handleCaseExpr(x *ast.CaseExpr) { var currType *types.FieldType for _, w := range x.WhenClauses { t := w.Result.GetType() if currType == nil { currType = t continue } mtp := types.MergeFieldType(currType.Tp, t.Tp) if mtp == t.Tp && mtp != currType.Tp { currType.Charset = t.Charset currType.Collate = t.Collate } currType.Tp = mtp } if x.ElseClause != nil { t := x.ElseClause.GetType() if currType == nil { currType = t } else { mtp := types.MergeFieldType(currType.Tp, t.Tp) if mtp == t.Tp && mtp != currType.Tp { currType.Charset = t.Charset currType.Collate = t.Collate } currType.Tp = mtp } } x.SetType(currType) // TODO: We need a better way to set charset/collation x.Type.Charset, x.Type.Collate = types.DefaultCharsetForType(x.Type.Tp) }
func (e *Evaluator) caseExpr(v *ast.CaseExpr) bool { tmp := types.NewDatum(boolToInt64(true)) target := &tmp if v.Value != nil { target = v.Value.GetDatum() } if !target.IsNull() { for _, val := range v.WhenClauses { cmp, err := target.CompareDatum(*val.Expr.GetDatum()) if err != nil { e.err = errors.Trace(err) return false } if cmp == 0 { v.SetDatum(*val.Result.GetDatum()) return true } } } if v.ElseClause != nil { v.SetDatum(*v.ElseClause.GetDatum()) } else { v.SetNull() } return true }
func (e *Evaluator) caseExpr(v *ast.CaseExpr) bool { var target interface{} = true if v.Value != nil { target = v.Value.GetValue() } if target != nil { for _, val := range v.WhenClauses { cmp, err := types.Compare(target, val.Expr.GetValue()) if err != nil { e.err = errors.Trace(err) return false } if cmp == 0 { v.SetValue(val.Result.GetValue()) return true } } } if v.ElseClause != nil { v.SetValue(v.ElseClause.GetValue()) } else { v.SetValue(nil) } return true }