Skip to content

literal() emits invalid SQL for non-finite numbers (NaN/Infinity) #13

Description

@smiggleworth

Summary

literal() (src/sql.ts:60-67) accepts string | number | boolean | null and for the number branch does String(value) with no finiteness validation. NaN/Infinity satisfy typeof value === "number" at runtime, producing literal SQL text NaN/Infinity, which are not valid PostgreSQL numeric literal tokens outside a quoted/cast form.

Steps to reproduce

compileSql(sql`SELECT ${literal(1/0)}`).text // => "SELECT Infinity"

This fails to parse against a real Postgres server.

Expected

Either literal() throws a clear validation error for non-finite numbers, or emits a valid quoted/cast form ('Infinity'::float8).

Actual

Emits invalid, unparseable SQL text with no warning.

Why it matters

A computed value (e.g. a ratio with a zero denominator) landing in literal() produces a confusing runtime SQL syntax error instead of a clear validation error at the ORM layer.

Acceptance criteria

  • Guardrail (prevent this class of bug): Add Number.isFinite boundary tests (NaN, +/-Infinity) to any function that stringifies a JS number directly into SQL/output text — this is a cheap, mechanical check to add as a standing input-validation test for every literal()-style formatter.

  • literal() validates numeric input with Number.isFinite() and either throws a clear error or emits a valid quoted/cast representation for non-finite values.

  • Regression test covering NaN and both Infinity signs.

Definition of done

Fix implemented; regression test added and green.

Severity

Low — edge-case input, fails loudly (query error) rather than silently.


Found via the same adversarial stress pass on @askrjs/orm as the compileKeyedSql issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions