Skip to content

[finding] The NUMERIC column family diverges from driver-sql in both migration formats — driver real, generators numeric, and rating is real against integer #16318

Description

@os-litant

Found while re-sweeping the whole column surface for #16091 (PR #16298). Deliberately out of that diff: #16091 and its PR are scoped to the CHARACTER column, and this is a different family with its own governing question.

The measurement

Live PostgreSQL 16.13, one object driven through all three producers (driver-sql via initObjects, os generate migration --format sql via db.raw, the typescript format by importing the emitted module and calling up(db)), columns read back out of information_schema.columns. No maxLength, no unique — the plainest possible declaration:

             driver    sql gen   ts gen
number       real      numeric   numeric
currency     real      numeric   numeric
percent      real      numeric   numeric
slider       real      numeric   numeric
summary      real      numeric   numeric
progress     real      numeric   numeric
rating       real      integer   integer

Seven of seven diverge, in both formats, on every declaration shape probed (plain, with a maxLength, keyed, unkeyed — the numeric arms read none of those).

Where each side comes from

  • SqlDriver.createColumn gives number / float / currency / percent and rating / slider / progress one arm: col = table.float(name), which knex compiles to real on PostgreSQL. The arm's own comment records why rating/slider/progress were MOVED there — without an explicit case they fell to table.string, giving the column TEXT affinity so SQLite stored '4' rather than 4.
  • generate.ts gives them DECIMAL (sql format) / table.decimal (typescript format), and rating INTEGER / table.integer.

Why it is not obviously a "generator follows the driver" repair

real is IEEE-754 binary32. It is a lossy column for currency, which is the one member of this family where the loss is a correctness question rather than a display one, and numeric is the type a money column normally wants. So the two sides may genuinely disagree about the right answer rather than the generator merely being stale, which is the #15041 shape, not the #15040 shape — the direction is a decision, not a mechanical repair.

rating is the narrower half and may be separable: real against integer for a star count is a fidelity question on its own.

Scope

PostgreSQL only, the single dialect --format sql claims (#15521). SQLite affinity is what put rating/slider/progress in the driver's float arm in the first place, so any move has to be judged there too.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions