PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

A função superior do Postgres no caractere turco não retorna o resultado esperado


Seu problema é 100% Windows. (Ou melhor, o Microsoft Visual Studio, com o qual o PostgreSQL foi construído, para ser mais preciso.)

Para o registro, SQL UPPER acaba chamando o Windows LCMapStringW (via towupper via str_toupper ) com quase todos os parâmetros corretos (localidade 1055 turco para um UTF-8 -codificado, Turkish_Turkey base de dados),

mas

o Visual Studio Runtime (towupper ) não define o LCMAP_LINGUISTIC_CASING bit em LCMapStringW 's dwMapFlags . (Posso confirmar que a configuração resolve o problema.) Isso não é considerado um bug na Microsoft; é por design e provavelmente nunca será "consertado" (oh as alegrias do legado.)

Você tem três saídas para isso:
  • implementar a solução wrapper do @Sorrow (ou escrever sua própria substituição de função nativa (DLL).)
  • execute sua instância do PostgreSQL em, por exemplo, Ubuntu que exibe o comportamento correto para localidades turcas (@Sorrow confirmou que funciona para ele); esta é provavelmente a saída mais simples e limpa.
  • incorpore um MSVCR100.DLL de 32 bits corrigido no seu bin do PostgreSQL diretório (mas embora UPPER e LOWER funcionaria, outras coisas como agrupamento podem continuar a falhar -- novamente, no nível do Windows. YMMV.)

Para completar (e diversão nostálgica) SOMENTE , aqui está o procedimento para corrigir um sistema Windows (mas lembre-se, a menos que você esteja gerenciando esta instância do PostgreSQL do início ao fim, você pode causar muito sofrimento ao(s) seu(s) sucessor(es); sempre que implantar um novo sistema de teste ou backup de você ou seu(s) sucessor(es) teriam que se lembrar de aplicar o patch novamente -- e se digamos que você um dia atualize para o PostgreSQL 10, que diz usar MSVCR120.DLL em vez de MSVCR100.DLL , então você terá que tentar a sorte corrigindo a nova DLL também.) Em um sistema de teste
  • use HxD para abrir C:\WINDOWS\SYSTEM32\MSVCR100.DLL
  • salve a DLL imediatamente com o mesmo nome em seu PostgreSQL bin diretório (não tente copiar o arquivo usando o Explorer ou a linha de comando, eles podem copiar a versão de 64 bits)
  • com o arquivo ainda aberto em HxD, vá para Pesquisar> Substituir , escolha Tipo de dados:valores hexadecimais , então
    • procurar por... 4E 14 33 DB 3B CB 0F 84 41 12 00 00 B8 00 01 00 00
    • substituir por... 4E 14 33 DB 3B CB 0F 84 41 12 00 00 B8 00 01 00 01
    • ...e mais uma vez...
    • procurar por... FC 51 6A 01 8D 4D 08 51 68 00 02 00 00 50 E8 E2
    • substituir por... FC 51 6A 01 8D 4D 08 51 68 00 02 00 01 50 E8 E2
  • ... e salve novamente no bin do PostgreSQL diretório, reinicie o PostgreSQL e execute novamente sua consulta.
    • se sua consulta ainda não funcionar (certifique-se de que seu banco de dados esteja codificado em UTF-8 com Turkish_Turkey para ambos LC_CTYPE e LC_COLLATE ) abra postgres.exe em 32-bit Dependency Walker e certifique-se de que indica que carrega MSVCR100.DLL do PostgreSQL bin diretório.
    • se todas as funções copiem bem a DLL corrigida para o PostgreSQL de produção bin diretório e reinicie.

MAS LEMBRE-SE, no momento em que você mover os dados do sistema Ubuntu ou do sistema Windows corrigido para um sistema Windows não corrigido, você terá o problema novamente e poderá não conseguir importar esses dados de volta no Ubuntu se a instância do Windows introduzir duplicatas em um citext campo ou em um UPPER /LOWER índice de função baseado.