Opened 7 years ago
Last modified 4 weeks ago
#46146 new defect (bug)
dbDelta not parsing enum correctly
| Reported by: | janjakes | Owned by: | |
|---|---|---|---|
| Priority: | normal | Milestone: | Awaiting Review |
| Component: | Database | Version: | |
| Severity: | normal | Keywords: | has-patch |
| Cc: | Focuses: |
Description
Given an enum definition such as:
enum('a', 'b')
The dbDelta function parses it as:
enum('a',
Which causes a change to be detected on every execution. I'm also afraid other cases with spaces (like strings with spaces in enum values, etc.) will cause similar problem since the regular expressions in the dbDelta function seem to cover only some particular cases.
Change History (3)
#2
@
4 weeks ago
This issue still exists: differences are detected where there are none, in case of uppercase enum values, and enum values with spaces in them.
Example
These two will both trigger a Changed Type
input
enum('cart','individual purchase')
enum('True','False')
output
[foo.bar] => Changed type of betaal.Betalingsbron from enum('cart','individual purchase') to enum('cart','individual
[foo.baz] => Changed type of sidebase.aandacht from enum('True','False') to enum('True','False')
Solution
Caused by this part of the code:
preg_match( '|`?' . $tablefield->Field . '`? ([^ ]*( unsigned)?)|i', $cfields[ $tablefield_field_lowercased ], $matches ); $fieldtype = $matches[1]; $fieldtype_lowercased = strtolower( $fieldtype ); ... if ( $tablefield->Type !== $fieldtype_lowercased ) {
While the regex should match field types like
int(11)
varchar
enum('True','False')
enum('cart','individual purchase')
... in reality it ends matching at the first space. Instead it could try to match \w+ (or only [a-z]) with optionally brackets immediately after it*:
preg_match( '|`?' . $tablefield->Field . '`? (\w+(?:\([^)]*\))?(?: unsigned)?)|i', $cfields[ $tablefield_field_lowercased ], $matches );
Furthermore the later comparison with $tablefield->Type could be done on the non-lowercased version, or with both old and new type lowercased if you want to ignore case:
if ( $tablefield->Type !== $fieldtype ) {
if ( strtolower($tablefield->Type) !== $fieldtype_lowercased ) {
★ this still means it'll break on a closing bracket; to avoid this would require proper parsing of the string, beyond simple regexes.
This ticket was mentioned in PR #12164 on WordPress/wordpress-develop by ANB5Dev.
4 weeks ago
#3
- Keywords has-patch added
- fix regex to capture field type correctly
- compare original case field with original case reference
Trac ticket: https://core.trac.wordpress.org/ticket/46146
## Use of AI Tools
AI assistance: No
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
I found that having spaces is no longer an issue in newer versions of WordPress, but there is still a parsing issue with ENUMs if there are new lines between the elements. For example:
enum('a', 'b', 'c' )This is a problem with WordPress 5.6.