{{announcement.body}}
{{announcement.title}}

Snowflake External Functions

DZone 's Guide to

Snowflake External Functions

In this article, we will demonstrate how to invoke an API via Amazon Web Services API Gateway that will trigger an AWS Lambda function.

· Big Data Zone ·
Free Resource

Introduction

Snowflake has recently announced external functions available in public preview. This allows developers to invoke external APIs from within their Snowflake SQL queries and blend the response into their query result, in the same way as if they were internal Snowflake functions.

In this article, we will demonstrate how to invoke an API via Amazon Web Services API Gateway that will trigger an AWS Lambda function. The Lambda function (written in Python) then  invokes a public API from to return the exchange rate for USD and multiple foreign currencies that can be used to calculate our sales values in USD and a number of selected currencies in SQL query running in our Snowflake warehouse. This solution eliminates the need for loading exchange rates into Snowflake regularly and also guarantees accurate, reliable real-time currency values.

Architecture

The solution architecture is as follows:

As mentioned about, Snowflake initiates the API request to AWS API Gateway using an External Function that is referred in an SQL statement.  AWS API Gateway triggers the Lambda function that will call the ExchangeRate-APO REST API and process the response returned in JSON. I will then pack the requested exchange rate into a Snowflake-defined JSON format so the External function can interpret the values and blend it into the query result in Snowflake. Similar architecture could be used to handle stock values, translated texts and many other publicly available APIs.

AWS Configuration

First we will need define the Lambda function, in our case it is written in Python (note: in the code below you need to replace XXXXXXX with your own API key for )

Python
 




x


 
1
import json
2
from botocore.vendored import requests
3
import logging
4
 
          
5
logger = logging.getLogger()
6
logger.setLevel(logging.DEBUG)
7
 
          
8
def lambda_handler(event, context):
9
    logger.debug('event input')
10
    logger.debug(event)
11
 
          
12
    event_data = event['data']
13
    logger.debug(event_data)
14
 
          
15
    currency = event_data[0][1]
16
    logger.debug(currency)
17
 
          
18
    requested_rate = []
19
    # HTTP Request using Exchange Rate API
20
    response = requests.get('https://v6.exchangerate-api.com/v6/XXXXXXXX/latest/USD')
21
    logger.debug(response.text)
22
    exchange_rates = json.loads(response.text) #load data into a dict of objects
23
    conversion_rates = exchange_rates['conversion_rates']
24
    logger.debug(conversion_rates)
25
    
26
    row_to_return = [0, conversion_rates[currency]]
27
    requested_rate.append(row_to_return)
28
    logger.debug(requested_rate)
29
    
30
    json_response = json.dumps({"data" : requested_rate})
31
    status_code = 200
32
    
33
    return {
34
        'statusCode': status_code,
35
        'data': requested_rate
36
    }
37
   



We can test the Lambda function using the Test feature e.g. with the following test event:

JSON
 




xxxxxxxxxx
1


1
{
2
  "data": [
3
    [
4
      0,
5
      "GBP"
6
    ]
7
  ]
8
}



If the Lambda function returned the JSON response as expected then we can expose it via API Gateway:


We need to define a REST POST method that can be invoked using a specific URL:


AWS API Gateway also provides a Client Test feature where we can specify the incoming request body and execute the end-to-end flow including the Lambda function.

Once the API Gateway works as expected, we can move over to Snowflake.

Snowflake Confguration

The first step is to create the API using the specific Snowflake SQL statement (note: the Account Id and the API-GW values need to be replaced with your own parameters from the AWS configuration described above) This will also require a particuar AWS IAM role (in our case called APIGW-Lambda) that allows the API Gateway call from Snowflake. This parameter is referred in the API_AWS_ROLE_ARN attribute below:

SQL
 




x


 
1
-- create API integration
2
create or replace api integration exchange_rate_api
3
   api_provider=aws_api_gateway
4
   api_aws_role_arn='arn:aws:iam::<Account ID>:role/APIGW-Lambda'
5
   api_allowed_prefixes=('https://<API-GW>.execute-api.us-east-1.amazonaws.com/Dev')
6
   enabled=true;



Then the next step is to define the External Function:

SQL
 




x


1
-- create external function
2
create or replace external function exchange_rate(input string)
3
   returns string
4
   api_integration = exchange_rate_api
5
   as 'https://<API-GW>.execute-api.us-east-1.amazonaws.com/Dev';



The AWS IAM Role needs to have an established trust relationship so we need to define a Trust Policy for this role:


JSON
 




x


 
1
    {
2
      "Effect": "Allow",
3
      "Principal": {
4
        "AWS": "arn:aws:iam::<ACCOUNT>:user/<SNOWFLAKE>"
5
      },
6
      "Action": "sts:AssumeRole",
7
      "Condition": {
8
        "StringEquals": {
9
          "sts:ExternalId": "<EXTERNAL ID>"
10
        }
11
      }
12
    }



The required values for the AWS trust policy can be retrieved using :

SQL
 




xxxxxxxxxx
1


1
describe integration exchange_rate_api;



And now we have everything ready to invoke the external function from Snowflake Worksheet:

SQL
 




x
14
9


1
create or replace table sales(name string, value_in_USD number);
2
 
          
3
insert into sales values ('Sales_1', 100);
4
 
          
5
select * from sales;
6
 
          
7
# Invoke the external function
8
select value_in_USD, exchange_rate('EUR')*value_in_USD as value_in_EUR, exchange_rate('GBP')*value_in_USD as value_in_GBP   from sales;   
9
 
          



And the result will look like this:


Conclusion

This tutorial demonstrates a simple use case of how we can embed external functions into Snowflake SQL and invoke 3rd-party APIs from within SQL. The Lambda function could be more elaborate to handle multiple rows but in general, it should provide you a fairly good understanding of how these functions and the API calls can be used. This can take our data warehouse toolset of built-in and user-defined-functions to the next level; I am really looking forward to seeing various real-life scenarios where external functions can provide great value. More details about Snowflake External Functions can be found  here.

Topics:
aws api gateway, aws lambda, big data, cloud analytics, cloud computing, snowflake

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}