Skip to content

[finding] driver-sql and both migration generators default an absent or unknown field type to DIFFERENT families — string versus text, so the unvalidated authoring door produces two different columns #16319

Description

@os-litant

Found while stating what the #16091 probe set cannot reach (PR #16298). Every probe on that card is a real FieldType member; these two shapes are not, so no sweep there could have found them.

The two defaults

SqlDriver.createColumn   const type = field.type || 'string';
generate.ts              String(fieldDef.type || 'text')          (both formats)

'string' heads createColumn's STRING-family arm, which sizes the column from declaredVarcharLength(field) — the declared maxLength verbatim, knex's 255 without one. 'text' heads the generators' TEXT arm, which is unbounded unless the column is keyed. Two different families, from the same declaration.

An unknown type string splits the same way for a different reason: the driver falls to its catch-all (table.string(name), varchar(255)), the generators to their own default: arm (TEXT).

The measurement

Live PostgreSQL 16.13, all three producers driven from one object, columns read back out of information_schema.columns:

                                                    driver                  sql gen   ts gen
{ maxLength: 100 }                    (no `type`)   character varying(100)  text      text
{ type: 'this_is_not_a_field_type',
  maxLength: 100 }                                  character varying(255)  text      text

Both directions of harm are present in the first row: the platform REFUSES a 101-character value that both generated tables accept.

Reachability, honestly

Neither shape parses. FieldSchema requires type and rejects a non-member at [type] (#12593 measured the same for 'string' itself). So this is the UNVALIDATED authoring door only — a config loaded without os validate, a hand-built object, a metadata row written by something other than the authoring path. fieldTypeToSql's own docblock already says that door exists and can deliver a type string.

That is exactly why it is filed rather than repaired inside #16298: the fix is one character of default text on each side, but WHICH side moves is a decision about what an unvalidated field means, and #16091's ruling ("the generator follows the driver", #15521) was given for declarations that parse.

The narrower half

FieldType.options omits 'string' and there is no Field.string builder (#12593), so createColumn's case 'string': is reachable only through this same door — the driver's default and its own arm are consistent with each other, and it is the generators' || 'text' that disagrees.

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