How to pass a stored procedure as a parameter in snowflake - snowflake-cloud-data-platform

I have a stored procedure which takes the name of another stored procedure to call on it and with the parameters
However when I try to execute this stored procedure I get an error
What am I doing wrong? From my code below I think I know how to call on a passed stored procedure however I am wondering if it is my syntax that is incorrect.
CREATE OR REPLACE PROCEDURE "ADMINDB"."TOOLKIT".LOG_PROCEDURES("P_PROCEDURE_NAME" VARCHAR, "P_PROCEDURE_PARAMETERS" VARCHAR)
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT='Inserts into the table PROCEDURE_LOGGING information about the last runned procedure'
EXECUTE AS CALLER
AS
$$
var v = P_PROCEDURE_PARAMETERS;
var v_sqlCode;
if(P_PROCEDURE_PARAMETERS.length > 0){
v_sqlCode = `CALL ` + P_PROCEDURE_NAME + `(` + P_PROCEDURE_PARAMETERS + `)`;
}else{
return "there was no parameter passed";
}
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
return "success!";
$$;
CREATE OR REPLACE PROCEDURE "ADMINDB"."TOOLKIT".TESTFORLOG("P" VARCHAR)
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT='Inserts into the table PROCEDURE_LOGGING information about the last runned procedure'
EXECUTE AS CALLER
AS
$$
var v_sqlCode = 'CREATE TABLE ' + P + `(name varchar)`;
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
return "success!";
$$;
CALL ADMINDB.TOOLKIT.LOG_PROCEDURES('TESTFORLOG','P');

Combining all of the above comments, here are updated stored procedures which are working when I test here on my dev account.
Notes:
be careful with the context and use fully qualified names where possible if doing cross schema/database object references
review your query history when debugging
backticks are awesome for SQL, I have one sample with and one without in the below
I like having the SQL in one block (with backticks) and then doing the replace, as illustrated.
CREATE OR REPLACE PROCEDURE sp_stacko_1(p1 varchar, p2 varchar)
RETURNS VARCHAR
LANGUAGE javascript
EXECUTE AS caller
AS
$$
var p_procedure_name = P1;
var p_params = P2;
if(p_params.length > 0) {
v_sqlCode = `
CALL <p_procedure_name>('<p_params>')
`;
v_sqlCode = v_sqlCode.replace("<p_procedure_name>", p_procedure_name);
v_sqlCode = v_sqlCode.replace("<p_params>", p_params);
}
else {
return "there was no parameter passed";
}
try {
snowflake.execute({sqlText: v_sqlCode});
}
catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
return "success!";
$$;
CREATE OR REPLACE PROCEDURE sp_stacko_2(p3 varchar)
RETURNS VARCHAR
LANGUAGE javascript
EXECUTE AS caller
AS
$$
var p_table_name = P3;
var v_sqlCode = "CREATE TABLE <table_name> (name varchar)";
v_sqlCode = v_sqlCode.replace("<table_name>", p_table_name);
try {
snowflake.execute({sqlText: v_sqlCode});
}
catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
return "success!";
$$;
CALL sp_stacko_1('sp_stacko_2','P');

Related

Invalid Identifier when passing a string into sql query in snowflake

I have a stored procedure which takes a string(SCHEMA_NAME) as a parameter
It then puts this string name into a query
The problem I am facing is when I pass the parameter into the sql query I get a
Invalid identifier error
Below is my code and what I have tried
CREATE OR REPLACE PROCEDURE "CREATE_SCHEMA"("SCHNAME" VARCHAR(16777216))
RETURNS VARCHAR(16777216)
LANGUAGE JAVASCRIPT
COMMENT='Creates schemas'
EXECUTE AS CALLER
AS
$$
var v_sqlCode = "select * from dbschemas where name = " + "''" + SCHNAME + "''";
try{
var sqlStmt = snowflake.createStatement({sqlText:v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
$$;
I have tried writing my sql query in three ways
1. var v_sqlCode = `select * from dbschemas where name = `+ SCHNAME;
2. var v_sqlCode = "select * from dbschemas where name = " + "''" + SCHNAME + "''"
3.var v_sqlCode = `SELECT * FROM DBSCHEMAS WHERE NAME = {$SCHENAME}`
The way in which I call the stored procedure is as follows : CALL CREATE_SCHEMA('SCHEMA_NAME');
Any help would be greatly appreciated.
It is recommended to parametrize query to be executed instead of concatenating the SQL query string.
More info: Binding variables
CREATE OR REPLACE PROCEDURE CREATE_SCHEMA(SCHNAME VARCHAR(16777216))
RETURNS VARCHAR(16777216)
LANGUAGE JAVASCRIPT
COMMENT='Creates schemas'
EXECUTE AS CALLER
AS
$$
var v_sqlCode = "select * from dbschemas where name = ?";
try{
var sqlStmt = snowflake.createStatement({sqlText:v_sqlCode, binds:[SCHNAME]});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
$$;
Call:
CALL CREATE_SCHEMA('SCHEMA_NAME');

Inserting into a table snowflake with a passed variable

I have a table which has 3 attributes
ATTRIBUTE DATATYPE FLAG( 0 OR 1)
My stored procedure takes a string of records in the form
"Att1 Datatype1 1, Att2 Datatype2 0, Att3 Datatype3 0...)
so for example a passed string can be
"DATABASE VARCHAR 1, SCHEMA VARCHAR 1, TIMESTAMP TIMESTAMP 0"
My code gets the column names of the table and stores it in a string
My code takes the passed string and puts them into array elements seperated by the ,
However the issue arrises when I try to do an insertion into my table
I keep getting the error "invalid Identifier"
CREATE OR REPLACE PROCEDURE "ADMINDB"."TOOLKIT".ADD_ATTRIBUTES_SESSION_META ("P_ATTRIBUTE_DATATYPE_FLAG" VARCHAR(16777216))
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT='Add Attributes to the table SESSION_ATTRIBUTES_META'
EXECUTE AS CALLER
AS
$$
var v_list = P_ATTRIBUTE_DATATYPE_FLAG;
var arr_list = [];
arr_list = P_ATTRIBUTE_DATATYPE_FLAG.split(',');
var v_string;
var arr_col_att = [];
var v_sqlCode = `SELECT * FROM ` + "ADMINDB" + "." + "TOOLKIT" + "." + "SESSION_ATTRIBUTES_META";
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
for (i = 1; i <= sqlStmt.getColumnCount(); i++) {
arr_col_att.push(sqlStmt.getColumnName(i));
}
arr_col_att[0] = arr_col_att[0].replace(/\s/g, ',');
var v_col_att = arr_col_att.toString();
v_string = arr_list[0].toString();
v_string = v_string.replace(/\s/g, ',');
v_sqlCode = `INSERT INTO ` + "ADMINDB" + "." + "TOOLKIT" + "."
+ "SESSION_ATTRIBUTES_META" + `(` + v_col_att + `) VALUES( ` + v_string + `)`;
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
return "SUCCESS!";
$$;
CALL "ADMINDB"."TOOLKIT".ADD_ATTRIBUTES_SESSION_META('DATABASE VARCHAR 1,SCHEMA VARCHAR 1,TIMESTAMP TIMESTAMP 0');
Modifying line 33 and 36, fixes the issue:
CREATE OR REPLACE PROCEDURE "ADMINDB"."TOOLKIT".ADD_ATTRIBUTES_SESSION_META ("P_ATTRIBUTE_DATATYPE_FLAG" VARCHAR(16777216))
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT='Add Attributes to the table SESSION_ATTRIBUTES_META'
EXECUTE AS CALLER
AS
$$
var v_list = P_ATTRIBUTE_DATATYPE_FLAG;
var arr_list = [];
arr_list = P_ATTRIBUTE_DATATYPE_FLAG.split(',');
var v_string;
var arr_col_att = [];
var v_sqlCode = `SELECT * FROM ` + "ADMINDB" + "." + "TOOLKIT" + "." + "SESSION_ATTRIBUTES_META";
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
for (i = 1; i <= sqlStmt.getColumnCount(); i++) {
arr_col_att.push(sqlStmt.getColumnName(i));
}
arr_col_att[0] = arr_col_att[0].replace(/\s/g, ',');
var v_col_att = arr_col_att.toString();
v_string = arr_list[0].toString();
v_string = v_string.replace(/\s/g, "','" );
v_sqlCode = `INSERT INTO ` + "ADMINDB" + "." + "TOOLKIT" + "."
+ "SESSION_ATTRIBUTES_META" + `(` + v_col_att + `) VALUES( '` + v_string + `' )`;
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
return "SUCCESS!";
$$;
CALL "ADMINDB"."TOOLKIT".ADD_ATTRIBUTES_SESSION_META('DATABASE VARCHAR 1,SCHEMA VARCHAR 1,TIMESTAMP TIMESTAMP 0');
As far I see, you haven't implemented the process multiple records in the argument for now, but I think you can handle it.

Creating a temp table in stored procedure with SQL and Snowflake

I have a stored procedure which gets the session variables
in snowflake. I want to store these variables in a temporary table
so then I can use it later on.
My logic works but I am unable to write the syntax correctly. Any help would be greatly appreciated.
Here is my code
CREATE OR REPLACE PROCEDURE GET_CONTEXT()
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT = 'Saves current database and current schema in an array'
EXECUTE AS CALLER
AS
$$
var arr_context = [];
v_sqlCode = "SELECT CURRENT_DATABASE(), CURRENT_SCHEMA()";
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
var v_sqlCode = "CREATE TEMPORARY TABLE TEMP_HOLDER (DATABASE VARCHAR(16777216), SCHEMA VARCHAR(16777216))";
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS2 = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
v_sqlCode = "INSERT INTO TEMP_HOLDER(DATABASE, SCHEMA)
VALUES(" + sqlRS.getColumnValue(1) + ", "+sqlRS.getColumnValue(2)+")";
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + sqlRS.getColumnValue(1);
errMessage += "\nStack Trace:\n" + err.stackTraceTxt;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
$$;
CALL GET_CONTEXT();
This simplifies it. It also changes the column names from DATABASE and SCHEMA, which are reserved keywords, by prefixing with THE_ such as THE_DATABASE.
CREATE OR REPLACE PROCEDURE GET_CONTEXT()
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT = 'Saves current database and current schema in an array'
EXECUTE AS CALLER
AS
$$
let v_sqlCode = "create or replace temp table TEMP_HOLDER as select current_database() as THE_DATABASE,current_schema() as THE_SCHEMA";
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + sqlRS.getColumnValue(1);
errMessage += "\nStack Trace:\n" + err.stackTraceTxt;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
$$;

Obtaining column name from array of strings and using it to alter SQL Table

I am writing a stored procedure in SQL which accepts a String. The string contains a list of column names which contain the column name and the type
ex) "NAME VARCHAR, AGE NUMBER"
ALTER TABLE T1
ADD COLUMN NAME VARCHAR
I am working with Snowflake
My logic is correct, however I am struggling to properly write the syntax
In the code below, the alter table statement with the array is where I am stuck
Any help would be greatly appreciated
CREATE OR REPLACE PROCEDURE ADD_COLUMNS_CONTEXTUAL_ATTRIBUTES("P_COL_NAME_SPACE_TYPE" VARCHAR(16777216))
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT = 'Turns column string list into array'
EXECUTE AS CALLER
AS
$$
var arr = [];
var v_storing_passed_parameter = P_COL_NAME_SPACE_TYPE;
arr = v_storing_passed_parameter.split(',');
for (i = 0; i < arr.length; i++){
try{
var v_sqlCode = ***`ALTER TABLE CONTEXTUAL_ATTRIBUTES
ADD COLUMN ' + arr[i];***
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
};
return "success";
$$;
CALL ADD_COLUMNS_CONTEXTUAL_ATTRIBUTES('AGE NUMBER, NAME VARCHAR');
Here you go:
CREATE OR REPLACE PROCEDURE ADD_COLUMNS_CONTEXTUAL_ATTRIBUTES("P_COL_NAME_SPACE_TYPE" VARCHAR(16777216))
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT = 'Turns column string list into array'
EXECUTE AS CALLER
AS
$$
var arr = [];
var v_storing_passed_parameter = P_COL_NAME_SPACE_TYPE;
arr = v_storing_passed_parameter.split(',');
for (i = 0; i < arr.length; i++){
try{
var v_sqlCode = `ALTER TABLE CONTEXTUAL_ATTRIBUTES ADD COLUMN ${arr[i]}`;
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
};
return "success";
$$;

USE DATABASE in stored procedure

I am trying to set my database inside the stored procedure, but getting errors, Any advice? Thanks in advance
Below code return error "Unsupported statement type 'USE'."
CREATE PROCEDURE PROC_TEST()
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
AS
$$
try{
var my_sql_command = "USE DATABASE EDWH_DEV";
var statement1 = snowflake.createStatement( {sqlText: my_sql_command} );
statement1.execute();
result = "Succeeded";
}
catch (err) {
result = "Failed: Code: " + err.code + "\n State: " + err.state;
result += "\n Message: " + err.message;
result += "\nStack Trace:\n" + err.stackTraceTxt;
}
return result;
$$;
CALL PROC_TEST();
You need to include line, On which privilege the procedure need to execute:
Include line: execute as caller It will work
CREATE or replace PROCEDURE PROC_TEST()
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
execute as caller
AS
$$
try{
var my_sql_command = "USE DATABASE GCP";
var statement1 = snowflake.createStatement( {sqlText: my_sql_command} );
statement1.execute();
result = "Succeeded";
}
catch (err) {
result = "Failed: Code: " + err.code + "\n State: " + err.state;
result += "\n Message: " + err.message;
result += "\nStack Trace:\n" + err.stackTraceTxt;
}
return result;
$$;

Resources