Observed while converting sql-driver-aggregation-conformance.test.ts to the live-dialect matrix (#11456), where the fixture object declares id: { type: 'text', name: 'id' } and I needed to know what that produced on MySQL before trusting the conversion. Filed unassigned.
What was observed
SqlDriver.initObjects emits the three builtin columns itself, then skips any declared field that collides with one — packages/drivers/driver-sql/src/sql-driver.ts @ 1958979fc6:
constbuiltinColumns=newSet(['id','created_at','updated_at']);// ...awaitthis.knex.schema.createTable(tableName,(table)=>{table.string('id').primary();this.createAuditTimestampColumn(table,'created_at');this.createAuditTimestampColumn(table,'updated_at');if(obj.fields){for(const[name,field]ofObject.entries(obj.fields)){if(builtinColumns.has(name))continue;// <- silentthis.createColumn(table,name,field,keyedColumns.get(name));}}});continue, with no warning, no throw, and no record anywhere that the author's declaration was discarded. The same builtinColumns skip appears on the shard path (line ~8643) and governs the ADD COLUMN diff (line ~9125), so the declaration is inert on create, on alter and on shards alike.
Measured on live PostgreSQL 16.13: an object declaring id: { type: 'text' } gets id varchar(255) PRIMARY KEY — table.string('id'), not TEXT. The declared type is not what lands and nothing says so.
Why it matters
The driver is right to own its primary key; the defect is that it disagrees with the author in silence. An author who writes id: { type: 'number' } expecting a numeric key gets a varchar key and a green boot. That is the declared-≠-enforced shape this repo treats as a first-class hazard, and it is squarely in the family of #11431 (the string family ignores maxLength), #11875 (signature/qrcode bounds bind nothing) and #11374 — declared field metadata that the emitter quietly does not honour.
It bites hardest on the surface the platform most wants hard to get wrong: metadata objects authored by an AI, where a silently-dropped declaration produces a schema nobody inspects and a mismatch that only shows up as data behaving oddly much later.
The shape of a fix, and why this is filed rather than done
Two candidates, and choosing between them is a contract decision rather than an edit:
There is also a prior question worth settling first: whether declaring id should be meaningful for the type of the key rather than merely refused, which is a bigger surface than either option above.
⛔ No source change was made under #11456 — that card is a test-harness conversion and this is a driver-behaviour question, so it is recorded here instead.
Related: #11456 (where it was observed), #11431, #11875, #11374, #11674.
Observed while converting
sql-driver-aggregation-conformance.test.tsto the live-dialect matrix (#11456), where the fixture object declaresid: { type: 'text', name: 'id' }and I needed to know what that produced on MySQL before trusting the conversion. Filed unassigned.What was observed
SqlDriver.initObjectsemits the three builtin columns itself, then skips any declared field that collides with one —packages/drivers/driver-sql/src/sql-driver.ts@1958979fc6:continue, with no warning, no throw, and no record anywhere that the author's declaration was discarded. The samebuiltinColumnsskip appears on the shard path (line ~8643) and governs the ADD COLUMN diff (line ~9125), so the declaration is inert on create, on alter and on shards alike.Measured on live PostgreSQL 16.13: an object declaring
id: { type: 'text' }getsid varchar(255) PRIMARY KEY—table.string('id'), not TEXT. The declared type is not what lands and nothing says so.Why it matters
The driver is right to own its primary key; the defect is that it disagrees with the author in silence. An author who writes
id: { type: 'number' }expecting a numeric key gets a varchar key and a green boot. That is the declared-≠-enforced shape this repo treats as a first-class hazard, and it is squarely in the family of #11431 (the string family ignoresmaxLength), #11875 (signature/qrcodebounds bind nothing) and #11374 — declared field metadata that the emitter quietly does not honour.It bites hardest on the surface the platform most wants hard to get wrong: metadata objects authored by an AI, where a silently-dropped declaration produces a schema nobody inspects and a mismatch that only shows up as data behaving oddly much later.
The shape of a fix, and why this is filed rather than done
Two candidates, and choosing between them is a contract decision rather than an edit:
initObjectsthrows on a declared field colliding with a builtin, naming the field and that the platform owns it. Loudest, matches "declared = enforced", but it is a new rejection door on an existing accept path, so it can break objects that boot today (the [finding] sql-driver-aggregation-conformance.test.ts hard-codes better-sqlite3, so the aggregate-vocabulary standard never runs on Postgres — its pagination sibling already uses the live-dialect cells #11456 fixture is one, and it is presumably not alone).There is also a prior question worth settling first: whether declaring
idshould be meaningful for the type of the key rather than merely refused, which is a bigger surface than either option above.⛔ No source change was made under #11456 — that card is a test-harness conversion and this is a driver-behaviour question, so it is recorded here instead.
Related: #11456 (where it was observed), #11431, #11875, #11374, #11674.