View Source Snowpack (Snowpack v0.7.3)

Snowflake driver for Elixir.

features

Features

  • Automatic decoding and encoding of Elixir values to and from Snowflake's ODBC driver formats
  • Supports transactions, prepared queries, pooling and more via DBConnection
  • Supports Snowflake ODBC Drivers 2.24.7+

todo

TODO

usage

Usage

Add :snowpack to your dependencies:

def deps() do
  [
    {:snowpack, "~> 0.6.0"}
  ]
end

Make sure you are using the latest version!

opts = [
  connection: [
    role: "DEV",
    warehouse: System.get_env("SNOWFLAKE_WH"),
    uid: System.get_env("SNOWFLAKE_UID"),
    pwd: System.get_env("SNOWFLAKE_PWD")
  ]
]

{:ok, pid} = Snowpack.start_link(opts)
Snowpack.query!(pid, "select current_user()")

Snowpack.query(pid, "SELECT * FROM data")
{:ok,
 %Snowpack.Result{
   columns: ["id", "title"],
   num_rows: 3,
   rows: [[1, "Data 1"], [2, "Data 2"], [3, "Data 3"]]
 }}

It's recommended to start Snowpack under a supervision tree:

defmodule MyApp.Application do
  use Application

  def start(_type, _args) do
    children = [
      {Snowpack, uid: "snowflake-uid", name: :snowpack}
    ]

    opts = [strategy: :one_for_one, name: MyApp.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

and then we can refer to it by its :name:

Snowpack.query!(:snowpack, "SELECT NOW()").rows
[[~N[2018-12-28 13:42:31]]]

data-representation

Data representation

Snowflake ODBC       Elixir
-----                ------
NULL                 nil
bool                 true | false
int                  42
float                42.0
decimal              42.0 # (1)
date                 ~D[2013-10-12]
time                 ~T[00:37:14]
datetime             ~N[2013-10-12 00:37:14]  # (2)
timestamp            ~U[2013-10-12 00:37:14Z] # (2)
char                 "é"
text                 "snowpack"
binary               <<1, 2, 3>>
bit                  <<1::size(1), 0::size(1)>>
array                [1, 2, 3]
object               %{key: "value"}

Notes:

  1. See Decimal

  2. Datetime fields are represented as NaiveDateTime, however a UTC DateTime can be used for encoding as well.

Link to this section Summary

Functions

Returns a supervisor child specification for a DBConnection pool.

Closes a prepared query.

Executes a prepared query.

Executes a prepared query.

Prepares a query to be executed later.

Prepares and executes a query in a single step.

Prepares and executes a query in a single step.

Starts the connection process and connects to Snowflake.

Return the transaction status of a connection.

Link to this section Types

@type conn() :: DBConnection.conn()
@type option() :: DBConnection.option()
@type query_option() :: {:parse_results, boolean()} | DBConnection.option()
Link to this type

snowflake_conn_option()

View Source
@type snowflake_conn_option() ::
  {:dsn, String.t()}
  | {:driver, String.t()}
  | {:server, String.t()}
  | {:role, String.t()}
  | {:warehouse, String.t()}
  | {:database, String.t()}
  | {:schema, String.t()}
  | {:uid, String.t()}
  | {:pwd, String.t()}
  | {:authenticator, String.t()}
  | {:token, String.t()}
  | {:priv_key_file, String.t()}
  | {:priv_key_file_pwd, String.t()}
@type start_option() ::
  {:connection, snowflake_conn_option()} | DBConnection.start_option()

Link to this section Functions

@spec child_spec([start_option()]) :: :supervisor.child_spec()

Returns a supervisor child specification for a DBConnection pool.

Link to this function

close(conn, query, opts \\ [])

View Source
@spec close(conn(), Snowpack.Query.t(), [option()]) :: :ok | {:error, Exception.t()}

Closes a prepared query.

Returns :ok on success, or raises an exception if there was an error.

options

Options

Options are passed to DBConnection.close/3, see it's documentation for all available options.

Link to this function

execute!(conn, query, params, opts \\ [])

View Source
@spec execute!(conn(), Snowpack.Query.t(), list(), keyword()) :: Snowpack.Result.t()

Executes a prepared query.

Returns %Snowpack.Result{} on success, or raises an exception if there was an error.

See: execute/4.

Link to this function

execute(conn, query, params, opts \\ [])

View Source
@spec execute(conn(), Snowpack.Query.t(), list(), [query_option()]) ::
  {:ok, Snowpack.Query.t(), Snowpack.Result.t()} | {:error, Exception.t()}

Executes a prepared query.

options

Options

Options are passed to DBConnection.execute/4, see it's documentation for all available options.

examples

Examples

iex> {:ok, query} = Snowpack.prepare(conn, "", "SELECT ? * ?")
iex> {:ok, %Snowpack.Result{rows: [row]}} = Snowpack.execute(conn, query, [2, 3])
iex> row
[6]
Link to this function

prepare!(conn, name, statement, opts \\ [])

View Source
@spec prepare!(conn(), iodata(), iodata(), [query_option()]) :: Snowpack.Query.t()

Prepares a query.

Returns %Snowpack.Query{} on success, or raises an exception if there was an error.

See prepare/4.

Link to this function

prepare(conn, name, statement, opts \\ [])

View Source
@spec prepare(conn(), iodata(), iodata(), [query_option()]) ::
  {:ok, Snowpack.Query.t()} | {:error, Exception.t()}

Prepares a query to be executed later.

To execute the query, call execute/4. To close the query, call close/3. If a name is given, the name must be unique per query, as the name is cached but the statement isn't. If a new statement is given to an old name, the old statement will be the one effectively used.

options

Options

Options are passed to DBConnection.prepare/3, see it's documentation for all available options.

additional-options

Additional Options

  • :parse_results - Wether or not to do type parsing on the results. Requires execution to be performed inside a transaction and an extra DESCRIBE RESULT to get the types of the columns in the result. Only important for SELECT queries. Default true.

examples

Examples

iex> {:ok, query} = Snowpack.prepare(conn, "", "SELECT ? * ?")
iex> {:ok, %Snowpack.Result{rows: [row]}} = Snowpack.execute(conn, query, [2, 3])
iex> row
[6]
Link to this function

prepare_execute!(conn, name, statement, params \\ [], opts \\ [])

View Source
@spec prepare_execute!(conn(), iodata(), iodata(), list(), [query_option()]) ::
  {Snowpack.Query.t(), Snowpack.Result.t()}

Prepares and executes a query in a single step.

Returns {%Snowpack.Query{}, %Snowpack.Result{}} on success, or raises an exception if there was an error.

See: prepare_execute/5.

Link to this function

prepare_execute(conn, name, statement, params \\ [], opts \\ [])

View Source
@spec prepare_execute(conn(), iodata(), iodata(), list(), keyword()) ::
  {:ok, Snowpack.Query.t(), Snowpack.Result.t()} | {:error, Exception.t()}

Prepares and executes a query in a single step.

multiple-results

Multiple results

If a query returns multiple results (e.g. it's calling a procedure that returns multiple results) an error is raised. If a query may return multiple results it's recommended to use stream/4 instead.

options

Options

Options are passed to DBConnection.prepare_execute/4, see it's documentation for all available options.

additional-options

Additional Options

  • :parse_results - Wether or not to do type parsing on the results. Requires execution to be performed inside a transaction and an extra DESCRIBE RESULT to get the types of the columns in the result. Only important for SELECT queries. Default true.

examples

Examples

iex> {:ok, _query, %Snowpack.Result{rows: [row]}} = Snowpack.prepare_execute(conn, "", "SELECT ? * ?", [2, 3])
iex> row
[6]
Link to this function

query!(conn, statement, params \\ [], opts \\ [])

View Source
@spec query!(conn(), iodata(), list(), [query_option()]) :: Snowpack.Result.t()

Runs a query.

Returns %Snowpack.Result{} on success, or raises an exception if there was an error.

See query/4.

Link to this function

query(conn, statement, params \\ [], options \\ [])

View Source
@spec query(conn(), iodata(), list(), [query_option()]) ::
  {:ok, Snowpack.Result.t()} | {:error, Exception.t()}

Runs a query.

options

Options

Options are passed to DBConnection.prepare/3, see it's documentation for all available options.

additional-options

Additional Options

  • :parse_results - Wether or not to do type parsing on the results. Requires execution to be performed inside a transaction and an extra DESCRIBE RESULT to get the types of the columns in the result. Only important for SELECT queries. Default true.

examples

Examples

iex> Snowpack.query(conn, "SELECT * FROM RECORDS")
{:ok, %Snowpack.Result{}}

iex> Snowpack.query(conn, "INSERT INTO RECORDS (ROW1, ROW2) VALUES(?, ?)", [1, 2], parse_results: false)
@spec start_link([start_option()]) :: {:ok, pid()} | {:error, Snowpack.Error.t()}

Starts the connection process and connects to Snowflake.

options

Options

snowflake-connection-options

Snowflake Connection Options

See: https://docs.snowflake.com/en/user-guide/odbc-parameters.html#required-connection-parameters

  • :connection
    • :dsn - Specifies the name of your DSN

    • :driver - Snowflake ODBC driver path

    • :server - Specifies the hostname for your account

    • :role - Specifies the default role to use for sessions initiated by the driver

    • :warehouse - Specifies the default warehouse to use for sessions initiated by the driver

    • :database - Specifies the default database to use for sessions initiated by the driver

    • :schema - Specifies the default schema to use for sessions initiated by the driver (default: public)

    • :uid - Specifies the login name of the Snowflake user to authenticate

    • :pwd - A password is required to connect to Snowflake

    • :authenticator - Specifies the authenticator to use for verifying user login credentials

    • :token - Specifies the token to use for token based authentication

    • :priv_key_file - Specifies the local path to the private key file

dbconnection-options

DBConnection Options

The given options are passed down to DBConnection, some of the most commonly used ones are documented below:

  • :after_connect - A function to run after the connection has been established, either a 1-arity fun, a {module, function, args} tuple, or nil (default: nil)

  • :pool - The pool module to use, defaults to built-in pool provided by DBconnection

  • :pool_size - The size of the pool

See DBConnection.start_link/2 for more information and a full list of available options.

examples

Examples

Start connection using basic User / Pass configuration:

iex> {:ok, pid} = Snowpack.start_link(connection: [server: "account-id.snowflakecomputing.com", uid: "USER", pwd: "PASS"])
{:ok, #PID<0.69.0>}

Start connection using DNS configuration:

iex> {:ok, pid} = Snowpack.start_link(connection: [dsn: "snowflake"])
{:ok, #PID<0.69.0>}

Run a query after connection has been established:

iex> {:ok, pid} = Snowpack.start_link(connection: [dsn: "snowflake"], after_connect: &Snowpack.query!(&1, "SET time_zone = '+00:00'"))
{:ok, #PID<0.69.0>}
Link to this function

status(conn, opts \\ [])

View Source
@spec status(conn(), opts :: Keyword.t()) :: DBConnection.status()

Return the transaction status of a connection.