PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

La fonction supérieure de Postgres sur le caractère turc ne renvoie pas le résultat attendu

Votre problème est 100 % Windows. (Ou plutôt Microsoft Visual Studio, avec lequel PostgreSQL a été construit, pour être plus précis.)

Pour mémoire, SQL UPPER finit par appeler LCMapStringW de Windows (via towupper via str_toupper ) avec presque tous les bons paramètres (locale 1055 turc pour un UTF-8 -encodé, Turkish_Turkey base de données),

mais

le Runtime de Visual Studio (towupper ) ne définit pas le LCMAP_LINGUISTIC_CASING bit dans LCMapStringW dwMapFlags de . (Je peux confirmer que le réglage fait l'affaire.) Ceci n'est pas considéré comme un bogue chez Microsoft ; c'est voulu et ne sera probablement jamais "réparé" (oh les joies de l'héritage.)

Vous avez trois façons de vous en sortir :

  • implémentez la solution wrapper de @Sorrow (ou écrivez votre propre remplacement de fonction native (DLL).)
  • exécutez votre instance PostgreSQL, par ex. Ubuntu qui présente le bon comportement pour les paramètres régionaux turcs (@Sorrow a confirmé que cela fonctionnait pour lui); c'est probablement la solution la plus simple et la plus propre.
  • ajoutez un fichier MSVCR100.DLL 32 bits corrigé dans votre bin PostgreSQL répertoire (mais bien que UPPER et LOWER fonctionnerait, d'autres choses telles que le classement peuvent continuer à échouer - encore une fois, au niveau de Windows. YMMV.)

Pour être complet (et plaisir nostalgique) SEULEMENT , voici la procédure pour corriger un système Windows (mais rappelez-vous, à moins que vous ne gériez cette instance PostgreSQL du berceau à la tombe, vous risquez de causer beaucoup de problèmes à votre ou vos successeurs ); chaque fois que vous déployez un nouveau système de test ou de sauvegarde à partir de vous ou vos successeurs devrez vous rappeler d'appliquer à nouveau le correctif - et si disons qu'un jour vous mettez à niveau vers PostgreSQL 10, qui dit utilise MSVCR120.DLL au lieu de MSVCR100.DLL , vous devrez également tenter votre chance en corrigeant la nouvelle DLL.) Sur un système de test

  • utiliser HxD pour ouvrir C:\WINDOWS\SYSTEM32\MSVCR100.DLL
  • enregistrez immédiatement la DLL avec le même nom sous votre PostgreSQL bin répertoire (n'essayez pas de copier le fichier à l'aide de l'Explorateur ou de la ligne de commande, ils pourraient copier la version 64 bits)
  • avec le fichier toujours ouvert dans HxD, allez dans Rechercher> Remplacer , sélectionnez Type de données :valeurs hexadécimales , alors
    • chercher...... 4E 14 33 DB 3B CB 0F 84 41 12 00 00 B8 00 01 00 00
    • remplacer par... 4E 14 33 DB 3B CB 0F 84 41 12 00 00 B8 00 01 00 01
    • ...puis encore une fois...
    • rechercher...... FC 51 6A 01 8D 4D 08 51 68 00 02 00 00 50 E8 E2
    • remplacer par... FC 51 6A 01 8D 4D 08 51 68 00 02 00 01 50 E8 E2
  • ...et ré-enregistrer sous le bin PostgreSQL répertoire, puis redémarrez PostgreSQL et relancez votre requête.
    • si votre requête ne fonctionne toujours pas (assurez-vous que votre base de données est encodée en UTF-8 avec Turkish_Turkey pour les deux LC_CTYPE et LC_COLLATE ) ouvrez postgres.exe dans Explorateur de dépendances 32 bits et assurez-vous qu'il indique qu'il charge MSVCR100.DLL depuis le bin de PostgreSQL répertoire.
    • si tout fonctionne bien, copiez la DLL corrigée dans le bin PostgreSQL de production répertoire et redémarrez.

MAIS N'OUBLIEZ PAS, au moment où vous déplacez les données du système Ubuntu ou du système Windows corrigé vers un système Windows non corrigé, vous aurez à nouveau le problème, et vous ne pourrez peut-être pas réimporter ces données sur Ubuntu si l'instance Windows introduit des doublons dans un citext champ ou dans un UPPER /LOWER index de fonction basé sur.