从任务调用时存储过程的行为

Behaviour of stored procedures when called from a task

我正在尝试使用存储过程插入日志 table(以及其他一些不相关的功能)。此过程需要由任务自动调用,执行一些代码,然后写入 table。我可以执行上述所有操作,但是当我包含用于错误处理的 try/catch 块时,该过程不会更新日志 tables.

最小工作示例:

正在创建日志 table 和写入日志的过程,

create or replace table test_log_table (
  PROC_NAME VARCHAR, 
  MESSAGE VARCHAR,
  TIME TIMESTAMP
   );

CREATE OR REPLACE PROCEDURE LOG_SP_TEST(TRGT_TABLE VARCHAR, MESSAGE VARCHAR)
RETURNS  VARCHAR
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$  
    const PROC_NAME = Object.keys(this)[0]; // name of executing procedure
    
    insert_sql =
    `INSERT INTO ` + TRGT_TABLE+`
    (
      PROC_NAME, 
      MESSAGE,
      TIME
    )
    VALUES
    ('`+ PROC_NAME +`','`+MESSAGE+`', CURRENT_TIMESTAMP());` 
    
    try{col_list_fetch_trgt = snowflake.execute(
        { sqlText: insert_sql })
    }
    catch(err){
        return "failed: "+err
    }
$$;

当手动调用该过程时,它的所有行为都符合预期

call log_sp_test('test_log_table', 'calling manually');
select * from test_log_table;

select*returns以下table

PROC_NAME MESSAGE TIME
LOG_SP_TEST calling manually 2022-01-28 09:26:22.791

现在我们创建一个任务并自动再次调用该过程

-- now test calling this proc using a task
create task mytask_minute
  warehouse = COMPUTE_WH
  schedule = '1 minute'
as
  call log_sp_test('test_log_table', 'calling via trigger');
  
alter task mytask_minute resume;
show tasks;

-- can then check when a task is next due to run by
select timestampdiff(second, current_timestamp, scheduled_time) as next_run, scheduled_time, current_timestamp, name, state 
from table(information_schema.task_history()) where state = 'SCHEDULED' order by completed_time desc;

select * from test_log_table;
alter task mytask_minute suspend;
show tasks;

select*语句还是returns一样

PROC_NAME MESSAGE TIME
LOG_SP_TEST calling manually 2022-01-28 09:26:22.791

而如果我们删除过程中的 try/catch 块,我们将得到预期的

PROC_NAME MESSAGE TIME
LOG_SP_TEST calling manually 2022-01-28 09:26:22.791
LOG_SP_TEST calling via trigger 2022-01-28 09:33:21.881

如何自动调用此过程,同时仍然能够写入日志 table 并正确处理错误?

变化:

  • 在行尾使用 ;
  • 使用参数而不是串联
  • 使用架构名称调用过程'PUBLIC.test_log_table'

程序:

CREATE OR REPLACE PROCEDURE LOG_SP_TEST(TRGT_TABLE VARCHAR, MESSAGE VARCHAR)
RETURNS  VARCHAR
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$  
    const PROC_NAME = Object.keys(this)[0]; // name of executing procedure
    
    insert_sql = `INSERT INTO IDENTIFIER(?) ( PROC_NAME,  MESSAGE, TIME)
                 VALUES(?, ?, CURRENT_TIMESTAMP());`;
    
    try{
      col_list_fetch_trgt = snowflake.execute(
        { sqlText: insert_sql, binds:[TRGT_TABLE, PROC_NAME, MESSAGE] });
    }
    catch(err){
        return "failed: "+err
    }
$$;

任务:

create OR REPLACE task mytask_minute
  warehouse = COMPUTE_WH
  schedule = '1 minute'
as
  call PUBLIC.log_sp_test('PUBLIC.test_log_table', 'calling via trigger');

输出: