[2C] Trigger Oracle/Protheus não captura delete lógico (D_E_L_E_T_) quando entidade possui SQL condicional

Description

Contexto

Identificamos um possível problema no 2C em ambiente Oracle + Protheus, quando uma entidade sincronizada por trigger possui SQL condicional configurado.

Cenário do cliente

  • 2C versão 3.7.4

  • Banco Oracle 19.30

  • Conexão marcada como Protheus

  • ignoreTriggers=false

  • Entidade impactada: PHL000

  • Entidade com SQL condicional: SUBSTR(PHL_CMPDIF, 4,4) || SUBSTR(PHL_CMPDIF, 1,2) >= '202307'

Problema observado

No Protheus, a exclusão lógica ocorre por UPDATE no campo D_E_L_E_T_, normalmente alterando o valor para *. Nesse caso, a trigger de UPDATE deveria inserir um registro na CAROL_3C_QUEUE com op_type = 1 para que a exclusão seja enviada à Carol.

Porém, a trigger Oracle/Protheus gerada para UPDATE contém uma cláusula WHEN restringindo a execução a registros ativos:

WHEN ((TRIM(n.D_E_L_E_T_) IS NULL) AND (...condicional da entidade...))

Dentro da própria trigger existe a lógica:

CASE WHEN TRIM(:n.D_E_L_E_T_) IS NULL THEN 0 ELSE 1 END

A intenção dessa lógica é mapear:

  • D_E_L_E_T_ vazio/nulo => op_type = 0

  • D_E_L_E_T_ preenchido => op_type = 1

Mas, como o WHEN exige TRIM(n.D_E_L_E_T_) IS NULL, quando o D_E_L_E_T_ passa para *, a trigger não executa. Assim, o caminho ELSE 1 fica inalcançável nesse cenário e a exclusão lógica não entra na fila.

Diferença observada em relação ao SQL Server

No SQL Server, o template da trigger de UPDATE Protheus calcula o op_type com base em D_E_L_E_T_, mas o gerador não injeta automaticamente uma condição equivalente a n.D_E_L_E_T_ IS NULL no filtro da trigger de update. Portanto, o problema específico do Oracle parece estar associado ao WHEN gerado para Oracle/Protheus com SQL condicional.

Evidências

  • Heartbeat do cliente confirma:

    • versão 2C: 3.7.4

    • banco: Oracle 19.30

    • conexão type=ORACLE

    • isProtheus=true

    • useProtheusCompanyCode=true

    • ignoreTriggers=false

    • entidade PHL000 com conditionalSql configurado

    • syncByFullLoad=false

    • syncByTimestamp=false

  • Healthcheck mostra as triggers insert/update/delete da PHL000 como OK, mas isso valida apenas existência/status da trigger, não a regra lógica do WHEN.

  • A fila pendente do heartbeat não mostra PHL000, compatível com o cenário em que o update de delete lógico não gerou entrada na CAROL_3C_QUEUE.

  • DDL da trigger de UPDATE enviada pelo cliente mostra:

    • WHEN ((TRIM(n.D_E_L_E_T_) IS NULL) AND (...))

    • CASE WHEN TRIM(:n.D_E_L_E_T_) IS NULL THEN 0 ELSE 1 END

Análise técnica

A trigger de DELETE não cobre esse cenário, pois ela dispara apenas para DELETE físico no banco. No Protheus, o delete comum é lógico, via UPDATE em D_E_L_E_T_. Portanto, a correção deve considerar a trigger de UPDATE Oracle/Protheus.

Sugestão de investigação

Avaliar ajuste na geração da condição da trigger de UPDATE Oracle/Protheus para permitir a transição de registro ativo para deletado lógico, por exemplo considerando o estado anterior e novo de D_E_L_E_T_:

  • registro novo ainda ativo: manter comportamento de update normal;

  • D_E_L_E_T_ mudou de vazio/nulo para preenchido: permitir execução e gravar op_type = 1;

  • preservar o filtro condicional da entidade para registros dentro do escopo.

Resultado esperado

Quando um registro Protheus em Oracle for marcado com D_E_L_E_T_ = '*', a trigger de UPDATE deve inserir entrada na CAROL_3C_QUEUE com op_type = 1, permitindo que a exclusão lógica seja enviada à Carol.