Repository: pingcap/tidb
File: pkg/sessionctx/variable/slow_log.go (Go)

Code before:
	case int:
		return v == 0
	case uint64:
		return v == 0
	case int64:
		return v == 0
	case float64:
		return v == 0
	default:
		return false
	}
}

// ParseString converts the input string to lowercase and returns it.
func ParseString(v string) (any, error) { return v, nil }
func parseInt64(v string) (any, error) {
	n, err := strconv.ParseInt(v, 10, 64)
	if err != nil {
		return nil, err
	}
	if n < 0 {
		return nil, fmt.Errorf("threshold value must be non-negative, got %d", n)
	}
	return n, nil
}
func parseUint64(v string) (any, error) { return strconv.ParseUint(v, 10, 64) }
func parseFloat64(v string) (any, error) {
	f, err := strconv.ParseFloat(v, 64)
	if err != nil {
		return nil, err
	}
	if f < 0 {
		return nil, fmt.Errorf("threshold value must be non-negative, got %v", f)
	}
	return f, nil
}
func parseBool(v string) (any, error) { return strconv.ParseBool(v) }

// SlowLogRuleFieldAccessors defines the set of field accessors for SlowQueryLogItems
// that are relevant to evaluating and triggering SlowLogRules.
// It's exporting for testing.
var SlowLogRuleFieldAccessors = map[string]SlowLogFieldAccessor{
	strings.ToLower(SlowLogConnIDStr): {
		Parse: parseUint64,
		Match: func(seVars *SessionVars, _ *SlowQueryLogItems, threshold any) bool {
			return matchGE(threshold, seVars.ConnectionID)
		},
	},
	strings.ToLower(SlowLogSessAliasStr): {
		Parse: ParseString,
		Match: func(seVars *SessionVars, _ *SlowQueryLogItems, threshold any) bool {

Review comment (suggestion):
**Suggestion:** Consider rejecting `NaN`/`Inf` for float thresholds in `parseFloat64`.

- `strconv.ParseFloat` accepts values like `NaN`, `Inf`, `-Inf`, which can lead to surprising rule behavior (e.g. `>= NaN` never matches).
- A small guard like `math.IsNaN(f) || math.IsInf(f, 0)` returning a parse error would make the rule contract clearer.

Code after:
	switch v := threshold.(type) {
	case int:
		return v == 0
	case uint64:
		return v == 0
	case int64:
		return v == 0
	case float64:
		return v == 0
	default:
		return false
	}
}

// ParseString returns the input string as-is.
func ParseString(v string) (any, error) { return v, nil }
func parseInt64(v string) (any, error) {
	n, err := strconv.ParseInt(v, 10, 64)
	if err != nil {
		return nil, err
	}
	if n < 0 {
		return nil, fmt.Errorf("threshold value must be non-negative, got %d", n)
	}
	return n, nil
}
func parseUint64(v string) (any, error) { return strconv.ParseUint(v, 10, 64) }
func parseFloat64(v string) (any, error) {
	f, err := strconv.ParseFloat(v, 64)
	if err != nil {
		return nil, err
	}
	if math.IsNaN(f) || math.IsInf(f, 0) {
		return nil, fmt.Errorf("threshold value must be finite, got %v", f)
	}
	if f < 0 {
		return nil, fmt.Errorf("threshold value must be non-negative, got %v", f)
	}
	return f, nil
}
func parseBool(v string) (any, error) { return strconv.ParseBool(v) }

// SlowLogRuleFieldAccessors defines the set of field accessors for SlowQueryLogItems
// that are relevant to evaluating and triggering SlowLogRules.
// It's exporting for testing.
var SlowLogRuleFieldAccessors = map[string]SlowLogFieldAccessor{
	strings.ToLower(SlowLogConnIDStr): {
		Parse: parseUint64,
		Match: func(seVars *SessionVars, _ *SlowQueryLogItems, threshold any) bool {
			return matchGE(threshold, seVars.ConnectionID)
		},