Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Snowflake - Connection Cell and SQL Cell #61

Merged
merged 9 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions lib/assets/connection_cell/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,10 @@ export function init(ctx, info) {
type: String,
default: "Select secret",
},
required: {
type: Boolean,
default: false,
},
},

methods: {
Expand Down Expand Up @@ -245,6 +249,7 @@ export function init(ctx, info) {
readonly
@click="selectSecret"
@input="$emit('update:secretInputValue', $event.target.value)"
:required="!secretInputValue && required"
/>
<BaseInput
v-else
Expand All @@ -255,6 +260,7 @@ export function init(ctx, info) {
inputClass="input input-icon-text"
:grow
@input="$emit('update:textInputValue', $event.target.value)"
:required="!textInputValue && required"
/>
<div class="icon-container">
<label class="hidden-checkbox">
Expand Down Expand Up @@ -579,11 +585,82 @@ export function init(ctx, info) {
`,
};

const SnowflakeForm = {
name: "SnowflakeForm",

components: {
BaseInput: BaseInput,
BaseSwitch: BaseSwitch,
BaseSelect: BaseSelect,
BaseSecret: BaseSecret,
},

props: {
fields: {
type: Object,
default: {},
},
},

template: `
<div class="row">
<BaseInput
name="username"
label="User name"
type="text"
v-model="fields.username"
inputClass="input"
:grow
:required
/>
<BaseInput
name="account"
label="Account"
type="text"
v-model="fields.account"
inputClass="input"
:grow
:required
/>
</div>
<div class="row">
<BaseInput
name="database"
label="Database"
type="text"
v-model="fields.database"
inputClass="input"
:grow
/>
<BaseInput
name="schema"
label="Schema"
type="text"
v-model="fields.schema"
inputClass="input"
:grow
/>
<BaseSecret
textInputName="password"
secretInputName="password_secret"
toggleInputName="use_password_secret"
label="Password"
v-model:textInputValue="fields.password"
v-model:secretInputValue="fields.password_secret"
v-model:toggleInputValue="fields.use_password_secret"
modalTitle="Set password"
:required
/>
</div>
`,
};

const app = Vue.createApp({
components: {
BaseInput: BaseInput,
BaseSelect: BaseSelect,
SQLiteForm: SQLiteForm,
SnowflakeForm: SnowflakeForm,
DefaultSQLForm: DefaultSQLForm,
BigQueryForm: BigQueryForm,
AthenaForm: AthenaForm,
Expand Down Expand Up @@ -619,6 +696,7 @@ export function init(ctx, info) {
</div>

<SQLiteForm v-bind:fields="fields" v-if="isSQLite" />
<SnowflakeForm v-bind:fields="fields" v-if="isSnowflake" />
<BigQueryForm v-bind:fields="fields" v-bind:helpBox="helpBox" v-if="isBigQuery" />
<AthenaForm v-bind:fields="fields" v-bind:helpBox="helpBox" v-bind:hasAwsCredentials="hasAwsCredentials" v-if="isAthena" />
<DefaultSQLForm v-bind:fields="fields" v-if="isDefaultDatabase" />
Expand All @@ -639,6 +717,7 @@ export function init(ctx, info) {
{ label: "SQLite", value: "sqlite" },
{ label: "Google BigQuery", value: "bigquery" },
{ label: "AWS Athena", value: "athena" },
{ label: "Snowflake", value: "snowflake" },
],
};
},
Expand All @@ -648,6 +727,10 @@ export function init(ctx, info) {
return this.fields.type === "sqlite";
},

isSnowflake() {
return this.fields.type === "snowflake";
},

isBigQuery() {
return this.fields.type === "bigquery";
},
Expand Down
1 change: 1 addition & 0 deletions lib/assets/sql_cell/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ export function init(ctx, payload) {
sqlite: "SQLite",
bigquery: "Google BigQuery",
athena: "AWS Athena",
snowflake: "Snowflake",
},
};
},
Expand Down
56 changes: 55 additions & 1 deletion lib/kino_db/connection_cell.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ defmodule KinoDB.ConnectionCell do
"token" => attrs["token"] || "",
"region" => attrs["region"] || "us-east-1",
"workgroup" => attrs["workgroup"] || "",
"output_location" => attrs["output_location"] || ""
"output_location" => attrs["output_location"] || "",
"account" => attrs["account"] || "",
"schema" => attrs["schema"] || ""
}

ctx =
Expand Down Expand Up @@ -129,6 +131,11 @@ defmodule KinoDB.ConnectionCell do
else:
~w|access_key_id secret_access_key token region workgroup output_location database|

"snowflake" ->
if fields["use_password_secret"],
do: ~w|database schema account username password_secret|,
else: ~w|database schema account username password|

type when type in ["postgres", "mysql"] ->
if fields["use_password_secret"],
do: ~w|database hostname port use_ipv6 username password_secret|,
Expand Down Expand Up @@ -157,6 +164,12 @@ defmodule KinoDB.ConnectionCell do
else: ~w|access_key_id secret_access_key_secret region database|
)

"snowflake" ->
if(Map.has_key?(attrs, "password_secret"),
do: ~w|account username password_secret|,
else: ~w|account username password|
)

type when type in ["postgres", "mysql"] ->
~w|hostname port|
end
Expand Down Expand Up @@ -193,6 +206,17 @@ defmodule KinoDB.ConnectionCell do
end
end

defp to_quoted(%{"type" => "snowflake"} = attrs) do
quote do
:ok = Adbc.download_driver!(:snowflake)
uri = unquote(build_snowflake_uri(attrs))
{:ok, db} = Kino.start_child({Adbc.Database, driver: :snowflake, uri: uri})

{:ok, unquote(quoted_var(attrs["variable"]))} =
Kino.start_child({Adbc.Connection, database: db})
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
quote do
:ok = Adbc.download_driver!(:snowflake)
uri = unquote(build_snowflake_uri(attrs))
{:ok, db} = Kino.start_child({Adbc.Database, driver: :snowflake, uri: uri})
{:ok, unquote(quoted_var(attrs["variable"]))} =
Kino.start_child({Adbc.Connection, database: db})
end
var = quoted_var(attrs["variable"])
quote do
:ok = Adbc.download_driver!(:snowflake)
uri = unquote(build_snowflake_uri(attrs))
{:ok, db} = Kino.start_child({Adbc.Database, driver: :snowflake, uri: uri})
{:ok, unquote(var)} = Kino.start_child({Adbc.Connection, database: db})
end

end

defp to_quoted(%{"type" => "postgres"} = attrs) do
quote do
opts = unquote(shared_options(attrs))
Expand Down Expand Up @@ -324,6 +348,7 @@ defmodule KinoDB.ConnectionCell do
Code.ensure_loaded?(Exqlite) -> "sqlite"
Code.ensure_loaded?(ReqBigQuery) -> "bigquery"
Code.ensure_loaded?(ReqAthena) -> "athena"
Code.ensure_loaded?(Adbc) -> "snowflake"
true -> "postgres"
end
end
Expand Down Expand Up @@ -358,6 +383,12 @@ defmodule KinoDB.ConnectionCell do
end
end

defp missing_dep(%{"type" => "snowflake"}) do
unless Code.ensure_loaded?(Adbc) do
~s|{:adbc, "~> 0.1.0"}|
end
end

defp missing_dep(_ctx), do: nil

defp join_quoted(quoted_blocks) do
Expand Down Expand Up @@ -397,4 +428,27 @@ defmodule KinoDB.ConnectionCell do
do: true,
else: (_ -> false)
end

defp build_snowflake_uri(attrs), do: build_snowflake_uri(attrs, quoted_pass(attrs))

defp build_snowflake_uri(attrs, password) when is_binary(password) do
"#{attrs["username"]}:#{password}@#{attrs["account"]}"
|> build_database_and_schema(attrs)
end

defp build_snowflake_uri(%{"username" => username, "account" => account} = attrs, password) do
rest = build_database_and_schema("@#{account}", attrs)

quote do
unquote("#{username}:") <> unquote(password) <> unquote(rest)
end
end

defp build_database_and_schema(uri, %{"database" => ""}), do: uri

defp build_database_and_schema(uri, %{"database" => database, "schema" => ""}),
do: "#{uri}/#{database}"

defp build_database_and_schema(uri, %{"database" => database, "schema" => schema}),
do: "#{uri}/#{database}/#{schema}"
end
20 changes: 19 additions & 1 deletion lib/kino_db/sql_cell.ex
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ defmodule KinoDB.SQLCell do
_ -> nil
end
else
_ -> nil
_ -> connection_from_adbc(connection)
end
end

Expand All @@ -136,6 +136,15 @@ defmodule KinoDB.SQLCell do

defp connection_type(_connection), do: nil

defp connection_from_adbc(connection) when is_pid(connection) do
with true <- Code.ensure_loaded?(Adbc),
true <- is_snowflake_conn?(connection) do
"snowflake"
else
_ -> nil
end
end

@impl true
def to_attrs(ctx) do
%{
Expand Down Expand Up @@ -166,6 +175,10 @@ defmodule KinoDB.SQLCell do
to_quoted(attrs, quote(do: Exqlite), fn n -> "?#{n}" end)
end

defp to_quoted(%{"connection" => %{"type" => "snowflake"}} = attrs) do
to_quoted(attrs, quote(do: Adbc.Connection), fn n -> "?#{n}" end)
end

defp to_quoted(%{"connection" => %{"type" => "bigquery"}} = attrs) do
to_req_quoted(attrs, fn _n -> "?" end, :bigquery)
end
Expand Down Expand Up @@ -271,4 +284,9 @@ defmodule KinoDB.SQLCell do
defp parameterize(<<char::utf8, rest::binary>>, raw, params, n, next) do
parameterize(rest, <<raw::binary, char::utf8>>, params, n, next)
end

defp is_snowflake_conn?(conn) when conn == self(), do: false
defp is_snowflake_conn?(conn) when is_pid(conn), do: is_snowflake_conn?(:sys.get_state(conn))
defp is_snowflake_conn?(%{queue: _, lock: _, conn: conn}) when is_reference(conn), do: true
defp is_snowflake_conn?(_), do: false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
defp is_snowflake_conn?(conn) when conn == self(), do: false
defp is_snowflake_conn?(conn) when is_pid(conn), do: is_snowflake_conn?(:sys.get_state(conn))
defp is_snowflake_conn?(%{queue: _, lock: _, conn: conn}) when is_reference(conn), do: true
defp is_snowflake_conn?(_), do: false
defp snowflake_conn?(conn) when conn == self(), do: false
defp snowflake_conn?(conn) when is_pid(conn), do: is_snowflake_conn?(:sys.get_state(conn))
defp snowflake_conn?(%{queue: _, lock: _, conn: conn}) when is_reference(conn), do: true
defp snowflake_conn?(_), do: false

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adbc.Connection.get_driver

end
1 change: 1 addition & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ defmodule KinoDB.MixProject do
{:exqlite, "~> 0.11", optional: true},
{:myxql, "~> 0.6.2 or ~> 0.7", optional: true},
{:db_connection, "~> 2.4.2", optional: true},
{:adbc, github: "elixir-explorer/adbc", branch: "main", optional: true},
{:req_bigquery, "~> 0.1.0", optional: true},
{:req_athena, "~> 0.1.1", optional: true},
{:ex_doc, "~> 0.28", only: :dev, runtime: false}
Expand Down
Loading
Loading