Skip to content

HGInsights/snowpack

Repository files navigation

Snowpack

CI hex.pm version hex.pm license Last Updated

Snowflake driver for Elixir.

⚠️ Important ⚠️ - Not in active development

This project is no longer under active development. Please consider these alternatives:

  • Avalanche: uses Snowflake's V2 REST API (For projects that do not need the ODBC driver)
  • Snowflex: uses the ODBC driver (like Snowpack)

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+

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

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.

Documentation

Documentation is automatically published to hexdocs.pm on release. You may build the documentation locally with

MIX_ENV=docs mix docs

Erlang ODBC on Apple M1

Install Dependencies via Homebrew

brew install asdf openssl@1.1 libiodbc wxwidgets

NOTE: you may need to unlink unixodbc to install and use libiodbc, or replace libiodbc with unixodbc below.

Configure your shell for asdf.

Install asdf plugins.

asdf plugin add erlang
asdf plugin add elixir

Configure the KERL compiler used by asdf.

export CFLAGS="-O2 -g -fno-stack-check"
export KERL_CONFIGURE_OPTIONS="--with-ssl=$(brew --prefix openssl@1.1)/ --with-wx-config=$(brew --prefix wxwidgets)/bin/wx-config --with-odbc=$(brew --prefix libiodbc)"
export CPPFLAGS="-I$(brew --prefix libiodbc)/include"
export LDFLAGS="-L$(brew --prefix libiodbc)/lib"

Install Erlang and Elixir

asdf install erlang 25.0.3
asdf install elixir 1.13.4-otp-25

Running tests locally

Copy over the contents from .env.test to .env.test.local:

cp .env.test .env.test.local

Generate an rsa_key for your Snowflake instance and replace the following env vars in .env.test.local (they have replace_me default values). It will look something like this:

SNOWPACK_DRIVER=/path/to/driver/libSnowflake.dylib
SNOWPACK_SERVER=something_like_this.snowflakecomputing.com
SNOWPACK_PRIV_KEY_FILE=/path/for/the/rsa_key.p8>

Notes:

  • /opt/snowflake/snowflakeodbc/lib/libSnowflake.dylib is the default on Macs.
  • You can learn more about them here
  • There is no need to load this to your env since we are using Vapor to handle config.

Contributing

Issues and PRs are welcome! See our organization CONTRIBUTING.md for more information about best-practices and passing CI.