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.
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-sqlviainitObjects,os generate migration --format sqlviadb.raw, the typescript format by importing the emitted module and callingup(db)), columns read back out ofinformation_schema.columns. NomaxLength, nounique— the plainest possible declaration: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.createColumngivesnumber/float/currency/percentandrating/slider/progressone arm:col = table.float(name), which knex compiles torealon PostgreSQL. The arm's own comment records whyrating/slider/progresswere MOVED there — without an explicit case they fell totable.string, giving the column TEXT affinity so SQLite stored'4'rather than4.generate.tsgives themDECIMAL(sql format) /table.decimal(typescript format), andratingINTEGER/table.integer.Why it is not obviously a "generator follows the driver" repair
realis IEEE-754 binary32. It is a lossy column forcurrency, which is the one member of this family where the loss is a correctness question rather than a display one, andnumericis 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.ratingis the narrower half and may be separable:realagainstintegerfor a star count is a fidelity question on its own.Scope
PostgreSQL only, the single dialect
--format sqlclaims (#15521). SQLite affinity is what putrating/slider/progressin the driver's float arm in the first place, so any move has to be judged there too.