Add JSONB Support for Snowflake
This guide shows you how to enable JSONB support in PromptQL for Snowflake data sources using native queries in Hasura DDN. It should be used as a template and modified to fit your own schema.
For JSONB support, we need two things:
- A native query — which is your own custom SQL — to retrieve the relevant information.
- Descriptions added to the metadata to augment PromptQL’s knowledge of the data source.
Create a new project with the Snowflake connector enabled
If you haven’t done so already, complete the steps in our guide for connecting Snowflake to PromptQL.
Create a native query
Native queries enable you to write your own SQL and expose it as a root-level field in your GraphQL API. This field will then also be available to PromptQL for retrieving data from your Snowflake instance. We can use the existing JSON operator built into Snowflake to transform a column’s value into structured JSON.
As an example, imagine we have a table called USERS
in an database called ECOMM
; if the user_details
are stored as
a string — but are in fact JSON — we can use a native query to return the structured output to our API:
--- This will return the user_id and email in their existing format, while transforming the user_details to JSON:
select user_id, email, TO_JSON(user_details) as user_details, created_at from PUBLIC.ECOMM.USERS
We can then include this SQL in a native query by adding it to the nativeQueries
object of our configuration.json
found in our connector’s directory:
"nativeQueries": {
"ECOMM_USERS": {
"sql": {
"parts": [
{
"type": "text",
"value": "select user_id, email, TO_JSON(user_details) as user_details, created_at from PUBLIC.ECOMM.USERS"
}
]
},
"columns": {
"USER_DETAILS": {
"type": "named",
"name": "STRING"
},
"USER_ID": {
"type": "named",
"name": "BIGINTEGER"
},
"CREATED_AT": {
"type": "named",
"name": "TIMESTAMP"
},
"EMAIL": {
"type": "named",
"name": "STRING"
}
},
"arguments": {},
"description": null,
"isProcedure": false
}
}
The key of the new object is the name which will be exposed as a top-level field in your API. After adding your custom SQL, include the returned columns along with their types.
Click to see an explanation of the fields
nativeQueries
Description: A top-level object containing all native query definitions.
Structure: Each key represents the name of a native query, and the value defines its configuration.
Query Name (e.g., ECOMM_USERS)
Description: A unique identifier for the native query. This name is used to reference the query in the application.
sql
Description: Specifies the SQL query for the native query.
Structure: Contains a parts
array where each part has:
- type: Indicates the type of part. Currently, only
text
is supported. - value: The actual SQL query as a string.
columns
Description: Maps the output columns of the SQL query to their types.
Structure: An object where each key represents a column name and the value specifies its type.
- type: Defines how the column type is specified. Typically
named
. - name: The name of the data type. The data type must match the types supplied by the connector in the data connector link configuration.
arguments
Description: Defines any arguments required by the query. Used for parameterized queries.
Structure: An object where each key is the argument name and the value specifies its type and properties. If no
arguments are needed, this is an empty object.
description
Description: An optional field for adding a human-readable description of the query.
Structure: A string value or null
if no description is provided.
isProcedure
Description: Indicates whether the native query represents a mutation or a query.
Structure: A boolean value (true
for mutations and false
for queries).
Re-introspect your connector
As you’ve made a new field available in your connector’s configuration, you’ll need to re-introspect your connector:
ddn connector introspect <connector-name>
Add the model
Then, add the new model using the name you provided in your native query’s key:
# E.g., ddn model add my_snowflake "ECOMM_USERS"
ddn model add <connector-name> "<model-name>"
This will generate an HML file, which you’ll use in the next step, representing your model.
Augment the metadata description
The more context afforded to PromptQL, the better it understands your data and the ways it can interact with it. If we add a description to the metadata object, PromptQL will infer that structured JSON will be returned.
For example:
kind: ObjectType
version: v1
definition:
name: EcommUsers
fields:
- name: createdAt
type: Timestamp!
- name: email
type: String_1!
- name: userDetails
type: String_1!
description:
"This is stringified JSON it has the following fields: address, shipping_state, phone, preferences is an object
which has newsletter and theme {address: '123 Main St', shipping_state: 'CA', phone: '555-555-5555',
preferences: {newsletter: true, theme: 'dark'}}"
- name: userId
type: Biginteger!
graphql:
typeName: EcommUsers
inputTypeName: EcommUsersInput
dataConnectorTypeMapping:
- dataConnectorName: snow
dataConnectorObjectType: ECOMM_USERS
fieldMapping:
createdAt:
column:
name: CREATED_AT
email:
column:
name: EMAIL
userDetails:
column:
name: USER_DETAILS
userId:
column:
name: USER_ID
Here, we’re not only explaining that this is stringified JSON, but also an example of what can be expected to be returned.
Create a new build and start your services
First, create a new build:
ddn supergraph build local
Then, start your services and open the development console:
ddn run docker-start
ddn console --local
Talk to your data
Ask any questions you wish about your Snowflake data…including those that utilize your structured JSON directly from Snowflake!
If you run into issues, first try executing a query in the GraphiQL explorer and ensure your native query is behaving as expected.