Skip to content

Add more TableEditor methods#6966

Merged
morozov merged 2 commits intodoctrine:4.3.xfrom
morozov:more-table-editor-methods
May 24, 2025
Merged

Add more TableEditor methods#6966
morozov merged 2 commits intodoctrine:4.3.xfrom
morozov:more-table-editor-methods

Conversation

@morozov
Copy link
Member

@morozov morozov commented May 21, 2025

Currently, the API of TableEditor is quite rudimentary and is primarily aimed at replacing the Table constructor. This PR introduces the methods for actually editing tables.

Object Collections

Unlike all other objects for which we have feature-complete editors, Table is the only one that internally contains
collections of other objects (columns, indexes, and so on). To manage them efficiently, I'm introducing an internal
Schema\Collections namespace with the following classes and interfaces:

  1. ObjectSet – a common interface for the following two classes.
  2. NamedObjectSet – will be used for representing table columns and indexes.
  3. OptionallyNamedObjectSet – will be used for representing table unique and foreign key constraints.

Currently, the key of an element in the above sets is derived from the lower-case element name. Therefore, these collections, for example, cannot represent a pair of columns id and ID. This limitation is temporary and mimics the current logic of the Table class. Later, it will be possible to parameterize a collection with one or more UnquotedIdentifierFoldings, and the current case-insensitive behavior will be deprecated.

Editor Operations

  • Column operations:

    • Add, modify, rename, and drop columns
    • Renaming a column automatically updates references to this column in related objects (indexes, constraints)
  • Index operations:

    • Add, rename, and drop indexes. Unlike columns, indexes cannot be modified (similar to SQL)
  • Constraint operations:

    • Add and drop unique and foreign key constraints. Unlike columns and indexes, constraints cannot be renamed (similar to SQL)
  • Other operations:

    • Support for editing table comments

API design considerations

  1. For each internal object collection (e.g. columns), there is a method to set the collection to a given value (e.g.
    setColumns()), and there are also methods for adding or removing elements (e.g. addColumn() and dropColumn()).
    The first one is handy when creating new tables (e.g. during schema introspection or in unit tests), the other two
    are good for editing an existing table.
  2. The same applies to the primary key constraints. Even though there exists the
    setPrimaryKeyConstraint(?PrimaryKeyConstraint $primaryKeyConstraint) method, I'm adding
    addPrimaryKeyConstraint(PrimaryKeyConstraint $primaryKeyConstraint) and dropPrimaryKeyConstraint(). They share the same implementation but express different intents.
  3. Each method that accepts an element name (e.g. modifyColumn(UnqualifiedName $columnName)) is accompanied by a method with the "ByUnquotedName" suffix that accepts the name as string (e.g. modifyColumnByUnquotedName(string $columnName)). Currently, there are no "ByQuotedName" methods, because the collections do not respect the semantics of quoted identifiers, so their behavior would be identical to the one of the "ByUnquotedName" methods. We will introduce these methods once we add the support for UnquotedIdentifierFoldings to the collections.

Next steps

  1. I have a pending PR that reworks most of the existing tests to use TableEditor and its new methods. Besides TableEditorTest, the editor will be covered by the existing tests.
  2. This PR enables the next steps on deprecating Column::$_platformOptions.

@morozov morozov added this to the 4.3.0 milestone May 21, 2025
@morozov morozov force-pushed the more-table-editor-methods branch from 64d0b97 to 8ca55a4 Compare May 21, 2025 02:10
@morozov morozov marked this pull request as ready for review May 21, 2025 02:22
@morozov morozov requested a review from greg0ire May 21, 2025 03:07
@morozov morozov force-pushed the more-table-editor-methods branch from 8ca55a4 to 907b503 Compare May 24, 2025 12:14
@greg0ire
Copy link
Member

greg0ire commented May 24, 2025

They share the same implementation but express different intents.

Do you mean that setPrimaryKeyConstraint is probably going to be use by Symfony bundles that need to accept null or a key, while the 2 other methods should be used by code that is less dynamic?

@morozov
Copy link
Member Author

morozov commented May 24, 2025

Do you mean that setPrimaryKeyConstraint is probably going to be use by Symfony bundles that need to accept null or a key, while the 2 other methods should be used by code that is less dynamic?

No, I mean that "set", "add" and "drop" methods/verbs express different semantics.

Let's say your application has some logic that builds or doesn't build the primary key definition, so this value is nullable. When you build a table from this definition, you can use this value as is. This method doesn't validate the current state of the table (i.e. whether the PK already exists or not), it just sets the PK definition to the new value.

If you're altering an existing table, you will use "add" (similar to ALTER TABLE ... ADD PRIMARY KEY) or "drop" (similar to ALTER TABLE ... DROP PRIMARY KEY). In those cases you implicitly assert that the PK doesn't exist (so you're adding it) or that it does exist (so you're dropping it).

@morozov morozov merged commit b075768 into doctrine:4.3.x May 24, 2025
82 checks passed
@morozov morozov deleted the more-table-editor-methods branch May 24, 2025 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants