From 738cfc2ea6a1510fe23cba9006fef9291be70f7b Mon Sep 17 00:00:00 2001 From: Mike Hynes Date: Thu, 23 Nov 2023 00:11:46 -0500 Subject: [PATCH] Add BigQuery Adapter (#125) --- README.markdown | 1 + autoload/db.vim | 9 +++++++-- autoload/db/adapter/bigquery.vim | 34 ++++++++++++++++++++++++++++++++ doc/dadbod.txt | 11 +++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 autoload/db/adapter/bigquery.vim diff --git a/README.markdown b/README.markdown index 7995d72..bc51e23 100644 --- a/README.markdown +++ b/README.markdown @@ -8,6 +8,7 @@ take on [dbext.vim][], improving on it on the following ways: * All interaction is through invoking `:DB`, not 53 different commands and 35 different maps (omitting many of the more esoteric features, of course) * Supports a modern array of backends, including NoSQL databases: + - Big Query - ClickHouse - Impala - jq diff --git a/autoload/db.vim b/autoload/db.vim index 70a5d96..026bf9e 100644 --- a/autoload/db.vim +++ b/autoload/db.vim @@ -331,8 +331,13 @@ function! db#connect(url) abort endif let pattern = db#adapter#call(url, 'auth_pattern', [], 'auth\|login') try - call writefile(split(db#adapter#call(url, 'auth_input', [], "\n"), "\n", 1), input, 'b') - let [out, exit_status] = call('s:systemlist', filter) + let auth_input = db#adapter#call(url, 'auth_input', [], "\n") + " Short-circuit the authentication if unnecessary for the adapter + if auth_input == v:false + return url + endif + call writefile(split(auth_input, "\n", 1), input, 'b') + let [out, exit_status] = call('s:systemlist', s:filter(url, input)) if exit_status && join(out, "\n") =~? pattern && resolved =~# '^[^:]*://[^:/@]*@' let password = inputsecret('Password: ') let url = substitute(resolved, '://[^:/@]*\zs@', ':'.db#url#encode(password).'@', '') diff --git a/autoload/db/adapter/bigquery.vim b/autoload/db/adapter/bigquery.vim new file mode 100644 index 0000000..a70ed96 --- /dev/null +++ b/autoload/db/adapter/bigquery.vim @@ -0,0 +1,34 @@ +function! db#adapter#bigquery#auth_input() abort + return v:false +endfunction + +function! s:command_for_url(url, subcmd) abort + let cmd = ['bq'] + let parsed = db#url#parse(a:url) + if has_key(parsed, 'opaque') + let host_targets = split(substitute(parsed.opaque, '/', '', 'g'), ':') + + " If the host is specified as bigquery:project:dataset, then parse + " the optional (project, dataset) to supply them to the CLI. + if len(host_targets) == 2 + call add(cmd, '--project_id=' . host_targets[0]) + call add(cmd, '--dataset_id=' . host_targets[1]) + elseif len(host_targets) == 1 + call add(cmd, '--project_id=' . host_targets[0]) + endif + endif + + for [k, v] in items(parsed.params) + let op = '--'.k.'='.v + call add(cmd, op) + endfor + return cmd + [a:subcmd] +endfunction + +function! db#adapter#bigquery#filter(url) abort + return s:command_for_url(a:url, 'query') +endfunction + +function! db#adapter#bigquery#interactive(url) abort + return s:command_for_url(a:url, 'shell') +endfunction diff --git a/doc/dadbod.txt b/doc/dadbod.txt index 38bf73b..3850138 100644 --- a/doc/dadbod.txt +++ b/doc/dadbod.txt @@ -81,6 +81,17 @@ Handling these parameters is up to the individual adapters. By default, unrecognized parameters are ignored. Pass Boolean parameters as the literal strings "true" and "false" (e.g., `?ssl=true`). + *dadbod-bigquery* +bigquery ~ +> + bigquery:[[:]][?...] + bigquery:?project_id=&dataset_id=[&...] +< + +The first form of the URL assumes your default dataset belongs to your default project. If it doesn't, use the second form. + +Additional query parameters can be any valid global flag, for example, `&disable_ssl_validation=true`. Note that subcommand flags are not supported as query parameters, but they can be specified in `~/.bigqueryrc`. + *dadbod-dbext* dbext ~ >