« Compensa aprender python?Rails Rally: Apertem os cintos, o piloto sumiu »

Armadilha no LISTEN e NOTIFY (PostgreSQL)

14/03/2007

Tradução do texto de Greg Sabino Mullane em seu blog.

O título original é LISTEN AND NOTIFY gotcha. Resolvi traduzir gotcha como armadilha. Primeiro, a definição de gotcha da wikipedia:
Em programação, um gotcha é uma característica de um sistema, um programa, ou uma linguagem de programação que funciona da forma como está documentado mas é contra-intuitivo e quase sempre propícia à erro porque é fácil de usar e impredizível em seu resultado.

Existe um problema sutil com os comandos LISTEN e NOTIFY. Enquanto o nome que você atribui no comando LISTEN parece um texto comum, ele é na verdade aquilo que é chamado de "nome" no PostgreSQL, que significa que está sujeito às mesmas estranhas regras e comportamento. Eu pessoalmente adoraria ver isso mudado de uma nome de relação para uma string normal, mas até que isso ocorra, seja cuidadoso com a forma que você usa essa dupla. Aqui está um exemplo de uso comum:

$ LISTEN employee;
LISTEN

$ NOTIFY employee;
NOTIFY
Asynchronous notification "employee" received from server process with PID 8875.

No exemplo acima, nós começamos a ouvir por evemtos com o nome "employee", então disparamos um NOTIFY com o mesmo nome e obtemos uma notificação imediata sobre isso. Porém, como o nome está sujeito a todas as regras de nomes de relações, existem outros problemas:

$ LISTEN host;
LISTEN

$ LISTEN user;
ERROR:  syntax error at or near "user"
LINE 1: listen user;
               ^

$ LISTEN "user";
LISTEN

$ SELECT * FROM pg_listener;
 relname  | listenerpid | notification 
----------+-------------+--------------
 employee |        8875 |            0
 user     |        8875 |            0
 host     |        8875 |            0
(3 rows)

$ NOTIFY user;
ERROR:  syntax error at or near "user"
LINE 1: listen user;
               ^

$ NOTIFY "user";
NOTIFY
Asynchronous notification "employee" received from server process with PID 8875.

Observe que precisamos colocar a palavra "user" entre aspas, pois a palavra user não é válida como um nome de relação sem aspas. Agora note que a tabela pg_listener não nos dá nenhuma dica que isso precisa estar entre aspas. O problema real acontece quando adicionamos pontos ao nosso "nome". O Postgres trata isso como uma sequência de esquema, tabela, e coluna e remove tudo, exceto a parte final do nome:

$ LISTEN newyork.employee;
LISTEN

$ NOTIFY newyork.emplyee;
NOTIFY
Asynchronous notification "employee" received from server process with PID 8875.

$ NOTIFY losangeles.employee;
NOTIFY
Asynchronous notification "employee" received from server process with PID 8875.

$ NOTIFY elephants.makeagood.employee;
NOTIFY
Asynchronous notification "employee" received from server process with PID 8875.

$ LISTEN thisworks.forunquoted.user;
LISTEN

$ LISTEN cannot.handle.three.dots;                       
ERROR:  improper qualified name (too many dotted names): cannot.handle.three.dots                                           

Eu enviei uma correção para a documentação, mas tome cuidado, principalmente se você escreve código que gera nomes automáticos para os seus argumentos LISTEN.


Email por Walter Cruz em Bancos de Dados, PostgreSQL

Endereço de trackback para este post

Trackback URL (clique direito e copie atalho/localização do link)

2 comentários

Comentário de: Luciano Pacheco [Visitante] Email · http://lucmult.wordpress.com
Mande um link da documentação ! :)

Eu não sei o que são esses comandos e gostaria de lê-la para saber. ;)

Até mais.
14/03/2007 @ 15:09
Comentário de: Walter Cruz [Membro] Email · http://waltercruz.com
De fato, faltaram os links!Lá vão:
  1. LISTEN
  2. NOTIFY
14/03/2007 @ 15:25

Deixe seu comentário


Seu endereço de e-mail não será revelado nesse site.

Sua URL será exibida.
PobreExcelente
=> :!: :?: :idea: :) :D :p B) ;) :> :roll: :oops: :| :-/ :( >:( :'( |-| :>> ;D :P :)) 88| :. :no: XX( :lalala: :crazy: >:XX
(Quebras de linha se tornam <br />)
(Nome, e-mail & website)
(Permitir que usuários o contatem através de um formulário eletrônico (seu e-mail não será exibido.))

You can just use your OpenID to provide your name, e-mail and url.