Mercurial > vim
comparison plugins/dbtables/dbtables.vim @ 6:3017fd33ad8b
Better support for db tables.
Adding some simple diffing support for hg.
| author | Luka Sitas <lsitas@avatarasoftware.com> |
|---|---|
| date | Tue, 28 Oct 2025 15:26:12 -0400 |
| parents | 4a7bc1c8551b |
| children |
comparison
equal
deleted
inserted
replaced
| 5:4a7bc1c8551b | 6:3017fd33ad8b |
|---|---|
| 1 let g:db_user = "" " Replace with your default database username | 1 let g:db_user = "" |
| 2 let g:db_password = "" " Replace with your default database password | 2 let g:db_password = "" |
| 3 let g:db_name = "" " Replace with your default database name | 3 let g:db_name = "" |
| 4 let g:db_host = "" " Replace with your default database name | 4 let g:db_host = "" |
| 5 | 5 |
| 6 | 6 " Execute shell commands |
| 7 " Helper function to execute a command and handle errors | |
| 8 function! s:ExecuteShellCommand(command) | 7 function! s:ExecuteShellCommand(command) |
| 9 let result = system(a:command . ' 2>&1') | 8 let result = system(a:command . ' 2>&1') |
| 10 if v:shell_error != 0 | 9 return [v:shell_error == 0, result] |
| 11 return [v:false, result] | 10 endfunction |
| 12 endif | 11 |
| 13 return [v:true, result] | 12 " Execute a SQL query |
| 14 endfunction | |
| 15 | |
| 16 function! s:ExecuteDBQuery(query) | 13 function! s:ExecuteDBQuery(query) |
| 17 let db_user = shellescape(g:db_user) | 14 let command = printf('mariadb --user=%s --password=%s --database=%s --host=%s -e %s', |
| 18 let db_password = shellescape(g:db_password) | 15 \ shellescape(g:db_user), shellescape(g:db_password), |
| 19 let db_name = shellescape(g:db_name) | 16 \ shellescape(g:db_name), shellescape(g:db_host), |
| 20 let db_host = shellescape(g:db_host) | 17 \ shellescape(a:query)) |
| 21 | 18 |
| 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) | 19 let [success, result] = s:ExecuteShellCommand(command) |
| 29 | 20 if success |
| 30 if !success | 21 return split(result, "\n") |
| 22 else | |
| 31 call s:HandleDBError(result, command) | 23 call s:HandleDBError(result, command) |
| 32 return [] | 24 return [] |
| 33 endif | 25 endif |
| 34 return split(result, "\n") | 26 endfunction |
| 35 endfunction | 27 |
| 36 | 28 " Handle database command errors |
| 37 function! s:HandleDBError(result, command) | 29 function! s:HandleDBError(result, command) |
| 38 echoerr 'Shell command failed: ' . a:command | 30 echoerr 'Shell command failed: ' . a:command |
| 39 echoerr a:result | |
| 40 | |
| 41 if a:result =~# 'Access denied' | 31 if a:result =~# 'Access denied' |
| 42 echoerr 'Authentication error: Check your username and password.' | 32 echoerr 'Authentication error: Check your username and password.' |
| 43 elseif a:result =~# 'Unknown database' | 33 elseif a:result =~# 'Unknown database' |
| 44 echoerr 'Database error: The specified database does not exist.' | 34 echoerr 'Database error: The specified database does not exist.' |
| 45 elseif a:result =~# 'Could not connect' | 35 elseif a:result =~# 'Could not connect' |
| 49 else | 39 else |
| 50 echoerr 'Unexpected error: ' . a:result | 40 echoerr 'Unexpected error: ' . a:result |
| 51 endif | 41 endif |
| 52 endfunction | 42 endfunction |
| 53 | 43 |
| 54 | 44 " Display schema or data in a new buffer |
| 55 " Show the structure/schema of the selected table | 45 function! s:OpenInNewTab(title, data) |
| 56 function! s:ShowTableSchema(table) | |
| 57 " Open a new tab for schema | |
| 58 tabnew | 46 tabnew |
| 59 enew | 47 enew |
| 60 execute 'file ' . table . '_schema' | 48 execute 'file ' . a:title |
| 61 " Describe the table structure | 49 if !empty(a:data) |
| 62 let data = s:ExecuteDBQuery('DESCRIBE ' . table . ';') | 50 call append(0, a:data) |
| 63 if len(data) > 0 | 51 else |
| 64 call append(0, data) | 52 call append(0, 'No data found or an error occurred.') |
| 65 else | 53 endif |
| 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 | 54 setlocal filetype=sql buftype=nofile bufhidden=wipe nobuflisted noswapfile nomodifiable |
| 70 endfunction | 55 endfunction |
| 71 | 56 |
| 57 " Open the database schema | |
| 58 function! s:OpenTableSchema(table) | |
| 59 call s:OpenInNewTab(a:table . '_schema', s:ExecuteDBQuery('DESCRIBE ' . a:table . ';')) | |
| 60 endfunction | |
| 61 | |
| 62 " Open the table data | |
| 63 function! s:OpenTableData(table) | |
| 64 call s:OpenInNewTab(a:table, s:ExecuteDBQuery('SELECT * FROM ' . a:table . ';')) | |
| 65 endfunction | |
| 72 | 66 |
| 73 let s:popup_table = "" | 67 let s:popup_table = "" |
| 74 " Popup selection for table actions | 68 " Popup selection for table actions |
| 75 function! s:ShowTablePopup() | 69 function! s:ShowTablePopup() |
| 76 " Use Vim popup_menu if available | 70 " Use Vim popup_menu if available |
| 99 | 93 |
| 100 function! s:ClosePopup() | 94 function! s:ClosePopup() |
| 101 unlet! s:popup_table | 95 unlet! s:popup_table |
| 102 endfunction | 96 endfunction |
| 103 | 97 |
| 104 | 98 " Open the database tables list |
| 105 " Internal: remove any existing dropdown option lines from the DBTables buffer | 99 function! s:OpenDBTablesWindow() |
| 106 function! s:ClearTableOptions() | 100 execute '34 vsplit' |
| 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 | 101 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 | 102 file DBTables |
| 157 | |
| 158 let tables = s:ExecuteDBQuery("SHOW TABLES;") | 103 let tables = s:ExecuteDBQuery("SHOW TABLES;") |
| 159 if empty(tables) | 104 if empty(tables) |
| 160 echo "No tables found or an error occurred." | 105 echo "No tables found or an error occurred." |
| 161 return | 106 else |
| 162 endif | 107 call append(0, ['Available Tables:'] + tables[1:]) |
| 163 | 108 setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nomodifiable nonumber norelativenumber winfixwidth |
| 164 " Display the tables in the buffer | 109 nnoremap <buffer> <CR> :call <SID>ShowTablePopup()<CR> |
| 165 call append(0, 'Available Tables:') | 110 endif |
| 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 | 111 endfunction |
| 213 | 112 |
| 214 let s:query_history = [] | 113 let s:query_history = [] |
| 215 | 114 |
| 216 " Function to execute SQL from the current buffer with parameter prompt | 115 " Function to execute SQL from the current buffer with parameter prompt |
| 217 function! s:ExecuteSQLQuery() | 116 function! s:ExecuteSQLQuery() |
| 218 " Get the content of the current buffer (SQL query) | |
| 219 let query = join(getline(1, '$'), "\n") | 117 let query = join(getline(1, '$'), "\n") |
| 220 | |
| 221 " Execute query with prompt for parameters | |
| 222 call s:PromptAndExecuteQuery(query) | 118 call s:PromptAndExecuteQuery(query) |
| 223 endfunction | 119 endfunction |
| 224 | 120 |
| 225 " Function to execute SQL from a visual selection with parameter prompt | 121 " Function to execute SQL from a visual selection with parameter prompt |
| 226 function! s:ExecuteVisualSQLQuery() range | 122 function! s:ExecuteVisualSQLQuery() range |
| 230 | 126 |
| 231 " Execute query with prompt for parameters | 127 " Execute query with prompt for parameters |
| 232 call s:PromptAndExecuteQuery(query) | 128 call s:PromptAndExecuteQuery(query) |
| 233 endfunction | 129 endfunction |
| 234 | 130 |
| 235 | 131 " Handle parameter prompts and execute query |
| 236 " Function to prompt user for parameter values and execute query | |
| 237 function! s:PromptAndExecuteQuery(query) | 132 function! s:PromptAndExecuteQuery(query) |
| 238 " Identify parameters in the form of :parameter_name | 133 " Identify parameters in the form of :parameter_name |
| 239 let pattern = ':\(\k\+\)' | 134 let pattern = ':\(\k\+\)' |
| 240 let params = [] | 135 let params = [] |
| 241 | 136 |
| 259 endfor | 154 endfor |
| 260 | 155 |
| 261 " Replace parameters in the query with user-provided values | 156 " Replace parameters in the query with user-provided values |
| 262 let updated_query = a:query | 157 let updated_query = a:query |
| 263 for [param, value] in items(param_values) | 158 for [param, value] in items(param_values) |
| 264 let updated_query = substitute(updated_query, param, shellescape(value), 'g') | 159 let updated_query = substitute(updated_query, param, value, 'g') |
| 265 endfor | 160 endfor |
| 266 | 161 |
| 267 " Append the query to history | |
| 268 call add(s:query_history, updated_query) | 162 call add(s:query_history, updated_query) |
| 269 | 163 call s:OpenInNewTab('SQLQueryResult', s:ExecuteDBQuery(updated_query)) |
| 270 " Execute the updated query | 164 endfunction |
| 271 let data = s:ExecuteDBQuery(updated_query) | 165 |
| 272 | 166 " View query history |
| 273 " Open results in a new tab | |
| 274 tabnew | |
| 275 enew | |
| 276 execute 'file SQLQueryResult' | |
| 277 call append(0, data) | |
| 278 | |
| 279 " Set buffer options and highlight | |
| 280 setlocal filetype=sql | |
| 281 setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nomodifiable | |
| 282 endfunction | |
| 283 | |
| 284 | |
| 285 function! s:OpenQueryHistory() | 167 function! s:OpenQueryHistory() |
| 286 " Open the query history in a new split window | 168 " Open the query history in a new split window |
| 287 execute 'vsplit' | 169 execute 'vsplit' |
| 288 enew | 170 enew |
| 289 call setline(1, s:query_history) | 171 call setline(1, s:query_history) |
| 290 | |
| 291 " Allow selecting a query to be put into a new buffer to execute | |
| 292 nnoremap <buffer> <CR> :call <SID>ExecuteHistoryQuery(line('.'))<CR> | 172 nnoremap <buffer> <CR> :call <SID>ExecuteHistoryQuery(line('.'))<CR> |
| 293 | 173 setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile |
| 294 " Set buffer options | |
| 295 setlocal buftype=nofile | |
| 296 setlocal bufhidden=wipe | |
| 297 setlocal nobuflisted | |
| 298 setlocal noswapfile | |
| 299 endfunction | 174 endfunction |
| 300 | 175 |
| 301 function! s:ExecuteHistoryQuery(lnum) | 176 function! s:ExecuteHistoryQuery(lnum) |
| 302 " Execute the selected query from history | |
| 303 let query = getline(a:lnum) | 177 let query = getline(a:lnum) |
| 304 execute 'normal! i' . query | 178 execute 'normal! i' . query |
| 305 " Optionally call the execute function directly or process | 179 " Optional execution or further processing |
| 306 endfunction | 180 endfunction |
| 307 | 181 |
| 308 | 182 " Open MariaDB console |
| 309 function! DBConsole() | 183 function! DBConsole() |
| 310 " Save the current cursor position | 184 " Save the current cursor position |
| 311 let save_cursor = getpos(".") | 185 let save_cursor = getpos(".") |
| 312 | 186 let command = printf('mariadb --user=%s --password=%s --database=%s --host=%s', |
| 313 "Format the files | 187 \ g:db_user, g:db_password, |
| 314 let db_user = g:db_user | 188 \ g:db_name, g:db_host) |
| 315 let db_password = g:db_password | 189 |
| 316 let db_name = g:db_name | 190 let command = substitute(command, '\n', '', 'g') |
| 317 " let db_host = shellescape(g:db_host) | 191 execute ':term ' . command |
| 318 let db_host = g:db_host | 192 call setpos(".", save_cursor) |
| 319 | |
| 320 | |
| 321 | |
| 322 let command = 'mariadb --user=' . db_user . ' --password=' . db_password . ' --database=' . db_name . ' --host=' . db_host . ' ' | |
| 323 let command = substitute(command, '\n', '', 'g') | |
| 324 execute ':term ' . command | |
| 325 call setpos(".", save_cursor) | |
| 326 endfunction | 193 endfunction |
| 327 | 194 |
| 328 " Keybinding to open query history | 195 " Keybinding to open query history |
| 329 nnoremap <Leader>qh :call <SID>OpenQueryHistory()<CR> | 196 nnoremap <Leader>qh :call <SID>OpenQueryHistory()<CR> |
| 330 nnoremap <Leader>db :call DBConsole()<cr> | 197 nnoremap <Leader>db :call DBConsole()<CR> |
| 331 | |
| 332 command! DBTables call s:OpenDBTablesWindow() | 198 command! DBTables call s:OpenDBTablesWindow() |
| 333 command! ExecuteSQL call s:ExecuteSQLQuery() | 199 command! ExecuteSQL call s:ExecuteSQLQuery() |
| 334 | 200 |
| 335 " Function to refresh the list of tables | 201 " Function to refresh the list of tables |
| 336 nnoremap <Leader>rt :DBTables<CR> | 202 nnoremap <Leader>rt :DBTables<CR> |
