How to return result from a stored procedure to TASK RETURN_VALUE in snowflake? - snowflake-cloud-data-platform

I would like to return logging and status messages from a stored procedure to the TASK that calls it.
create or replace procedure status_return()
returns string not null
language javascript
as
$$
var result_status = 'The return status and debug information in string format';
return result_status; // Statement returned for info/debug purposes
$$;
I would like to pass the result from stored procedure call status_return() back to the task
-- Create a task that calls the stored procedure every hour
create or replace task call_SP
warehouse = SMALL
schedule = '1 minute'
as
call status_return();
When I execute TASK_HISTORY to view RETURN_VALUE is always empty.
select *
from table(information_schema.task_history(SCHEDULED_TIME_RANGE_START => dateadd(hours, -5, current_timestamp()) ,
TASK_NAME => 'call_sp'));
How can I view the result of a stored procedure in task_history for SUCCESS, FAILURE, or ERRORS?
I have tried creating a task in the following way, but I was unsuccessful and it return with errors.
create or replace task call_SP
warehouse = EDS_SMALL
schedule = '1 minute'
as
call system$set_return_value(call status_return());
Can I use Javascript in Tasks? To store the result of a stored procedure call into a variable and return it back to the TASK result

In order to be able to get a RETURN_VALUE in your TASK_HISTORY you have to set the return_value in your stored procedure using call system$set_return_value().
Examples can be found in snowflake documentation.
This is what it should looks like if you want the return_value field of the task_history to return your result status var when your task is launched :
create or replace procedure status_return()
returns string not null
language javascript
as
$$
var result_status = 'The return status and debug information in string format';
var rv_stmt = snowflake.createStatement({sqlText:`call system$set_return_value('` + result_status + `');`});
var rv_res = rv_stmt .execute(); // Set return_value
return result_status; // Statement returned for info/debug purposes
$$;

Related

Snowflake Syntax when passing array into insert query

My code obtains the column list of a table I have created
the attributes of this table are the contextual values of a session in snowflake
such as USER,DATABASE,WAREHOUSE...ETC
Afterwards it places those attribute names into an array
I then try to call on these names in making an insert query and this is where I am struggling with the syntax
Because each value in my array is USER, DATABASE,WAREHOUSE
I am trying to call on the context functions
like CURRENT_WAREHOUSE()
Can someone please help me with the syntax
for(i=0;i<arr.length;i++){
v_sqlCode = `INSERT INTO SESSION_ATTRIBUTES( arr[i] )
"VALUES ("CALL CURRENT_"+arr[i]+"()")';
}
You can't directly use the output of a Snowflake stored procedure programmatically. If you need to use the output value, you have to collect it using the RESULT_SCAN table function. That can get a bit complex to handle, directly in code, so it's far better to place it into a helper function. See this example of one SP calling another one and using its output value. It does this by calling the SP using the callSP helper function. Use the entire SQL statement including the call command into the SQL parameter for that function. It will run the SP, grab the result from the result_scan table function and return it.
create or replace procedure HELLO_WORLD()
returns string
language javascript
as
$$
return "Hello, world.";
$$;
create or replace procedure CALL_HELLO_WORLD()
returns string
language javascript
execute as caller
as
$$
return callSP(`call HELLO_WORLD()`);
// ---- Main function above, helper functions below.
function callSP(sql){
let cmd = {sqlText: sql};
let stmt = snowflake.createStatement(cmd);
stmt.execute();
let result_scan = `select $1 from table(result_scan(last_query_id()));`;
let result_cmd = {sqlText: result_scan};
let result_stmt = snowflake.createStatement(result_cmd);
let rs = stmt.execute();
if(rs.next()) {
return rs.getColumnValue(1);
} else {
return null;
}
}
$$;
call call_hello_world();

Query `list stage` in Snowflake UDF

I am trying to write a Snowflake UDF that accepts a stage name and specific folder name as input parameters and returns the latest file id ( striping from full file name) as the output. Could anyone help me with a simple code to achieve this?
I'm not sure if you want a UDF or stored procedure. The syntax to create would be similar so I think this can help. Here is a stored procedure which will fetch latest staged file from a given stage and path. Just be aware of the limit 1 in query, multiple staged files may share the same last modified date while this procedure returns a scalar (single) value.
Stored Procedure Definition
create or replace procedure "MYDB"."MYSCHEMA"."LATEST_STAGED_FILE"(stage_name text, folder text)
returns string not null
language javascript
execute as caller
as
$$
var sql_text = "list #" + STAGE_NAME + "/" + FOLDER ;
var sql_command0 = snowflake.createStatement({ sqlText: sql_text});
var sql_command1 = snowflake.createStatement({ sqlText:`SELECT "name" FROM table(result_scan(last_query_id())) WHERE "last_modified" = (select MAX("last_modified") from table(result_scan(last_query_id()))) LIMIT 1;`});
try {
sql_command0.execute();
var resultSet = sql_command1.execute();
while(resultSet.next())
{
var resultFile = resultSet.getColumnValue('name').split("/")
return resultFile[resultFile.length - 1]
}
}
catch (err) {
return "Failed: " + err;
}
$$;
You can then call the stored procedure like
call "MYDB"."MYSCHEMA"."LATEST_STAGED_FILE"('MYDB.MYSCHEMA.MYSTAGE', 'mypath/myotherpath');
References
select from list #
list stage via SP

Execution error in stored procedure in Snowflake

I compiled a stored procedure but I'm unable to execute it - getting this error:
Execution error in stored procedure SAMPLE_ETL_MONITORING_PROC: Stored procedure execution error: Requested information on the current user is not accessible in stored procedure. At Statement.execute, line 18 position 45
I have write access to the database but not sure If I have to include any commands/statements in the script. Can anyone please suggest what needs to be done?
Here is the script:
CREATE OR REPLACE PROCEDURE sample_etl_monitoring_proc()
returns string not null
language javascript
as
$$
var insert_cmd = `
truncate table OOBE.monitoring.load_history_1
`
var sql_insert = snowflake.createStatement({sqlText: insert_cmd});
var insert_result = sql_insert.execute();
var stream_select_cmd = `
insert into OOBE.monitoring.load_history_1
select * from (
select * from OOBE.information_schema.load_history
union
select * from snowplow.information_schema.load_history);
`
var sql_select_stream = snowflake.createStatement({sqlText: stream_select_cmd});
var select_stream_result = sql_select_stream.execute();
return '👍';
$$;
I reproduced the error and got this to work by adding an explicit caller's right declaration:
CREATE OR REPLACE PROCEDURE sample_etl_monitoring_proc()
returns string not null
language javascript
execute as caller
as

get the value and use that value as check to process next steps in snowflake

I have to check the distinct "Status" columnin 1 table and and if that Status='Complete' then I have to call different other Stored Procedures. How can I retrieve the value from the sample code below.
CREATE OR REPLACE PROCEDURE TEMP_KK()
RETURNS STRING NOT NULL
LANGUAGE JAVASCRIPT
AS
$$
var load_status=`SELECT DISTINCT TABLESTATUS from "PLNG_ANALYSIS"."LOAD"."LET_LOAD_VERIFICATION";`
var load_check = snowflake.execute({sqlText: load_status});
if (load_check='Complete') /* HOW DO i get the TABLESTATUS value returned from above select statement */
{
CALL ABC();
CALL XYZ();
}
$$;
CALL TEMP_KK();
Assuming that query returns single row:
var load_status=`SELECT DISTINCT TABLESTATUS from "PLNG_ANALYSIS"."LOAD"."LET_LOAD_VERIFICATION";`
var load_check = snowflake.execute({sqlText: load_status});
load_check.next();
if(load_check.getColumnValue(1) == 'Complete') {
...
}

Executing a SQL statement, present in a table, and returning the resulting record set in Snowflake

I need help with a practical scenario. I have a table called CONFIG_TBL in Snowflake. This table has SQL statements, 1 per row. My goal is to use Snowflake Stored Procedures or Snowflake UDF, or a combination of the two, and return a result set that will be obtained after execution of that statment.
The statements are simple select statements, like "select * from ABC'.
I could have done this, very easily in SQL server, since procedures can return table values. However, I don't know how to do this in Snowflake.
Any help will be greatly appreciated.
Thanks in advance.
Here's something to get you started at least. Procedures use javascript (SQL Stored Procedures are coming soon), but they can be used to run dynamic queries like you are looking for.
You can get the results in a couple of ways. By either returning a variant object or by using result_scan after calling the procedure.
This example just runs one query so your final solution will be different depending on just what you want the output to look like.
CREATE OR REPLACE PROCEDURE SCHEMA.PROCEDURE_NAME()
RETURNS VARIANT
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS $$
retrieve_queries_sql = "select top 1 query from CONFIG_TBL";
retrieve_queries_result_set = snowflake.execute({sqlText: retrieve_queries_sql });
query_to_run = retrieve_queries_result_set.next().getColumnValue(1);
rs = snowflake.execute({sqlText: query_to_run})
var return_value = "";
if (rs.next()) {
return_value += rs.getColumnValue(1);
return_value += ", " + rs.getColumnValue(2);
}
while (rs.next()) {
return_value += "\n";
return_value += rs.getColumnValue(1);
return_value += ", " + rs.getColumnValue(2);
}
}
return return_value;
$$
CALL SCHEMA.PROCEDURE_NAME()
SELECT *
FROM table(result_scan(last_query_id()))
Edit: Fixed to have example correctly return a result which can then be used by the result_scan. Example taken from here. There are various more examples for getting results out of a procedure, including using JSON output.
We can use language as SQL and return the value to table, Which can return table values.
CREATE OR REPLACE PROCEDURE DDL_TEST_SQL()
RETURNS TABLE(CARRIERFILEID integer, BLOBPATH varchar)
LANGUAGE SQL
EXECUTE AS OWNER
AS
$$
DECLARE
QUERY STRING;
res resultset;
BEGIN
QUERY := 'SELECT TOP 10 CARRIERFILEID,BLOBPATH from CONFIG.CARRIERFILE';
res := (EXECUTE IMMEDIATE :QUERY);
return table(res);
END;
$$;
CALL DDL_TEST_SQL()

Resources