Este é um post cruzado de um problema que eu coloco no repositório GORM Github. Não tenho certeza se o problema está no Postgres 11 ou no GORM.
Veja: https://github.com/jinzhu/gorm/issues/2872
Tenho uma tabela contendo um ID como chave primária e apenas mais uma coluna (mega_herz) que é uma numérica(7,3). O campo numérico também possui uma restrição exclusiva. Quando faço a seguinte consulta de pgadmin4 ou psql recebo uma linha como resposta:
SELECT *
FROM "ttnmapper_frequencies"
WHERE ("ttnmapper_frequencies"."mega_herz" = 868.3)
ORDER BY "ttnmapper_frequencies"."id" ASC
LIMIT 1
Mas quando faço a mesma consulta via GORM ele não retorna nenhum resultado, e quando tento inserir ele falha:
(/home/jpmeijers/go/src/ttnmapper-postgres-insert-raw/main.go:342)
[2020-02-03 14:52:28] [3.07ms]
SELECT *
FROM "ttnmapper_frequencies"
WHERE ("ttnmapper_frequencies"."mega_herz" = 868.3)
ORDER BY "ttnmapper_frequencies"."id" ASC
LIMIT 1
[0 rows affected or returned ]
(/home/jpmeijers/go/src/ttnmapper-postgres-insert-raw/main.go:342)
[2020-02-03 14:52:28] [2.10ms]
INSERT INTO "ttnmapper_frequencies"
("mega_herz")
VALUES
(868.3)
RETURNING "ttnmapper_frequencies"."id"
[0 rows affected or returned ]
(/home/jpmeijers/go/src/ttnmapper-postgres-insert-raw/main.go:345)
[2020-02-03 14:52:28] pq: duplicate key value violates unique constraint "ttnmapper_frequencies_mega_herz_key"
Por que a consulta select não retornaria nenhum resultado? Devo especificar o número com três casas decimais na cláusula where?
Atualização 2020-02-09:
A saída de log do Postgres mostra o seguinte:
2020-02-09 05:43:45.679 UTC [59458] ttnmapper@ttnmapper LOG: execute <unnamed>: SELECT * FROM "ttnmapper_frequencies" WHERE ("ttnmapper_frequencies"."mega_herz" = $1) ORDER BY "ttnmapper_frequencies"."id" ASC LIMIT 1
2020-02-09 05:43:45.679 UTC [59458] ttnmapper@ttnmapper DETAIL: parameters: $1 = '868.2999877929688'
2020-02-09 05:43:45.688 UTC [59458] ttnmapper@ttnmapper LOG: statement: BEGIN READ WRITE
2020-02-09 05:43:45.689 UTC [59458] ttnmapper@ttnmapper LOG: execute <unnamed>: INSERT INTO "ttnmapper_frequencies" ("mega_herz") VALUES ($1) RETURNING "ttnmapper_frequencies"."id"
2020-02-09 05:43:45.689 UTC [59458] ttnmapper@ttnmapper DETAIL: parameters: $1 = '868.2999877929688'
2020-02-09 05:43:45.704 UTC [59458] ttnmapper@ttnmapper ERROR: duplicate key value violates unique constraint "ttnmapper_frequencies_mega_herz_key"
2020-02-09 05:43:45.704 UTC [59458] ttnmapper@ttnmapper DETAIL: Key (mega_herz)=(868.300) already exists.
A pergunta
SELECT * FROM "ttnmapper_frequencies" WHERE ("ttnmapper_frequencies"."mega_herz" = 868.2999877929688) ORDER BY "ttnmapper_frequencies"."id" ASC LIMIT 1
não retorna nenhum resultado.
Mas, no entanto, a consulta
SELECT * FROM "ttnmapper_frequencies" WHERE ("ttnmapper_frequencies"."mega_herz" = 868.3) ORDER BY "ttnmapper_frequencies"."id" ASC LIMIT 1
retorna uma única linha.
Portanto, tenho que assumir que o Postgres não arredonda automaticamente os parâmetros para consultas selecionadas. Qual seria a melhor solução para isso?
O problema foi resolvido quando alterei o tipo de dados do campo MegaHerz na definição da estrutura golang de float64 para decimal.Decimal.
No entanto, você precisa incluir uma biblioteca de terceiros para o tipo de ponto fixo decimal.Decimal.
import "github.com/shopspring/decimal"