Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add explicit renameColumn method for Table #6080

Merged
merged 1 commit into from
Jan 20, 2024

Conversation

Tofandel
Copy link
Contributor

@Tofandel Tofandel commented Jun 29, 2023

Q A
Type feature
Fixed issues doctrine/migrations#57

Summary

Reopening #6078 on 3.7.x

Add a renameColumn in the Table class

This allow to create migration with schemas that rename columns explicitely, which is a missing feature

Right now only implicit detection is done (it looks for added columns with the same definition as a dropped column), and that means if you change an option or the type of the column, it will not consider it as a rename anymore and instead will drop and recreate, by being explicit, this is not a problem anymore

This PR allows the following migration, without losing the column data

    public function up(Schema $schema): void
    {
        $schema->getTable('test')->renameColumn('foo', 'bar')->setType(Type::getType('text'));
    }
    
    public function down(Schema $schema): void
    {
        $schema->getTable('test')->renameColumn('bar', 'foo')->setType(Type::getType('string'));
    }

Which before would have to drop the column and recreate it, as well as needing a full redefinition of the column, and losing the data in the process

    public function up(Schema $schema): void
    {
        $schema->getTable('test')->dropColumn('foo')->addColumn('bar', 'text');
    }
    
    public function down(Schema $schema): void
    {
        $schema->getTable('test')->dropColumn('bar')->addColumn('foo', 'string');
    }

PS: I'm building a feature for the doctrine/migration package to generate diffs of schema, directly using Schema instead of platform specific sql and without this renameColumn this would be impossible, it would also allow other frameworks which use schemas (Yes I'm thinking laravel) to rename columns without using internals

@@ -128,7 +128,8 @@ public function getAlterTableColumnCommentsSQL(): array
{
return [
'ALTER TABLE mytable ' .
'ADD COLUMN quota INTEGER NOT NULL WITH DEFAULT',
'ADD COLUMN quota INTEGER NOT NULL WITH DEFAULT ' .
Copy link
Contributor Author

@Tofandel Tofandel Jun 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See

$tableDiff->changedColumns['bar'] = new ColumnDiff(
'bar',
new Column(
'baz',
Type::getType(Types::STRING),
['comment' => 'B comment'],
),
['comment'],
);

To understand why those tests were incorrect

The column is renamed in the test, but not in the test case output

@Tofandel Tofandel force-pushed the feat/rename-columns branch 4 times, most recently from 9dd2ebb to 65270cd Compare June 29, 2023 14:44
@Tofandel

This comment was marked as outdated.

src/Schema/Table.php Outdated Show resolved Hide resolved
src/Schema/Table.php Outdated Show resolved Hide resolved
src/Schema/Table.php Outdated Show resolved Hide resolved
src/Schema/Table.php Outdated Show resolved Hide resolved
src/Schema/Table.php Outdated Show resolved Hide resolved
src/Platforms/DB2Platform.php Outdated Show resolved Hide resolved
@Tofandel

This comment was marked as resolved.

@derrabus
Copy link
Member

Sorry, I simply haven't had time to take another look at this PR. I'm adding it to the milestone so I hopefully won't forget it.

@derrabus derrabus added this to the 3.7.0 milestone Jul 27, 2023
@Tofandel
Copy link
Contributor Author

Tofandel commented Aug 28, 2023

I've been cleaning up the PR, and in the end decided to do some deprecations directly in this PR so it's more clear

I deprecated the getRenamedColums and for backwards compatibility I changed getModifiedColumns to getChangedColumns so that getRenamedColum and getModifiedColumns will still output exactly the same as before, but getChangedColumns will be a mix of the renamed and modified columns

I also digged a bit on the case sensitivty issue, none of them are case sensitive (unless the identifier is quoted) and the Comparator is already case insensitive (strtolower in Table::normalizeIdentifier), so we are already assuming everyone is using lower case column names, so for now I don't think it's necessary to handle case sensitive renames at all, so I'm just throwing an exception if we use renameColumn('foo', 'Foo')

Unrelated: Does anyone have the issue where phpunit just exits when it encounters a skipped test? I've been trying to run them but it stops in the middle because of this I can't run all the tests locally

@@ -1427,7 +1430,6 @@ public static function getGeneratesIdentifierNamesInAlterTableSQL(): iterable
"CONSTRAINT DF_6B2BD609_4AD86123 DEFAULT 'foo'",
'ALTER TABLE mytable DROP COLUMN removecolumn',
'ALTER TABLE mytable DROP CONSTRAINT DF_6B2BD609_9BADD926',
'ALTER TABLE mytable ALTER COLUMN mycolumn NVARCHAR(255) NOT NULL',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This statement was not needed, if you look at the column diff

[
    'mycolumn' => new ColumnDiff(
        'mycolumn',
        new Column('mycolumn', Type::getType(Types::STRING), ['default' => 'bar']),
        ['default'],
        new Column('mycolumn', Type::getType(Types::STRING), ['default' => 'foo']),
    ),
],

Because only the default value changed, the type didn't

tests/Platforms/SQLServerPlatformTest.php Show resolved Hide resolved
@Tofandel Tofandel force-pushed the feat/rename-columns branch 5 times, most recently from d803926 to 09a504b Compare August 28, 2023 20:24
src/Schema/TableDiff.php Outdated Show resolved Hide resolved
@stof
Copy link
Member

stof commented Sep 14, 2023

The automatic detection of renames should be kept IMO, as not all Schema diffing happens for a Schema that has been manipulating based on the introspected one.
The common case for doctrine/migrations is that the introspected schema is compared to an ideal schema built based on the ORM mapping.

PS: I'm building a feature for the doctrine/migration package to generate diffs of schema, directly using Schema instead of platform specific sql and without this renameColumn this would be impossible, it would also allow other frameworks which use schemas (Yes I'm thinking laravel) to rename columns without using internals

Note that Schema-based migrations have 2 big drawbacks compared to generating the SQL at generation time:

  • they are much slower as they require introspecting the database between each executed migration (they cannot rely on using the schema altered in the previous migration as extra SQL queries might also have been executed to do more changes)
  • they are unable to migrate data, making them safe to run only on an empty database (when generating SQL, you can add extra queries in the middle to perform the necessary data updates).

src/Schema/TableDiff.php Outdated Show resolved Hide resolved
@derrabus derrabus merged commit adc5315 into doctrine:3.8.x Jan 20, 2024
87 of 88 checks passed
@greg0ire
Copy link
Member

greg0ire commented Jan 21, 2024

@Tofandel can you please try merging this up into 4.0.x? Or alternatively, send an equivalent PR to 4.0.x? @derrabus and I both tried the merge up, and it's a nightmare, mostly because of #5788, which also touches a lot of the files you touched.

@Tofandel
Copy link
Contributor Author

Tofandel commented Jan 22, 2024

@greg0ire When I have some time sure, I was looking at submitting it at 4.x originally because I saw how much code I was touching was already modified, but I was told to do it on 3.7. So yes I can imagine the nightmare, I think the main problem is that a big chunk of the tests that this rellies on where also modifed or removed

@Tofandel
Copy link
Contributor Author

Tofandel commented Jan 22, 2024

@greg0ire I'm having a look, is it okay if I replace all arguments of TableDiff with named arguments? It's a class with a ton of them and it's hard to keep track of them, it will make this kind of changes easier to work with

image

image

@greg0ire
Copy link
Member

@Tofandel on 4.0.x, yes, on 3.8.x no, because named arguments were introduced in PHP 8.0

derrabus pushed a commit that referenced this pull request Jan 22, 2024
Follow up of #6080 

While preparing the merge request to port to 4.0.x I found that some
comments point to a deprecated method (one even points to itself)

I also found that in DB2 the reorg happens even if there is no query
running which was a bit weird and adding column was not triggering a
reorg which is wrong and was not picked up by tests (because other
changed columns triggered it)
derrabus added a commit to derrabus/dbal that referenced this pull request Jan 25, 2024
derrabus added a commit that referenced this pull request Jan 25, 2024
This PR reverts PR #6080 and its follow-up #6273. Merging this feature
up to 4.0 is more difficult that I anticipated and I don't want to
postpone the release of 3.8 and 4.0 any further.

@Tofandel: Please take all the time that you need to redo your PR on
4.x. As soon as you did that, I'd be more than happy to restore this
change and do another 3.x feature release.
derrabus added a commit to derrabus/dbal that referenced this pull request Jan 25, 2024
* 3.8.x:
  Revert the rename column feature (doctrine#6276)
  fix: TableDiff deprecation points to wrong method (doctrine#6273)
  Stop using chocolatey shims (doctrine#6269)
  Add explicit renameColumn method for Table (doctrine#6080)
@derrabus derrabus removed this from the 3.8.0 milestone Jan 25, 2024
@derrabus
Copy link
Member

I've reverted the PR for now, in order to not block the new releases any further, see #6276. This buys us some time. Once we have a version of this feature for 4.x, we can restore your changes and do another 3.x feature release.

Tofandel added a commit to Tofandel/dbal that referenced this pull request Jan 26, 2024
Tofandel added a commit to Tofandel/dbal that referenced this pull request Jan 26, 2024
Tofandel added a commit to Tofandel/dbal that referenced this pull request Jan 26, 2024
Tofandel added a commit to Tofandel/dbal that referenced this pull request Jan 26, 2024
Tofandel added a commit to Tofandel/dbal that referenced this pull request Jan 26, 2024
Tofandel added a commit to Tofandel/dbal that referenced this pull request Jan 26, 2024
Tofandel added a commit to Tofandel/dbal that referenced this pull request Jan 26, 2024
Tofandel added a commit to Tofandel/dbal that referenced this pull request Jan 26, 2024
Tofandel added a commit to Tofandel/dbal that referenced this pull request Jan 26, 2024
Tofandel added a commit to Tofandel/dbal that referenced this pull request Jan 26, 2024
derrabus pushed a commit that referenced this pull request Aug 2, 2024
Merges the changes of #6080 into 4.0.x
@derrabus derrabus mentioned this pull request Aug 2, 2024
derrabus added a commit that referenced this pull request Aug 2, 2024
|      Q       |   A
|------------- | -----------
| Type         | bug
| Fixed issues | N/A

#### Summary

The internal API changes of #6080 conflicted with recently added tests.
This is my attempt to fix those.

/**
* @throws LogicException
* @throws SchemaException
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Tofandel where in this method is SchemaException thrown?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not, i think it was a leftover because I was not sure which exception to chose and I started with SchemaException

Copy link
Member

@morozov morozov Oct 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Tofandel do you mind filing a PR that removes it? PhpStorm treats it as check exception meaning that the caller of this method should either catch it or have a @throws SchemaException annotation in its declaration. This is false-positive and should be fixed.

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.

5 participants