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

Fix Comparator column diff for blob length #4551

Closed
wants to merge 6 commits into from

Conversation

ausi
Copy link
Contributor

@ausi ausi commented Mar 23, 2021

Q A
Type bug
BC Break no
Fixed issues #2663

Summary

In MySQL the blob type depends on the length to use one of TINYBLOB, BLOB, MEDIUMBLOB or LONGBLOB. When diffing two blob columns the length is currently ignored which results in missing changes of the underlying database column type.

UPDATE: It is the same with the text type which uses one of TINYTEXT, TEXT, MEDIUMTEXT or LONGTEXT.

greg0ire
greg0ire previously approved these changes Mar 23, 2021
Copy link
Member

@greg0ire greg0ire left a comment

Choose a reason for hiding this comment

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

The patch looks good, and the tests fail as they should when reverting changes in lib:

There were 4 failures:

1) Doctrine\Tests\DBAL\Platforms\MariaDb1027PlatformTest::testAlterTableChangeBlobColumnLength
Failed asserting that false is not false.

/home/gregoire/dev/doctrine-dbal/tests/Doctrine/Tests/DBAL/Platforms/AbstractMySQLPlatformTestCase.php:840

2) Doctrine\Tests\DBAL\Platforms\MySQL57PlatformTest::testAlterTableChangeBlobColumnLength
Failed asserting that false is not false.

/home/gregoire/dev/doctrine-dbal/tests/Doctrine/Tests/DBAL/Platforms/AbstractMySQLPlatformTestCase.php:840

3) Doctrine\Tests\DBAL\Platforms\MySqlPlatformTest::testAlterTableChangeBlobColumnLength
Failed asserting that false is not false.

/home/gregoire/dev/doctrine-dbal/tests/Doctrine/Tests/DBAL/Platforms/AbstractMySQLPlatformTestCase.php:840

4) Doctrine\Tests\DBAL\Schema\ComparatorTest::testCompareChangedBlobColumn
Failed asserting that two objects are equal.
--- Expected
+++ Actual
@@ @@
     'removedNamespaces' => Array ()
     'newTables' => Array ()
     'changedTables' => Array (
-        'foo' => Doctrine\DBAL\Schema\TableDiff Object (...)
     )
     'removedTables' => Array ()
     'newSequences' => Array ()

/home/gregoire/dev/doctrine-dbal/tests/Doctrine/Tests/DBAL/Schema/ComparatorTest.php:1126

About the target branch, I'm unsure if there will be more releases of 2.12.x in the future, but it appears this branch has been contributed recently though. @morozov will know more about this.

@morozov
Copy link
Member

morozov commented Mar 23, 2021

Yes, all bugfixes currently go to 2.12.x. It will be released right before 2.13.0.

Copy link
Member

@morozov morozov left a comment

Choose a reason for hiding this comment

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

Does the same logic apply to the TEXT/CLOB columns?

@@ -482,6 +482,10 @@ public function diffColumn(Column $column1, Column $column2)
if ($properties1['fixed'] !== $properties2['fixed']) {
$changedProperties[] = 'fixed';
}
} elseif ($properties1['type'] instanceof Types\BlobType) {
if ($properties1['length'] !== $properties2['length']) {
Copy link
Member

@morozov morozov Mar 23, 2021

Choose a reason for hiding this comment

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

Looks like it will introduce a false-positive diff when comparing say BLOB(1) and BLOB(2) which both would translate to a TINYBLOB in MySQL.

While the fix seems to be within the current comparator design, the design obviously has flaws. A proper approach might be to add platform awareness to the comparator API and compare the SQL generated against a given platform. It will also likely eliminate the need for the hack introduced in #3382.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, but changing the comparator API cannot be done in a bugfix release I guess?

Copy link
Member

Choose a reason for hiding this comment

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

2.12.2 and 2.13.0 should be released at about the same time, so the release schedule shouldn't be a concern. If it's a non-breaking change (e.g. that adds a new optional parameter to the API), it could be released in 2.13.0. Why does it have to be a bugfix release?

Copy link
Contributor Author

@ausi ausi Mar 24, 2021

Choose a reason for hiding this comment

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

Why does it have to be a bugfix release?

I would consider it a bug because the MySQL diff for blob/text columns doesn’t work currently.

Looks like it will introduce a false-positive diff when comparing say BLOB(1) and BLOB(2)

Wouldn’t such false positives also occur for many other types already? Like binary(fixed=true) vs binary(fixed=false) on PostgreSQL/SQLite or smallint vs integer on SQLite?

/**
* @return string[]
*/
protected function getAlterTableChangeBlobColumnLength(): array
Copy link
Member

Choose a reason for hiding this comment

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

Why does it have to be a separate method?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to use the same coding style as other similar tests. Should I integrate it into the testAlterTableChangeBlobColumnLength() method instead?

$oldSchema = new Schema();

$tableFoo = $oldSchema->createTable('foo');
$tableFoo->addColumn('id', 'string', ['length' => 127]);
Copy link
Member

Choose a reason for hiding this comment

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

The issue is about BLOB columns. Why does the test compare string column lengths?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There was no test yet that tested the length changes for string columns. I mainly added this test to confirm my expectation about how the API works. I can move this test to its own pull request, or remove it alltogehter, however you prefer ☺️

@ausi
Copy link
Contributor Author

ausi commented Mar 23, 2021

Does the same logic apply to the TEXT/CLOB columns?

Yes, added in a85737f

@ausi ausi force-pushed the fix/schema-diff-blob-size branch from 89cadaf to 0efc0ac Compare March 24, 2021 09:03
case 'clob':
$length = $tableColumn['length'];
break;

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 needs to be removed in order for Db2SchemaManagerTest::testDiffListTableColumns() to succeed.

I think this is correct because DB2Platform does currently not handle lengths for blob and text types, see

public function getClobTypeDeclarationSQL(array $column)
{
// todo clob(n) with $column['length'];
return 'CLOB(1M)';
and
public function getBlobTypeDeclarationSQL(array $column)
{
// todo blob(n) with $column['length'];
return 'BLOB(1M)';
and this change normalizes the behavior for blob and text to work the same now.

@morozov morozov closed this Apr 21, 2021
@morozov morozov deleted the branch doctrine:3.1.x April 21, 2021 16:26
@morozov morozov reopened this Apr 21, 2021
@morozov morozov changed the base branch from 2.12.x to 3.1.x May 2, 2021 17:39
@Toflar
Copy link

Toflar commented May 25, 2021

Any chance this is going to be merged into 3.1 if conflicts are resolved?
I just ran into this bug again :/

@ausi ausi force-pushed the fix/schema-diff-blob-size branch from d4916d2 to 6fccbbc Compare May 25, 2021 10:53
@morozov
Copy link
Member

morozov commented May 25, 2021

Any chance this is going to be merged into 3.1 if conflicts are resolved?

I do not intend to merge it in the current state: #4551 (comment).

@ausi
Copy link
Contributor Author

ausi commented May 26, 2021

While the fix seems to be within the current comparator design, the design obviously has flaws. A proper approach might be to add platform awareness to the comparator API and compare the SQL generated against a given platform. It will also likely eliminate the need for the hack introduced in #3382.

I will try to work on this. I would add a constructor to the Comparator class with an optional argument for passing an AbstractPlatform object.

Should I mark using the comparator without a platform as deprecated?

Is this considered to be a new feature and based on the 3.2.x branch or a bugfix based on 3.1.x instead?

@morozov
Copy link
Member

morozov commented May 27, 2021

I would add a constructor to the Comparator class with an optional argument for passing an AbstractPlatform object.

I think it'd make more sense to pass the platform to all methods explicitly. This will keep the comparator free of dependencies.

Should I mark using the comparator without a platform as deprecated?

I wouldn't bother about deprecation and backward compatibility for now. I'd start with prototyping a solution with the new API and see if it solves the problem and reduces the number of platform-specific edge cases to be handled in the code. Once this is confirmed, we can think of the rest.

Is this considered to be a new feature and based on the 3.2.x branch or a bugfix based on 3.1.x instead?

It's definitely a new feature.

@ausi
Copy link
Contributor Author

ausi commented May 29, 2021

Done: #4659

@morozov
Copy link
Member

morozov commented Jul 13, 2021

Closing in favor of #4659.

@morozov morozov closed this Jul 13, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 20, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants