Eu faria assim:
CREATE OR REPLACE FUNCTION list(
_category varchar(100)
, _limit int
, _offset int
, _order_by varchar(100)
, _order_asc_desc text = 'ASC') -- last param with default value
RETURNS TABLE(id int, name varchar, clientname varchar, totalcount bigint)
LANGUAGE plpgsql AS
$func$
DECLARE
_empty text := '';
BEGIN
-- Assert valid _order_asc_desc
IF upper(_order_asc_desc) IN ('ASC', 'DESC', 'ASCENDING', 'DESCENDING') THEN
-- proceed
ELSE
RAISE EXCEPTION 'Unexpected value for parameter _order_asc_desc.
Allowed: ASC, DESC, ASCENDING, DESCENDING. Default: ASC';
END IF;
RETURN QUERY EXECUTE format(
'SELECT id, name, clientname, count(*) OVER() AS full_count
FROM design_list
WHERE ($1 = $2 OR category ILIKE $1)
ORDER BY %I %s
LIMIT %s
OFFSET %s'
, _order_by, _order_asc_desc, _limit, _offset)
USING _category, _empty;
END
$func$;
Recurso principal:use o formato
format()
para concatenar com segurança e elegância sua string de consulta. Relacionado:- INSERT com nome da tabela dinâmica na função de gatilho
- Especificador de formato para variáveis inteiras em format() para EXECUTE?
ASC / DESC (ou ASCENDING / DESCENDING ) são palavras-chave fixas. Adicionei uma verificação manual (IF ... ) e depois concatenar com um simples %s . Isso é um maneira de afirmar a entrada legal. Por conveniência, adicionei uma mensagem de erro para entrada inesperada e um parâmetro padrão, para que a função padrão seja ASC se o último parâmetro for omitido na chamada. Relacionado:- Argumento opcional no PL função /pgSQL
- ERRO:os parâmetros de entrada após um com um valor padrão também devem ter padrões no Postgres
Abordando Pavel é válido comentar , eu concateno
_limit e _offset diretamente, então a consulta já está planejada com esses parâmetros. _limit e _offset são integer parâmetros, para que possamos usar %s simples sem o perigo de injeção de SQL. Você pode querer afirmar valores razoáveis (excluir valores negativos e valores muito altos) antes de concatenar... Outras notas:
-
Use uma convenção de nomenclatura consistente. Prefixei todos os parâmetros e variáveis com um sublinhado_, não apenas algumas .
-
Não usando qualificação de tabela dentro deEXECUTE, já que há apenas uma única tabela envolvida e oEXECUTEtem seu escopo separado.
-
Renomeei alguns parâmetros para esclarecer._order_byem vez de_sort_by;_order_asc_descem vez de_order.