-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Generate alter add/change column with explicit position for MySQL #4276
Generate alter add/change column with explicit position for MySQL #4276
Conversation
c2b4179
to
354a914
Compare
Thank you for the patch, @mvorisek. Before proceeding, please make sure the new logic is covered with a functional test that demonstrates the desired end result. |
48c5d0c
to
f9e6b05
Compare
} | ||
|
||
if (! $columnFound) { | ||
throw new InvalidArgumentException('Column name "' . $columnName . '" not found'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to avoid having this exception by using a more suitable method signature? Each column is either first or goes after some other column. See #4145 for example. Otherwise, this will need a functional test that demonstrates the exception being thrown.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can call $toTable->getColumn()
before the foreach loop which should check if the column exists or not
please sudgest ideal approach to this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might work if instead of having the $toTable
in the SchemaDiff
, the ColumnDiff
had a property like $afterColumn
that would contain the column name and be non-empty only if the column position has changed. This assumes that a similar SQL syntax could be used on other supported platforms. This would also solve the problem of having the FIRST
and AFTER
fragments unnecessarily generated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ColumnDiff
can not be used as we need position also for Column
. @morozov I would like to finish this PR asap, please advise, if the $toTable
is ok - used like $fromTable
already used - or if you have a better alternative. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ColumnDiff can not be used as we need position also for Column
I do not understand what this means. Can you please elaborate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ColumnDiff can not be used as we need position also for Column
I do not understand what this means. Can you please elaborate?
if column already exists, then ColumnDiff
instance is returned from the comparator
if the column is new (not renamed/modified), then there is no ColumnDiff
for it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exception is covered by added test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mvorisek please make sure you don't resolve the conversations that you didn't start unless you're resolving one on the starter's behalf.
@@ -260,7 +286,7 @@ public function testColumnCharsetChange(): void | |||
$diff = $fromSchema->getMigrateToSql($toSchema, $this->connection->getDatabasePlatform()); | |||
self::assertContains( | |||
'ALTER TABLE test_column_charset_change CHANGE col_string' | |||
. ' col_string VARCHAR(100) CHARACTER SET ascii NOT NULL', | |||
. ' col_string VARCHAR(100) CHARACTER SET ascii NOT NULL FIRST', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we expect the SQL to contain the FIRST
/AFTER
qualifiers if the column position doesn't change? I believe these should be only generated when necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we generate this for ALTER TABLE only, for TABLE CREATE, position is not generated
if position is the same, we regenerate whole column definition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we generate the column position only if it's changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can add a condition, if the previous column is the same for fromTable and toTable, then to not add the position. Tests may however need more changes as currently, we expect that SQL column definition is always fully regenerated.
Let solve this as the last step before merge, firstly, I want to make sure toTable
property will stay
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think toTable
should stay since the other solution with ColumnDiff
instance will not handle the case of new columns, which means we can resume this conversation. Let's generate the position only when necessary please.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's generate the position only when necessary please.
I understand we want to generate minimalistic diff, but I think we do not want it. ALTER TABLE ADD/MODIFY column is always generated fully even if there is a minor column definition change like column comment. Adding position based on the original table will violate this definition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we agree on this
If it's always generated fully indeed then it's ok with me.
can we merge this PR
In theory yes, in practice the tests fail
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CI fixed
As long as this new feature requires breaking or non-breaking API changes, I'd like to make sure that the new API could be used to implement the same feature for other platforms. Otherwise, it may require a BC break in the future. @mvorisek could you do some research and see which SQL syntax could be used for the rest of the platforms to implement this in the future? |
the proposed data structure (with
I already did, other DB platforms require table recreation, ie. create table, insert into select, drop table |
In this case, I'm not sure we should be adding this feature. |
This feature - reflecting column order defined by I think:
@morozov can we agree on this and merge? wdyt about adding |
What's the use case for this? When does the order of columns in a table matter to the application that uses it?
I disagree. I expressed my concerns above.
This is not completely true. We cannot introduce a new API that works for one DB platform and expect it to work for others that knowingly don't support the way of implementing the feature. That's why I asked to check how other platforms behave in this regard.
It's not the best idea. Every time a "supports" method is added to the API, it forces the platform-specific logic to be implemented outside of the platform. It invalidates the purpose of the API which is to encapsulate the details of each its implementation behind a common interface.
What if it's not supported? If the code can handle this case for other platforms, why can't it handle for MySQL? For now, this could be reliably used in the code: if ($platform instanceof MySQLPlatform) {
// reordering supported
} |
Basically any applications that use the database/column order like:
the later point is very important from developers UX perspective and this PR improves it hugely, as column order is now like when a all tables would be created freshly - good for visual orientation, diffs, ...
I know, please reply to #4276 (comment) , I will then solve the impl. according to that, I think,
now I propose for MySQL only, later, see above, it can be implemented with multiple SQL queries like "RENAME TABLE", "CREATE TABLE", "INSERT INTO SELECT", "DROP TABLE" |
The link to #4276 (comment) doesn't take me anywhere. Could you please quote your question?
IMO it's an edge case that we can potentially support in a subset of supported platforms. Given how unclear the current approach is, it's not a priority for me personally at the moment. I'm fine if somebody else from the project team works on this and helps solve the issues I identified above. |
@greg0ire can you please review and provide your feedback? |
Can you please link to Github tickets in the "fixed issues" row of the table in your original message? |
Added. From my side, this PR is complete, but if you have any ideas, I am ready to implement them so we can release this asap. Thanks. |
I think you still have to address this, both codecov and Sergei mentioned it. |
91056a7
to
9348097
Compare
@greg0ire I fixed merge conflict, please rereview and please include this in the next upcoming 2.11 release. |
all feedback has been fixed, can we merge now? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@greg0ire what's your take on whether this behavior should be added in the first place? See #4276 (comment).
|
||
$comparator = new Comparator(); | ||
$diff = $comparator->diffTable($table, $table2); | ||
$diff->toTable = $table2WithoutAColumn; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once the diff is generated from the two tables, why should it be possible to change the referenced table via the API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is test - to test exception https://github.com/doctrine/dbal/pull/4276/files#diff-548b552a74ea52eab68318520c213a142ba77527a4b965c4d3bd50eeba1afa9aR675
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test was meant to be added to document the case when this exception can happen because IMO it shouldn't be possible in the first place (https://github.com/doctrine/dbal/pull/4276/files#r493065750). The test doesn't show a valid case. Which means that there is no justification for this API to throw an exception.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the diff object is built using Comparator::diff which will add the input, then this exception can not happen.
However, the toTable
is public property - like fromTable
already present - and if the table is replaced by the user with different table that has not all the column names set - this exception is legit and this test cover it.
I think you know far more than I do about the philosophy of this project, and if you're not sure, I'm even less sure than you are… maybe @beberlei can advise on this? @beberlei, is it commonplace to accept PRs that add features that can never be implemented on other platforms? |
We have features that are not supported by other platforms, but might be added at some point. Here we can't implement it to certain platforms because there a recreation is needed. I'm not really sold yet to improve one platform that might be the only one with this feature, because the mentioned benefits aren't big ones. While doing some research I found something in the PostgreSQL docs that has one technical benefit mentioned in http://wiki.postgresql.org/wiki/Alter_column_position:
But I'm not sure if this is also the same benefit in MySQL. |
263ce35
to
2355a3a
Compare
7c4bbec
to
d491ef2
Compare
d491ef2
to
f0a78df
Compare
f0a78df
to
e6408e2
Compare
@greg0ire please reaprove, I rebased it from 2.11.x to 2.12.x branch.
see https://stackoverflow.com/questions/894522/is-there-any-reason-to-worry-about-the-column-order-in-a-table - there is some performance improvement with controlled columns placement Is there anything I can do from my side to get this PR merged? |
solved privately, contact me in PM if you are a company and want to pay to open source it, more work needed than this PR |
- doctrine/orm#8258
- doctrine/migrations#558
- https://stackoverflow.com/questions/34873327/doctrine-migration-add-column-after-other-one
- https://stackoverflow.com/questions/24148568/doctrineschemaupdate-doesnt-respect-column-order