PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como usar configurações de variáveis ​​em funções de gatilho?


Lide com todos os casos possíveis para a opção personalizada devidamente:

  1. opção ainda não definida

    Todas as referências a ele geram uma exceção , incluindo current_setting() a menos que seja chamado com o segundo parâmetro missing_ok . O manual:

  2. opção definida como um literal inteiro válido

  3. opção definida como um literal inteiro inválido

  4. opção reset (que se reduz a um caso especial de 3. )

    Por exemplo, se você definir uma opção personalizada com SET LOCAL ou set_config('myvars.user_id3', '55', true) , o valor da opção é zerado ao final da transação. Ele ainda existe , pode ser referenciado, mas retorna uma string vazia agora ('' ) - que não pode ser convertido em integer .

Erros óbvios em sua demonstração à parte, você precisa se preparar para todos os 4 casos. Então:
CREATE OR REPLACE FUNCTION add_transition1()
  RETURNS trigger AS
$func$
DECLARE
   _user_id text := current_setting('myvars.user_id', true);  -- see 1.
BEGIN
   IF _user_id ~ '^\d+$' THEN  -- one or more digits?

      INSERT INTO transitions1 (user_id, house_id)
      VALUES (_user_id::int, NEW.id);  -- valid int, cast is safe

   ELSE

      INSERT INTO transitions1 (user_id, house_id)
      VALUES (NULL, NEW.id);           -- use NULL instead

      RAISE WARNING 'Invalid user_id % for house_id % was reset to NULL!'
                  , quote_literal(_user_id), NEW.id;  -- optional
   END IF;

   RETURN NULL;  -- OK for AFTER trigger
END
$func$  LANGUAGE plpgsql;

db<>fiddle aqui

Notas:

  • Evite nomes de variáveis ​​que correspondam aos nomes das colunas. Muito propenso a erros. Uma convenção de nomenclatura popular é preceder os nomes das variáveis ​​com um sublinhado:_user_id .

  • Atribua no momento da declaração para salvar uma atribuição. Observe o tipo de dados text . Faremos a conversão mais tarde, depois de classificar a entrada inválida.

  • Evite levantar/capturar uma exceção se possível . O manual:

  • Teste para strings inteiras válidas. Essa expressão regular simples permite apenas dígitos (sem sinal inicial, sem espaço em branco):_user_id ~ '^\d+$' . Eu redefino para NULL para qualquer entrada inválida. Adapte-se às suas necessidades.

  • Adicionei um WARNING opcional para sua conveniência de depuração.

  • Casos 3. e 4. só surgem porque as opções personalizadas são literais de string (tipo text ), os tipos de dados válidos não podem ser aplicados automaticamente.

Relacionado:

Deixando tudo isso de lado, pode haver soluções mais elegantes para o que você está tentando fazer sem opções personalizadas, dependendo de suas necessidades exatas. Talvez isto: