Skip to content

Commit

Permalink
feat: Add option to use function for generating connection string
Browse files Browse the repository at this point in the history
Add ability to use function for generating a connection string through
`g:dbs` variable.
Closes #251 and #204
  • Loading branch information
kristijanhusak committed Jul 9, 2024
1 parent 696e1ed commit dc6975d
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 5 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,20 +107,32 @@ let g:db_ui_dotenv_variable_prefix = 'MYPREFIX_'
Provide list with all databases that you want to use through `g:dbs` variable as an array of objects or an object:

```vimL
function s:resolve_production_url()
let url = system('get-prod-url')
return url
end
let g:dbs = {
\ 'dev': 'postgres://postgres:mypassword@localhost:5432/my-dev-db',
\ 'staging': 'postgres://postgres:mypassword@localhost:5432/my-staging-db',
\ 'wp': 'mysql://root@localhost/wp_awesome',
\ 'production': function('s:resolve_production_url')
\ }
```

Or if you want them to be sorted in the order you define them, this way is also available:

```vimL
function s:resolve_production_url()
let url = system('get-prod-url')
return url
end
let g:dbs = [
\ { 'name': 'dev', 'url': 'postgres://postgres:mypassword@localhost:5432/my-dev-db' }
\ { 'name': 'staging', 'url': 'postgres://postgres:mypassword@localhost:5432/my-staging-db' },
\ { 'name': 'wp', 'url': 'mysql://root@localhost/wp_awesome' },
\ { 'name': 'production', 'url': function('s:resolve_production_url') },
\ ]
```
Just make sure to **NOT COMMIT** these. I suggest using project local vim config (`:help exrc`)
Expand Down
29 changes: 24 additions & 5 deletions autoload/db_ui.vim
Original file line number Diff line number Diff line change
Expand Up @@ -266,25 +266,44 @@ function! s:dbui.generate_new_db_entry(db) abort
return db
endfunction

function! s:dbui.resolve_url_global_variable(Value) abort
if type(a:Value) ==? type('')
return a:Value
endif

if type(a:Value) ==? type(function('tr'))
return call(a:Value, [])
endif

" if type(a:Value) ==? type(v:t_func)
" endif
"
" echom string(type(a:Value))
" echom string(a:Value)
"
throw 'Invalid type global variable database url:'..type(a:Value)
endfunction

function! s:dbui.populate_from_global_variable() abort
if exists('g:db') && !empty(g:db)
let gdb_name = split(g:db, '/')[-1]
call self.add_if_not_exists(gdb_name, g:db, 'g:dbs')
let url = self.resolve_url_global_variable(g:db)
let gdb_name = split(url, '/')[-1]
call self.add_if_not_exists(gdb_name, url, 'g:dbs')
endif

if !exists('g:dbs') || empty(g:dbs)
return self
endif

if type(g:dbs) ==? type({})
for [db_name, db_url] in items(g:dbs)
call self.add_if_not_exists(db_name, db_url, 'g:dbs')
for [db_name, Db_url] in items(g:dbs)
call self.add_if_not_exists(db_name, self.resolve_url_global_variable(Db_url), 'g:dbs')
endfor
return self
endif

for db in g:dbs
call self.add_if_not_exists(db.name, db.url, 'g:dbs')
call self.add_if_not_exists(db.name, self.resolve_url_global_variable(db.url), 'g:dbs')
endfor

return self
Expand Down
26 changes: 26 additions & 0 deletions doc/dadbod-ui.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,15 @@ vim-dadbod `g:db` variable is read first.

Object example:
>
function s:resolve_production_url()
return system('get-prod-url')
end
let g:dbs = {
\ 'dev': 'postgres://postgres:mypassword@localhost:5432/my-dev-db',
\ 'staging': 'postgres://postgres:mypassword@localhost:5432/my-staging-db',
\ 'wp': 'mysql://root@localhost/wp_awesome',
\ 'production': function('s:resolve_production_url')
\ }
<
Array of objects example:
Expand All @@ -174,15 +179,36 @@ Array of objects example:
\ { 'name': 'dev', 'url': 'postgres://postgres:mypassword@localhost:5432/my-dev-db' }
\ { 'name': 'staging', 'url': 'postgres://postgres:mypassword@localhost:5432/my-staging-db' },
\ { 'name': 'wp', 'url': 'mysql://root@localhost/wp_awesome' },
\ { 'name': 'production', 'url': function('s:resolve_production_url') },
\ ]
<

If you use Neovim, you can also use lua to define the connections:
>
vim.g.dbs = {
{
{ name = 'dev', url = 'postgres://postgres:mypassword@localhost:5432/my-dev-db' }
{ name = 'staging', url = 'postgres://postgres:mypassword@localhost:5432/my-staging-db' },
{ name = 'wp', url = 'mysql://root@localhost/wp_awesome' },
{
name = 'production',
url = function()
return vim.fn.system('get-prod-url')
end
},
}
}
<


Currently, only difference between these two methods is that array ensures
order, while order of connections with g:dbs as object has arbitrary order.

If you use this method, make sure to `keep it out of version control` .
One way to ensure it's not commited is to use `exrc` option, which allows
creating project level vimrc to hold this configuration. After that, add that
file to your global gitignore file, and you're safe.
Other solution is to have it as a function that resolves a value dynamically.

==============================================================================
4.3 Using `DBUIAddConnection` command *vim-dadbod-ui-connections-add*
Expand Down
33 changes: 33 additions & 0 deletions test/test-initialization-with-dbs-array-function-variable.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
let s:suite = themis#suite('Initialization with g:dbs variable as functions in a dictionary')
let s:expect = themis#helper('expect')

function! s:db_conn() abort
return 'sqlite:tests/dadbod_ui_test.db'
endfunction

function! s:suite.before() abort
call SetupTestDbs()
let g:dbs = [
\ { 'name': 'dadbod_gdb_test_function', 'url': function('s:db_conn') },
\ { 'name': 'dadbod_gdb_test_str', 'url': 'sqlite:test/dadbod_ui_test' },
\ ]
endfunction

function! s:suite.after() abort
call Cleanup()
endfunction

function! s:suite.should_read_global_dbs_variable() abort
:DBUI
call s:expect(&filetype).to_equal('dbui')
call s:expect(getline(1)).to_equal(printf('%s %s', g:db_ui_icons.collapsed.db, 'dadbod_gdb_test_function'))
call s:expect(getline(2)).to_equal(printf('%s %s', g:db_ui_icons.collapsed.db, 'dadbod_gdb_test_str'))
norm o
call s:expect(getline(1, '$')).to_equal([
\ '▾ dadbod_gdb_test_function '.g:db_ui_icons.connection_ok,
\ ' + New query',
\ ' ▸ Saved queries (0)',
\ ' ▸ Tables (2)',
\ '▸ dadbod_gdb_test_str',
\ ])
endfunction
33 changes: 33 additions & 0 deletions test/test-initialization-with-dbs-dictionary-function-variable.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
let s:suite = themis#suite('Initialization with g:dbs variable as functions in a dictionary')
let s:expect = themis#helper('expect')

function! s:db_conn() abort
return 'sqlite:tests/dadbod_ui_test.db'
endfunction

function! s:suite.before() abort
call SetupTestDbs()
let g:dbs = {
\ 'dadbod_gdb_test_fn': function('s:db_conn'),
\ 'dadbod_gdb_test_string': 'sqlite:test/dadbod_ui_test',
\ }
endfunction

function! s:suite.after() abort
call Cleanup()
endfunction

function! s:suite.should_read_global_dbs_variable() abort
:DBUI
call s:expect(&filetype).to_equal('dbui')
call s:expect(getline(1)).to_equal(printf('%s %s', g:db_ui_icons.collapsed.db, 'dadbod_gdb_test_string'))
call s:expect(getline(2)).to_equal(printf('%s %s', g:db_ui_icons.collapsed.db, 'dadbod_gdb_test_fn'))
norm jo
call s:expect(getline(1, '$')).to_equal([
\ '▸ dadbod_gdb_test_string',
\ '▾ dadbod_gdb_test_fn '.g:db_ui_icons.connection_ok,
\ ' + New query',
\ ' ▸ Saved queries (0)',
\ ' ▸ Tables (2)',
\ ])
endfunction

0 comments on commit dc6975d

Please sign in to comment.