Skip to content

Commit 10cc97e

Browse files
committed
Add support for Snowflake CLI alongside SnowSQL
- Add g:db_adapter_snowflake_use_cli variable to toggle between tools - Switch to long cli args to simplify command invocation (same args for both) - Switch to csv completion for the same reason (snow cli doesn't support tsv) - Keep SnowSQL as default for backward compatibility - Add tests to ensure functionality Relates to #174 Signed-off-by: Jonas-Taha El Sesiy <github@elsesiy.com>
1 parent e95afed commit 10cc97e

File tree

4 files changed

+93
-10
lines changed

4 files changed

+93
-10
lines changed

autoload/db/adapter/run_tests.vim

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
source ../../db.vim
2+
source ../url.vim
3+
source ../adapter.vim
4+
source snowflake.vim
5+
source test_snowflake.vim
6+
7+
call TestSnowflakeAdapterDefault()
8+
call TestSnowflakeAdapterCLI()
9+
call TestSnowflakeCompleteDatabase()
10+
11+
:silent !echo "All tests passed"

autoload/db/adapter/snowflake.vim

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,42 @@
1+
let s:use_cli = get(g:, 'db_adapter_snowflake_use_cli', 0)
2+
3+
function! s:get_base() abort
4+
return s:use_cli ? ['snow', 'sql'] : ['snowsql']
5+
endfunction
6+
7+
function! s:get_env_var() abort
8+
return s:use_cli ? 'SNOWFLAKE_PASSWORD' : 'SNOWSQL_PWD'
9+
endfunction
10+
11+
" Use long args as they match for both snowsql and snow cli
12+
" ref: https://docs.snowflake.com/en/user-guide/snowsql-start#connection-parameters-reference
13+
" ref: https://docs.snowflake.com/en/developer-guide/snowflake-cli/command-reference/sql-commands/sql#options
14+
function! s:map_argv(url) abort
15+
return db#url#as_argv(a:url, '--accountname ', '', '', '--username ', '','--dbname ')
16+
endfunction
17+
118
function! db#adapter#snowflake#interactive(url) abort
219
let url = db#url#parse(a:url)
3-
let cmd = (has_key(url, 'password') ? ['env', 'SNOWSQL_PWD=' . url.password] : []) +
4-
\ ["snowsql"] +
5-
\ db#url#as_argv(a:url, '-a ', '', '', '-u ', '','-d ')
20+
let cmd = (has_key(url, 'password') ? ['env', s:get_env_var() . '=' . url.password] : []) +
21+
\ s:get_base() +
22+
\ s:map_argv(url)
623
for [k, v] in items(url.params)
7-
call add(cmd, '--' . k . '=' . v)
24+
if s:use_cli
25+
call add(cmd, '-D ' . k . '=' . v)
26+
else
27+
call add(cmd, '--' . k . '=' . v)
28+
endif
829
endfor
930
return cmd
1031
endfunction
1132

1233
function! db#adapter#snowflake#filter(url) abort
13-
return db#adapter#snowflake#interactive(a:url) +
14-
\ ['-o', 'friendly=false', '-o', 'timing=false']
34+
if s:use_cli
35+
return db#adapter#snowflake#interactive(a:url) + ['--silent']
36+
else
37+
return db#adapter#snowflake#interactive(a:url) +
38+
\ ['-o', 'friendly=false', '-o', 'timing=false']
39+
endif
1540
endfunction
1641

1742
function! db#adapter#snowflake#input(url, in) abort
@@ -24,8 +49,13 @@ endfunction
2449

2550
function! db#adapter#snowflake#complete_database(url) abort
2651
let pre = matchstr(a:url, '[^:]\+://.\{-\}/')
27-
let cmd = db#adapter#snowflake#filter(pre) +
28-
\ ['-o', 'header=false', '-o', 'output_format=tsv'] +
29-
\ ['-q', 'show terse databases']
30-
return map(db#systemlist(cmd), { _, v -> split(v, "\t")[1] })
52+
if s:use_cli
53+
let cmd = db#adapter#snowflake#filter(pre) +
54+
\ ['--format', 'csv', '-q', 'show terse databases']
55+
else
56+
let cmd = db#adapter#snowflake#filter(pre) +
57+
\ ['-o', 'header=false', '-o', 'output_format=csv'] +
58+
\ ['-q', 'show terse databases']
59+
endif
60+
return map(db#systemlist(cmd), { _, v -> split(v, ",")[1] })
3161
endfunction
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
let s:test_url = 'snowflake://user:pass@account/database'
2+
3+
function! TestSnowflakeAdapterDefault()
4+
" Test default behavior uses snowsql
5+
let cmd = db#adapter#snowflake#interactive(s:test_url)
6+
call assert_equal('snowsql', cmd[0])
7+
call assert_true(index(cmd, '--accountname') >= 0)
8+
endfunction
9+
10+
function! TestSnowflakeAdapterCLI()
11+
" Test with CLI enabled
12+
let g:db_adapter_snowflake_use_cli = 1
13+
let cmd = db#adapter#snowflake#interactive(s:test_url)
14+
call assert_equal('snow', cmd[0])
15+
call assert_equal('sql', cmd[1])
16+
call assert_true(index(cmd, '--accountname') >= 0)
17+
unlet g:db_adapter_snowflake_use_cli
18+
endfunction
19+
20+
function! TestSnowflakeCompleteDatabase()
21+
let url = 'snowflake://user@account/'
22+
let result = db#adapter#snowflake#complete_database(url)
23+
" Assume mock or check structure
24+
call assert_true(type(result) == type([]))
25+
endfunction
26+
27+
function! TestSnowflakeCompleteDatabaseCSV()
28+
" Test CSV parsing for completion
29+
let original_systemlist = function('db#systemlist')
30+
function! db#systemlist(cmd)
31+
return ['database1,database2']
32+
endfunction
33+
try
34+
let url = 'snowflake://user@account/'
35+
let result = db#adapter#snowflake#complete_database(url)
36+
call assert_equal(['database2'], result)
37+
finally
38+
let db#systemlist = original_systemlist
39+
endtry
40+
endfunction

doc/dadbod.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ Snowflake ~
202202
Query parameters can be used to set additional command line options (e.g.,
203203
`?warehouse=foo`).
204204

205+
Defaults to `snowsql`, set `let db_adapter_snowflake_use_cli = 1` to use
206+
`snow` cli instead.
205207
*dadbod-sqlserver*
206208
SQL Server ~
207209
>

0 commit comments

Comments
 (0)