O limite de comprimento imposto por
varchar(N)
tipos e calculados pelo length
a função está em caracteres, não em bytes. Então 'abcdef'::char(3)
está truncado para 'abc'
mas 'a€cdef'::char(3)
é truncado para 'a€c'
, mesmo no contexto de um banco de dados codificado como UTF-8, onde 'a€c'
é codificado usando 5 bytes. Se restaurar um arquivo de despejo reclamou que
'Mér'
não entraria em um varchar(3)
coluna, que sugere que você estava restaurando um arquivo de despejo codificado em UTF-8 em um banco de dados SQL_ASCII. Por exemplo, eu fiz isso em um banco de dados UTF-8:
create schema so4249745;
create table so4249745.t(key varchar(3) primary key);
insert into so4249745.t values('Mér');
E então despejei isso e tentei carregá-lo em um banco de dados SQL_ASCII:
pg_dump -f dump.sql --schema=so4249745 --table=t
createdb -E SQL_ASCII -T template0 enctest
psql -f dump.sql enctest
E com certeza:
psql:dump.sql:34: ERROR: value too long for type character varying(3)
CONTEXT: COPY t, line 1, column key: "Mér"
Por outro lado, se eu criar o banco de dados enctest como codificação LATIN1 ou UTF8, ele carrega bem.
Esse problema ocorre devido a uma combinação de despejar um banco de dados com uma codificação de caracteres de vários bytes e tentar restaurá-lo em um banco de dados SQL_ASCII. Usar SQL_ASCII basicamente desabilita a transcodificação de dados do cliente para dados do servidor e assume um byte por caractere, deixando para os clientes a responsabilidade de usar o mapa de caracteres correto. Como o arquivo de despejo contém a string armazenada como UTF-8, ou seja, quatro bytes, um banco de dados SQL_ASCII vê isso como quatro caracteres e, portanto, considera que viola a restrição. E imprime o valor, que meu terminal remonta como três caracteres.