Problem/Motivation
Schema::addField() and ::changeField() are a bit weird in the sense that they require in input parts of the schema definition, duplicating information that is already present in the schema definition itself. With the new SchemaDefinition structure, we could just pass the target structure and determine the operations needed.
Proposed resolution
Introduce two new methods to Schema:
addTableColumnFromDefinition(SchemaDefinition $targetSchema, string $tableName, string $targetColumnName, ?Expression $initializationExpression = NULL): voidchangeTableColumnFromDefinition(SchemaDefinition $targetSchema, string $tableName, string $targetColumnName, ?string $currentColumnName = NULL): void
Also do some additional ancillary changes:
- Support an initialization SQL expression when adding a column, useful for populating existing rows.
- Automatically handle dropping and rebuilding of indexes, unique keys, and primary keys affected by column addtion/changes.
- Add
::columnNames()helpers toTableandKeyBase. - Strengthen
Tablevalidation to ensure keys reference existing columns. - Add
Schema::uniqueKeyExists()to the schema API, filling a surprising gap. - Improve PostgreSQL handling of transformed index/constraint names.
- Add MySQL handling for failures when dropping primary keys.
- Adjust SQLite table rebuild logic to preserve keys/indexes.
And add relative tests.
In the future, these methods could potentially replace :addField() and ::changeField() once all the conversions to SchemaDefinition will have been made.
Remaining tasks
User interface changes
Introduced terminology
API changes
Data model changes
Release notes snippet
Issue fork drupal-3620121
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
mondrakeComment #4
mondrakeComment #5
mondrakeUsed a bit of AI to summarize the changes and updated the proposed resultion in the IS accordingly. The MR is all human brain, though.
Comment #6
mondrakeComment #7
amateescu commentedPosted a comment on the MR which is a hard blocker, so I haven't reviewed past it.
Comment #8
mondrakeCan you make an example? In my (maybe simplistic, ok) view, the target schema is the lighthouse: we need to get there. ‘How’ we get there and the intermediate states are implementation details. So with a case we can discuss what the solution could be?
Comment #9
mondrakeGotcha. It's about the intermediate state between update functions, i.e. the schema version. If we just rely on the latest version, update functions that change between earlier versions will not have the data. I think at this point we could have versioned schema definitions too; it would be a bit verbose but we would also have all the intermediate versions clearly described, which is a bonus, to me.
Comment #10
mondrakeMade the simplest change I could think of
Comment #11
mondrakeLet's revert the changes to the update function from here. I've filed #3621166: Introduce a VersionedSchema object to hold multiple versions of a database Schema to enable schema versioning.
Comment #12
mondrakeComment #13
mondrake