diff --git a/main.go b/main.go index 66d352f..18e46ed 100644 --- a/main.go +++ b/main.go @@ -47,18 +47,6 @@ func main() { } } -var debuglog *log.Logger - -func init() { - if os.Getenv("DEBUG") != "" { - debuglog = log.New(os.Stderr, "", log.LstdFlags) - } else { - debuglog = log.New(io.Discard, "", log.LstdFlags) - } - // suppress - _ = debuglog -} - type opts struct { Database string `arg:"" required:"" help:"ID of the database."` Sql string `name:"sql" xor:"sql" required:"" help:"SQL query text; exclusive with --sql-file."` @@ -403,13 +391,10 @@ func _main() error { return err } - ctx, tp, traceCancel, err := enableTracing(ctx, o) + ctx, tp, err := enableTracing(ctx, o) if err != nil { return err } - if traceCancel != nil { - defer traceCancel() - } if tp != nil { defer func() { if err := shutdownTracing(context.Background(), tp); err != nil { diff --git a/params/load.go b/params/load.go index 2a74b3e..e1f282a 100644 --- a/params/load.go +++ b/params/load.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "maps" + "math" "os" "path/filepath" "strings" @@ -137,9 +138,9 @@ func paramFileValueToString(v any) (string, error) { } return "FALSE", nil case float64: - return formatParamFloat(x), nil + return formatParamFloat(x) case float32: - return formatParamFloat(float64(x)), nil + return formatParamFloat(float64(x)) case time.Time: return fmt.Sprintf("TIMESTAMP %q", x.Format(time.RFC3339Nano)), nil case []any, map[string]any, map[any]any: @@ -149,15 +150,18 @@ func paramFileValueToString(v any) (string, error) { } } -func formatParamFloat(x float64) string { - s := fmt.Sprintf("%g", x) - if s == "NaN" || s == "+Inf" || s == "-Inf" { - return s +func formatParamFloat(x float64) (string, error) { + if math.IsNaN(x) { + return "", fmt.Errorf("NaN is not a valid parameter value") + } + if math.IsInf(x, 0) { + return "", fmt.Errorf("infinity is not a valid parameter value") } + s := fmt.Sprintf("%g", x) if !strings.ContainsAny(s, ".eE") { s += ".0" } - return s + return s, nil } // MergeParams returns file params with cli params overriding on name conflict. diff --git a/params/load_test.go b/params/load_test.go index 3652998..55477c0 100644 --- a/params/load_test.go +++ b/params/load_test.go @@ -1,6 +1,7 @@ package params import ( + "math" "os" "path/filepath" "testing" @@ -108,6 +109,51 @@ func TestLoadParamFile(t *testing.T) { } } +func TestFormatParamFloat(t *testing.T) { + t.Parallel() + + s, err := formatParamFloat(42) + if err != nil { + t.Fatal(err) + } + if s != "42.0" { + t.Fatalf("got %q, want %q", s, "42.0") + } +} + +func TestFormatParamFloatRejectsNonFinite(t *testing.T) { + t.Parallel() + + for _, tc := range []struct { + name string + value float64 + }{ + {"NaN", math.NaN()}, + {"positive infinity", math.Inf(1)}, + {"negative infinity", math.Inf(-1)}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + if _, err := formatParamFloat(tc.value); err == nil { + t.Fatal("expected error") + } + }) + } +} + +func TestLoadParamFileRejectsNonFiniteFloat(t *testing.T) { + t.Parallel() + + dir := t.TempDir() + path := filepath.Join(dir, "params-nan.yaml") + if err := os.WriteFile(path, []byte("x: .nan\n"), 0o644); err != nil { + t.Fatal(err) + } + if _, err := LoadParamFile(path); err == nil { + t.Fatal("expected error for NaN in param file") + } +} + func TestMergeParams(t *testing.T) { t.Parallel() diff --git a/trace.go b/trace.go index da991be..7a24f52 100644 --- a/trace.go +++ b/trace.go @@ -56,21 +56,19 @@ func traceConfig(o opts) (tracing.Config, error) { } } -func enableTracing(ctx context.Context, o opts) (context.Context, *sdktrace.TracerProvider, context.CancelFunc, error) { +func enableTracing(ctx context.Context, o opts) (context.Context, *sdktrace.TracerProvider, error) { if !tracingEnabled(o) { - return ctx, nil, nil, nil + return ctx, nil, nil } cfg, err := traceConfig(o) if err != nil { - return ctx, nil, nil, err + return ctx, nil, err } tp, err := tracing.NewTracerProvider(cfg) if err != nil { - return ctx, nil, nil, err + return ctx, nil, err } - - traceCtx, traceCancel := context.WithCancel(ctx) - return traceCtx, tp, traceCancel, nil + return ctx, tp, nil } func shutdownTracing(ctx context.Context, tp *sdktrace.TracerProvider) error { diff --git a/trace_test.go b/trace_test.go index 3b3c08d..055106e 100644 --- a/trace_test.go +++ b/trace_test.go @@ -69,14 +69,13 @@ func TestTraceFlagsMutuallyExclusiveViaKong(t *testing.T) { } func TestEnableTracingStdout(t *testing.T) { - ctx, tp, traceCancel, err := enableTracing(context.Background(), opts{TraceStdout: true}) + ctx, tp, err := enableTracing(context.Background(), opts{TraceStdout: true}) if err != nil { t.Fatal(err) } - if tp == nil || traceCancel == nil { - t.Fatal("expected tracer provider and cancel func") + if tp == nil { + t.Fatal("expected tracer provider") } - defer traceCancel() _, span := tp.Tracer("execspansql").Start(ctx, "test-query") span.End()