Execution error in stored procedure in Snowflake - snowflake-cloud-data-platform

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

Related

schema does not exist and not authorized

I am trying to create a Procedure in snowflake.
CREATE OR REPLACE PROCEDURE test()
returns string not null language javascript as
$$
var cmd = "select count(1) from Test1.table1";
var sql = snowflake.createStatement({sqlText: cmd});
var result = sql.execute();
return '1';
$$;
"table1" existing in schema "schema1" but i am trying to create this procedure in schema2. schema2 does have an access to "table1.
when I run the same query in snowflake web UI with schema "schema2" where i am creating the procedure select count(1) from Test1.table1 it is working but inside procedure it is not working and displaying me error
schema does not exist and not authorized
CREATE OR REPLACE PROCEDURE test()
returns string not null language javascript as
$$
var cmd = "select count(1) from Test1.table1";
var sql = snowflake.createStatement({sqlText: cmd});
var result = sql.execute();
return '1';
$$;
if you fully qualify you names, things just work:
use schema test.test;
create schema test.test1;
create table test.test1.table1(id int);
CREATE OR REPLACE PROCEDURE test.test1.test()
returns string not null language javascript as
$$
var cmd = "select count(1) from test.test1.table1";
var sql = snowflake.createStatement({sqlText: cmd});
var result = sql.execute();
return '1';
$$;
call test.test1.test();
TEST
1
create schema test.test2;
use schema test.test2;
call test.test1.test();
TEST
1
use schema test.test2;
CREATE OR REPLACE PROCEDURE test.test2.test()
returns string not null language javascript as
$$
var cmd = "select count(1) from test.test1.table1";
var sql = snowflake.createStatement({sqlText: cmd});
var result = sql.execute();
return 'called table1 from schema2';
$$;
call test.test2.test();
TEST
called table1 from schema2
So why your error?
The below SQL I have made non fully qualified. So the function will be in the current scehma. Which for me is test.test2. But now I am referring to schema schema1.table1 and schema1 does not exist. thus the error message when I run the code.
CREATE OR REPLACE PROCEDURE test()
returns string not null language javascript as
$$
var cmd = "select count(1) from schema1.table1";
var sql = snowflake.createStatement({sqlText: cmd});
var result = sql.execute();
return 'called table1 from schema2';
$$;
call test.test2.test();
gives:
SQL compilation error:
Schema 'TEST.SCHEMA1' does not exist or not authorized.
At Statement.execute, line 4 position 21
The other possible outcome is you have the function defined as EXECUTE AS OWNER and the two functions do have two different owners, with different owning permissions. But I am going to doubt that.

How to return result from a stored procedure to TASK RETURN_VALUE in snowflake?

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
$$;

Use of Variable in Snowflake Stored Procedure

I have to add a variable MaxDate in my SQL Stored Proc (shown below). The code gets errored out since MaxDate is not represented by its value. Any idea on how I can pass a variable in a stored proc?
create or replace procedure Load_Employee()
returns varchar not null
language javascript
EXECUTE AS CALLER
as
$$
//Variable Initialization
var IntegrationTable ='EMPLOYEE';
var TypeID=0;
var MaxDate=' ';
var cmd = "Select max(COMPLETED_DATE) from SCHEMA.TABLE where TARGET_TABLE_NAME= " + "'" + IntegrationTable + "'" ;
var sql = snowflake.createStatement({sqlText: cmd});
var result = sql.execute();
result.next();
MaxDate=result.getColumnValue(1);
var cmd=` Insert into PersonTable
select SHA1(concat(Person_id,'|','Person')) ,12345678,SHA1(concat('Payroll','|','Pay','|', Load_Date)) ,current_timestamp() , Tenant
from Schema.PERSONTABLE where Date_Added >= MaxDate
where TYPE='ABC' ;`;
$$
;
If your query to get MaxDate works right, then the value should be in the variable. The problem is it's not being replaced in the sql variable defining the insert statement.
Since you're using backticks to open and close the string, you can use a special JavaScript notation to replace the variable with its value, ${MaxDate}.
Your definition of the insert statement would look like this:
var cmd=` Insert into PersonTable
select SHA1(concat(Person_id,'|','Person')) ,12345678,SHA1(concat('Payroll','|','Pay','|', Load_Date)) ,current_timestamp() , Tenant
from Schema.PERSONTABLE where Date_Added >= ${MaxDate}
where TYPE='ABC' ;`;
If that doesn't work, try cutting the SP short with return MaxDate; to see what got assigned to that variable. Also it's very helpful to check the query history view to see what SQL actually ran inside a stored procedure.
Also, I think this is the same SP that was having an issue with a null return. You'll need to return a string value using something like return 'Success'; or something to avoid getting an error for the null return. That's because of the returns varchar not null in the definition.

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

Retrieve the Variable value and insert into another table

I can retrieve the values of before(0) and after counts(4) from the below statements, but when I make use of those variables (load_cnt_before, load_cnt_after) from the code below and refer them to have the values inserted into a table it says it cant find the variables(refer to error below). How can I use those values to INSERT them into table.
Error: Execution error in stored procedure REC_COUNT_CHECK: SQL compilation error: error line 1 at position 114 invalid identifier 'LOAD_CNT_BEFORE' At Statement.execute, line 25 position 90
Code:
CREATE OR REPLACE PROCEDURE REC_COUNT_CHECK()
RETURNS VARCHAR LANGUAGE JAVASCRIPT
AS $$
/***** Get the Record Count before Refresh ****/
var load_cnt=`SELECT Count(*) as record_cnt from "PLNG_ANALYSIS"."LOADDATA"."LOAD_VERIFICATION" WHERE EXTRACTDATE=Current_date()-1 ;`
var load_cnt_check = snowflake.createStatement({sqlText: load_cnt}).execute();
load_cnt_check.next();
load_cnt_before = load_cnt_check.getColumnValue(1);
/***** Execute the SP ****/
var sp_call = "CALL LOAD_VERIFICATION()"; /***Refreshes data in table LOAD_VERIFICATION***/
var result = snowflake.execute({sqlText: sp_call});
result.next();
var return_msg2 = result.getColumnValue(1);
/***** Check the After Refresh Count ****/
var load_cnt_after=`SELECT Count(*) as record_cnt from "PLNG_ANALYSIS"."HFM"."LOAD_VERIFICATION" WHERE EXTRACTDATE=Current_date() ;`
var load_cnt_check_after = snowflake.createStatement({sqlText: load_cnt_after}).execute();
load_cnt_check_after.next();
load_cnt_after= load_cnt_check_after.getColumnValue(1);
/***** INSERT BEFORE AND AFTER COUNTS INTO LOG TABLE ****/
var insert_status_sp1=`INSERT INTO LOAD_STATUS_LOG_KK values (Current_TIMESTAMP(),1,'LOAD_VERIFICATION','Success','',**load_cnt_before,load_cnt_after**,1);`
var exec_sp1_status = snowflake.createStatement({sqlText: insert_status_sp1}).execute();
exec_sp1_status.next();
return 'Success'
$$;
CALL REC_COUNT_CHECK();
JS variables should be passed into SQL query. The mechanism is called Binding Variables
var insert_status_sp1=`INSERT INTO LOAD_STATUS_LOG_KK values (Current_TIMESTAMP(),1,'LOAD_VERIFICATION','Success','',:1,:2,1);`
var exec_sp1_status = snowflake.createStatement(
{sqlText: insert_status_sp1,binds:[load_cnt_before,load_cnt_after]}
).execute();

Resources