#49364 closed defect (bug) (fixed)
dbDelta() should not change display width for integer data types on MySQL 8.0.17+
Reported by: | SergeyBiryukov | Owned by: | SergeyBiryukov |
---|---|---|---|
Milestone: | 6.1 | Priority: | normal |
Severity: | normal | Version: | |
Component: | Database | Keywords: | has-patch needs-testing early needs-testing-info |
Focuses: | Cc: |
Description
Background: #49344
MySQL 8.0.17 removed support for the display width attribute for integer data types:
As of MySQL 8.0.17, the ZEROFILL attribute is deprecated for numeric data types, as is the display width attribute for integer data types. Support for ZEROFILL and display widths for integer data types will be removed in a future MySQL version. Consider using an alternative means of producing the effect of these attributes.
With this change, when creating a table, BIGINT(20)
becomes just BIGINT
, causing quite a few failures in tests/dbdelta.php
(25 in total). They all look similar to this:
2) Tests_dbDelta::test_column_type_change Failed asserting that two arrays are equal. --- Expected +++ Actual @@ @@ Array ( - 'wptests_dbdelta_test.id' => 'Changed type of wptests_dbdelta_test.id from bigint(20) to int(11)' + 'wptests_dbdelta_test.id' => 'Changed type of wptests_dbdelta_test.id from bigint to int(11)' ) tests/phpunit/tests/dbdelta.php:151
Most of these failures will be addressed in #49344.
This ticket is for addressing the remaining failure caused by the same BIGINT(20)
/BIGINT
discrepancy coming from wp_get_db_schema()
:
1) Tests_dbDelta::test_wp_get_db_schema_does_no_alter_queries_on_existing_install Failed asserting that an array is empty. tests/phpunit/tests/dbdelta.php:693
Currently, when running on MySQL 8.0.17+, dbDelta()
tries to convert BIGINT
back to BIGINT(20)
, INT
back to INT(11)
, etc. This does not have any effect on the database, but is pointless and should not happen.
Attachments (2)
Change History (40)
This ticket was mentioned in Slack in #core by sergey. View the logs.
4 years ago
#5
@
4 years ago
The original ticket states:
Currently, when running on MySQL 8.0.17+, dbDelta() tries to convert BIGINT back to BIGINT(20), INT back to INT(11), etc. This does not have any effect on the database, but is pointless and should not happen.
However, this isn't always a silent failure. It can cause failures where an INT with a display width is also a primary key. Consider the plugin below:
<?php /* * Plugin Name: dbDelta Display Width Issue * Description: dbDelta Display Width Issue * Version: 1.0.0 */ if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } function ddwi_install() { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( <<<SQL CREATE TABLE `wp_ddwi_test` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, ) SQL ); } register_activation_hook( __FILE__, 'ddwi_install' );
The first activation will go without issues. However deactivating and re-activating the plugin attempts to run the following (unnecessary) alter statement:
ALTER TABLE wp_ddwi_test CHANGE COLUMN `id` `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY
This yields the following error:
WordPress database error Multiple primary key defined for query ALTER TABLE wp_ddwi_test CHANGE COLUMN `id` `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY
and gives an error on WP-CLI , or through online activation about excess output produced during activation.
#6
@
3 years ago
- Milestone changed from Future Release to 5.9
I'd like to solve the MySQL 8 test failures for 5.9 to that we can look at expanding our testing combinations.
This ticket was mentioned in PR #1781 on WordPress/wordpress-develop by pbearne.
3 years ago
#7
- Keywords has-unit-tests added
Add regx to dbDelta() function so any calls in the old form are handled
Trac ticket: https://core.trac.wordpress.org/ticket/49364
This ticket was mentioned in PR #1782 on WordPress/wordpress-develop by pbearne.
3 years ago
#8
Add regex to dbDelta() function so any calls in the old form are handled
and included the corrected schema
Trac ticket: https://core.trac.wordpress.org/ticket/49364
#9
@
3 years ago
- Keywords needs-testing has-unit-tests removed
Hi All
I dug into this and checked the testing
It seems to me that we will have issues with current code/plugins still trying to use the old format
So I added a regx_replace to fix the SQL on the fly
Maybe we should look at adding a do_it_wrong notice but I didn't do that it would increase the overhead
The new patch is in pull request #1781 and the combined patch is in #1782
I hope this helps
Paul
#11
@
3 years ago
- Milestone changed from 5.9 to 6.0
5.9 Beta 1 is in 4 days. Like the other MySQL 8.0 tickets, moving to 6.0.
#12
follow-up:
↓ 13
@
3 years ago
I'm having this problems with MariaDB 10.5.
https://make.wordpress.org/hosting/test-results/r52797/wpsabot-r52797/
I think this may be related with
@@SQL_MODE: STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
Mainly: STRICT_TRANS_TABLES. MariaDB 10.2.4+ has the STRICT_TRANS_TABLES by default...
https://mariadb.com/kb/en/sql-mode/#strict_trans_tables
Strict mode. Statements with invalid or missing data are aborted and rolled back, except that for non-transactional storage engines and statements affecting multiple rows where the invalid or missing data is not the first row, MariaDB will convert the invalid value to the closest valid value, or, if a value is missing, insert the column default value. Default since MariaDB 10.2.4.
#13
in reply to:
↑ 12
@
3 years ago
Replying to JavierCasares:
I'm having this problems with MariaDB 10.5.
https://make.wordpress.org/hosting/test-results/r52797/wpsabot-r52797/
I think this may be related with
@@SQL_MODE: STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTIONMainly: STRICT_TRANS_TABLES. MariaDB 10.2.4+ has the STRICT_TRANS_TABLES by default...
Thanks! I'm not sure it's related to STRICT_TRANS_TABLES
though, as WordPress specifically disables this and other incompatible modes as of [27072] / #26847. Perhaps the disabling fails for some reason?
It's interesting that the failure messages are the exact opposite of what I had in the ticket description.
MySQL 8.0.17 changes from bigint(20)
to bigint
:
Tests_dbDelta::test_column_type_change Failed asserting that two arrays are equal. --- Expected +++ Actual @@ @@ Array ( - 'wptests_dbdelta_test.id' => 'Changed type of wptests_dbdelta_test.id from bigint(20) to int(11)' + 'wptests_dbdelta_test.id' => 'Changed type of wptests_dbdelta_test.id from bigint to int(11)' )
MariaDB 10.5.15 changes from bigint
to bigint(20)
:
Tests_dbDelta::test_column_type_change Failed asserting that two arrays are identical. --- Expected +++ Actual @@ @@ Array &0 ( - 'wptests_dbdelta_test.id' => 'Changed type of wptests_dbdelta_test.id from bigint to int(11)' + 'wptests_dbdelta_test.id' => 'Changed type of wptests_dbdelta_test.id from bigint(20) to int(11)' )
It also looks like the same tests do successfully pass on another host:
https://make.wordpress.org/hosting/test-results/r52797/cloudingbot-r52797/
I think the test changes in [47184] may need some adjustment, specifically this check:
if ( version_compare( $db_version, '8.0.17', '<' ) ) { // Prior to MySQL 8.0.17, default width of 20 digits was used: BIGINT(20). $this->bigint_display_width = '(20)'; }
However, it's not quite clear to me why this works for me locally with MariaDB 10.4.12, as well as on some hosts with MariaDB 10.5.15, but not on the one with the failures. It might be helpful to check whether STRICT_TRANS_TABLES
is related or not, and make sure that the disabling actually works.
#14
@
3 years ago
I can try to change the SQL_MODE in my machine (I don't have anything in this machine, is only to do tests). So I can try and check changing this option.
I'll do a manual test and leave the report here.
#15
@
3 years ago
Well... after testing it without the STRICT_TRANS_TABLES
it gave me the same errors... so, no, it seems not to be that. I'm going to do some more testing and configurations.
This ticket was mentioned in Slack in #core-test by hellofromtonya. View the logs.
3 years ago
This ticket was mentioned in Slack in #core by costdev. View the logs.
3 years ago
#18
@
3 years ago
- Keywords needs-refresh needs-testing early added
- Milestone changed from 6.0 to 6.1
Per the discussion in the bug scrub, I'm moving this to the 6.1 milestone and adding the early
keyword.
There are merge conflicts on the PRs and this needs more testing.
This ticket was mentioned in Slack in #core by costdev. View the logs.
3 years ago
#20
@
3 years ago
This ticket was discussed in the recent bug scrub.
@pbearne, do you have time to refresh the PR to resolve merge conflicts?
This ticket was mentioned in Slack in #core by costdev. View the logs.
3 years ago
#22
@
3 years ago
- Keywords needs-refresh removed
@pbearne has refreshed PR 1782.
This could use more testing. Can anyone perform this testing and include some testing instructions so that the Test team can pick this one up?
Thanks!
This ticket was mentioned in Slack in #core by chaion07. View the logs.
3 years ago
This ticket was mentioned in Slack in #core by chaion07. View the logs.
2 years ago
This ticket was mentioned in Slack in #hosting-community by javier. View the logs.
2 years ago
This ticket was mentioned in Slack in #core by chaion07. View the logs.
2 years ago
This ticket was mentioned in Slack in #core by audrasjb. View the logs.
2 years ago
This ticket was mentioned in Slack in #core by chaion07. View the logs.
2 years ago
This ticket was mentioned in Slack in #core by audrasjb. View the logs.
2 years ago
#32
@
2 years ago
This is not easy to test
What I did was do a fresh install on an old DB (per 8.0.17) and a new DB (after 8.0.17)
I then checked the DB Schema to make sure they were set correctly.
#33
@
2 years ago
Spent some more time looking into this.
I was able to reproduce the observations from comment:13:
MySQL 8.0.17 changes from
bigint(20)
tobigint
:
Tests_dbDelta::test_column_type_change Failed asserting that two arrays are equal. Array ( - 'wptests_dbdelta_test.id' => 'Changed type of wptests_dbdelta_test.id from bigint(20) to int(11)' + 'wptests_dbdelta_test.id' => 'Changed type of wptests_dbdelta_test.id from bigint to int(11)' )MariaDB 10.5.15 changes from
bigint
tobigint(20)
:
Tests_dbDelta::test_column_type_change Failed asserting that two arrays are identical. Array &0 ( - 'wptests_dbdelta_test.id' => 'Changed type of wptests_dbdelta_test.id from bigint to int(11)' + 'wptests_dbdelta_test.id' => 'Changed type of wptests_dbdelta_test.id from bigint(20) to int(11)' )...
However, it's not quite clear to me why this works for me locally with MariaDB 10.4.12, as well as on some hosts with MariaDB 10.5.15, but not on the one with the failures.
See these more recent test runs for example:
- Fails: PHP 8.0.21 + MariaDB 10.4.25
- Passes: PHP 7.4.30 + MariaDB 10.4.25
MariaDB version is the same, the only notable difference is PHP 8.0.x vs. PHP 7.4.x. That is indeed the reason for different results: when running the tests with the same versions locally, they fail on PHP 8.0 and pass on PHP 7.4.
The reason is that $wpdb->db_version()
reports MariaDB version differently between PHP versions:
- PHP 8.0.21:
10.6.8-MariaDB
- PHP 7.4.30:
5.5.5-10.6.5-MariaDB
This was previously noted in comment:7:ticket:47738 and appears to be addressed in PHP 8.0.16 or later:
- php-src: #7972: MariaDB version prefix 5.5.5- is not stripped
- php-src: PR #7963 Fix GH-7932: MariaDB version prefix not always stripped
This leads to the version_compare( $db_version, '8.0.17', '<' )
checks added in [47184] working as expected on PHP 7.4.x and earlier, but not on PHP 8.0.x or later. We erroneously set $bigint_display_width
to an empty string for MariaDB, as the 10.6.8 version is greater than 8.0.17. However, display width support was only removed for integer data types specifically in MySQL 8.0.17+, it is still available and expected in MariaDB.
Thinking about this some more, I believe 49364.diff (and the refreshed PR) is not quite in the right direction: changing the schema would not really solve the issue. Instead, dbDelta()
should match the database server behavior: keep display width for integer data types on MariaDB and older MySQL versions, but ignore it on MySQL 8.0.17 or later, which would mean treating BIGINT(20)
same as BIGINT
, INT(11)
same as INT
, etc.
See 49364.2.diff for the suggested solution, which reverts most of [47184] as no longer needed.
This change is covered by existing unit tests:
- 20+
dbDelta()
tests which currently fail on PHP 8.0.x + MariaDB and pass with this patch. - One test from the ticket description which currently fails on MySQL 8.0.17+ and passes with this patch.
It also resolves an issue with plugin activation described in comment:5:
The first activation will go without issues. However deactivating and re-activating the plugin attempts to run the following (unnecessary) alter statement:
ALTER TABLE wp_ddwi_test CHANGE COLUMN `id` `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEYThis yields the following error:
WordPress database error Multiple primary key defined for query ALTER TABLE wp_ddwi_test CHANGE COLUMN `id` `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY
Tested on:
- PHP 8.0.22 + MariaDB 10.6.8
- PHP 7.4.30 + MariaDB 10.6.8
- PHP 5.6.40 + MariaDB 10.6.8
- PHP 8.0.22 + MySQL 8.0.30
- PHP 7.4.30 + MySQL 8.0.30
- PHP 5.6.40 + MySQL 8.0.30
#34
@
2 years ago
- Owner set to SergeyBiryukov
- Resolution set to fixed
- Status changed from new to closed
In 53897:
SergeyBiryukov commented on PR #1781:
2 years ago
#35
Thanks for the PR! This is now addressed in r53897.
SergeyBiryukov commented on PR #1782:
2 years ago
#36
Thanks for the PR! This is now addressed in r53897.
In 47184: