From 0af3d13bd3a8041af70d505e0161183d88dbb0f9 Mon Sep 17 00:00:00 2001 From: doeke Date: Thu, 7 Nov 2024 15:36:26 -0500 Subject: [PATCH 01/14] Duplicate duckdb adapter and change function names to `md` --- autoload/db/adapter/md.vim | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 autoload/db/adapter/md.vim diff --git a/autoload/db/adapter/md.vim b/autoload/db/adapter/md.vim new file mode 100644 index 0000000..c00dfc2 --- /dev/null +++ b/autoload/db/adapter/md.vim @@ -0,0 +1,45 @@ +function! db#adapter#md#canonicalize(url) abort + return db#url#canonicalize_file(a:url) +endfunction + +function! db#adapter#md#test_file(file) abort + if getfsize(a:file) < 100 + return + endif + let firstline = readfile(a:file, '', 1)[0] + " DuckDB can also open SQLite databases + if firstline[8:11] ==# 'DUCK' || firstline =~# '^SQLite format 3\n' + return 1 + endif +endfunction + +function! s:path(url) abort + let path = db#url#file_path(a:url) + if path =~# '^[\/]\=$' + if !exists('s:session') + let s:session = tempname() . '.duckdb' + endif + let path = s:session + endif + return path +endfunction + +function! db#adapter#md#dbext(url) abort + return {'dbname': s:path(a:url)} +endfunction + +function! db#adapter#md#command(url) abort + return ['duckdb', s:path(a:url)] +endfunction + +function! db#adapter#md#interactive(url) abort + return db#adapter#md#command(a:url) + ['-column', '-header'] +endfunction + +function! db#adapter#md#tables(url) abort + return split(join(db#systemlist(db#adapter#md#command(a:url) + ['-noheader', '.tables']))) +endfunction + +function! db#adapter#md#massage(input) abort + return a:input . "\n;" +endfunction From 6dfc83f769d672cae526cde8061d09ddae76e905 Mon Sep 17 00:00:00 2001 From: doeke Date: Thu, 7 Nov 2024 15:37:29 -0500 Subject: [PATCH 02/14] Use box output format instead of column --- autoload/db/adapter/md.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/db/adapter/md.vim b/autoload/db/adapter/md.vim index c00dfc2..4f8b0ee 100644 --- a/autoload/db/adapter/md.vim +++ b/autoload/db/adapter/md.vim @@ -33,7 +33,7 @@ function! db#adapter#md#command(url) abort endfunction function! db#adapter#md#interactive(url) abort - return db#adapter#md#command(a:url) + ['-column', '-header'] + return db#adapter#md#command(a:url) + ['-box', '-header'] endfunction function! db#adapter#md#tables(url) abort From f7cdbfa4fdb237fd997a72610a6a6f2f41b17947 Mon Sep 17 00:00:00 2001 From: doeke Date: Thu, 7 Nov 2024 15:50:18 -0500 Subject: [PATCH 03/14] Canonicalize URL by just returning the URL unchanged --- autoload/db/adapter/md.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/db/adapter/md.vim b/autoload/db/adapter/md.vim index 4f8b0ee..db81387 100644 --- a/autoload/db/adapter/md.vim +++ b/autoload/db/adapter/md.vim @@ -1,5 +1,5 @@ function! db#adapter#md#canonicalize(url) abort - return db#url#canonicalize_file(a:url) + return a:url endfunction function! db#adapter#md#test_file(file) abort From cea0c93a37f32d8a800b96bb74e519d02d4dc68d Mon Sep 17 00:00:00 2001 From: doeke Date: Thu, 7 Nov 2024 15:51:27 -0500 Subject: [PATCH 04/14] Change command to run MotherDuck `attach` and `use` statements --- autoload/db/adapter/md.vim | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/autoload/db/adapter/md.vim b/autoload/db/adapter/md.vim index db81387..95252d9 100644 --- a/autoload/db/adapter/md.vim +++ b/autoload/db/adapter/md.vim @@ -13,23 +13,27 @@ function! db#adapter#md#test_file(file) abort endif endfunction -function! s:path(url) abort - let path = db#url#file_path(a:url) - if path =~# '^[\/]\=$' - if !exists('s:session') - let s:session = tempname() . '.duckdb' - endif - let path = s:session +function! s:dbname(url) abort + let parsed = db#url#parse(a:url) + if has_key(parsed, 'opaque') + return parsed.opaque endif - return path + return '' endfunction function! db#adapter#md#dbext(url) abort - return {'dbname': s:path(a:url)} + return {'dbname': s:dbname(a:url)} endfunction function! db#adapter#md#command(url) abort - return ['duckdb', s:path(a:url)] + let dbname = s:dbname(a:url) + if dbname != '' + let attachment = "attach 'md:" . dbname . "'; use " . dbname . ";" + else + let attachment = "attach 'md:';" + endif + let cmd = ['duckdb', '-cmd', attachment] + return cmd endfunction function! db#adapter#md#interactive(url) abort From c2375539796aa76c128fe553c3a6dd53d89a6f6c Mon Sep 17 00:00:00 2001 From: doeke Date: Thu, 7 Nov 2024 16:37:12 -0500 Subject: [PATCH 05/14] Enable basic usage by attaching to MotherDuck database --- autoload/db/adapter/md.vim | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/autoload/db/adapter/md.vim b/autoload/db/adapter/md.vim index 95252d9..639c005 100644 --- a/autoload/db/adapter/md.vim +++ b/autoload/db/adapter/md.vim @@ -26,18 +26,21 @@ function! db#adapter#md#dbext(url) abort endfunction function! db#adapter#md#command(url) abort + let cmd = ['duckdb'] let dbname = s:dbname(a:url) if dbname != '' - let attachment = "attach 'md:" . dbname . "'; use " . dbname . ";" + let attach = ['-cmd', "attach 'md:" . dbname . "'"] + let use = ['-cmd', 'use ' . dbname] + let cmd = cmd + attach + use else - let attachment = "attach 'md:';" + let attach = ['-cmd', "attach 'md:'"] + let cmd = cmd + attach endif - let cmd = ['duckdb', '-cmd', attachment] return cmd endfunction function! db#adapter#md#interactive(url) abort - return db#adapter#md#command(a:url) + ['-box', '-header'] + return db#adapter#md#command(a:url) + ['-cmd', '.output', '-header'] endfunction function! db#adapter#md#tables(url) abort From 5efbc33984dc978b0ccaa454a598f2a875e87f66 Mon Sep 17 00:00:00 2001 From: doeke Date: Thu, 7 Nov 2024 17:12:59 -0500 Subject: [PATCH 06/14] Drop uneccesary `-header` flag --- autoload/db/adapter/md.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/db/adapter/md.vim b/autoload/db/adapter/md.vim index 639c005..531619e 100644 --- a/autoload/db/adapter/md.vim +++ b/autoload/db/adapter/md.vim @@ -40,7 +40,7 @@ function! db#adapter#md#command(url) abort endfunction function! db#adapter#md#interactive(url) abort - return db#adapter#md#command(a:url) + ['-cmd', '.output', '-header'] + return db#adapter#md#command(a:url) + ['-cmd', '.output'] endfunction function! db#adapter#md#tables(url) abort From 591564f7ff4a088450a7e2c379df67b274b7ad1c Mon Sep 17 00:00:00 2001 From: doeke Date: Thu, 7 Nov 2024 17:25:44 -0500 Subject: [PATCH 07/14] Fix tables function given the extra command args --- autoload/db/adapter/md.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/db/adapter/md.vim b/autoload/db/adapter/md.vim index 531619e..fb97583 100644 --- a/autoload/db/adapter/md.vim +++ b/autoload/db/adapter/md.vim @@ -44,7 +44,7 @@ function! db#adapter#md#interactive(url) abort endfunction function! db#adapter#md#tables(url) abort - return split(join(db#systemlist(db#adapter#md#command(a:url) + ['-noheader', '.tables']))) + return split(join(db#systemlist(db#adapter#md#command(a:url) + ['-noheader', '-c', '.tables']))) endfunction function! db#adapter#md#massage(input) abort From 44b2cc66261b385566c128d83de0f3b5fb1ef91e Mon Sep 17 00:00:00 2001 From: doeke Date: Thu, 7 Nov 2024 17:26:26 -0500 Subject: [PATCH 08/14] Delete `test_file` function since this adapter isn't for local files --- autoload/db/adapter/md.vim | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/autoload/db/adapter/md.vim b/autoload/db/adapter/md.vim index fb97583..634ea73 100644 --- a/autoload/db/adapter/md.vim +++ b/autoload/db/adapter/md.vim @@ -2,17 +2,6 @@ function! db#adapter#md#canonicalize(url) abort return a:url endfunction -function! db#adapter#md#test_file(file) abort - if getfsize(a:file) < 100 - return - endif - let firstline = readfile(a:file, '', 1)[0] - " DuckDB can also open SQLite databases - if firstline[8:11] ==# 'DUCK' || firstline =~# '^SQLite format 3\n' - return 1 - endif -endfunction - function! s:dbname(url) abort let parsed = db#url#parse(a:url) if has_key(parsed, 'opaque') From 5c862a55cbd8b7b17ab5e1ae5d4b5f4d3ab11793 Mon Sep 17 00:00:00 2001 From: doeke Date: Thu, 7 Nov 2024 20:55:01 -0500 Subject: [PATCH 09/14] Add section in help text --- doc/dadbod.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/dadbod.txt b/doc/dadbod.txt index 88c63f2..0e548de 100644 --- a/doc/dadbod.txt +++ b/doc/dadbod.txt @@ -143,6 +143,20 @@ MongoDB ~ < Any valid MongoDB connection string URI can be used. + *dadbod-md* +MotherDuck ~ +> + md: + md:database +< +MotherDuck authenticates using a token stored as an environment variable +`motherduck_token`. If this environment variable is missing, all invocations +will open a browser and prompt the user to login to the MotherDuck console. + +If the database is provided, it will be used as the default database (so +queries do not have to specify a database. If not, queries must specify a +database. + *dadbod-mysql* MySQL ~ > From f3462403046269afb86922c7a7212b829a84684c Mon Sep 17 00:00:00 2001 From: doeke Date: Thu, 7 Nov 2024 20:55:48 -0500 Subject: [PATCH 10/14] Add MotherDuck to list of supported databases --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index fe7717a..f638d41 100644 --- a/README.markdown +++ b/README.markdown @@ -14,6 +14,7 @@ take on [dbext.vim][], improving on it on the following ways: - Impala - jq - MongoDB + - MotherDuck - MySQL - MariaDB - Oracle From 0db406d5b40f1b2daca127386fd4bd913ce3de66 Mon Sep 17 00:00:00 2001 From: doeke Date: Thu, 7 Nov 2024 20:59:36 -0500 Subject: [PATCH 11/14] Conform to `database` argument formatting convention in help text --- doc/dadbod.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dadbod.txt b/doc/dadbod.txt index 0e548de..6249f86 100644 --- a/doc/dadbod.txt +++ b/doc/dadbod.txt @@ -147,7 +147,7 @@ Any valid MongoDB connection string URI can be used. MotherDuck ~ > md: - md:database + md:[] < MotherDuck authenticates using a token stored as an environment variable `motherduck_token`. If this environment variable is missing, all invocations From f8b682322ea8f0e0815eef0bc5723aaf4ddd61db Mon Sep 17 00:00:00 2001 From: doeke Date: Sat, 9 Nov 2024 15:38:55 -0500 Subject: [PATCH 12/14] Use (non-elided) duckbox output format for duckdb adapter too --- autoload/db/adapter/duckdb.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/db/adapter/duckdb.vim b/autoload/db/adapter/duckdb.vim index 763cb51..d56dc85 100644 --- a/autoload/db/adapter/duckdb.vim +++ b/autoload/db/adapter/duckdb.vim @@ -33,7 +33,7 @@ function! db#adapter#duckdb#command(url) abort endfunction function! db#adapter#duckdb#interactive(url) abort - return db#adapter#duckdb#command(a:url) + ['-column', '-header'] + return db#adapter#duckdb#command(a:url) + ['-cmd', '.output'] endfunction function! db#adapter#duckdb#tables(url) abort From 69bb7eebdf611f63d0851682d1ff68556de7acd4 Mon Sep 17 00:00:00 2001 From: Doeke Date: Mon, 11 Nov 2024 17:51:11 -0500 Subject: [PATCH 13/14] Be a little more robust in connecting to a specific database --- autoload/db/adapter/md.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/db/adapter/md.vim b/autoload/db/adapter/md.vim index 634ea73..186edad 100644 --- a/autoload/db/adapter/md.vim +++ b/autoload/db/adapter/md.vim @@ -18,8 +18,8 @@ function! db#adapter#md#command(url) abort let cmd = ['duckdb'] let dbname = s:dbname(a:url) if dbname != '' - let attach = ['-cmd', "attach 'md:" . dbname . "'"] - let use = ['-cmd', 'use ' . dbname] + let attach = ['-cmd', "attach 'md:" . dbname . "' as " . '"' . dbname . '"'] + let use = ['-cmd', "use '" . dbname . "'"] let cmd = cmd + attach + use else let attach = ['-cmd', "attach 'md:'"] From 1e46b63a7f0c7d399c39908f7fa9580dd31bf892 Mon Sep 17 00:00:00 2001 From: Doeke Date: Thu, 5 Jun 2025 09:51:46 -0400 Subject: [PATCH 14/14] Simplify motherduck connection so it's less likely to break. --- autoload/db/adapter/md.vim | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/autoload/db/adapter/md.vim b/autoload/db/adapter/md.vim index 186edad..404c9b2 100644 --- a/autoload/db/adapter/md.vim +++ b/autoload/db/adapter/md.vim @@ -15,17 +15,10 @@ function! db#adapter#md#dbext(url) abort endfunction function! db#adapter#md#command(url) abort - let cmd = ['duckdb'] - let dbname = s:dbname(a:url) - if dbname != '' - let attach = ['-cmd', "attach 'md:" . dbname . "' as " . '"' . dbname . '"'] - let use = ['-cmd', "use '" . dbname . "'"] - let cmd = cmd + attach + use - else - let attach = ['-cmd', "attach 'md:'"] - let cmd = cmd + attach + if a:url != '' + return ['duckdb', a:url] endif - return cmd + return ['duckdb', 'md:'] endfunction function! db#adapter#md#interactive(url) abort