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
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.
Summary
literal()(src/sql.ts:60-67) acceptsstring | number | boolean | nulland for thenumberbranch doesString(value)with no finiteness validation.NaN/Infinitysatisfytypeof value === "number"at runtime, producing literal SQL textNaN/Infinity, which are not valid PostgreSQL numeric literal tokens outside a quoted/cast form.Steps to reproduce
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.isFiniteboundary 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 everyliteral()-style formatter.literal()validates numeric input withNumber.isFinite()and either throws a clear error or emits a valid quoted/cast representation for non-finite values.Regression test covering
NaNand bothInfinitysigns.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/ormas thecompileKeyedSqlissue.