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

WordPress database error COLLATION utf8_general_ci is not valid for CHARACTER SET utf8mb4 for query #32

Closed
rvdsteege opened this issue May 31, 2023 · 6 comments · Fixed by #35
Assignees

Comments

@rvdsteege
Copy link
Member

An user encountered the following error on plugin activation in a WordPress multisite:

WordPress database error COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'utf8mb4' for query:

INSERT IGNORE INTO wp_pronamic_pay_mollie_customer_users (
	customer_id,
	user_id
)
			SELECT
				mollie_customer.id AS mollie_customer_id,
				wp_user.ID AS wp_user_id
			FROM
				wp_pronamic_pay_mollie_customers AS mollie_customer
					INNER JOIN
				wp_usermeta AS wp_user_meta
						ON wp_user_meta.meta_value = mollie_customer.mollie_id COLLATE utf8_general_ci
					INNER JOIN
				wp_users AS wp_user
						ON wp_user_meta.user_id = wp_user.ID
			WHERE
				wp_user_meta.meta_key IN (
	'_pronamic_pay_mollie_customer_id',
	'_pronamic_pay_mollie_customer_id_test'
)
AND
wp_user_meta.meta_value != ''
;

This query is from the gateway install:

/**
* Collate caluse.
*
* Force a specific collate to fix:
* "Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and
* (utf8mb4_unicode_520_ci,IMPLICIT) for operation '='. ".
*
* @link https://dev.mysql.com/doc/refman/8.0/en/charset-collate.html
*/
$collate_clause = '';
if ( ! empty( $wpdb->collate ) ) {
$collate_clause = \sprintf(
'COLLATE %s',
$wpdb->collate
);
}
$query = "
INSERT IGNORE INTO $wpdb->pronamic_pay_mollie_customer_users (
customer_id,
user_id
)
SELECT
mollie_customer.id AS mollie_customer_id,
wp_user.ID AS wp_user_id
FROM
$wpdb->pronamic_pay_mollie_customers AS mollie_customer
INNER JOIN
$wpdb->usermeta AS wp_user_meta
ON wp_user_meta.meta_value = mollie_customer.mollie_id $collate_clause
INNER JOIN
$wpdb->users AS wp_user
ON wp_user_meta.user_id = wp_user.ID
WHERE
wp_user_meta.meta_key IN (
'_pronamic_pay_mollie_customer_id',
'_pronamic_pay_mollie_customer_id_test'
)
AND
wp_user_meta.meta_value != ''
;
";
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query is prepared.
$result = $wpdb->query( $query );

The collation in $wpdb->collate is determined in:

However, I would expect it to result in something utf8mb4-ish there (utf8mb4_unicode_520_ci in my non-multisite development environment)?

According to site health, constants are set as follows:

  • DB_CHARSET: utf8
  • DB_COLLATE: undefined

In this case, explicitly setting the DB_COLLATE constant resolved the issue:

define( 'DB_COLLATE', 'utf8mb4_unicode_520_ci' );

Screenshot-2023-05-31-at-8 27 08-AM

Internal Help Scout ticket: https://secure.helpscout.net/conversation/2258876225/25718

@remcotolsma
Copy link
Member

remcotolsma commented Jul 20, 2023

I couldn't reproduce this on a clean install. Adding the collate was once a fix for a problem: 593e4ff. Perhaps the collate differed per table and that caused problems? That may also be difficult to catch, but should we throw an exception for errors with this query?

if ( false === $result ) {
throw new \Exception(
sprintf(
'Could not convert user meta, database error: %s.',
$wpdb->last_error
)
);
}

@remcotolsma remcotolsma moved this to In Progress in Pronamic Pay Jul 20, 2023
@rvdsteege
Copy link
Member Author

I'm also unable to reproduce it. Probably better to not throw an exception then?

@rvdsteege rvdsteege assigned remcotolsma and unassigned rvdsteege Jul 27, 2023
@remcotolsma
Copy link
Member

I removed the collate clause, maybe the issue back in Mar 27, 2020 was related to:
https://bugs.mysql.com/bug.php?id=101891

Currently i can't reproduce the following error:

Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb4_unicode_520_ci,IMPLICIT) for operation '='.

By removing the COLLATE utf8_general_ci clause i think we solved this issue.

Removing the exception might not be a good idea, the meta convert routine might be crucial for subscription websites.

@remcotolsma remcotolsma linked a pull request Jul 27, 2023 that will close this issue
@github-project-automation github-project-automation bot moved this from In Progress to Done in Pronamic Pay Jul 27, 2023
@rvdsteege
Copy link
Member Author

rvdsteege commented Sep 21, 2023

Just received a message about the same error occurring again:

Uncaught Exception: Could not convert user meta, database error: Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb4_unicode_520_ci,IMPLICIT) for operation '='. in /public_html/wp-content/plugins/pronamic-ideal/packages/wp-pay-gateways/mollie/src/Install.php:375

Internal HelpScout ticket: https://secure.helpscout.net/conversation/2367890922/26189/

@rvdsteege rvdsteege reopened this Sep 21, 2023
@github-project-automation github-project-automation bot moved this from Done to In Progress in Pronamic Pay Sep 21, 2023
@rvdsteege
Copy link
Member Author

From what I understand, the issue is caused by the fact that the wp_usermeta was originally created with a version of MySQL older than MySQL version 5.6.0 and that the current MySQL version is >= 5.6.0. This causes the collation determined by WordPress being changed from utf8mb4_unicode_ci to utf8mb4_unicode_520_ci:

Because the wp_usermeta.meta_value column then has the utf8mb4_unicode_ci collation and wp_pronamic_pay_mollie_customers.mollie_id the utf8mb4_unicode_520_ci, the "Illegal mix of collations" error occurs.

I found that if we want to ignore collations in this query, we can also use BINARY like so:

	INNER JOIN
		$wpdb->usermeta AS wp_user_meta
			ON BINARY wp_user_meta.meta_value = mollie_customer.mollie_id

I think that would be beneficial for this query, to prevent future collation issues.

To modify the collation of the wp_pronamic_pay_mollie_customers.mollie_id column, I used the following query:

ALTER TABLE `wp_pronamic_pay_mollie_customers` MODIFY `mollie_id` VARCHAR(16) COLLATE 'utf8mb4_unicode_ci';

remcotolsma added a commit that referenced this issue Sep 27, 2023
@remcotolsma
Copy link
Member

Added in fd373d1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

2 participants