Mercurial > vim_plugins > dbtables
comparison autoload/dbtables.vim @ 1:8530ebeda72c
Adding actual db tables implementation from original script.
| author | Luka Sitas <lsitas@avatarasoftware.com> |
|---|---|
| date | Wed, 11 Mar 2026 08:53:55 -0400 |
| parents | 238b45cc333b |
| children |
comparison
equal
deleted
inserted
replaced
| 0:238b45cc333b | 1:8530ebeda72c |
|---|---|
| 1 " autoload/dbtables.vim | 1 " autoload/dbtables.vim |
| 2 " Functions are loaded on demand | 2 " Functions are loaded on demand |
| 3 | 3 |
| 4 if exists('*dbtables#greet') | 4 if exists('*dbtables#*') |
| 5 finish | 5 finish |
| 6 endif | 6 endif |
| 7 | 7 |
| 8 function! dbtables#greet() abort | 8 |
| 9 echo g:dbtables_greeting | 9 |
| 10 endfunction | 10 "============================================= |
| 11 " Utilities | |
| 12 "============================================= | |
| 13 | |
| 14 let s:query_history = [] | |
| 15 let s:snippets = [] | |
| 16 | |
| 17 | |
| 18 | |
| 19 " - - - - - - - - - - - - - - - - - - - - - - | |
| 20 " DB/shell interaction | |
| 21 " - - - - - - - - - - - - - - - - - - - - - - | |
| 22 | |
| 23 " Execute shell commands | |
| 24 function! s:ExecuteShellCommand(command) | |
| 25 let result = system(a:command . ' 2>&1') | |
| 26 return [v:shell_error == 0, result] | |
| 27 endfunction | |
| 28 | |
| 29 " Execute a SQL query, directly to the db | |
| 30 function! s:ExecuteDBQuery(query) | |
| 31 let command = printf('mariadb --user=%s --password=%s --database=%s --host=%s -e %s', | |
| 32 \ shellescape(g:db_user), shellescape(g:db_password), | |
| 33 \ shellescape(g:db_name), shellescape(g:db_host), | |
| 34 \ shellescape(a:query)) | |
| 35 | |
| 36 let [success, result] = s:ExecuteShellCommand(command) | |
| 37 if success | |
| 38 return split(result, "\n") | |
| 39 else | |
| 40 call s:HandleDBError(result, command) | |
| 41 return [] | |
| 42 endif | |
| 43 endfunction | |
| 44 | |
| 45 " Function to execute SQL from the current buffer with parameter prompt | |
| 46 function! dbtables#ExecuteSQLQuery() | |
| 47 let query = join(getline(1, '$'), "\n") | |
| 48 call s:PromptAndExecuteQuery(query) | |
| 49 endfunction | |
| 50 | |
| 51 " Function to execute SQL from a visual selection with parameter prompt | |
| 52 function! dbtables#ExecuteVisualSQLQuery() range | |
| 53 " Get the content of the selected lines as a single SQL query | |
| 54 let lines = getline(a:firstline, a:lastline) | |
| 55 let query = join(lines, "\n") | |
| 56 | |
| 57 " Execute query with prompt for parameters | |
| 58 call s:PromptAndExecuteQuery(query) | |
| 59 endfunction | |
| 60 | |
| 61 " Handle parameter prompts and execute query | |
| 62 function! s:PromptAndExecuteQuery(query) | |
| 63 " Identify parameters in the form of :parameter_name | |
| 64 let pattern = ':\(\k\+\)' | |
| 65 let params = [] | |
| 66 | |
| 67 " Find all matches in the query | |
| 68 let start = 0 | |
| 69 while match(a:query, pattern, start) != -1 | |
| 70 let match = matchstr(a:query, pattern, start) | |
| 71 if index(params, match) == -1 | |
| 72 call add(params, match) | |
| 73 endif | |
| 74 let start = matchend(a:query, pattern, start) | |
| 75 endwhile | |
| 76 | |
| 77 " Initialize a dictionary for parameters and their values | |
| 78 let param_values = {} | |
| 79 | |
| 80 " Prompt user for each parameter | |
| 81 for param in params | |
| 82 let value = input('Enter value for ' . param . ': ') | |
| 83 let param_values[param] = value | |
| 84 endfor | |
| 85 | |
| 86 " Replace parameters in the query with user-provided values | |
| 87 let updated_query = a:query | |
| 88 for [param, value] in items(param_values) | |
| 89 let updated_query = substitute(updated_query, param, value, 'g') | |
| 90 endfor | |
| 91 | |
| 92 call add(s:query_history, updated_query) | |
| 93 call s:OpenInNewTab('SQLQueryResult', s:ExecuteDBQuery(updated_query)) | |
| 94 endfunction | |
| 95 | |
| 96 " Handle database command errors | |
| 97 function! s:HandleDBError(result, command) | |
| 98 echoerr 'Shell command failed: ' . a:command | |
| 99 if a:result =~# 'Access denied' | |
| 100 echoerr 'Authentication error: Check your username and password.' | |
| 101 elseif a:result =~# 'Unknown database' | |
| 102 echoerr 'Database error: The specified database does not exist.' | |
| 103 elseif a:result =~# 'Could not connect' | |
| 104 echoerr 'Connection error: Verify host and network connectivity.' | |
| 105 elseif a:result =~# 'You have an error in your SQL syntax' | |
| 106 echoerr 'Syntax error in SQL query.' | |
| 107 else | |
| 108 echoerr 'Unexpected error: ' . a:result | |
| 109 endif | |
| 110 endfunction | |
| 111 | |
| 112 | |
| 113 | |
| 114 " - - - - - - - - - - - - - - - - - - - - - - | |
| 115 " Visuals | |
| 116 " - - - - - - - - - - - - - - - - - - - - - - | |
| 117 | |
| 118 " Display data in a new read only buffer | |
| 119 function! s:OpenInNewTab(title, data) | |
| 120 tabnew | |
| 121 enew | |
| 122 execute 'file ' . a:title | |
| 123 if !empty(a:data) | |
| 124 call append(0, a:data) | |
| 125 else | |
| 126 call append(0, 'No data found or an error occurred.') | |
| 127 endif | |
| 128 setlocal filetype=sql buftype=nofile bufhidden=wipe nobuflisted noswapfile nomodifiable | |
| 129 endfunction | |
| 130 | |
| 131 | |
| 132 | |
| 133 "============================================= | |
| 134 " DBTables | |
| 135 "============================================= | |
| 136 " Open the list of tables in the database as a | |
| 137 " buffer on the right side. Selecting a table | |
| 138 " shows either the tables schema or the data | |
| 139 " in the table. | |
| 140 | |
| 141 function! dbtables#OpenDBTablesWindow() | |
| 142 execute '34 vsplit' | |
| 143 enew | |
| 144 file DBTables | |
| 145 let tables = s:ExecuteDBQuery("SHOW TABLES;") | |
| 146 if empty(tables) | |
| 147 echo "No tables found or an error occurred." | |
| 148 else | |
| 149 call append(0, ['Available Tables:'] + tables[1:]) | |
| 150 setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile | |
| 151 \ nomodifiable nonumber norelativenumber winfixwidth | |
| 152 nnoremap <buffer> <CR> :call <SID>ShowTablePopup()<CR> | |
| 153 endif | |
| 154 endfunction | |
| 155 | |
| 156 " Open the database schema | |
| 157 function! s:OpenTableSchema(table) | |
| 158 call s:OpenInNewTab(a:table . '_schema', s:ExecuteDBQuery('DESCRIBE ' . a:table . ';')) | |
| 159 endfunction | |
| 160 | |
| 161 " Open the table data | |
| 162 function! s:OpenTableData(table) | |
| 163 call s:OpenInNewTab(a:table, s:ExecuteDBQuery('SELECT * FROM ' . a:table . ';')) | |
| 164 endfunction | |
| 165 | |
| 166 let s:popup_table = "" | |
| 167 | |
| 168 " Popup selection for table actions | |
| 169 function! s:ShowTablePopup() | |
| 170 " Use Vim popup_menu if available | |
| 171 if exists('*popup_menu') | |
| 172 let s:popup_table = getline(line('.')) | |
| 173 let items = ['View Data', 'View Schema', 'Cancel'] | |
| 174 call popup_menu(items, #{ | |
| 175 \ callback: '<SID>HandlePopupSelection', | |
| 176 \ }) | |
| 177 return | |
| 178 endif | |
| 179 " Popup_menu not available | |
| 180 echoerr 'Floating popup requires Vim8.2+.' | |
| 181 call s:ShowTableMenuModal() | |
| 182 endfunction | |
| 183 | |
| 184 function! s:HandlePopupSelection(id, result) | |
| 185 let table = s:popup_table | |
| 186 call s:ClosePopup() | |
| 187 if a:result == 1 | |
| 188 call s:OpenTableData(table) | |
| 189 elseif a:result == 2 | |
| 190 call s:OpenTableSchema(table) | |
| 191 endif | |
| 192 endfunction | |
| 193 | |
| 194 function! s:ClosePopup() | |
| 195 unlet! s:popup_table | |
| 196 endfunction | |
| 197 | |
| 198 | |
| 199 | |
| 200 "============================================= | |
| 201 " Query History | |
| 202 "============================================= | |
| 203 " Shows the list of recently ran queries. | |
| 204 " Selecting a query will re-run it. | |
| 205 | |
| 206 " View query history | |
| 207 function! dbtables#OpenQueryHistory() | |
| 208 " Open the query history in a new split window | |
| 209 execute 'vsplit' | |
| 210 enew | |
| 211 call setline(1, s:query_history) | |
| 212 nnoremap <buffer> <CR> :call s:OpenInNewTab('SQLQueryResult', | |
| 213 \ s:ExecuteDBQuery(getline(line('.'))))<CR> | |
| 214 setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile wrap | |
| 215 endfunction | |
| 216 | |
| 217 | |
| 218 | |
| 219 "============================================= | |
| 220 " Query Snippets | |
| 221 "============================================= | |
| 222 " Shows the list of pre-set query snippets. | |
| 223 " Selecting a snippet will open it in a new | |
| 224 " tab to be executed or modified. | |
| 225 | |
| 226 " View query snippets | |
| 227 function! dbtables#OpenQuerySnippets() | |
| 228 " Open the query snippets in a new split window | |
| 229 execute '34 vsplit' | |
| 230 enew | |
| 231 | |
| 232 " Populate the buffer with the list of snippet files | |
| 233 let s:snippets = globpath(g:snippets_directory, '*', 0, 1) | |
| 234 let l:display = mapnew(s:snippets, 'fnamemodify(v:val, ":t:r")') | |
| 235 call setline(1, l:display) | |
| 236 | |
| 237 nnoremap <buffer> <CR> :call s:OpenInNewTab(line('.'), | |
| 238 \ fnameescape(s:snippets[a:lnum-1]))<CR> | |
| 239 | |
| 240 setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile wrap | |
| 241 endfunction | |
| 242 | |
| 243 | |
| 244 | |
| 245 "============================================= | |
| 246 " DB Console | |
| 247 "============================================= | |
| 248 " Opens a console to interact with the DB. | |
| 249 | |
| 250 " Open MariaDB console | |
| 251 function! dbtables#DBConsole() | |
| 252 " Save the current cursor position | |
| 253 let save_cursor = getpos(".") | |
| 254 let command = printf('mariadb --user=%s --password=%s --database=%s --host=%s', | |
| 255 \ g:db_user, g:db_password, | |
| 256 \ g:db_name, g:db_host) | |
| 257 | |
| 258 let command = substitute(command, '\n', '', 'g') | |
| 259 execute ':term ' . command | |
| 260 call setpos(".", save_cursor) | |
| 261 endfunction |
