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: #6146 - utf8/utf8mb3 alias causes redundant ALTER TABLE changes #6370

Open
wants to merge 957 commits into
base: 3.8.x
Choose a base branch
from

Conversation

fisharebest
Copy link

@fisharebest fisharebest commented Apr 29, 2024

Q A
Type bug
Fixed issues #6146

Summary

In MySQL (and MariaDB), utf8 and utf8mb3 are aliases. Depending on the database server version, the information schema may contain one or the other. Similarly, column definitions may contain one or the other.

When performing schema-comparisons, a mismatch between utf8 and utf8mb3 causes an ALTER TABLE statement to be generated - even when columns are identical.

The code already contains a function to normalize the charset/collation options:

private function normalizeOptions(array $options): array

My solution is to extend this function so that it also replaces utf8 with utf8mb3 (or vice-versa), to match the current database connection.

To detect the prefered character set for the connection, I've added:
AbstractMySQLPlatform::informationSchemaUsesUtf8mb3()
MariaDBPlatform::informationSchemaUsesUtf8mb3()

The obvious place for the new normalization logic is the CharsetMetadataProvider and CollationMetadataProvider classes. These are interfaces, so this is technically a BC break, however, they are marked @internal.

I've added tests which should cover all the new/modified code. I've run it against MySQL. I don't have MariaDB to hand.

…tected

Make internal Comparator methods protected
Remove property-based schema comparison APIs
…ftovers

Remove leftovers of handling foreign keys on non-InnoDB engines for MySQL
…traint-name

Introspect default constraint name
Remove conditional comments for MySQL older than 5.1.16
Remove support for "unique" and "check" column properties
Remove support for renaming tables via TableDiff
…lt-constraint-leftovers

Remove leftovers of renaming default contraints
…perties

Mark ColumnDiff properties as private and read-only
…handling-workaround

Remove workaround for PHP bug in PostgreSQL exception handler
SenseException and others added 5 commits March 19, 2024 20:58
To reduce Algolia operations and indexes older versions get removed
* 3.8.x:
  Add MariaDB 11.3 to the test matrix (doctrine#6342)
  Spell which properly
  Fix double quote used wrongly for literal value in SqliteSchemaManager (doctrine#6325)
* 3.8.x:
  Avoid calling deprecated Type::getName() (doctrine#6359)
  Ensure correct json default value normalization (doctrine#6358)
  Document how to run integration tests locally
  Remove unused script
@fisharebest
Copy link
Author

Just pushed a change to fix the psalm issues

@greg0ire
Copy link
Member

It seems there are CI jobs failing. Please take a look at this guide for more on how to handle those.

@greg0ire
Copy link
Member

ಠ_ಠ

@greg0ire
Copy link
Member

greg0ire commented May 1, 2024

I've added tests which should cover all the new/modified code. I've run it against MySQL. I don't have MariaDB to hand.

Codecov says that some of the new code is untested, most notably the parts using version_compare. Please add functional tests for this change. As you can see, our test suite features, among other platforms MariaDB 10.5 and MariaDB 10.6, so you should be able to test that schema comparisons on either version of MariaDB indeed doesn't cause ALTER TABLE statements to be generated. Same goes for MySQL.

You can learn more about such tests at https://www.doctrine-project.org/projects/doctrine-dbal/en/stable/reference/testing.html

@fisharebest
Copy link
Author

Codecov says that some of the new code is untested, most notably the parts using version_compare. Please add functional tests for this change.

Running the tests locally says the code is covered. (Ad hoc testing confirms this).

XDEBUG_MODE=coverage vendor/bin/phpunit -c ci/github/phpunit/pdo_mysql.xml --coverage-html=coverage

Screenshot 2024-05-01 at 13 47 44

However, Codecov says it isn't.

Screenshot 2024-05-01 at 13 48 31

@greg0ire
Copy link
Member

greg0ire commented May 1, 2024

I think I found the reason: [2024-05-01T09:48:28.648Z] ['error'] There was an error running the uploader: Error uploading to [https://codecov.io:](https://codecov.io/) Error: There was an error fetching the storage URL during POST: 429 - {'detail': ErrorDetail(string='Rate limit reached. Please upload with the Codecov repository upload token to resolve issue. Expected available in 1935 seconds.', code='throttled')}

Let me retry this.

greg0ire added a commit to greg0ire/dbal that referenced this pull request May 1, 2024
In a recent PR, we got reports from CodeCov about several lines not
being covered. After further inspection, I found an error message in the
coverage file upload saying we hit a rate limit.
This will make it more likely we spot such issues in the future.

The PR: doctrine#6370
@greg0ire
Copy link
Member

greg0ire commented May 1, 2024

From the Codecov UI:

Coverage data is based on head 9c87c57(2 uploads) compared to base 7fb00fd(5 uploads)

… we currently send 69 uploads, so there is no way we are going to be below the upload limit. I will have to look into this separately.

greg0ire
greg0ire previously approved these changes May 1, 2024
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.

Looks good overall, my feedback is not a blocker.

public function normalizeCollation(string $collation): string
{
if ($this->useUtf8mb3 && str_starts_with($collation, 'utf8_')) {
return 'utf8mb3' . substr($collation, 4);
Copy link
Member

Choose a reason for hiding this comment

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

I'd make things more obvious here:

Suggested change
return 'utf8mb3' . substr($collation, 4);
return 'utf8mb3' . substr($collation, strlen('utf8'));

}

if (! $this->useUtf8mb3 && str_starts_with($collation, 'utf8mb3_')) {
return 'utf8' . substr($collation, 7);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return 'utf8' . substr($collation, 7);
return 'utf8' . substr($collation, strlen('utf8mb3'));

@greg0ire
Copy link
Member

greg0ire commented May 1, 2024

Ah there is one issue though: since this is a fix, you should target 3.8.x

@fisharebest
Copy link
Author

Ah there is one issue though: since this is a fix, you should target 3.8.x

I can create another PR for this branch.

@greg0ire
Copy link
Member

greg0ire commented May 1, 2024

Please don't, we usually do merges up. Instead, let me retarget your PR, and please rebase your commits on 3.8.x and force push.

@greg0ire greg0ire changed the base branch from 4.0.x to 3.8.x May 1, 2024 16:36
@greg0ire greg0ire dismissed their stale review May 1, 2024 16:36

The base branch was changed.

greg0ire added a commit to greg0ire/dbal that referenced this pull request May 1, 2024
In a recent PR, we got reports from CodeCov about several lines not
being covered. After further inspection, I found an error message in the
coverage file upload saying we hit a rate limit.
This will make it more likely we spot such issues in the future.

The PR: doctrine#6370
@fisharebest
Copy link
Author

Please don't, we usually do merges up. Instead, let me retarget your PR, and please rebase your commits on 3.8.x and force push.

The PR uses Connection::getServerVersion() to select the prefered alias for utf8/utf8mb3.
In 3.8.x, this method isn't available, so I'll need to find another approach.

I'm going to be offline for the next week or so, and will look at this on my return.

@greg0ire
Copy link
Member

greg0ire commented May 2, 2024

Enjoy your time off 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet