Wednesday, January 30, 2013

MySQL - utf8_general_ci und 'ß'

Heute habe ich mir in meinem Framework einen Wolf gesucht, da ich der Annahme war, ein Encoding-Bug hätte sich irgendwo eingenistet.

Was war passiert? Ich wollte zwei Datensätze über einen 3-Spalten-Primaray-Key in der Datenbank hinzufügen.

Der sah dann so aus:

array(3) {
  [0]=>
  string(13) "`char` = 's'"
  [1]=>
  string(12) "`number` = 0"
  [2]=>
  string(12) "`userId` = 1"
}

und

array(3) {
  [0]=>
  string(13) "`char` = 'ß'"
  [1]=>
  string(12) "`number` = 0"
  [2]=>
  string(12) "`userId` = 1"
}

Der erste Datensatz lief ohne Probleme flüssig und sauber in die Datenbank. Der zweite, wurde aber niemals hinzugefügt.

Meine Applikationslogik hatte beim 2. Insert zuvor geprüft, ob der Datensatz schon vorhanden war. Und ja, der war da. Aber nicht etwa, weil ein Bug im Code existiert, sondern weil mysql bei der Collation uft8_general_ci ein bösen Encoding-Bug hat. (Seit Jahren...)

Wer das bei sich überprüfen will, kann folgendes ausführen:

SELECT 's' = 'ß' COLLATE utf8_general_ci;
SELECT 's' = 'ß' COLLATE utf8_unicode_ci;
Man wird staunen, was beim ersten Select für ein Ergebnis sich präsentiert. Also habe ich gezwungenermaßen in einem Sonderfall die Spalten-Collation auf utf8_unicode_ci geändert.

Mehr Details gibts auf MySQL: http://bugs.mysql.com/bug.php?id=27877

EDIT: Okay, von Bug kann man wohl nicht reden, aber von extrem verwirrend. Siehe: http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci