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>