O Hologres V3.2 e versões posteriores suportam expressões LAMBDA e cinco funções de array de ordem superior: HG_ARRAY_MAP, HG_ARRAY_FILL, HG_ARRAY_FILTER, HG_ARRAY_SORT e HG_ARRAY_FIRST_INDEX. Todas as cinco funções aceitam uma expressão LAMBDA como primeiro argumento e a aplicam elemento a elemento em um ou mais arrays de entrada.
Expressões LAMBDA
Uma expressão LAMBDA define uma função anônima diretamente no código, sem nome ou declarações explícitas de tipo.
Sintaxe
LAMBDA [ (lambda_arg1, ..., lambda_argn) => expr ]
Parâmetros
|
Componente |
Descrição |
|
|
Palavra-chave que declara uma expressão LAMBDA. |
|
|
Parâmetros de entrada. É possível definir qualquer quantidade de parâmetros sem especificar tipos de dados. Coloque múltiplos parâmetros entre parênteses |
|
|
Operador que separa a lista de parâmetros do corpo da expressão. |
|
|
Corpo da expressão. Apenas expressões escalares são suportadas. O corpo pode referenciar parâmetros de entrada e nomes de colunas de tabela. Expressões LAMBDA aninhadas também são permitidas — uma função de array de ordem superior contendo uma LAMBDA pode aparecer dentro de uma expressão escalar. |
Para obter mais informações sobre expressões PostgreSQL, consulte Expressões.
Limitações
O corpo da expressão não suporta:
Funções de agregação (por exemplo,
LAMBDA[x => max(x)])Funções de janela
Subconsultas (por exemplo,
LAMBDA[x => x + (SELECT 1)])
Exemplo
LAMBDA [ (x1, x2, x3) => x2 - x1 * x3 + array_min(arr_col) ]
Funções de array de ordem superior
Todas as cinco funções compartilham o mesmo padrão de assinatura:
FUNCTION_NAME(LAMBDA[func(x1 [, ..., xN])], source_arr1 [, ..., source_arrN]);
Requisitos comuns
Pelo menos um argumento deve ser não constante.
Ao especificar múltiplos arrays, todos devem ter o mesmo comprimento.
Todas as funções retornam NULL se qualquer array de entrada for NULL.
HG_ARRAY_MAP
Aplica uma expressão LAMBDA aos elementos correspondentes de um ou mais arrays e retorna um novo array com os resultados.
Sintaxe
HG_ARRAY_MAP(LAMBDA[func(x1 [, ..., xN])], source_arr1 [, ..., source_arrN]);
Parâmetros
|
Parâmetro |
Descrição |
|
|
Expressão LAMBDA a ser aplicada a cada conjunto de elementos correspondentes. |
|
|
Array de entrada. Quando múltiplos arrays são especificados, eles devem ter o mesmo comprimento. |
Valor de retorno
Retorna um array cujo tipo de elemento corresponde ao tipo de retorno da expressão LAMBDA. O comprimento é igual ao do primeiro array de entrada. Retorna NULL se qualquer array de entrada for NULL.
Exemplos
Os exemplos a seguir utilizam esta tabela de amostra:
DROP TABLE IF EXISTS tbl1;
CREATE TABLE tbl1(id INT, arr_col1 INT[], arr_col2 INT[], col3 INT, col4 INT);
INSERT INTO tbl1 VALUES(1, ARRAY[1,2,3], ARRAY[11,12,13],1,2);
INSERT INTO tbl1 VALUES(2, ARRAY[21,22,23], ARRAY[31,32,33],10,20);
Adicionar um valor de coluna a cada elemento do array (captura de coluna)
O corpo de uma LAMBDA pode referenciar colunas da mesma linha, não apenas elementos do array. Este exemplo adiciona col3 a cada elemento de arr_col1:
SELECT
id,
HG_ARRAY_MAP (LAMBDA[x => x + col3], arr_col1)
FROM
tbl1
ORDER BY
id;
Resultado:
id | hg_array_map
----+--------------
1 | {2,3,4}
2 | {31,32,33}
(2 rows)
Somar elementos de dois arrays e incluir uma agregação de subarray
Este exemplo soma os elementos correspondentes de arr_col1 e do array constante ARRAY[5,6,7], e depois adiciona o valor mínimo de arr_col2:
SELECT
id,
HG_ARRAY_MAP (LAMBDA[(x, y) => y + x + array_min (arr_col2)], arr_col1, ARRAY[5,6,7])
FROM
tbl1
ORDER BY
id;
Resultado:
id | hg_array_map
----+--------------
1 | {17,19,21}
2 | {57,59,61}
(2 rows)
Usar uma expressão LAMBDA aninhada
Neste exemplo, HG_ARRAY_MAP é aninhado dentro de outro HG_ARRAY_MAP. Primeiro, col3 é adicionado a cada elemento de arr_col2, obtém-se o mínimo desse array intermediário e, em seguida, o resultado é somado a cada elemento de arr_col1:
SELECT
id,
HG_ARRAY_MAP (LAMBDA[x => x + array_min (HG_ARRAY_MAP (LAMBDA[a => a + col3], arr_col2))], arr_col1)
FROM
tbl1
ORDER BY
id;
Resultado:
id | hg_array_map
----+--------------
1 | {13,14,15}
2 | {62,63,64}
(2 rows)
HG_ARRAY_FILL
Percorre os arrays de entrada da esquerda para a direita. Em cada posição, a expressão LAMBDA é avaliada: se retornar TRUE, o elemento correspondente do primeiro array de entrada torna-se o valor de preenchimento atual, propagando-se para cada posição subsequente até o próximo resultado TRUE. Caso a LAMBDA retorne FALSE na primeira posição, o primeiro elemento permanece inalterado.
Sintaxe
HG_ARRAY_FILL(LAMBDA[func(x1 [, ..., xN])], source_arr1 [, ..., source_arrN]);
Parâmetros
|
Parâmetro |
Descrição |
|
|
Expressão LAMBDA que retorna um valor booleano para cada posição. |
|
|
Array de entrada. Quando múltiplos arrays são especificados, eles devem ter o mesmo comprimento. |
Valor de retorno
Retorna um array com o mesmo tipo de dados e comprimento do primeiro array de entrada. Retorna NULL se qualquer array de entrada for NULL.
Exemplos
Os exemplos a seguir utilizam esta tabela de amostra:
DROP TABLE IF EXISTS tbl2;
CREATE TABLE tbl2(id INT, arr_col1 INT[], arr_col2 INT[], col3 INT, col4 INT);
INSERT INTO tbl2 VALUES(1, ARRAY[1,2,3,4,5,6,7,8,9],ARRAY[1,0,0,1,0,0,0,1,0],1,2);
INSERT INTO tbl2 VALUES(2, ARRAY[10,12,13,14,15,16,17,18,19],ARRAY[1,0,0,1,0,0,0,1,0],1,2);
Preenchimento progressivo quando o elemento de arr_col2 é maior que 0
As posições onde arr_col2 > 0 resultam em TRUE fazem com que o elemento correspondente de arr_col1 se torne o valor de preenchimento, propagando-se para cada posição subsequente até o próximo TRUE:
SELECT
id,
HG_ARRAY_FILL (LAMBDA[(x, y) => y > 0], arr_col1, arr_col2)
FROM
tbl2
ORDER BY
id;
Resultado:
id | hg_array_fill
----+------------------------------
1 | {1,1,1,4,4,4,4,8,8}
2 | {10,10,10,14,14,14,14,18,18}
(2 rows)
Preenchimento progressivo quando o elemento de arr_col2 é menor ou igual a 0
A condição é invertida: posições onde arr_col2 <= 0 resultam em TRUE. Como o primeiro elemento de arr_col2 é 1 (não <= 0), a LAMBDA retorna FALSE na posição 1 e o primeiro elemento permanece inalterado:
SELECT
id,
HG_ARRAY_FILL (LAMBDA[(x, y) => y <= 0], arr_col1, arr_col2)
FROM
tbl2
ORDER BY
id;
Resultado:
id | hg_array_fill
----+------------------------------
1 | {1,2,3,3,5,6,7,7,9}
2 | {10,12,13,13,15,16,17,17,19}
(2 rows)
HG_ARRAY_FILTER
Aplica uma expressão LAMBDA aos elementos correspondentes dos arrays de entrada para produzir um array booleano e mantém apenas os elementos do primeiro array onde o valor booleano é TRUE.
Sintaxe
HG_ARRAY_FILTER(LAMBDA[func(x1 [, ..., xN])], source_arr1 [, ..., source_arrN]);
Parâmetros
|
Parâmetro |
Descrição |
|
|
Expressão LAMBDA que retorna um valor booleano para cada elemento. |
|
|
Array de entrada. Quando múltiplos arrays são especificados, eles devem ter o mesmo comprimento. |
Valor de retorno
Retorna um array com o mesmo tipo de dados do primeiro array de entrada, contendo apenas os elementos para os quais a LAMBDA retornou TRUE. Retorna NULL se qualquer array de entrada for NULL.
Exemplos
Os exemplos a seguir utilizam esta tabela de amostra:
DROP TABLE IF EXISTS tbl3;
CREATE TABLE tbl3(id INT, arr_col1 INT[], arr_col2 INT[], col3 INT, col4 INT);
INSERT INTO tbl3 VALUES(1, ARRAY[0,2,3,4,5,6,7,0,9], ARRAY[1,0,0,1,0,0,0,1,18],1,2);
INSERT INTO tbl3 VALUES(2, NULL, ARRAY[31,32,33,34,35,36,37,38,39],10,20);
INSERT INTO tbl3 VALUES(3, ARRAY[0,2,3,4,5,6,7,0,9], ARRAY[11,12,13,14,15,16,17,18,19],NULL,2);
Manter elementos onde o elemento correspondente de arr_col2 é maior que 0
SELECT
id,
HG_ARRAY_FILTER (LAMBDA[(x, y) => y > 0], arr_col1, arr_col2)
FROM
tbl3
ORDER BY
id;
Resultado:
id | hg_array_filter
----+---------------------
1 | {0,4,0,9}
2 |
3 | {0,2,3,4,5,6,7,0,9}
(3 rows)
Para id=2, o resultado é NULL porque arr_col1 é NULL. No caso de id=3, todos os elementos de arr_col2 são maiores que 0, portanto todos os elementos de arr_col1 são mantidos.
Filtrar usando uma condição composta com referências de coluna
Este exemplo mantém elementos onde qualquer uma das seguintes condições é verdadeira: o elemento em arr_col1 é 0, col3 é NULL ou a soma de arr_col1[i] + arr_col2[i] + col3 + col4 excede 20. A consulta utiliza tbl1 dos exemplos de HG_ARRAY_MAP:
SELECT
id,
HG_ARRAY_FILTER (
LAMBDA[(x, y) =>
(x = 0)
OR (col3 IS NULL)
OR (x + y + col3 + col4 > 20)]
, arr_col1, arr_col2)
FROM
tbl1
ORDER BY
id;
Resultado:
id | hg_array_filter
----+---------------------
1 | {}
2 | {21,22,23}
(2 rows)
HG_ARRAY_SORT
Aplica uma expressão LAMBDA aos arrays de entrada para derivar um array de chaves de ordenação e retorna o primeiro array de entrada classificado em ordem ascendente dessas chaves.
Sintaxe
HG_ARRAY_SORT(LAMBDA[func(x1 [, ..., xN])], source_arr1 [, ..., source_arrN]);
Parâmetros
|
Parâmetro |
Descrição |
|
|
Expressão LAMBDA que produz a chave de ordenação para cada elemento. |
|
|
Array de entrada. Quando múltiplos arrays são especificados, eles devem ter o mesmo comprimento. |
Valor de retorno
Retorna um array com o mesmo tipo de dados e comprimento do primeiro array de entrada, ordenado pelas chaves de ordenação calculadas em ordem ascendente. Retorna NULL se qualquer array de entrada for NULL.
Exemplos
Ordenar um array constante pelos valores de outra coluna
DROP TABLE IF EXISTS tbl4;
CREATE TABLE tbl4(id INT, arr_col1 INT[]);
INSERT INTO tbl4 VALUES(1, ARRAY[3,1,2]);
INSERT INTO tbl4 VALUES(2, ARRAY[2,3,1]);
INSERT INTO tbl4 VALUES(3, ARRAY[1,2,3]);
INSERT INTO tbl4 VALUES(4, NULL);
SELECT
id,
HG_ARRAY_SORT (LAMBDA[(x,y) => y], ARRAY[4,5,6], arr_col1)
FROM
tbl4
ORDER BY
id;
O array constante ARRAY[4,5,6] é reordenado conforme a ordem ascendente dos valores de arr_col1. Resultado:
id | hg_array_sort
----+---------------
1 | {5,6,4}
2 | {6,4,5}
3 | {4,5,6}
4 |
(4 rows)
Ordenar um array de texto por um array de chaves de ordenação inteiro, com tratamento de NULL
DROP TABLE IF EXISTS tbl5;
CREATE TABLE tbl5(id INT, arr_col1 TEXT[], arr_col2 INT[]);
INSERT INTO tbl5 VALUES(1, ARRAY['1','2','3','4','5'], ARRAY[1,2,3,4,5]);
INSERT INTO tbl5 VALUES(2, ARRAY['1','2','3','4','5'], NULL);
INSERT INTO tbl5 VALUES(3, ARRAY['1','2','3','4','5'], ARRAY[21, 22, 20, 24, 25]);
INSERT INTO tbl5 VALUES(4, ARRAY['1','2','3','4','5'], ARRAY[21, 24, 22, 25, 23]);
INSERT INTO tbl5 VALUES(5, ARRAY['1','2','3','4','5'], ARRAY[21, 22, NULL, 24, 25]);
SELECT
id,
HG_ARRAY_SORT (LAMBDA[(x, y) => y], arr_col1, arr_col2)
FROM
tbl5
ORDER BY
id;
Resultado:
id | hg_array_sort
----+---------------
1 | {1,2,3,4,5}
2 |
3 | {3,1,2,4,5}
4 | {1,3,5,2,4}
5 | {3,1,2,4,5}
(5 rows)
Para id=2, como arr_col2 é NULL, a função retorna NULL.
HG_ARRAY_FIRST_INDEX
Aplica uma expressão LAMBDA aos arrays de entrada para produzir um array booleano e retorna o índice baseado em 1 do primeiro elemento TRUE. Retorna 0 se nenhum elemento for TRUE.
Sintaxe
HG_ARRAY_FIRST_INDEX(LAMBDA[func(x1 [, ..., xN])], source_arr1 [, ..., source_arrN]);
Parâmetros
|
Parâmetro |
Descrição |
|
|
Expressão LAMBDA que retorna um valor booleano para cada elemento. |
|
|
Array de entrada. Quando múltiplos arrays são especificados, eles devem ter o mesmo comprimento. |
Valor de retorno
Retorna o índice baseado em 1 do primeiro elemento para o qual a LAMBDA retorna TRUE. Retorna 0 se nenhum elemento for TRUE. Retorna NULL se qualquer array de entrada for NULL.
Exemplo
Encontre o índice do primeiro elemento em arr_col1 que seja maior ou igual a 3:
DROP TABLE IF EXISTS tbl6;
CREATE TABLE tbl6(id INT, arr_col1 INT[]);
INSERT INTO tbl6 VALUES(1, ARRAY[1,2,3,4,5]);
INSERT INTO tbl6 VALUES(2, NULL);
SELECT
id,
HG_ARRAY_FIRST_INDEX (LAMBDA[x => x >= 3], arr_col1)
FROM
tbl6
ORDER BY
id;
Resultado:
id | hg_array_first_index
----+----------------------
1 | 3
2 |
(2 rows)
Para id=1, o primeiro elemento >= 3 está no índice 3 (valor 3). Para id=2, como arr_col1 é NULL, a função retorna NULL.