snowflake
The snowflake plugin allows you to view and read Snowflake data. It supports establishing and closing connections to Snowflake, listing tables and views visible to the current Snowflake role in a specified database or schema, and retrieving column metadata for table schemas or query results. For data reads, the plugin can load Snowflake tables or query results into DolphinDB in-memory tables. It can also write table data or query results in batches to existing DolphinDB tables.
Writing DolphinDB data to Snowflake is not currently supported.
-
To download large amounts of data, see the official Snowflake documentation.
Prerequisites
A valid CA certificate and an RSA private key file must be configured on the server hosting DolphinDB Server.
The system clock on the server hosting DolphinDB Server must be accurate. Otherwise, JWT authentication may fail when the token's issue or expiration time is validated.
Create a Snowflake organization account, user, warehouse, database, and schema.
Generate a public key that matches the RSA private key on the server hosting DolphinDB Server, and configure the public key for the Snowflake user.
ALTER USER [USERNAME] SET RSA_PUBLIC_KEY = 'RSA public key'
Installation
Version Requirements
DolphinDB Server 2.00.16+ or 3.00.4+, and the package type is Linux x86_64 or Linux x86_64 ABI.
Installation Steps
In a DolphinDB client, use the listRemotePlugins function to view the plugins available for installation.
login("admin", "123456") listRemotePlugins()Use the installPlugin function to install the plugin.
installPlugin("snowflake")Use the loadPlugin function to load the plugin.
loadPlugin("snowflake")
Method References
connect
Syntax
snowflake::connect(config)
Details
Connects to a Snowflake database and returns a connection handle.
This method uses JWT for Snowflake key-pair authentication. When establishing a connection, the plugin reads the RSA private key from the local file path specified by "privateKeyPath" and generates a JWT based on "account" and "user". The plugin sends the JWT to Snowflake in the Authorization request header. Snowflake validates the JWT against the RSA public key preconfigured for the corresponding user and authenticates the user if validation succeeds.
Parameters
config is a dictionary (Dictionary<STRING, ANY>) specifying the connection settings. It supports the following key-value pairs:
| Key | Value | Required |
|---|---|---|
"account" |
A STRING scalar specifying the account identifier in the Snowflake organization, without specifying the region. The identifier must use the format "organization-account", for example, "WJCYPAV-TD40511". |
Yes |
"user" |
A STRING scalar specifying the user name in the Snowflake account. |
Yes |
"privateKeyPath" |
A STRING scalar specifying the path to the RSA private key file on DolphinDB Server. |
Yes |
"warehouse" |
A STRING scalar specifying the warehouse that provides the compute resources. The default is "warehouse". |
Yes |
"database" |
A STRING scalar specifying the database to access. The default is "database". |
Yes |
"schema" |
A STRING scalar specifying the schema in the database. The default is "schema". |
Yes |
"role" |
A STRING scalar specifying the role used to connect to Snowflake. The default is the role configured for the Snowflake user. |
No |
"options" |
is a dictionary (Dictionary<STRING, ANY>) specifying settings such as the hostname, JWT, polling interval, and timeouts. See the following table for details. |
No |
The options dictionary supports the following key-value pairs:
| Key | Value |
|---|---|
"host" |
A STRING scalar specifying the Snowflake hostname. Enter only the hostname; do not include a protocol such as |
"privateKeyPassphrase" |
A STRING scalar specifying the passphrase used to decrypt the RSA private key. Configure this option only when the local RSA private key is encrypted. The default is an empty string. |
"jwtLifetimeSeconds" |
An integer scalar in the range [1, 3600] specifying the JWT lifetime in seconds. The default is 3600. |
"jwtRefreshMarginSeconds" |
An integer scalar in the range [0, 3600] specifying how many seconds before expiration the JWT is refreshed. The plugin refreshes the JWT when the remaining time before expiration is less than this value. This value must be less than jwtLifetimeSeconds. The default is 300. |
"connectTimeoutSeconds" |
A positive integer scalar specifying the timeout, in seconds, for libcurl to establish a TCP/TLS connection. The default is 10. |
"requestTimeoutSeconds" |
A positive integer scalar specifying the timeout, in seconds, for a Snowflake statement request. This parameter sets only the timeout in the request body; it does not specify the total timeout for the entire libcurl HTTP request. The default is 60. |
"pollIntervalMillis" |
A positive integer scalar specifying the polling interval, in milliseconds, after the SQL API returns 202. The default is 500. |
"maxPollSeconds" |
A positive integer scalar specifying the maximum polling time for an asynchronous statement, in seconds. The default is 3600. |
"maxRetry" |
A nonnegative integer scalar specifying the number of retries for 429, 500, 502, 503, 504, and libcurl request errors; the total number of attempts is limited to |
"proxy" |
A STRING scalar specifying the HTTP/HTTPS proxy to use with libcurl. The default is an empty string, indicating that no proxy is configured. |
Returns
A connection handle.
Example
// Basic configuration
config = dict(STRING, ANY)
config["account"] = "myorg-myaccount"
config["user"] = "DDB_READER"
config["privateKeyPath"] = "/opt/dolphindb/keys/snowflake_rsa_key.p8"
config["warehouse"] = "DDB_WH"
config["database"] = "SALES_DB"
config["schema"] = "PUBLIC"
config["role"] = "DDB_READER_ROLE"
// Set the private key passphrase and timeout through the options dictionary
connOptions = dict(STRING, ANY)
connOptions["privateKeyPassphrase"] = "<PRIVATE_KEY_PASSPHRASE>"
connOptions["connectTimeoutSeconds"] = 20
connOptions["requestTimeoutSeconds"] = 120
connOptions["pollIntervalMillis"] = 1000
connOptions["maxPollSeconds"] = 1800
connOptions["maxRetry"] = 5
config["options"] = connOptions
conn = snowflake::connect(config)
close
Syntax
snowflake::close(conn)
Details
Closes the specified connection. After the connection is closed, passing its handle to any plugin method causes the method to return the following error: Invalid connection object.
Parameters
conn is a connection handle created by connect.
Returns
The string "Connection is closed."
showTables
Syntax
snowflake::showTables(conn, [database], [schema])
Details
Shows the tables or views visible to the current Snowflake user.
Parameters
conn is a connection handle created by connect.
database is a STRING scalar specifying the database to query. The default is the database specified when the corresponding connection handle was created.
schema is a STRING scalar specifying the schema to query. The default is the schema specified when the corresponding connection handle was created.
Returns
A table containing the following columns, or an empty table if no visible objects are found:
| Column Name | Data Type | Description |
|---|---|---|
database |
STRING |
Snowflake database. |
schema |
STRING |
The schema of the Snowflake database. |
name |
STRING |
The name of a Snowflake table or view. |
kind |
STRING |
The type of the Snowflake database object, such as BASE TABLE or VIEW. |
Example
// Query the connection's default database and schema
objects = snowflake::showTables(conn)
// Specify the database while using the connection's default schema
objects = snowflake::showTables(conn, "ARCHIVE_DB")
// Specify both the database and schema
objects = snowflake::showTables(conn, "ARCHIVE_DB", "REPORTING")
// Specify only the schema; set the database parameter to NULL
objects = snowflake::showTables(conn, NULL, "REPORTING")
extractTableSchema
Syntax
snowflake::extractTableSchema(conn, sourceTableName)
Details
Obtains the schema of a Snowflake table.
Parameters
conn is a connection handle created by connect.
sourceTableName is a STRING scalar specifying the Snowflake table name. Table names can use one-, two-, or three-part formats: TABLE_NAME, SCHEMA_NAME.TABLE_NAME, or DATABASE_NAME.SCHEMA_NAME.TABLE_NAME.
Returns
A table containing the following columns:
| Column Name | Data Type | Description |
|---|---|---|
name |
STRING |
The normalized DolphinDB column name. Column names are normalized according to the following rules:
|
type |
STRING |
The DolphinDB data type automatically mapped from the Snowflake data type. |
snowflakeType |
STRING |
The raw data type returned by the Snowflake SQL API. |
precision |
INT |
The precision in Snowflake metadata. If it is not provided in the metadata, -1 is returned. |
scale |
INT |
The number of decimal places in Snowflake metadata. If it is not provided in the metadata, 0 is returned. |
nullable |
BOOL |
Indicates whether the column allows NULL values. The value is taken from Snowflake metadata. |
extractQuerySchema
Syntax
snowflake::extractQuerySchema(conn, sql)
Details
Executes the specified SELECT statement against a Snowflake table to obtain the schema of the query result.
Parameters
conn is a connection handle created by connect.
sql is a STRING scalar specifying the query SQL statement. The plugin removes the trailing semicolon from the SQL statement and wraps the query in a statement similar to the following:
SELECT *
FROM (<sql>) AS SNOWFLAKE_PLUGIN_SCHEMA
WHERE 1 = 0
Therefore, sql must be a SELECT statement that can be used as a subquery. Do not pass DDL or DML statements to this method.
Returns
A table containing the following columns:
| Column Name | Data Type | Description |
|---|---|---|
name |
STRING |
The normalized DolphinDB column name. Column names are normalized according to the following rules:
|
type |
STRING |
The DolphinDB data type automatically mapped from the Snowflake data type. |
snowflakeType |
STRING |
The raw data type returned by the Snowflake SQL API. |
precision |
INT |
The precision in Snowflake metadata. If it is not provided in the metadata, -1 is returned. |
scale |
INT |
The number of decimal places in Snowflake metadata. If it is not provided in the metadata, 0 is returned. |
nullable |
BOOL |
Indicates whether the column allows NULL values. The value is taken from Snowflake metadata. |
loadTable
Syntax
snowflake::loadTable(conn, sourceTableName, [options])
Details
Loads data from a Snowflake table and returns it as a DolphinDB in-memory table.
Parameters
conn is a connection handle created by connect.
sourceTableName is a STRING scalar specifying the Snowflake table name. Table names can use one-, two-, or three-part formats: TABLE_NAME, SCHEMA_NAME.TABLE_NAME, or DATABASE_NAME.SCHEMA_NAME.TABLE_NAME.
options (optional) is a dictionary (Dictionary<STRING, ANY>) supporting the keys "columnSchema", "offset", "limit", and "allowEmptyResult". For details, see Common Parameter for Data Query Methods.
Returns
A DolphinDB in-memory table.
Example
// Do not specify additional options
orders = snowflake::loadTable(conn, "SALES_DB.PUBLIC.ORDERS")
// Return data in pages
options = dict(STRING, ANY)
options["offset"] = 1000
options["limit"] = 500
options["allowEmptyResult"] = true
ordersPage = snowflake::loadTable(
conn,
"SALES_DB.PUBLIC.ORDERS",
options
)
// User-defined column types
columnSchema = table(
["order_id", "customer", "amount"] as name,
["LONG", "STRING", "DOUBLE"] as type
)
options = dict(STRING, ANY)
options["columnSchema"] = columnSchema
orders = snowflake::loadTable(
conn,
"SALES_DB.PUBLIC.ORDER_SUMMARY",
options
)
query
Syntax
snowflake::query(conn, sql, [options])
Details
Executes the specified SELECT statement on a Snowflake table and returns the query results as a DolphinDB in-memory table.
Parameters
conn is a connection handle created by connect.
sql is a STRING scalar specifying the query SQL statement. The plugin removes the trailing semicolon from the SQL statement and wraps the query in a statement similar to the following:
SELECT *
FROM (<sql>) AS SNOWFLAKE_PLUGIN_SCHEMA
WHERE 1 = 0
Therefore, sql must be a SELECT statement that can be used as a subquery. Do not pass DDL or DML statements to this method.
options (optional) is a dictionary (Dictionary<STRING, ANY>) supporting the keys "columnSchema" and "allowEmptyResult". For details, see Common Parameter for Data Query Methods.
query does not support "offset" or "limit" in options. Specify LIMIT, OFFSET, and ORDER BY directly in the SQL statement.
Returns
A DolphinDB in-memory table.
Example
// Do not specify additional options
sql = "SELECT ORDER_ID, AMOUNT FROM SALES_DB.PUBLIC.ORDERS WHERE AMOUNT > 100 ORDER BY ORDER_ID"
result = snowflake::query(conn, sql)
// Return data in pages
sql = "SELECT ORDER_ID, AMOUNT FROM SALES_DB.PUBLIC.ORDERS ORDER BY ORDER_ID LIMIT 500 OFFSET 1000"
options = dict(STRING, ANY)
options["allowEmptyResult"] = true
result = snowflake::query(conn, sql, options)
loadTableInto
Syntax
snowflake::loadTableInto(conn, sourceTableName, targetTable, [options])
Details
Loads data from a Snowflake table and writes it to a DolphinDB table.
Writes are not guaranteed to be transactionally atomic. Partitions are written sequentially. If a later partition fails after earlier partitions have been written successfully, the previously written data is not rolled back automatically. To ensure atomicity, first write the data to a temporary table. After validating the data, use a script to replace the production table with the temporary table.
Parameters
conn is a connection handle created by connect.
sourceTableName is a STRING scalar specifying the Snowflake table name. Table names can use one-, two-, or three-part formats: TABLE_NAME, SCHEMA_NAME.TABLE_NAME, or DATABASE_NAME.SCHEMA_NAME.TABLE_NAME.
targetTable is a DolphinDB in-memory table or DFS table.
options (optional) is a dictionary (Dictionary<STRING, ANY>) supporting the keys "columnSchema", "offset", "limit", and "batchTransform". For details, see Common Parameter for Data Query Methods.
Returns
None.
Example
// Write to a DolphinDB in-memory table
target = table(
100000:0,
`order_id`customer`amount,
[LONG, STRING, DOUBLE]
)
writtenRows = snowflake::loadTableInto(
conn,
"SALES_DB.PUBLIC.ORDER_SUMMARY",
target
)
// Limit the number of rows read
options = dict(STRING, ANY)
options["limit"] = 10000
writtenRows = snowflake::loadTableInto(
conn,
"SALES_DB.PUBLIC.ORDER_SUMMARY",
target,
options
)
queryInto
Syntax
snowflake::queryInto(conn, sql, targetTable, [options])
Details
Executes the specified SELECT statement on a Snowflake table and writes the query results to a DolphinDB table.
Writes are not guaranteed to be transactionally atomic. Partitions are written sequentially. If a later partition fails after earlier partitions have been written successfully, the previously written data is not rolled back automatically. To ensure atomicity, first write the data to a temporary table. After validating the data, use a script to replace the production table with the temporary table.
Parameters
conn is a connection handle created by connect.
sql is a STRING scalar specifying the query SQL statement. The plugin removes the trailing semicolon from the SQL statement and wraps the query in a statement similar to the following:
SELECT *
FROM (<sql>) AS SNOWFLAKE_PLUGIN_SCHEMA
WHERE 1 = 0
Therefore, sql must be a SELECT statement that can be used as a subquery. Do not pass DDL or DML statements to this method.
targetTable is a DolphinDB in-memory table or DFS table.
options (optional) is a dictionary (Dictionary<STRING, ANY>) supporting the keys "columnSchema" and "batchTransform". For details, see Common Parameter for Data Query Methods.
queryInto does not support "offset" or "limit" in options. Specify LIMIT, OFFSET, and ORDER BY directly in the SQL statement.
Returns
None.
Example
// Write to a DolphinDB in-memory table
target = table(
100000:0,
`order_id`customer`amount,
[LONG, STRING, DOUBLE]
)
sql = "SELECT ORDER_ID, CUSTOMER, AMOUNT FROM SALES_DB.PUBLIC.ORDERS ORDER BY ORDER_ID"
writtenRows = snowflake::queryInto(conn, sql, target)
// Write to a DolphinDB DFS table
target = loadTable("dfs://sales", `orders)
sql = "SELECT ORDER_ID, CUSTOMER, AMOUNT FROM SALES_DB.PUBLIC.ORDERS"
writtenRows = snowflake::queryInto(conn, sql, target)
Common Parameter for Data Query Methods
loadTable, query, loadTableInto,
and queryInto all support the options parameter. The
supported key-value pairs are listed in the following table. The set of supported
keys varies by method. Passing an unsupported key causes the method call to
fail.
| Key | Value | Methods Supporting This Key |
|---|---|---|
|
"columnSchema" |
A table used to override result column names and target data types. The table must meet the following conditions:
|
|
|
"offset" |
"offset" specifies the number of rows to skip before returning data, and "limit" specifies the maximum number of rows to return.
|
|
|
"limit" |
||
|
"allowEmptyResult" |
A BOOL scalar that specifies whether an empty table can be returned. The default is false.
|
|
|
"batchTransform" |
A user-defined DolphinDB function that processes batches of data.
|
|
Supported Data Types
Snowflake and DolphinDB Data Type Mapping
The plugin maps types based on thetype, precision, and scale in the metadata returned by the Snowflake SQL API, rather than determining them solely from the type names used in the table-creation DDL.
| Snowflake Metadata Type | Condition | Automatically Mapped DolphinDB Type |
|---|---|---|
fixed, number, decimal, numeric |
|
INT |
|
LONG |
|
|
STRING |
|
|
DOUBLE |
|
real, float, double |
Any |
DOUBLE |
boolean, bool |
Any |
BOOL |
All other metadata types |
Any |
STRING |
The following Snowflake data types are currently mapped to STRING:
CHAR, VARCHAR, TEXT
DATE, TIME
TIMESTAMP_NTZ, TIMESTAMP_LTZ, TIMESTAMP_TZ
BINARY, VARBINARY
ARRAY, OBJECT, VARIANT
GEOGRAPHY, GEOMETRY, VECTOR
All other types not listed in the mapping rules above
For types mapped to STRING, the returned value is the textual representation of the value returned by the Snowflake SQL API. In particular, do not currently assume that the return values for DATE, TIME, or TIMESTAMP are native DolphinDB temporal types.
Target Types Supported by columnSchema
columnSchema supports the following target types and aliases. Type names are case-insensitive.
| Type Name | Available Aliases | Accepted Non-NULL Text |
|---|---|---|
BOOL |
BOOLEAN, DT_BOOL, DT_BOOLEAN |
true, false, 1, or 0; case-insensitive |
INT |
DT_INT |
A decimal integer that can be parsed in full and whose value falls within the range representable by DolphinDB INT. |
LONG |
DT_LONG |
A decimal integer that can be parsed in full and whose value falls within the range representable by DolphinDB LONG. |
DOUBLE |
DT_DOUBLE |
Text that can be fully parsed as a DolphinDB DOUBLE. |
STRING |
DT_STRING |
Any non-empty text. |
SYMBOL |
DT_SYMBOL |
Any non-empty text. |
Non-NULL text refers to the textual representation of a non-NULL field value returned by the Snowflake SQL API.
If columnSchema specifies a type not included in the list above, the API returns the following error: schema type ... is not supported yet
NULL Values and Type Conversion
When requesting data from the Snowflake SQL API, the plugin sets nullable=true and processes the returned values according to the following rules:
Snowflake SQL NULL: Returned as JSON null and converted to the NULL value of the corresponding DolphinDB type.
The string "null": Treats it as an ordinary string rather than NULL.
Non-NULL empty string: DolphinDB uses an empty string to represent NULL. Consequently, directly converting a non-NULL empty string from Snowflake would incorrectly interpret it as NULL, so the plugin blocks the conversion and reports an error.
Non-NULL numeric value: If a non-NULL numeric value returned by Snowflake equals the NULL representation of the corresponding DolphinDB type, directly converting it would incorrectly interpret it as NULL. To prevent data errors, the plugin blocks the conversion and reports an error. For example, the minimum INT value returned by Snowflake, the minimum LONG value, and any numeric value equal to the DolphinDB DOUBLE NULL representation cannot be converted as non-NULL values.
Numeric conversion: Numeric text must be fully parsed as the target type. A conversion error is returned if the text contains extra characters or exceeds the range representable by the target type.
NUMBER/DECIMAL: When
scale != 0, the value is mapped to DOUBLE by default, which may result in floating-point precision loss. To preserve the original numeric text exactly, specify the column as STRING through columnSchema.
Complete Example
Example 1: The following example demonstrates the complete workflow: loading the plugin, establishing a connection, viewing objects, retrieving the schema, querying data, writing data to a target table, and closing the connection.
// 1. Load the plugin
loadPlugin("snowflake")
// 2. Create a connection
config = dict(STRING, ANY)
config["account"] = "myorg-myaccount"
config["user"] = "DDB_READER"
config["privateKeyPath"] = "/opt/dolphindb/keys/snowflake_rsa_key.p8"
config["warehouse"] = "DDB_WH"
config["database"] = "SALES_DB"
config["schema"] = "PUBLIC"
config["role"] = "DDB_READER_ROLE"
conn = snowflake::connect(config)
// 3. List visible objects
objects = snowflake::showTables(conn)
// 4. Inspect the query result schema
sql = "SELECT ORDER_ID, CUSTOMER, AMOUNT FROM SALES_DB.PUBLIC.ORDERS ORDER BY ORDER_ID"
sourceSchema = snowflake::extractQuerySchema(conn, sql)
// 5. Return a small result directly as an in-memory table
options = dict(STRING, ANY)
options["allowEmptyResult"] = true
preview = snowflake::query(conn, sql + " LIMIT 100", options)
// 6. Write a large result to an existing target table in batches
target = table(
100000:0,
`order_id`customer`amount,
[LONG, STRING, DOUBLE]
)
columnSchema = table(
["order_id", "customer", "amount"] as name,
["LONG", "STRING", "DOUBLE"] as type
)
writeOptions = dict(STRING, ANY)
writeOptions["columnSchema"] = columnSchema
writtenRows = snowflake::queryInto(conn, sql, target, writeOptions)
// 7. Close the connection when finished
snowflake::close(conn)
Example 2: Use columnSchema to explicitly specify target types.
columnSchema = table(
["order_id", "customer", "amount"] as name,
["LONG", "STRING", "DOUBLE"] as type
)
options = dict(STRING, ANY)
options["columnSchema"] = columnSchema
target = table(
100000:0,
`order_id`customer`amount,
[LONG, STRING, DOUBLE]
)
sql = "SELECT ORDER_ID, CUSTOMER, AMOUNT FROM SALES_DB.PUBLIC.ORDERS"
writtenRows = snowflake::queryInto(conn, sql, target, options)
