func ddecimal(f float64) copyableExpr { return func() Expr { dd := &DDecimal{} decimal.SetFromFloat(&dd.Dec, f) return dd } }
func makeDecimalTestDatum(count int) []Datum { rng, _ := randutil.NewPseudoRand() vals := make([]Datum, count) for i := range vals { dd := &DDecimal{} decimal.SetFromFloat(&dd.Dec, rng.Float64()) vals[i] = dd } return vals }
// TestNumericConstantVerifyAndResolveAvailableTypes verifies that test NumVals will // all return expected available type sets, and that attempting to resolve the NumVals // as each of these types will all succeed with an expected Datum result. func TestNumericConstantVerifyAndResolveAvailableTypes(t *testing.T) { wantInt := numValAvailIntFloatDec wantDecButCanBeInt := numValAvailDecFloatInt wantDec := numValAvailDecFloat testCases := []struct { str string avail []Type }{ {"1", wantInt}, {"0", wantInt}, {"-1", wantInt}, {"9223372036854775807", wantInt}, {"1.0", wantDecButCanBeInt}, {"-1234.0000", wantDecButCanBeInt}, {"1e10", wantDecButCanBeInt}, {"1E10", wantDecButCanBeInt}, {"1.1", wantDec}, {"1e-10", wantDec}, {"1E-10", wantDec}, {"-1231.131", wantDec}, {"876543234567898765436787654321", wantDec}, } for i, test := range testCases { tok := token.INT if strings.ContainsAny(test.str, ".eE") { tok = token.FLOAT } val := constant.MakeFromLiteral(test.str, tok, 0) if val.Kind() == constant.Unknown { t.Fatalf("%d: could not parse value string %q", i, test.str) } // Check available types. c := &NumVal{Value: val, OrigString: test.str} avail := c.AvailableTypes() if !reflect.DeepEqual(avail, test.avail) { t.Errorf("%d: expected the available type set %v for %v, found %v", i, test.avail, c.Value.ExactString(), avail) } // Make sure it can be resolved as each of those types. for _, availType := range avail { if res, err := c.ResolveAsType(&SemaContext{}, availType); err != nil { t.Errorf("%d: expected resolving %v as available type %s would succeed, found %v", i, c.Value.ExactString(), availType, err) } else { resErr := func(parsed, resolved interface{}) { t.Errorf("%d: expected resolving %v as available type %s would produce a Datum"+ " with the value %v, found %v", i, c, availType, parsed, resolved) } switch typ := res.(type) { case *DInt: var i int64 var err error if tok == token.INT { if i, err = strconv.ParseInt(test.str, 10, 64); err != nil { t.Fatal(err) } } else { var f float64 if f, err = strconv.ParseFloat(test.str, 64); err != nil { t.Fatal(err) } i = int64(f) } if resI := int64(*typ); i != resI { resErr(i, resI) } case *DFloat: f, err := strconv.ParseFloat(test.str, 64) if err != nil { t.Fatal(err) } if resF := float64(*typ); f != resF { resErr(f, resF) } case *DDecimal: d := new(inf.Dec) if !strings.ContainsAny(test.str, "eE") { if _, ok := d.SetString(test.str); !ok { t.Fatalf("could not set %q on decimal", test.str) } } else { f, err := strconv.ParseFloat(test.str, 64) if err != nil { t.Fatal(err) } decimal.SetFromFloat(d, f) } if resD := &typ.Dec; d.Cmp(resD) != 0 { resErr(d, resD) } } } } } }