Problem/Motivation
Setting collation in the table schema for MySQL tables has no effect. Per the original report:
I would very much like to see it fixed in D7 ASAP, because it's causing major problems for my module, S3 File System. I define a table with utf8_bin collation, since I need case-sensitive primary keys, but the collation setting gets ignored, and I have to run
db_query("ALTER TABLE {s3fs_file} CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin");manually to fix it.This bug also makes it clear that the tests for the database creation code are incomplete.
Proposed resolution
Apply any explicit collation settings in the table schema before checking for collation settings in the connection info.
Remaining tasks
Write tests (MySQL-specific, presumably - do the other core db engines purport to support table-specific collations?).
User interface changes
N/A
API changes
N/A
Data model changes
N/A
Release notes snippet
TBD
Original issue summary
There's a typo in DatabaseSchema_mysql::createTableSql() which makes the 'collation' setting in schema definitions get silently ignored. The schema info variable is called $table, but it's referenced in the collation code as $info. Since it's wrapped in a !empty() check, PHP happily confirms that $info['collation'] is always empty, because $info is undefined.
The fix is simply to rename $info to $table, which I've done in the attached patches (this bug exists in D8 and D7).
I would very much like to see it fixed in D7 ASAP, because it's causing major problems for my module, S3 File System. I define a table with utf8_bin collation, since I need case-sensitive primary keys, but the collation setting gets ignored, and I have to run db_query("ALTER TABLE {s3fs_file} CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin"); manually to fix it.
This bug also makes it clear that the tests for the database creation code are incomplete. Unfortunately, I know nothing about drupal testing, so I can't write a patch for that.
| Comment | File | Size | Author |
|---|---|---|---|
| #32 | D8-mysql_collation_fix-2193059-32.patch | 1.12 KB | anya_m |
Issue fork drupal-2193059
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
coredumperror commentedD7-mysql_collation_fix.patch queued for re-testing.
Comment #4
coredumperror commentedThe test bot is complaining about the D7 patch failing to apply because it's attempting to apply it against 8.x-dev.
Should I open a separate issue for the D7 version of this bug?
Comment #5
jhedstromI started to add a test, but quickly realized it would require adding new methods to our Schema classes (mysql stores this information in
information_schema.table), but we can't just code that directly into the test since that would break on non-mysql drivers.Setting to RTBC since this fixes an obvious typo, and need not be blocked by the creation of a test.
Re #4 once this is committed to 8, and the version is set to 7.x, then your tests should run.
Comment #6
coredumperror commentedThank you! I am very much looking forward to this fix making into the official Drupal release.
Comment #7
alexpottI'm not sure this is the correct fix. The collation should be set on the connection options. in D8 $info is set by the first line DatabaseSchema::createTableSql() see https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Database%...
This means that the collation needs to be set in the settings.php and is set for all tables. At the moment the implementation does not support per table or per column collation settings.
Comment #8
coredumperror commentedWow, I completely missed the definition of the
$infovariable up there at the top of the function. I vaguely recall assuming this was a copy-paste typo based on some other implementation ofcreateTableSql(), and it appears I may have been mistaken.Still, the docs state that you can set the collation in the schema definition, which this function, as it currently stands, does not actually allow.
> At the moment the implementation does not support per table or per column collation settings.
Why not? What bad things could happen if
$infowere changed to$tablehere? Myself and all of other users of S3 File System have been using a single utf8_bin collated column in ours3fs_filestables for months, with no issues (I found a workaround).Comment #9
alexpottSo - we need to first check the collation on the schema definition and then fallback to collation set in the connection properties. So we can't just change $info to $table since that would be breaking existing functionality that other sites rely on.
Comment #10
coredumperror commentedAh, right. OK, here are modified patches that should do just that.
Comment #11
coredumperror commentedOh damnit, I'm a moron. The typo I was complaining about which wasn't actually a typo... is a typo that I totally left in my updated patches. Wow I feel like a fool now.
Here's the un-typo'd patches.
Comment #12
kars-t commentedI move the issue to "needs review" so the testbot can test it.
Test seem to be a problem here. I searched core if there are already collation tests. I only found "CaseSensitivityTest" which doesn't really seem to test if a table got a different collation. So it seems core here misses tests and this issue imho shouldn't get RTBC if there are no tests. And finally: If someone writes a test wouldn't that be mysql only?
Besides missing tests I believe the patches should fix the issue.
Comment #13
kars-t commentedI changed the issue title as stated in #9 the core behaviour is correct and the setting per table simply ignored.
Comment #17
kars-t commentedReadding the patches while adding "do-not-test" to the D7 patch. By this the D8 patch can go green. @see https://www.drupal.org/node/332678#versions
Comment #18
kars-t commentedForgot to change to "needs review".
Comment #19
jhedstromIssue summary needs to be updated to take into account the most recent patch (it was determined this is not a typo).
Small nit:
Should be
elseif.Comment #20
jhedstromThis is at needs work for tests.
Comment #21
jhedstromAlthough, note the test may need to be MySQL-specific given #5.
Comment #27
mikeryanBump - this is still a problem: #2972251: "s3fs_file" table has no primary key.
Since it's been three years and a day since the last activity here, let's retest that last patch...
Comment #31
mikeryanComment #32
anya_m commentedRerolled patch for 8.7.x
Comment #33
mikeryanThanks for the reroll @anya_m!
Setting back to "Needs work" as we still need tests...
I've updated the issue summary.
Comment #44
pameeela commentedCreated an MR based on the latest patch.
Given that this is a pretty simple change, and tests will be difficult to add, I think it might qualify for the test exemption per the updated policy. Interestingly this was suggested 10 years ago in #5 but now the policy is official :)
Comment #46
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue.
While you are making the above changes, we recommend that you convert this patch to a merge request. Merge requests are preferred over patches. Be sure to hide the old patch files as well. (Converting an issue to a merge request without other contributions to the issue will not receive credit.)