Tenho uma coluna do tipo JSONB
, onde cada linha contém um JSON com um array de objetos, ex:
[
{
"grade": "4.44/5",
"endYear": 2011,
"startYear": 2006,
"userId": "defg"
},
{
"grade": "9.133/10",
"endYear": 2010,
"startYear": 2006,
"userId": "abcd"
}
]
Estou tentando expandir essas JSONB
coleções em linhas, como:
| grade | startYear | endYear | userId |
-------------------------------------------
| 4.44/5 | 2006 | 2011 | defg |
| 9.133/10 | 2006 | 2010 | abcd |
-------------------------------------------
..usando a seguinte consulta:
WITH arr AS (SELECT jsonb_array_elements(jsonbrecords) AS jsons
FROM "table-with-jsonb"),
lines AS (
SELECT x.*
FROM arr, jsonb_to_record(jsons) AS x(
"field1" VARCHAR
)
) SELECT *
FROM lines
Estou usando o Datagrip, que pagina os resultados e a consulta termina bem nas primeiras 500 linhas.
No entanto, quando tento carregar a última página de resultados, recebo este erro:
[22023] ERROR: cannot call populate_composite on a scalar
Pesquisar esse erro no Google quase não mostra resultados úteis (o primeiro para mim), exceto o código-fonte do Postgres .
Eu não falo C, mas como o jsonb_array_elements
CTE avalia bem por conta própria, estou assumindo que o problema é que algumas linhas têm um valor escalar na jsonbrecords
coluna em vez de um JSONB
.
Para garantir que eu tivesse apenas JSONB
valores, retirei as linhas que não continham '{'
com esta consulta:
UPDATE "table-with-jsonb" SET jsonbrecords = NULL
WHERE jsonbrecords :: TEXT !~ '{'
Isso excluiu cerca de uma dúzia de linhas, mas o erro permanece.
Também tentei encontrar o problema inspecionando as JSONB
linhas brutas na tabela, mas não encontrei nada.
Estou correto em pensar que o erro significa que uma linha não tem JSONB
valor? Se sim, como posso corrigir? Se não, como posso depurar?
Não relacionado, mas: você pode simplificar sua consulta para:
Agora para a pergunta real. O erro pode ser evitado não usando
jsonb_to_record
e acessando cada chave individualmente:Você realmente não perde flexibilidade, pois também precisa especificar a lista de colunas
jsonb_to_record()
.Exemplo online: http://rextester.com/VVGJ34083
Eu descobri isso. O problema estava em uma linha específica de dados:
O
null
no final estava quebrandojsonb_to_record
. Depois de deletar, tudo funciona.Não sei se isso pode acontecer através do uso normal, mas no meu caso, acho que foi porque escrevi os dados no banco de dados a partir de um
nodejs
script, mas acidentalmente configurei a coluna de destino para typeTEXT
em vez de typeJSONB
.Eu mudei o tipo para
JSONB
com os dados já nele, então onull
deve ter se infiltrado dessa maneira.