Mercurial > vim
comparison plugins/dbtables/dbtables.vim @ 3:951569ccb9c7
Updated the dbtables plugin with a popup for selecting data vs schema.
| author | luka |
|---|---|
| date | Thu, 24 Apr 2025 20:28:09 -0400 |
| parents | |
| children | 4a7bc1c8551b |
comparison
equal
deleted
inserted
replaced
| 2:13ee7346431d | 3:951569ccb9c7 |
|---|---|
| 1 let g:db_user = "" " Replace with your default database username | |
| 2 let g:db_password = "" " Replace with your default database password | |
| 3 let g:db_name = "" " Replace with your default database name | |
| 4 let g:db_host = "" " Replace with your default database name | |
| 5 | |
| 6 | |
| 7 " Helper function to execute a command and handle errors | |
| 8 function! s:ExecuteShellCommand(command) | |
| 9 let result = system(a:command . ' 2>&1') | |
| 10 if v:shell_error != 0 | |
| 11 return [v:false, result] | |
| 12 endif | |
| 13 return [v:true, result] | |
| 14 endfunction | |
| 15 | |
| 16 function! s:ExecuteDBQuery(query) | |
| 17 let db_user = shellescape(g:db_user) | |
| 18 let db_password = shellescape(g:db_password) | |
| 19 let db_name = shellescape(g:db_name) | |
| 20 let db_host = shellescape(g:db_host) | |
| 21 | |
| 22 let command = 'mariadb --user=' . db_user | |
| 23 \ . ' --password=' . db_password | |
| 24 \ . ' --database=' . db_name | |
| 25 \ . ' --host=' . db_host | |
| 26 \ . ' -e ' . shellescape(a:query) | |
| 27 | |
| 28 let [success, result] = s:ExecuteShellCommand(command) | |
| 29 | |
| 30 if !success | |
| 31 call s:HandleDBError(result, command) | |
| 32 return [] | |
| 33 endif | |
| 34 return split(result, "\n") | |
| 35 endfunction | |
| 36 | |
| 37 function! s:HandleDBError(result, command) | |
| 38 echoerr 'Shell command failed: ' . a:command | |
| 39 echoerr a:result | |
| 40 | |
| 41 if a:result =~# 'Access denied' | |
| 42 echoerr 'Authentication error: Check your username and password.' | |
| 43 elseif a:result =~# 'Unknown database' | |
| 44 echoerr 'Database error: The specified database does not exist.' | |
| 45 elseif a:result =~# 'Could not connect' | |
| 46 echoerr 'Connection error: Verify host and network connectivity.' | |
| 47 elseif a:result =~# 'You have an error in your SQL syntax' | |
| 48 echoerr 'Syntax error in SQL query.' | |
| 49 else | |
| 50 echoerr 'Unexpected error: ' . a:result | |
| 51 endif | |
| 52 endfunction | |
| 53 | |
| 54 | |
| 55 " Show the structure/schema of the selected table | |
| 56 function! s:ShowTableSchema(table) | |
| 57 " Open a new tab for schema | |
| 58 tabnew | |
| 59 enew | |
| 60 execute 'file ' . table . '_schema' | |
| 61 " Describe the table structure | |
| 62 let data = s:ExecuteDBQuery('DESCRIBE ' . table . ';') | |
| 63 if len(data) > 0 | |
| 64 call append(0, data) | |
| 65 else | |
| 66 call append(0, 'No schema found or an error occurred.') | |
| 67 endif | |
| 68 " Set buffer options and syntax | |
| 69 setlocal filetype=sql buftype=nofile bufhidden=wipe nobuflisted noswapfile nomodifiable | |
| 70 endfunction | |
| 71 | |
| 72 | |
| 73 let s:popup_table = "" | |
| 74 " Popup selection for table actions | |
| 75 function! s:ShowTablePopup() | |
| 76 " Use Vim popup_menu if available | |
| 77 if exists('*popup_menu') | |
| 78 let s:popup_table = getline(line('.')) | |
| 79 let items = ['View Data', 'View Schema', 'Cancel'] | |
| 80 call popup_menu(items, #{ | |
| 81 \ callback: '<SID>HandlePopupSelection', | |
| 82 \ }) | |
| 83 return | |
| 84 endif | |
| 85 " Popup_menu not available | |
| 86 echoerr 'Floating popup requires Vim8.2+.' | |
| 87 call s:ShowTableMenuModal() | |
| 88 endfunction | |
| 89 | |
| 90 function! s:HandlePopupSelection(id, result) | |
| 91 let table = s:popup_table | |
| 92 call s:ClosePopup() | |
| 93 if a:result == 1 | |
| 94 call s:OpenTableData(table) | |
| 95 elseif a:result == 2 | |
| 96 call s:OpenTableSchema(table) | |
| 97 endif | |
| 98 endfunction | |
| 99 | |
| 100 function! s:ClosePopup() | |
| 101 unlet! s:popup_table | |
| 102 endfunction | |
| 103 | |
| 104 | |
| 105 " Internal: remove any existing dropdown option lines from the DBTables buffer | |
| 106 function! s:ClearTableOptions() | |
| 107 let to_del = [] | |
| 108 for lnum in range(1, line('$')) | |
| 109 let ln = getline(lnum) | |
| 110 if ln =~# '^\s\+\(Data\|Schema\)$' | |
| 111 call add(to_del, lnum) | |
| 112 endif | |
| 113 endfor | |
| 114 if !empty(to_del) | |
| 115 for lnum in reverse(to_del) | |
| 116 call deletebufline('%', lnum) | |
| 117 endfor | |
| 118 endif | |
| 119 endfunction | |
| 120 | |
| 121 | |
| 122 " Open table data for a given table name | |
| 123 function! s:OpenTableData(table) | |
| 124 tabnew | |
| 125 enew | |
| 126 execute 'file ' . a:table | |
| 127 let data = s:ExecuteDBQuery('SELECT * FROM ' . a:table . ';') | |
| 128 if !empty(data) | |
| 129 call append(0, data) | |
| 130 else | |
| 131 call append(0, 'No data found.') | |
| 132 endif | |
| 133 setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nomodifiable | |
| 134 endfunction | |
| 135 | |
| 136 " Open table schema for a given table name | |
| 137 function! s:OpenTableSchema(table) | |
| 138 tabnew | |
| 139 enew | |
| 140 execute 'file ' . a:table . '_schema' | |
| 141 let data = s:ExecuteDBQuery('DESCRIBE ' . a:table . ';') | |
| 142 if !empty(data) | |
| 143 call append(0, data) | |
| 144 else | |
| 145 call append(0, 'No schema found or an error occurred.') | |
| 146 endif | |
| 147 setlocal filetype=sql buftype=nofile bufhidden=wipe nobuflisted noswapfile nomodifiable | |
| 148 endfunction | |
| 149 | |
| 150 function! s:OpenDBTablesWindow() | |
| 151 " Open a new vertical split window | |
| 152 execute '34 vsplit' | |
| 153 " Create a new buffer | |
| 154 enew | |
| 155 " Set buffer name to "DBTables" | |
| 156 file DBTables | |
| 157 | |
| 158 let tables = s:ExecuteDBQuery("SHOW TABLES;") | |
| 159 if empty(tables) | |
| 160 echo "No tables found or an error occurred." | |
| 161 return | |
| 162 endif | |
| 163 | |
| 164 " Display the tables in the buffer | |
| 165 call append(0, 'Available Tables:') | |
| 166 call remove(tables, 0) | |
| 167 for table in tables | |
| 168 call append('$', table) | |
| 169 endfor | |
| 170 | |
| 171 " Set buffer options | |
| 172 setlocal buftype=nofile | |
| 173 setlocal bufhidden=wipe | |
| 174 setlocal nobuflisted | |
| 175 setlocal noswapfile | |
| 176 setlocal nomodifiable | |
| 177 setlocal nonumber | |
| 178 setlocal norelativenumber | |
| 179 setlocal winfixwidth | |
| 180 | |
| 181 " Map <Enter> to a modal menu (data or schema) | |
| 182 nnoremap <buffer> <CR> :call <SID>ShowTablePopup()<CR> | |
| 183 endfunction | |
| 184 | |
| 185 | |
| 186 function! s:ShowTableData() | |
| 187 " Get the current line (table name) | |
| 188 let lnum = line('.') | |
| 189 let table_name = getline(lnum) | |
| 190 | |
| 191 " Open a new tab and create a new buffer | |
| 192 tabnew | |
| 193 enew | |
| 194 " Set buffer name to the table name | |
| 195 execute 'file ' . table_name | |
| 196 | |
| 197 let data = s:ExecuteDBQuery("SELECT * FROM " . table_name . ";") | |
| 198 | |
| 199 " Display the table data in the buffer | |
| 200 if len(data) > 0 | |
| 201 call append(0, data) | |
| 202 else | |
| 203 call append(0, 'No data found.') | |
| 204 endif | |
| 205 | |
| 206 " Set buffer options | |
| 207 setlocal buftype=nofile | |
| 208 setlocal bufhidden=wipe | |
| 209 setlocal nobuflisted | |
| 210 setlocal noswapfile | |
| 211 setlocal nomodifiable | |
| 212 endfunction | |
| 213 | |
| 214 let s:query_history = [] | |
| 215 | |
| 216 function! s:ExecuteSQLQuery() | |
| 217 " Get the content of the current buffer (SQL query) | |
| 218 let query = join(getline(1, '$'), " ") | |
| 219 | |
| 220 " Append the query to history | |
| 221 call add(s:query_history, query) | |
| 222 | |
| 223 let data = s:ExecuteDBQuery(query) | |
| 224 | |
| 225 tabnew | |
| 226 enew | |
| 227 execute 'file SQLQueryResult' | |
| 228 call append(0, data) | |
| 229 | |
| 230 " Set the buffer file type to SQL for syntax highlighting | |
| 231 setlocal filetype=sql | |
| 232 | |
| 233 setlocal buftype=nofile | |
| 234 setlocal bufhidden=wipe | |
| 235 setlocal nobuflisted | |
| 236 setlocal noswapfile | |
| 237 setlocal nomodifiable | |
| 238 endfunction | |
| 239 | |
| 240 " Execute SQL from a visual selection | |
| 241 function! s:ExecuteVisualSQLQuery() range | |
| 242 " Get the content of the selected lines as a single SQL query | |
| 243 let lines = getline(a:firstline, a:lastline) | |
| 244 let query = join(lines, " ") | |
| 245 | |
| 246 " Append the query to history | |
| 247 call add(s:query_history, query) | |
| 248 | |
| 249 " Execute the query and capture results | |
| 250 let data = s:ExecuteDBQuery(query) | |
| 251 | |
| 252 " Open results in a new tab | |
| 253 tabnew | |
| 254 enew | |
| 255 execute 'file SQLQueryResult' | |
| 256 call append(0, data) | |
| 257 | |
| 258 " Set buffer options and highlight | |
| 259 setlocal filetype=sql | |
| 260 setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nomodifiable | |
| 261 endfunction | |
| 262 | |
| 263 function! s:OpenQueryHistory() | |
| 264 " Open the query history in a new split window | |
| 265 execute 'vsplit' | |
| 266 enew | |
| 267 call setline(1, s:query_history) | |
| 268 | |
| 269 " Allow selecting a query to be put into a new buffer to execute | |
| 270 nnoremap <buffer> <CR> :call <SID>ExecuteHistoryQuery(line('.'))<CR> | |
| 271 | |
| 272 " Set buffer options | |
| 273 setlocal buftype=nofile | |
| 274 setlocal bufhidden=wipe | |
| 275 setlocal nobuflisted | |
| 276 setlocal noswapfile | |
| 277 endfunction | |
| 278 | |
| 279 function! s:ExecuteHistoryQuery(lnum) | |
| 280 " Execute the selected query from history | |
| 281 let query = getline(a:lnum) | |
| 282 execute 'normal! i' . query | |
| 283 " Optionally call the execute function directly or process | |
| 284 endfunction | |
| 285 | |
| 286 | |
| 287 function! DBConsole() | |
| 288 " Save the current cursor position | |
| 289 let save_cursor = getpos(".") | |
| 290 | |
| 291 "Format the files | |
| 292 let db_user = g:db_user | |
| 293 let db_password = g:db_password | |
| 294 let db_name = g:db_name | |
| 295 " let db_host = shellescape(g:db_host) | |
| 296 let db_host = g:db_host | |
| 297 | |
| 298 | |
| 299 | |
| 300 let command = 'mariadb --user=' . db_user . ' --password=' . db_password . ' --database=' . db_name . ' --host=' . db_host . ' ' | |
| 301 let command = substitute(command, '\n', '', 'g') | |
| 302 execute ':term ' . command | |
| 303 call setpos(".", save_cursor) | |
| 304 endfunction | |
| 305 | |
| 306 " Keybinding to open query history | |
| 307 nnoremap <Leader>qh :call <SID>OpenQueryHistory()<CR> | |
| 308 nnoremap <Leader>db :call DBConsole()<cr> | |
| 309 | |
| 310 command! DBTables call s:OpenDBTablesWindow() | |
| 311 command! ExecuteSQL call s:ExecuteSQLQuery() | |
| 312 | |
| 313 " Function to refresh the list of tables | |
| 314 nnoremap <Leader>rt :DBTables<CR> | |
| 315 | |
| 316 " Function to execute the contents of the current buffer as an SQL query | |
| 317 nnoremap <Leader>eq :ExecuteSQL<CR> | |
| 318 | |
| 319 " Function to open the database tables window | |
| 320 nnoremap <Leader>dt :DBTables<CR> | |
| 321 | |
| 322 " Optional: Shortcut to open MariaDB console | |
| 323 nnoremap <Leader>mc :call DBConsole()<CR> | |
| 324 " Map visual selection to execute selected SQL | |
| 325 xnoremap <silent> <Leader>ev :call <SID>ExecuteVisualSQLQuery()<CR> |
