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

Add snowflake adapter #65

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

ssilwal29
Copy link

@ssilwal29 ssilwal29 commented Apr 25, 2020

Hi! new to vim and tried to follow current pattern for adapters to add support for Snowflake.
I am using snowsql to query snowflake https://docs.snowflake.com/en/user-guide/snowsql.html. Let me know if something doesnt look right and needs to change or not a good way in vim.

Thanks for this package!

*dadbod-snowflake*
Snowflake
>
snowflake://[<accountname>.snowflakecomputing.com]/?[username=<username>&dbname=<dbname>&warehouse=<warehouse>]
Copy link
Owner

@tpope tpope Mar 10, 2021

Choose a reason for hiding this comment

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

Absent a strong reason to do otherwise, this should support the user@host/dbname syntax. Something like

snowflake://[<user>@][<accountname>][/<database>][?warehouse=<warehouse>]

Depending on how `warehouse works exactly, I could see doing something like one of the following:

snowflake://[<user>@][<accountname>]/[<database>[/<warehouse>]]
snowflake://[<user>@][<accountname>]/[<warehouse>[/<database>]]

The idea is you shouldn't have to remember if it's user= or username=, or dbname= or database=, just construct a URL like any other.

Copy link

@AM-I-Human AM-I-Human Oct 3, 2023

Choose a reason for hiding this comment

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

It seems to be possible:
https://stackoverflow.com/questions/59203578/how-to-access-and-already-existing-snowflake-database-with-a-flask-application

'snowflake://<user_login_name>:<password>@<account_name>/<database_name>/<schema_name>?warehouse=<warehouse_name>&role=<role_name>'

I don't know how it works the repo and stuff, but if I found how to that I will fork and make a Pull request

Copy link
Contributor

Choose a reason for hiding this comment

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

Hi @tpope,
I am doing a lot of work in Snowflake ATM and looking at picking this back up as a Quality of Life improvement for myself.

Would you be open a url format like
snowflake:connection:[<warehouse>]/[<database>]/?options, similar to the bigquery adapter?
Here, connection would be specified in the snowsql config file as shown here

Unfortunately, Snowflake does not support passing passwords as a CLI argument, it must be read in from this snowsql config file. Warehouse is a required field, it determines who is billed for any queries executed using the connection. I have it as optional here since it can be provided in the snowsql config as well.

There's a world where snowflake://uname@account/... could be supported by looking for the connection username_account in snowsql config, but this seems like it would be too restrictive/confusing to configure, since the actual username and account parameters would be overridden by whatever is in the snowsql config.

Copy link
Owner

Choose a reason for hiding this comment

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

Hi @tpope, I am doing a lot of work in Snowflake ATM and looking at picking this back up as a Quality of Life improvement for myself.

Would you be open a url format like snowflake:connection:[<warehouse>]/[<database>]/?options, similar to the bigquery adapter? Here, connection would be specified in the snowsql config file as shown here

I think URLs should be supported as a baseline, but a shorthand for named connections could make sense. It's unclear to me if you're saying connection here is the name of a connection or the literal word "connection".

Unfortunately, Snowflake does not support passing passwords as a CLI argument, it must be read in from this snowsql config file. Warehouse is a required field, it determines who is billed for any queries executed using the connection. I have it as optional here since it can be provided in the snowsql config as well.

Looking at the docs, we could use SNOWFLAKE_PASSWORD. The SQL Server adapter demonstrates how to use environment variables.

It seems to be possible: https://stackoverflow.com/questions/59203578/how-to-access-and-already-existing-snowflake-database-with-a-flask-application

'snowflake://<user_login_name>:<password>@<account_name>/<database_name>/<schema_name>?warehouse=<warehouse_name>&role=<role_name>'

This looks perfect. It could be worth digging into how exactly that's implemented.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry I wasn't clear enough. connection there is the name of the connection.

SNOWFLAKE_PASSWORD could work. One of my uses cases is to sign in to different environments in the same vim session, which use different accounts, so setting it even per-project is probably not going to cut it. I will dig a bit & come back.

The URL support from the stackoverflow post is in SQLAlchemy, which uses the snowflake-connector-python library (see here) which has sane URL support. This behavior is explicitly disallowed by their CLI tool SnowSQL. I could hack together a wrapper using the python connector, but would prefer not to when there is already an existing solution.

Thanks for the fast reply (& for making Vim so usable)!

Copy link
Owner

Choose a reason for hiding this comment

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

I've been looking into this. I'm guessing that stackoverflow example would create a SQLAlchemy engine (official docs). The URL schema that create_engine uses is detailed in this section. There's then this place where the connection args are generated from the url, and from there I think we could trace down how to implement the snowflake connection.

Right, you're most of the way there, just need to find the url.translate_connect_args() that's used for Snowflake.

Choose a reason for hiding this comment

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

Here we go!

(In snowflake-sqlalchemy, the actual SQLAlchemy dialect that wraps snowflake-connector-python)

Copy link
Contributor

Choose a reason for hiding this comment

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

Apols for lack of attention, got a puppy this weekend and things have been hectic.

I have an implementation working with all but password using the snowsql cli. Is it worth bringing all this python code into this project as opposed to compromising on password provision and just documenting the required steps?

Copy link
Owner

Choose a reason for hiding this comment

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

Is it worth bringing all this python code into this project as opposed to compromising on password provision and just documenting the required steps?

No need for either. Use SNOWFLAKE_PASSWORD, like this:

return (has_key(url, 'password') ? ['env', 'SQLCMDPASSWORD=' . url.password] : []) +

Copy link
Contributor

Choose a reason for hiding this comment

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

You have taught me a valuable vimscript lesson. Thank you! Pr tom

@AM-I-Human
Copy link

I tried to connect using this, but it says that snowflake adapter does not exists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants