So I want to accept postgress function which takes an argument to determine what all features should user have access to.
In Javascript/Typescript I would ideally do something like this
const a = ['featureA', 'featureB', 'featureC'];
function unlockFeatures (abc) {
let unlock = ''
if (abc.includes('featureA')) {
unlock = 'somethingA'
}
else if (abc.includes('featureB')) {
unlock = 'somethingB'
}
else if (abc.includes('featureC')) {
unlock = 'somethingC'
}
return unock
}
unlockFeatures(a)
How can I write equivalent of this in postgres/sql function where I can pass array to function?
Something like this, I guess
CREATE FUNCTION unlockFeatures(abc TEXT[])
RETURNS TEXT
LANGUAGE plpgsql AS $$
DECLARE
unlock TEXT:= '';
BEGIN
IF (SELECT 'featureA' = ANY($1)) THEN
unlock:= 'somethingA';
ELSIF (SELECT 'featureB' = ANY($1)) THEN
unlock:= 'somethingB';
ELSEIF (SELECT 'featureC' = ANY($1)) THEN
unlock:= 'somethingC';
END IF;
RETURN unlock;
END; $$;
Like the Javascript includes() method PostgreSQL has the ANY() function.
The CASE expression checks multiple condition.
At the end SQL function return last query:
CREATE OR REPLACE FUNCTION test(abc text[])
RETURNS text AS
$BODY$
SELECT case
when 'featureA' = any(abc) then 'somethingA'
when 'featureB' = any(abc) then 'somethingB'
when 'featureC' = any(abc) then 'somethingC'
end$BODY$
LANGUAGE sql VOLATILE
COST 100;
SELECT test(
ARRAY['featureA', 'featureB', 'featureC', 'featureD']
);
Related
I created a stored procedure that sets the certain variable value and executes merge using this variable. Currently, it just returns a hardcoded message "Successfully executed.".
Is it possible to return the same result as the original merge query returns, like
number of rows inserted
number of rows updated
?
CREATE OR REPLACE PROCEDURE ALERTS_MERGE_PROCEDURE ()
RETURNS STRING NOT NULL
LANGUAGE JAVASCRIPT
AS
$$
var sql_command = '
MERGE INTO tablename
..
WHEN MATCHED THEN
UPDATE SET ...
WHEN NOT MATCHED THEN
INSERT ...
);
'
snowflake.execute(
{
sqlText: sql_command
});
return "Successfully executed.";
$$;
You can iterate over the columns of the first row of the returned object from the execution:
create or replace temp table tablename as
select 1::int id, 'a'::string tx;
create or replace temp table tablesource as
select 1::int id, 'b'::string tx
union select 2, 'c';
CREATE OR REPLACE PROCEDURE ALERTS_MERGE_PROCEDURE ()
RETURNS STRING NOT NULL
LANGUAGE JAVASCRIPT
AS
$$
var sql_command = `
merge into tablename a
using tablesource b
on a.id = b.id
when matched then update set tx=b.tx
when not matched then insert (id, tx) values (b.id, b.tx);
`;
var x = snowflake.execute({sqlText: sql_command});
x.next();
var result = '';
for (i=1; i<=x.getColumnCount(); i++) {
result += x.getColumnName(i) + ': ' + x.getColumnValue(i) + '\n';
}
return result;
$$;
call alerts_merge_procedure();
Returns:
number of rows inserted: 1
number of rows updated: 1
Yes, look at the methods of the statement object. This is all documented here: https://docs.snowflake.com/en/sql-reference/stored-procedures-api.html#object-statement
I have a query that is select from an s3 bucket, but the value I need to select from changes each quarter - indicated below by {}. Is there anyway in snowflake I can write logic to be the most recent quarter
Select $1:date
from
'#lake.lake./s3key/{variable}/data.json.gzip' );
I would want to variable = 2021Q3, and then next quarter 2022Q1 ect
Is this possible? Or will I have to get python involved
I tried to use identifier for stages, but it does not seem to work.
I guess you can use Stored Procedure to achieve this.
create or replace procedure get_stage_data(quarter varchar)
returns string
language javascript
as
$$
var query = "Select $1::date from '#lake.lake./s3key/"+QUARTER+"/data.json.gzip";
var stmt = snowflake.createStatement({sqlText: query});
var res = stmt.execute();
var retVal = '';
while (res.next()) {
retVal += res.getColumnValue(1) + "\n"
}
return retVal;
$$;
Maybe write data to a table then you can analyze later.
I have a Snowflake procedure, for brevity, lets just say it just runs a query using snowflake.execute
var rs = snowflake.execute( { sqlText:
`
CREATE OR REPLACE VIEW DATABASE.SCHEMA.VIEW_NAME_HERE AS
SELECT
column1
,${stuff} as column2
,${morestuff} as column3
FROM DATABASE.SCHEMA.TABLE_SOURCE_HERE
`
} );
return rs
How do i return rs so that it shows the query that it's running? I'm just getting an [object object] result.
The Statement object has a method called getSqlText():
https://docs.snowflake.com/en/sql-reference/stored-procedures-api.html#getSqlText
CREATE OR REPLACE PROCEDURE my_proc()
RETURNS STRING
LANGUAGE JAVASCRIPT
EXECUTE AS OWNER
AS
$$
snowflake.execute( {sqlText: "create or replace table test (col string)"} );
var column = 'col';
var stmt = snowflake.createStatement( {sqlText: `SELECT MAX(${column}) FROM test`} );
var ret = stmt.execute();
return stmt.getSqlText();
$$ ;
call my_proc();
It returns:
SELECT MAX(col) FROM test
I can't get a multiline SQL statement to work within a procedure/javascript without putting \ after each line.
This works:
CREATE or replace PROCEDURE PR_DELETEME()
RETURNS VARCHAR
LANGUAGE javascript
AS
$$
var rs = snowflake.execute( { sqlText:
'create or replace table deleteme as select sysdate() as my_date;'
} );
return 'Done.';
$$;
This fails:
CREATE or replace PROCEDURE PR_DELETEME()
RETURNS VARCHAR
LANGUAGE javascript
AS
$$
var rs = snowflake.execute( { sqlText:
'create or replace table deleteme as
select sysdate() as my_date;'
} );
return 'Done.';
$$;
call PR_DELETEME(); gives...
JavaScript compilation error: Uncaught SyntaxError: Invalid or unexpected token in PR_DELETEME at ' 'create or replace table deleteme as' position 6
I really don't want to have to put \ at the end of each line.
Use "backticks" not single quotes or double quotes. Below now works:
CREATE or replace PROCEDURE PR_DELETEME()
RETURNS VARCHAR
LANGUAGE javascript
AS
$$
var rs = snowflake.execute( { sqlText:
`create or replace table deleteme as
select sysdate() as sysd;`
} );
return 'Done.';
$$;
How can i recreate a while function in snowflake example:
WHILE #counter <= #LastRow
BEGIN
SELECT #DateLoad = CONVERT (date, SUNDAY)
FROM [Staging].[Stg_EC_WeeksLoad]
WHERE SEQUENCE = #counter;
EXEC #return_value = [dbo].[pETLFillFact_Demographics_History] #Date = #DateLoad;
SET #counter = #counter + 1;
END
Snowflake supports expressing stored procedures in JavaScript, and JavaScript supports multiple looping constructs including while (condition).
A rough translation of the described logic as a Snowflake procedure would appear as follows:
CREATE OR REPLACE PROCEDURE looping_process()
RETURNS BOOLEAN
LANGUAGE JAVASCRIPT
AS
$$
// Get 'LastRow' dynamically, or set/pass a constant alternatively
var row_count_query = snowflake.createStatement({ sqlText: "SELECT * FROM SOURCE_TABLE" });
var _resultSet = row_count_query.execute();
var LastRow = row_count_query.getRowCount();
var counter = 0;
while (counter <= LastRow) {
// Get the dynamic date value by applying the counter
var seq_query = `SELECT SUNDAY::DATE AS "DateLoad" FROM "Staging"."Stg_EC_WeeksLoad" WHERE SEQUENCE = $counter`;
var seq_stmt = snowflake.createStatement({ sqlText: seq_query });
var seq_result = seq_stmt.execute(); seq_result.next();
var DateLoad = seq_result.getColumnValue("DateLoad");
// Construct and run the nested procedure call with value found above
var sub_call_query = `CALL "dbo"."pETLFillFact_Demographics_History"($DateLoad)`;
var sub_call_stmt = snowflake.createStatement({ sqlText: sub_call_query });
var sub_call_result = sub_call_stmt.execute(); sub_call_stmt.next();
var return_value = sub_call_result.getColumnValue(1);
// Increment for the next loop
counter += 1;
}
// (… add other omitted logic, to return/error-handle/etc. …)
$$
;
Working with Loops:
Snowflake Scripting supports the following types of loops:
FOR
WHILE
REPEAT
LOOP
Query in question could be translated as:
DECLARE
c1 CURSOR FOR select SUNDAY::date AS DateLoad
from Staging.Stg_EC_WeeksLoad order by SEQUENCE;
BEGIN
FOR record IN c1 DO
CALL pETLFillFact_Demographics_History(record.DateLoad);
END FOR;
END;
An example of the WHILE specific syntax (from the Snowflake docs) looks like this:
while (condition) {
// Do something ...
}