Problem On MySQL and MariaDB, a table takes the default collation of its database at the moment it is created (Hibernate does not set any). An instance which went through upgrades, dump/restore cycles or extension installs often ends up with a mix of collations: most tables use the collation configured on the database (e.g. utf8mb4_bin) but a few still use an older one (e.g. utf8_general_ci, utf8mb4_general_ci). Such tables cause subtle problems: case-insensitive collisions between references which differ only in case, characters that cannot be stored when the table is still on a 3-byte charset, joins and foreign keys between columns with different collations, etc. Fixing it by hand is not trivial, since MariaDB refuses to convert a column used in a foreign key, even with FOREIGN_KEY_CHECKS=0. Proposal Add a Hibernate data migration, for MySQL and MariaDB only, which converts each table of the Hibernate mapping whose default collation or one of its columns does not match the collation configured on the database (CONVERT TO CHARACTER SET ... COLLATE ...):
- the conversion is done before the Hibernate schema update, after dropping the foreign keys involving string columns of the tables to convert, so that the schema update re-creates them
- the tables linked by such a foreign key are converted together and a failure is fatal, since the foreign key could not be re-created between columns with different collations
- a failure on any other table (e.g. a custom index too long for the new charset) does not prevent XWiki from starting: the table is left as it was and a warning lists the tables which could not be converted
|