Snowflake procedure - snowflake-cloud-data-platform

Basically I have created the notification alert using integrating AWS and Snowflake.
I want to add variable to my select statement. But its not working. So it will be for example "The token of user has expierd (name of the user).
Here is my function
`create or replace external function helloemailworld
(Sender varchar,Receiver Varchar , SUBJECT varchar, BODY_TEXT varchar)
returns variant
api_integration = hellotesting
as 'https://....execute-api.eu-...l-1.amazonaws.com/dev/helloworld';`
and here is my procedure
create or replace procedure Notification()
returns variant
language javascript
EXECUTE AS caller
as
$$
var my_sql_command = "select * from notification";
var statement1 = snowflake.createStatement( {sqlText: my_sql_command} );
var result_set1 = statement1.execute();
while (result_set1.next()) {
var column1 = result_set1.getColumnValue(1);
var column2 = result_set1.getColumnValue(2);
var column3 = result_set1.getColumnValue(3);
var execute = "select helloemailworld('lukasz#gmail.com','lukasz#op.pl','Alert', 'The token of user has expierd' + column1);"
var statement2= snowflake.createStatement( {sqlText: execute} );
var result_set2 = statement2.execute();
}
$$
;
The column 1 is a variable and in notification table first column is also a variable

Related

Create stored procedure that create users in snowflake

I am trying to create a stored procedure in snowflake that create users in snowflake. But I am unable to bind variables.
Here is what I tried using snowflake scripting. I was not successful in creating a version that works
create or replace procedure create_user(user_name varchar, password_value varchar)
returns varchar
language sql
as
$$
begin
create user :USER_NAME password = :password_value;
return 'Completed.';
end;
$$
;
In the above stored procedure, when I use :USER_NAME (I have tried upper and lower case). I get an error saying unexpected :. Password_value seems to work correctly.
I have also tried javascript version
CREATE OR REPLACE PROCEDURE security.create_user_v2(USER_NAME varchar, PASSWORD_VALUE varchar)
RETURNS BOOLEAN
LANGUAGE JAVASCRIPT
AS
$$
var cmd = "create user :1 password = :2;";
var stmt = snowflake.createStatement(
{
sqlText: cmd,
binds: [USER_NAME, PASSWORD_VALUE]
}
);
var result = stmt.execute();
result.next();
return true
$$
;
I get the same here as well, says unexpected :.
This version works, but this is concatenation, i want to avoid this (possible sql injection)
CREATE OR REPLACE PROCEDURE security.create_user_v2(USER_NAME varchar, PASSWORD_VALUE varchar)
RETURNS BOOLEAN
LANGUAGE JAVASCRIPT
AS
$$
var cmd = "create user "+USER_NAME+" password = :1;";
var stmt = snowflake.createStatement(
{
sqlText: cmd,
binds: [PASSWORD_VALUE]
}
);
var result = stmt.execute();
result.next();
return true
$$
;
How do I create a snowflake scripting version or javascript version that bind variables when creating users in stored procedure.
User name must be enclosed with IDENTIFIER in order to use variable:
CREATE OR REPLACE PROCEDURE security.create_user_v2(USER_NAME varchar,
PASSWORD_VALUE varchar)
RETURNS BOOLEAN
LANGUAGE JAVASCRIPT
AS
$$
var cmd = "create user IDENTIFIER(:1) password = :2;";
var stmt = snowflake.createStatement(
{
sqlText: cmd,
binds: [USER_NAME, PASSWORD_VALUE]
}
);
var result = stmt.execute();
result.next();
return true
$$
;
Call:
CALL security.create_user_v2('user1', 'password123');
CALL security.create_user_v2('"user1#x.com"', 'password123');
SHOW USERS;
Snowflake Scripting:
create or replace procedure security.create_user(user_name varchar,
password_value varchar)
returns varchar
language sql
as
$$
begin
create user IDENTIFIER(:USER_NAME) password = :password_value;
return 'Completed.';
end;
$$;

How to call nested stored create table procedures in Snowflake

Looking for advice on how to correct these two stored procedures so that one will trigger the other.
Stored procedure 2 is designed to simply create Table 2:
CREATE OR REPLACE PROCEDURE create_table_2()
returns string not null
language javascript
as
$$
var create_table_2 = `
create or replace table DATABASE.SCHEMA.TABLE_2
(
COL_1 string,
COL_2 string,
COL_3 date
)
;
`
var create_table_2_cmd = snowflake.createStatement({sqlText: create_table_2});
var result = sql_create_table_2.execute();
return 'Table 2 created';
$$;
And stored procedure 1, which should be run first, create table 1 and then run stored procedure 2:
CREATE OR REPLACE PROCEDURE create_table_1()
returns string not null
language javascript
as
$$
var create_table_1 = `
create or replace table DATABASE.SCHEMA.TABLE_1
(
COL_1 string,
COL_2 string,
COL_3 date
)
;
`
var create_table_1_cmd = snowflake.createStatement({sqlText: create_table_1 });
var result = create_table_1_cmd .execute();
return 'Table 1 created';
var call_next_function_cmd = `
call create_table_2();
;
`
var call_next_func = snowflake.createStatement({sqlText: call_next_function_cmd});
var final = call_next_func.execute();
$$;
The SQL code within the create_table_1() procedure executes without issue but does not call the create_table_2() procedure. Is there an adjustment to be made that can trigger this?
The return has to be moved to the end of stored procedure, at current position it makes the second call unreachable code:
CREATE OR REPLACE PROCEDURE create_table_1()
returns string not null
language javascript
as
$$
var create_table_1 = `
create or replace table DATABASE.SCHEMA.TABLE_1
(
COL_1 string,
COL_2 string,
COL_3 date
)
;
`
var create_table_1_cmd = snowflake.createStatement({sqlText: create_table_1 });
var result = create_table_1_cmd .execute();
//return 'Table 1 created'; -- << HERE
var call_next_function_cmd = `
call create_table_2();
;
`
var call_next_func = snowflake.createStatement({sqlText: call_next_function_cmd});
var final = call_next_func.execute();
return '...';
$$;

Getting same value for all records in snowflake

I have key_value table and key table. I have to load only key from key_value table and insert into key table using snowflake procedure. I have written below code. After executing it i am getting same key value in key table rather all the keys.
create or replace procedure proc_key_load()
returns varchar
language javascript
as
$$
var query=`select key from key_value`;
var ret=snowflake.createStatement( {sqlText: query}).execute();
var length=ret.getRowCount();
var counter=0;
while(counter<length){
ret.next();
var value=ret.getColumnValue(1);
var load_query=`insert into key_load values(` + value +`)`;
var ret=snowflake.createStatement( {sqlText: load_query}).execute();
counter += 1;
}
return 'SUCCESS';
$$
I didn't test it but as I see that you redefine "ret" in the loop. Try with assigning different variable:
create or replace procedure proc_key_load()
returns varchar
language javascript
as
$$
var query=`select key from key_value`;
var ret=snowflake.createStatement( {sqlText: query}).execute();
var length=ret.getRowCount();
var counter=0;
while(counter<length){
ret.next();
var value=ret.getColumnValue(1);
var load_query=`insert into key_load values(` + value +`)`;
var ret2 = snowflake.createStatement( {sqlText: load_query}).execute();
counter += 1;
}
return 'SUCCESS';
$$
Update: I tested the above code and it works. If you just need to copy some data from one table to another, you can just plain SQL right? Something like:
INSERT INTO key_load SELECT key FROM key_value;
Anyway, if you really need to use the above procedure, you can write it in a more efficient way:
create or replace procedure proc_key_load()
returns varchar
language javascript
as
$$
var query=`select key from key_value`;
var ret=snowflake.createStatement( {sqlText: query}).execute();
while(ret.next()){
var value=ret.getColumnValue(1);
var load_query=`insert into key_load values(?)`;
snowflake.createStatement( {sqlText: load_query, binds:[value] }).execute();
}
return 'SUCCESS';
$$;

Snowflake Stored Procedure - how do I retrieve the number of rows created by a CTAS Statement

In a snowflake stored procedure I am executing CTAS statements and want to retrieve the number of rows in the resultant object. We don't have access to QUERY_HISTORY (we get an error), and RESULT_SCAN(LAST_QUERY_ID()) doesn't help either (it gives us back the Table xyz Created result, but does not have meta-data i.e. number of rows created).
I can do it with a Select Count(*) in a separate query, but that seems to be a hack since the Row Count is right there in the History.
CREATE OR REPLACE PROCEDURE EDW_ADMIN.DAG_TEST()
RETURNS VARCHAR(512)
LANGUAGE JAVASCRIPT
AS
$$
{
let strCTAS = "";
let rsCTAS;
let rsRowsAffected;
let rowsAffected = 0;
strCTAS = "CREATE OR REPLACE TABLE EDW_ADMIN.DEMO_PROC_TEMP AS SELECT * FROM RAW_BIR.H_RPTUNIT;";
rsCTAS = snowflake.execute( {sqlText: strCTAS} );
// This works in a Query Worksheet in the browser, but gives me the following error when called from a procedure
// "[Stored procedure execution error: Requested information on the current user is not accessible in stored procedure.]"
rsRowsAffected = snowflake.execute( {sqlText: "SELECT ROWS_PRODUCED FROM TABLE(INFORMATION_SCHEMA.QUERY_HISTORY(RESULT_LIMIT=>100)) WHERE QUERY_ID = LAST_QUERY_ID();"} );
rsRowsAffected.next();
rowsAffected = rsRowsAffected.getColumnValue(1);
// This works, but you are doing execute i/o which is really un-necessary
// rsRowsAffected = snowflake.execute( {sqlText: "SELECT COUNT(*) FROM EDW_ADMIN.DEMO_PROC_TEMP;"} );
// rsRowsAffected.next();
// rowsAffected = rsRowsAffected.getColumnValue(1);
// This does NOT work, RESULT_SCAN has no metadata associated with it, this returns "Table DEMO_PROC_TEMP successfully created."
// rsRowsAffected = snowflake.execute ( {sqlText: "SELECT * FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()));" } );
// rsRowsAffected.next();
// rowsAffected = rsRowsAffected.getColumnValue(1);
return rowsAffected;
}
$$
;
CALL EDW_ADMIN.DAG_TEST();
DROP EDW_ADMIN.DEMO_PROC_TEMP;
DROP PROCEDURE EDW_ADMIN.DAG_TEST();
Try adding execute as caller to the stored procedure declaration. For example:
create or replace procedure p()
returns text
language javascript
execute as caller
as
$$
const stmt1 = snowflake.createStatement( { sqlText: "create or replace table t as select $1 x from values (1),(2),(3)" } )
const rs1 = stmt1.execute()
const stmt2 = snowflake.createStatement( { sqlText: "SELECT ROWS_PRODUCED FROM TABLE(INFORMATION_SCHEMA.QUERY_HISTORY(RESULT_LIMIT=>100)) WHERE QUERY_ID = LAST_QUERY_ID()" } )
const rs2 = stmt2.execute()
rs2.next()
const rowsAffected = rs2.getColumnValue(1)
return rowsAffected
$$
;
call p();
returns 3

Stream and Task Stored procedure example, I am not sure how to troubleshoot the javascript

I have just learned about Streams and Tasks in Snowflake and have tested the example for tracking members and sign ups in the first example here.
I have attempted to create a stored procedure that looks like this:
CREATE OR REPLACE procedure member_update()
returns string not null
language javascript
as
$$
var statement = snowflake.createStatement({sqlText: "BEGIN"} );
statement.execute();
var statement = snowflake.createStatement({sqlText: "UPDATE members SET fee = fee + 15 where fee > 0"} );
statement.execute();
var statement = snowflake.createStatement({sqlText: "SELECT * FROM member_check"} );
statement.execute();
var statement = snowflake.createStatement({sqlText: "COMMIT"} );
statement.execute();
var statement = snowflake.createStatement({sqlText: "SELECT * FROM member_check"} );
statement.execute();
$$
;
INSERT INTO members (id,name,fee)
VALUES
(11,'Bill',0),
(12,'Jason',0),
(13,'Suzan',0),
(14,'Michelle',0),
(15,'AARON',0);
SELECT * FROM MEMBER_CHECK;
INSERT INTO signup
VALUES
(11,'2018-01-01'),
(12,'2018-02-15'),
(13,'2018-05-01'),
(14,'2018-07-16'),
(15,'2018-08-21');
MERGE INTO members m
USING (
SELECT id, dt
FROM signup s
WHERE DATEDIFF(day, '2018-08-15'::date, s.dt::DATE) < -30) s
ON m.id = s.id
WHEN MATCHED THEN UPDATE SET m.fee = 90;
Call member_update();
I have run into an error and was hoping I might get some guidance on by very beginner stored procedure.
Error:
Execution error in store procedure MEMBER_UPDATE: empty argument
passed At Snowflake.createStatement, line 2 position 29

Resources