PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Die Postgres-Oberfunktion für türkische Zeichen gibt nicht das erwartete Ergebnis zurück

Ihr Problem ist 100 % Windows. (Oder genauer gesagt Microsoft Visual Studio, mit dem PostgreSQL erstellt wurde.)

Für den Datensatz SQL UPPER ruft schließlich LCMapStringW von Windows auf (über towupper über str_toupper ) mit fast alle richtigen Parameter (Gebietsschema 1055 Türkisch für ein UTF-8 -kodiert, Turkish_Turkey Datenbank),

aber

die Visual Studio Runtime (towupper ) legt den LCMAP_LINGUISTIC_CASING nicht fest Bit in LCMapStringW 's dwMapFlags . (Ich kann bestätigen, dass die Einstellung ausreicht.) Dies wird bei Microsoft nicht als Fehler betrachtet; es ist beabsichtigt und wird wahrscheinlich nie "behoben" (Oh, die Freuden des Vermächtnisses.)

Sie haben drei Auswege:

  • Implementieren Sie die Wrapper-Lösung von @Sorrow (oder schreiben Sie Ihre eigene native Funktionsersetzung (DLL).)
  • Führen Sie Ihre PostgreSQL-Instanz auf z. Ubuntu das das richtige Verhalten für türkische Gebietsschemata zeigt (@Sorrow bestätigte, dass es für ihn funktioniert); das ist wahrscheinlich der einfachste und sauberste Ausweg.
  • fügen Sie eine gepatchte 32-Bit-MSVCR100.DLL ein in Ihrem PostgreSQL-bin Verzeichnis (aber obwohl UPPER und LOWER funktionieren würde, können andere Dinge wie die Sortierung weiterhin fehlschlagen – wiederum auf Windows-Ebene. YMMV.)

Der Vollständigkeit halber (und nostalgischer Spaß) NUR , hier ist das Verfahren zum Patchen eines Windows-Systems (aber denken Sie daran, wenn Sie diese PostgreSQL-Instanz nicht von der Wiege bis zur Bahre verwalten, können Sie Ihren Nachfolgern viel Kummer bereiten); wann immer Sie ein neues Test- oder Sicherungssystem von bereitstellen Sie oder Ihre Nachfolger müssten daran denken, den Patch erneut anzuwenden – und wenn wir sagen, dass Sie eines Tages ein Upgrade auf PostgreSQL 10 durchführen, das beispielsweise MSVCR120.DLL verwendet statt MSVCR100.DLL , dann müssen Sie auch Ihr Glück mit dem Patchen der neuen DLL versuchen.) Auf einem Testsystem

  • benutze HxD um C:\WINDOWS\SYSTEM32\MSVCR100.DLL zu öffnen
  • Speichern Sie die DLL sofort unter dem gleichen Namen unter Ihrem PostgreSQL bin Verzeichnis (versuchen Sie nicht, die Datei mit dem Explorer oder der Befehlszeile zu kopieren, sie könnten die 64-Bit-Version kopieren)
  • während die Datei noch in HxD geöffnet ist, gehen Sie zu Suchen> Ersetzen , wählen Sie Datentyp:Hexwerte , dann
    • Suche nach...... 4E 14 33 DB 3B CB 0F 84 41 12 00 00 B8 00 01 00 00
    • ersetzen durch... 4E 14 33 DB 3B CB 0F 84 41 12 00 00 B8 00 01 00 01
    • ...dann noch einmal...
    • Suche nach...... FC 51 6A 01 8D 4D 08 51 68 00 02 00 00 50 E8 E2
    • ersetzen durch... FC 51 6A 01 8D 4D 08 51 68 00 02 00 01 50 E8 E2
  • ...und unter dem PostgreSQL-bin erneut speichern Verzeichnis, starten Sie dann PostgreSQL neu und führen Sie Ihre Abfrage erneut aus.
    • wenn Ihre Abfrage immer noch nicht funktioniert (stellen Sie sicher, dass Ihre Datenbank mit Turkish_Turkey UTF-8 codiert ist für beide LC_CTYPE und LC_COLLATE ) öffnen Sie postgres.exe in 32-Bit Dependency Walker und stellen Sie sicher, dass es anzeigt, dass MSVCR100.DLL geladen wird aus dem PostgreSQL-bin Verzeichnis.
    • Wenn alles gut funktioniert, kopieren Sie die gepatchte DLL in die Produktions-PostgreSQL-bin Verzeichnis und Neustart.

ABER BEACHTEN SIE, dass in dem Moment, in dem Sie die Daten vom Ubuntu-System oder vom gepatchten Windows-System auf ein ungepatchtes Windows-System verschieben, das Problem erneut auftritt und Sie diese Daten möglicherweise nicht wieder auf Ubuntu importieren können, wenn die Windows-Instanz Duplikate einführte ein citext Feld oder in einem UPPER /LOWER -basierter Funktionsindex.