schema does not exist and not authorized - snowflake-cloud-data-platform

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.

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

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

REGEXP_SUBSTR function in stored procedure returns null

I have the following string:
'AAA|BBB||CCC|1.23'
I would like to return: 'CCC|1.23'
When using the regexp: \w+\|\d(.\d+|$) I am able to get the desired results.
When in Snowflake running the following query, returns the correct results:
SELECT REGEXP_SUBSTR('AAA|BBB||CCC|1.23', '\\w+\\|\\d(.\\d+|$)') AS regexp_return;
However when used in a stored procedure as follows:
CREATE OR REPLACE PROCEDURE dnr.regexp_issue ()
returns string
language javascript
execute as owner
AS
$$
var sql_statement = `SELECT REGEXP_SUBSTR('AAA|BBB||CCC|1.23', '\\w+\\|\\d(.\\d+|$)') AS regexp_return;`
var query = snowflake.createStatement({sqlText: sql_statement});
var query_res = query.execute();
query_res.next();
result = query_res.getColumnValue(1);
return result;
$$;
The resulting CALL dnr.regexp_issue(); returns a NULL as if no matching pattern was found.
Any ideas?
the slashed need to be double double quoted as they are going through two string parsers.
CREATE OR REPLACE PROCEDURE regexp_issue ()
returns string
language javascript
execute as owner
AS
$$
var sql_statement = `SELECT REGEXP_SUBSTR('AAA|BBB||CCC|1.23', '\\\\w+\\\\|\\\\d(.\\\\d+|$)') AS regexp_return;`
var query = snowflake.createStatement({sqlText: sql_statement});
var query_res = query.execute();
query_res.next();
result = query_res.getColumnValue(1);
return result;
$$;
call regexp_issue();
gives:
REGEXP_ISSUE
CCC|1.23
To add to Simeon's answer, you can also use .replace(/\\/g, "\\\\") at the end of a string that with double backslashes for Snowflake. That avoids using quadruple backslashes JavaScript + Snowflake SQL escape characters. It can make for more legible strings. It would look like this:
var sql_statement = `SELECT REGEXP_SUBSTR('AAA|BBB||CCC|1.23', '\\w+\\|\\d(.\\d+|$)') AS regexp_return;`.replace(/\\/g, "\\\\");
You can also put it in two separate lines for even more clarity and a few microseconds more processing time.
var sql_statement = `SELECT REGEXP_SUBSTR('AAA|BBB||CCC|1.23', '\\w+\\|\\d(.\\d+|$)') AS regexp_return;`
sql_statement = sql_statement.replace(/\\/g, "\\\\");

How to assign a sql query result to a variable in stored procedure

I am trying to assign a simple sql query result in stored procedure to a variable which I will use it later in another sql statement. If I execute below statement with out putting in procedure it works but not with stored procedure, I get an error while calling sp , Can someone please help me here ?
Procedure code:
$$
VAR NAME = 'ABC'
SET (COUNT_VALUE) = (SELECT COUNT(*) FROM COUNT_TABLE)
With out Procedure below code works
SET (COUNT_VALUE) = (SELECT COUNT(*) FROM COUNT_TABLE)
select $COUNT_VALUE
Thanks
Here's an example that uses a simple helper function to return a result set from a query. You can read the Snowflake docs to see what the result set API has in it. The getResultSet function returns a variable that has the results of the query. Since the SQL is a count, you need to use rs.next() once to get to the first row and then read the value in the aliased count(*). You could also use rs.getColumnValue(1) to get a column by ordinal position, but I recommend using column names with SQL aliases is necessary.
create or replace procedure COUNT_EXAMPLE()
returns string
language javascript
as
$$
var rowCount = 0;
var sql = "select count(*) as ROW_COUNT from SNOWFLAKE_SAMPLE_DATA.TPCH_SF10000.ORDERS;";
try {
var rs = getResultSet(sql);
if (rs.next()) {
var rowCount = rs.getColumnValue("ROW_COUNT");
} else {
return "Error: Count query failed.";
}
}
catch(err) {
return "Error: " + err.message;
}
return "The table has " + rowCount + " rows.";
//--------------------------- End of main function ---------------------------
function getResultSet(sql){
cmd1 = {sqlText: sql};
stmt = snowflake.createStatement(cmd1);
var rs;
rs = stmt.execute();
return rs;
}
$$;
call COUNT_EXAMPLE();

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