Eu tenho um banco de dados Postgresql na codificação LATIN9.
Recentemente, migrei meus aplicativos da web (PHP) de iso_8859_15 (latin9) para UTF8.
Então, agora, os clientes podem especificar caracteres UTF-8 em formulários da web, como formulário de comentário ou formulário de contato.
Eu abro conexões PG na codificação UTF-8 do PHP (função PHP pg_set_client_encoding('UTF8') ou assim...)
Isso funciona bem para caracteres padrão como "éàù"... PG é capaz de convertê-los de UTF-8 para LATIN9 (a codificação do banco de dados). Mas se alguém inserir algum caractere exótico como caracteres japoneses "日本語" o PostgreSQL lançará um erro como este:
ERROR: character with byte sequence 0xe6 0x97 0xa5 in encoding "UTF8" has no equivalent in encoding "LATIN9"
Sei que devo migrar meu banco de dados para utf8 para resolver esse problema, mas por alguns motivos, não posso fazer isso no momento.
No meu caso, prefiro que o PostgreSQL salve minha string removendo caracteres que não pode converter ou, por exemplo, substituindo-os por algum símbolo como "?" ao invés de lançar um erro...
A única maneira que encontrei para fazer as coisas funcionarem assim é abrir minhas conexões no LATIN9 e usar a função PHP utf8_decode() que funciona assim (substituindo caracteres desconhecidos pelo símbolo "?")
É possível fazer isso de uma maneira melhor? Talvez um parâmetro PG (mas não vejo tal parâmetro no postgresql.conf)
Ou alguém tem outra ideia de como lidar com isso?
Obrigado,
PostgreSQL não suporta isso. É solicitado periodicamente, mas ninguém que solicita faz o trabalho de realmente implementá-lo no sistema e convencer a equipe de desenvolvimento de que é uma opção adequada a ser oferecida.
Você precisará fazer sua manipulação de texto do lado do cliente. No PHP, antes de enviar o texto para o PostgreSQL, você precisará filtrar os caracteres que não correspondem à codificação do banco de dados. Como fazer isso é totalmente específico do PHP (comece com o suporte a iconv, provavelmente). Você descreveu uma maneira de fazer isso, usando
utf8_decode
, já.Usar
utf8_decode
é realmente incorreto, porque a função (de acordo com os documentos) realmente assume que a entrada é ISO-8859-1, ou seja, Latin-1. Você está usando latin-9, ou seja, ISO-8859-15. Então, ele irá mutilar alguns de seus caracteres de entrada, em particular o símbolo do Euro. Veja as mudanças de ISO-8859-1 . Em vez disso, use aiconv
função. Veja os comentários surpreendentemente úteis nautf8_decode
documentação da função.Se no processo de filtragem do texto você converter para LATIN9 dentro do PHP, lembre-se que você deve configurar o seu
client_encoding
para latin9, pois é essa a codificação do texto que você estará enviando para o PostgreSQL. Isso significa que os resultados também estarão em latin-9, então você deve converter todos os resultados do PostgreSQL de latin-9 de volta para o utf-8 nativo do PHP.Se você usar
utf8_encode
para converter sua saída latin-9 do PostgreSQL para consumo em PHP, você terá o mesmo problema com latin-1 vs latin-9 que emutf8_decode
.Por esse motivo, se possível, tente usar um filtro que substitua caracteres não suportados em latin-9 sem realmente converter a string para latin-9. Isso vai lhe poupar um monte de problemas se você puder continuar
client_encoding
definidoutf-8
e apenas mutilar suas strings em vez de convertê-las.Dito isso, recomendo fortemente atualizar o banco de dados para utf-8. A única razão para mantê-lo em latin-9 seria se você tiver outros aplicativos clientes que não conseguem lidar com caracteres fora do intervalo latin-9 (ou seja, eles dependem de um latin-9
client_encoding
)