Vamos considerar o seguinte exemplo (do início de um script psql):
\c :db_to_run_on
TRUNCATE the_most_important_table;
-- tried to avoid similarities to anything that exists out there
Agora, se for executado pelo comando
psql [connection details] -v db_to_run_on=\'dev_database\'
então ele simplesmente roda e o usuário fica feliz. Mas e se ele decidir especificar -v db_to_run_on=production_database
? (Vamos supor que isso possa acontecer, assim como as pessoas executam rm -rf / # don't try this at home!!!
ocasionalmente.) Espero que haja um novo backup dessa tabela ...
Então surge a pergunta: como verificar as variáveis passadas para um script e interromper o processamento posterior com base em seu valor?
Existe uma opção em
psql
que para de executar comandos em caso de erro, éON_ERROR_STOP
. Se pudéssemos gerar um erro de alguma forma, isso faria o que queremos.O problema é que temos que testar a variável e produzir um erro de alguma forma. Como não se pode usar estruturas de controle em
psql
(porque não existem) *, minha única ideia era usar SQL para teste. Bem, produzir um erro condicionalmente é algo em quepl/pgsql
é muito bom, então escrevi uma função que geraria um erro. Agora posso chamar essa função a partir de umaCASE
estrutura simples. Um exemplo simples:*: Você pode usar qualquer comando shell depois
\!
e condicionais do shell, mas como\!
abre um novo shell, executar qualquer coisa lá não tem nenhum efeito para o script psql atual.PostgreSQL 10
PostgreSQL 10 traz condicionais para psql. Isso não é mais um problema.
Eu acho que você também poderia usar
DO
..Uma versão mais concisa da resposta de dezso:
Você pode então chamar isso como:
O que descobri que funciona muito bem para mim é usar uma linguagem de script para gerar um arquivo SQL que eu canalizo para o psql, algo assim:
Então, eu chamo isso de um script de driver:
Meu script de driver geralmente é um arquivo Rake, mas você entendeu.
Para sair
psql
de um script, você pode simplesmente usar o\quit
comando meta ou gerar um erro enquanto estiverON_ERROR_STOP
ativo. As diferenças são:\quit
fará uma saída limpa com status0
ou encerrará apenas o script em execução se estiver usando scripts aninhados ou\i
ON_ERROR_STOP
ser ativado sairá com status3
e se propagará para o script de nível superior no caso de scripts aninhados.Uma alternativa mais fácil para gerar um erro e executar
RAISE
a partir de uma função ou bloco de código anônimo é apenas um comando SQL inválido como:INVALID;
.Para exibir a mensagem de erro, você pode usar o
\warn
meta-comando que a envia parastderr
(começando na página 13) ou simplesmente\echo
parastdout
.Combinado com
\if
(começando na página 10), minha tentativa para o problema do OP seria:Infelizmente, não conheço uma maneira de suprimir a saída de 'erro de sintaxe' gerada pelo comando inválido. Portanto, dependendo do seu caso de uso, combinar
\warn 'You better not do this!'
e\quit
ou\set ON_ERROR_STOP on
eDO $$BEGIN RAISE 'You better not do this!'; END$$ LANGUAGE plpgsql;
pode ser mais adequado.Em um script de consulta (que eu acho que é de alguma forma diferente de um script psql),
\if
foi considerado um erro de sintaxe, mas um código como este funcionou para mim:Testado no PostgreSQL 13.2.
DO
O bloco externo não é necessário dentro de um procedimento armazenado.