雪花与存储的proc一起处理错误

时间:2020-10-23 12:45:19

标签: stored-procedures snowflake-cloud-data-platform

我在Snowflake中存储了一个示例程序,该程序一个接一个地执行以下步骤,

  1. 插入带有开始详细信息的元数据
  2. 获取作为参数传递的表的总数
  3. 通过成功/失败更新元数据

这里的问题是当给定的表名在数据库中不存在时,存储的过程以错误退出,但是它不更新带有错误详细信息的元数据,而元数据条目显示状态为“进行中”而存储的过程失败在第二点。

当数据库中不存在该表时,我正在寻找一个干净的出口,然后存储proc应该使用错误详细信息更新元数据并干净地退出。

有人可以看看下面的代码,并建议我是否在这里缺少什么。我是雪花和程序的新手。谢谢。

CREATE OR REPLACE PROCEDURE abc.PROC_GET_COUNT(table_name varchar)
RETURNS VARCHAR(16777216)
LANGUAGE JAVASCRIPT
EXECUTE AS OWNER
AS $$

// SQL Queries
var get_execution_id_sql = "select t.nextval from table(getnextval(EXECUTION_SEQUENCE)) t";

var get_count_sql = `select count(*) from abc.`+ TABLE_NAME +;

var result_set1 = snowflake.createStatement({sqlText: get_execution_id_sql}).execute();

result_set1.next();

var seq_num= result_set1.getColumnValue(1);

var insert_meta_sql1= `INSERT into abc.ERROR_LOG (EXECUTION_ID, STATUS, START_TS) values ( '` +seq_num+ `', 'In_Progress', CURRENT_TIMESTAMP)`;

try {
    message = 'In insert Metadata with start details';
    snowflake.execute({sqlText: insert_meta_sql1});

    message = 'In Process of get count';
    get_count_out = snowflake.execute ({sqlText: get_count_sql});
    get_count_out.next();
    rec_count = get_count_out.getColumnValue(1);
    
    upd_meta_sql = `UPDATE abc.ERROR_LOG SET  END_TS = current_timestamp, STATUS = 'SUCCESS', MESSAGE = '` + TABLE_NAME + ` - Total count: ` + rec_count + `'  where EXECUTION_ID = '` + seq_num + `';
    
    message = 'In update Metadata with end details';
    snowflake.execute ({sqlText: upd_meta_sql});
    
} catch (err)  {
    upd_meta_sql = `UPDATE abc.ERROR_LOG SET  
                                END_TS = current_timestamp,
                                STATUS = 'FAILED', 
                                MESSAGE = '` + message + `. Error Details -- \n Code: `+ err.code +`\n State: `+ err.state +`\n Message: `+ err.message +`\n Stack Trace: `+ err.stackTraceTxt +`' 
                    where EXECUTION_ID = '` + seq_num + `';
    snowflake.execute ({sqlText: upd_meta_sql});
    return "Failed: " + message + ' -- ' +err; 
    }

return 'SUCCESS';
$$;

2 个答案:

答案 0 :(得分:0)

示例代码中有一些语法错误,但是我认为所有这些都是在您将脚本复制到此处时引起的。主要问题是err.message包含带有单引号字符的文本,从而破坏了最后一个SQL。

这是我的测试环境的脚本(如果您在询问需要调试的问题时与他人共享您的脚本,这将对其他人非常有帮助)

create schema abc;
create table deneme ( id number ) as select seq4()
from table(generator(rowcount=>100));
create or replace table ERROR_LOG (EXECUTION_ID number, 
MESSAGE varchar, STATUS varchar, START_TS timestamp , END_TS timestamp);
create or replace sequence seq1;

这是该过程的固定版本:

CREATE OR REPLACE PROCEDURE abc.PROC_GET_COUNT(table_name varchar)
RETURNS VARCHAR(16777216)
LANGUAGE JAVASCRIPT
EXECUTE AS OWNER
AS $$

var get_execution_id_sql = "select t.nextval from table(getnextval(seq1)) t";

var get_count_sql = `select count(*) from abc.`+ TABLE_NAME ;

var result_set1 = snowflake.createStatement({sqlText: get_execution_id_sql}).execute();

result_set1.next();

var seq_num= result_set1.getColumnValue(1);

var insert_meta_sql1= `INSERT into abc.ERROR_LOG (EXECUTION_ID, STATUS, START_TS) values ( ` + seq_num + `, 'In_Progress', CURRENT_TIMESTAMP)`;

try {
    message = 'In insert Metadata with start details';
    snowflake.execute({sqlText: insert_meta_sql1});

    message = 'In Process of get count';
    get_count_out = snowflake.execute ({sqlText: get_count_sql});
    get_count_out.next();
    rec_count = get_count_out.getColumnValue(1);
    
    upd_meta_sql = `UPDATE abc.ERROR_LOG SET  END_TS = current_timestamp, STATUS = 'SUCCESS', MESSAGE = '` + TABLE_NAME + ` - Total count: ` + rec_count + `'  where EXECUTION_ID = '` + seq_num +`'`;
    
    
    message = 'In update Metadata with end details';
    snowflake.execute ({sqlText: upd_meta_sql});
    
} catch (err)  {
    upd_meta_sql = `UPDATE abc.ERROR_LOG SET  
                                END_TS = current_timestamp,
                                STATUS = 'FAILED',
                                MESSAGE = '` + message + `. Error Details -- \n Code: `+ err.code +`\n State: `+ err.state +`\n Message: `+ err.message.replace( /'/g , "''" )  +`\n Stack Trace: `+ err.stackTraceTxt +`' 

                    where EXECUTION_ID = '` + seq_num + `'`;
    snowflake.execute ({sqlText: upd_meta_sql});
    return "Failed: " + message + ' -- ' +err; 
    }

return 'SUCCESS';

$$;

您可能会注意到,生成SQL时,我使用err.message.replace(/'/ g,“''”)代替err.message。

call PROC_GET_COUNT( 'deneme' ); -- succesful as the table exits

call PROC_GET_COUNT( 'deneme21' ); -- shows error

这是第二次尝试的消息列的内容:

In Process of get count. Error Details -- 
 Code: 100183
 State: P0000
 Message: SQL compilation error:
Object 'GOKHAN_DB.ABC.DENEME21' does not exist or not authorized.
 Stack Trace: At Snowflake.execute, line 20 position 30

答案 1 :(得分:0)

我认为问题与错误消息中返回的单引号有关。

我建议,设置消息变量。当您编写较短的代码时,它会更加神秘且更难找到问题。

通过将代码分解为更简单的步骤,您会发现问题更容易。

CREATE OR REPLACE SCHEMA abc;

USE SCHEMA ABC;


CREATE  SEQUENCE  IF NOT EXISTS EXECUTION_SEQUENCE
   WITH 
   START  WITH   =  1
   INCREMENT  BY  =  1
   COMMENT = 'DEMO SEQUENCE ' ;



CREATE OR REPLACE TABLE abc.ERROR_LOG(EXECUTION_ID number , STATUS varchar, MESSAGE VARCHAR, START_TS timestamp_ltz , END_TS timestamp_ltz);


CREATE TABLE ABC.TEST_TABLE1(ID NUMBER, MESSAGE VARCHAR);

INSERT INTO ABC.TEST_TABLE1(ID, MESSAGE)
SELECT SEQ4() + 1 , RANDSTR(50, RANDOM()) 
FROM TABLE(GENERATOR(ROWCOUNT=>50));

SELECT * FROM ABC.TEST_TABLE1 ORDER BY 1 ASC;


CREATE OR REPLACE PROCEDURE abc.PROC_GET_COUNT(table_name varchar)
RETURNS VARCHAR(16777216)
LANGUAGE JAVASCRIPT
EXECUTE AS OWNER
AS $$

// SQL Queries
var get_execution_id_sql = "select t.nextval from table(getnextval(EXECUTION_SEQUENCE)) t";

var get_count_sql = `select count(*) from abc.`+ TABLE_NAME +`;`

var result_set1 = snowflake.createStatement({sqlText: get_execution_id_sql}).execute();

result_set1.next();

var seq_num= result_set1.getColumnValue(1);

var insert_meta_sql1= `INSERT into abc.ERROR_LOG (EXECUTION_ID, STATUS, START_TS,MESSAGE) values ( '` +seq_num+ `', 'In_Progress', CURRENT_TIMESTAMP(), '`+TABLE_NAME+`')`;

try {
    message = 'In insert Metadata with start details';
    snowflake.execute({sqlText: insert_meta_sql1});

    message = 'In Process of get count';
    get_count_out = snowflake.execute ({sqlText: get_count_sql});
    get_count_out.next();
    rec_count = get_count_out.getColumnValue(1);
    
    upd_meta_sql = `UPDATE abc.ERROR_LOG SET END_TS = current_timestamp(), STATUS = 'SUCCESS', MESSAGE = '` + TABLE_NAME + ` - Total count: ` + rec_count + `'  where EXECUTION_ID = ` + seq_num + `;`
    
    message = 'In update Metadata with end details';
    snowflake.execute ({sqlText: upd_meta_sql});
    
} catch (err)  {
    message = `Error Details\r\nCode: ` + err.code + `\r\nState:` + err.state +`\r\nMessage: ` + err.message + `\r\nStack Trace: ` + err.stackTraceTxt;

    // **** you need to replace the single quotes that are being returned in your error message
    message = message.replace(/'/g, `"`);
    upd_meta_sql = `UPDATE abc.ERROR_LOG 
                    SET END_TS = current_timestamp()
                    ,STATUS = 'FAILED'
                    , MESSAGE = '` + message +`' where EXECUTION_ID = ` + seq_num + `;`
    snowflake.execute ({sqlText: upd_meta_sql});
    return "Failed: " + message + ' -- ' +err; 
    }

return 'SUCCESS';
$$;



CALL abc.PROC_GET_COUNT('TEST_TABLE1');



CALL abc.PROC_GET_COUNT('TEST_TABLE_MISSING');


SELECT * FROM abc.ERROR_LOG ORDER BY 1 ASC;

解决方案是here