Eu tenho uma função pl/pgsql (veja abaixo) que lista alguns campos e limpa seu conteúdo usando comandos UPDATE construídos dinamicamente.
Quando defino log_statement = 'mod'
, não consigo ver nada no log durante a execução da função com SELECT fnct_clear_temp_fields();
. Quando defino log_statement = 'all'
e executo a função, posso ver SELECT fnct_clear_temp_fields();
no log, mas não os comandos UPDATE subjacentes.
Existe uma maneira de fazer com que os comandos UPDATE apareçam no log também?
Para informações, aqui está a função:
CREATE OR REPLACE FUNCTION fnct_clear_temp_fields() RETURNS VOID AS $$
DECLARE
--Put into a cursor a view dynamically listing all user-defined fields beginning with 'temp_'
dataset_1 CURSOR FOR
SELECT
column_name,
table_name
FROM information_schema.tables
NATURAL JOIN information_schema.columns
WHERE
table_schema='public'
AND table_type='BASE TABLE'
AND column_name ~ '^temp_'
ORDER BY table_name,column_name;
--Record variable to go through each line of the view above
dataset_1_row RECORD;
BEGIN
OPEN dataset_1; --Open the cursor
FETCH dataset_1 INTO dataset_1_row; --first row of the view
WHILE FOUND LOOP
RAISE NOTICE 'Table: %, Column: %', dataset_1_row.table_name,dataset_1_row.column_name;
--Set to NULL the contents of the current 'temp_' column
EXECUTE 'UPDATE '||dataset_1_row.table_name||' SET '||dataset_1_row.column_name||'=NULL WHERE '||dataset_1_row.column_name||' IS NOT NULL';
FETCH dataset_1 INTO dataset_1_row; --next row please.
END LOOP; --while end
CLOSE dataset_1;
RETURN;
END;
$$ LANGUAGE plpgsql;
Pergunta feita
Existe uma maneira interna de registrar todas as instruções dentro das funções plpgsql:
auto-explain
Detalhes nesta questão intimamente relacionada:
Plano de consulta Postgres de uma invocação UDF escrita em pgpsql
Potencialmente gera muita saída de log. Eu só usaria para depuração, não em produção.
Se você só precisa de uma declaração registrada, siga o conselho de @dezso .
Auditoria de código
Considere esta função reescrita:
Pontos principais
Você deve limpar todos os identificadores criados no SQL dinâmico, caso contrário, ele pode falhar com nomes não padrão que requerem aspas duplas. Pior, você está aberto à injeção de SQL.
Demonstrando
quote_ident()
, já que você está usando os identificadores higienizados várias vezes. Existem mais opções comregclass
ouformat()
:Nome da tabela como parâmetro de função do PostgreSQL
Prefiro basear essas consultas no catálogo do sistema em vez das exibições dolorosamente lentas do esquema de informações. Isso é uma questão de requisitos e gosto, no entanto. Demonstrando o equivalente, que é ~ 10 vezes mais rápido (sem falar em
UPDATE
comandos). Mais:Como verificar se uma tabela existe em um determinado esquema
LIKE
é geralmente mais rápido do que a correspondência de expressão regular mais poderosa (~
). SeLIKE
pode fazer o trabalho, use-o.Algumas outras pequenas simplificações.
Resposta relacionada com mais detalhes:
Atualizar registro de um cursor onde o nome da tabela é um parâmetro
Então, minha sugestão como uma resposta real:
Se você precisar apenas nesta função, você pode fazer um
RAISE LOG '%', your_statement;
, ou no seu código real:Além disso, acho o
construir muito mais suave.
Ótimo dezso, funciona! Aqui está a versão final da minha função: