提交 27147aa2 编写于 作者: C Cosmin Popescu

added asynchronous functionality

上级 22dc2167
......@@ -17,6 +17,7 @@ You can connect to any DBMS directly from VIM.
`sqldeleteinsert`, `xml`, `ods`, `html`, `json`
* search in object source
* search in table or views data
* asynchronous (you can execute any command asynchronous)
* fully customizable
CONTENTS:
......@@ -28,10 +29,11 @@ CONTENTS:
5. Searching
6. Exporting
7. Sessions
8. Commands
9. Settings
10. Screen shots
11. Missing features
8. Asynchronous
9. Commands
19. Settings
11. Screen shots
12. Missing features
Requirements
========================================
......@@ -511,6 +513,52 @@ that executing statements against the DBMS will produce vim errors. Before
executing any statement, you have to call the `SWSqlBufferRestore`. This will
also restore the autocomplete list, so you will also have the autocomplete.
Asynchronous
========================================
By default, VIM SQL workbench works in synchronous mode. This means that you
launch a command, then you will see on the screen the command being executed
and you have to wait for it to finish to execute another one.
If you set the variable `g:sw_asynchronious` to 1, then VIM SQL Workbench will
switch to work in asynchronous mode. This means that once you launch a
command, the control is returned back immediately, and when the command is
finished, you will see the output. The advantages of this approach are
evident: you can launch more than one command at the same time from different
SQL buffers, you can continue working if the command takes too much time etc.
For example, when you want to activate the intellisense. This can take more
than one minute. You can continue working in all this time.
In order to use the asynchronous mode on Windows, you have to have the [VIM
Dispatch](https://github.com/tpope/vim-dispatch) plugin installed. This is
because in Windows I cannot launch a command as daemon.
Another requirement to run VIM in asynchronous mode is to have the server
option installed and activated (see `:help client-server`). This is the way in
which VIM SQL Workbench will know that a command is finished.
If VIM is not in your `PATH` variable, or you are using other executable (like
`gvim` or `vim.exe` or `gvim.exe` on Windows), you have to set the
`g:sw_vim_exe` variable in order to use the asynchronous mode. The default
value is `vim`. This should work on most `GNU/Linux` distributions if you are
using vim in console mode. If you are using `gvim` or `macvim`, just set the
the variable to whatever you are using. On Windows, you will probably have to
set the variable with full path.
If the command takes to much and you want to launch another command from the
same buffer, by default you will have an error message telling you that
another command is in progress. You can use the `SWKillCurrentCommand`
command. This is mapped by default to <C-c>. You can change the mapping
or you can use it directly in command mode.
Please note that killing a command does not mean that the command will not be
sent to the DBMS. This only means that once it's finished, vim will simply
ignore its output. This is not a way to stop a wrongly sent `update`
statement. The statement will get execute anyway.
If any of the requirements is not met, you will not receive any error message.
The plugin will silently switch to synchronous mode and work without issues.
Commands
========================================
......@@ -842,6 +890,10 @@ This command will restore the properties of the sql buffer following a vim
session restore. This includes the autocomplete intellisense of the buffer, if
this was active when `mksession` was executed.
## SWKillCurrentCommand
This command will kill the current command being executed in asynchronous mode.
Settings
========================================
......@@ -922,6 +974,10 @@ and
* `g:sw_exe`: the location of the `SQL Workbench` executable; default value:
"sqlwbconsole.sh"
* `g:sw_tmp`: the location of your temporary folder; default value: "/tmp"
* `g:sw_asynchronious`: by default, the commands are executed synchronous; if
you set this to 1, then the commands will be executed asynchronous
* `g:sw_vim_exe`: the default VIM executable location; this is used in
conjunction with the asynchronous mode; default value: `vim`
Screen shots
========================================
......
......@@ -21,6 +21,150 @@ if !exists('g:Sw_unique_id')
let g:Sw_unique_id = 0
endif
let s:wake_vim_cmd = ''
let g:sw_async_ended = []
if exists('v:servername') && exists('g:sw_vim_exe')
if v:servername != ''
let s:wake_vim_cmd = g:sw_vim_exe . ' --servername ' . v:servername
endif
endif
function! sw#find_buffer_by_unique_id(uid)
for k in keys(g:sw_session)
if has_key(g:sw_session[k], 'unique_id')
if g:sw_session[k].unique_id == a:uid
return k
endif
endif
endfor
return ''
endfunction
function! s:get_buff_unique_id()
if exists('b:unique_id')
return b:unique_id
endif
if exists('b:r_unique_id')
return b:r_unique_id
endif
return -1
endfunction
function! sw#is_async()
if g:sw_asynchronious
if exists('v:servername')
if v:servername != ''
return 1
endif
endif
endif
return 0
endfunction
function! s:get_wake_vim_cmd()
return s:wake_vim_cmd . ' --remote-expr "sw#got_async_result(' . s:get_buff_unique_id() . ')"'
endfunction
function! sw#async_end()
let idx = index(g:sw_async_ended, s:get_buff_unique_id())
if idx != -1
unlet g:sw_async_ended[idx]
endif
if exists('b:async_on_progress')
unlet b:async_on_progress
if exists('b:on_async_result')
let func = b:on_async_result
execute "call " . func . "()"
endif
call delete(g:sw_tmp . '/' . s:input_file())
call delete(g:sw_tmp . '/' . s:output_file())
call delete(g:sw_tmp . '/' . s:async_input_file())
endif
endfunction
function! sw#reset_current_command()
let idx = index(g:sw_async_ended, s:get_buff_unique_id())
if idx != -1
unlet g:sw_async_ended[idx]
endif
if exists('b:async_on_progress')
unlet b:async_on_progress
endif
call delete(g:sw_tmp . '/' . s:input_file())
call delete(g:sw_tmp . '/' . s:output_file())
call delete(g:sw_tmp . '/' . s:async_input_file())
endfunction
function! sw#kill_current_command()
let idx = index(g:sw_async_ended, s:get_buff_unique_id())
if idx != -1
unlet g:sw_async_ended[idx]
endif
if exists('b:async_on_progress')
unlet b:async_on_progress
endif
if exists('b:on_async_result')
unlet b:on_async_result
endif
if exists('b:on_async_kill')
let func = b:on_async_kill
call sw#session#unset_buffer_variable('on_async_kill')
execute "call " . func . "()"
endif
call delete(g:sw_tmp . '/' . s:input_file())
call delete(g:sw_tmp . '/' . s:output_file())
call delete(g:sw_tmp . '/' . s:async_input_file())
endfunction
function! sw#check_async_result()
let uid = s:get_buff_unique_id()
if uid != -1
if index(g:sw_async_ended, uid) != -1
call sw#async_end()
endif
endif
endfunction
function! sw#got_async_result(unique_id)
call add(g:sw_async_ended, a:unique_id)
if s:get_buff_unique_id() == a:unique_id
if mode() == 'i' || mode() == 'R'
let m = mode()
if m == 'i'
let m = 'a'
endif
call sw#async_end()
execute "normal " . m
elseif mode() == 'V' || mode() == 'v' || mode() == 's'
let m = mode()
normal 
call sw#async_end()
normal gv
if m == 's'
normal 
endif
else
call sw#async_end()
endif
endif
redraw!
return ''
endfunction
function! s:on_windows()
if exists('v:progname')
return v:progname =~ '\v\.exe$'
endif
endfunction
" Executes a shell command{{{1
function! sw#do_shell(command)
let prefix = ''
......@@ -28,7 +172,38 @@ function! sw#do_shell(command)
let prefix = 'silent'
endif
execute prefix . ' !clear && echo Executting && cat ' . g:sw_tmp . '/' . s:input_file() . ' && ' . a:command
if sw#is_async()
let async = 0
if exists('v:progname')
let file = g:sw_tmp . '/' . s:async_input_file()
let commands = [a:command, s:get_wake_vim_cmd()]
if s:on_windows()
if exists('g:loaded_dispatch')
if g:loaded_dispatch
call writefile(commands, file)
execute "Start! " . file
let async = 1
endif
endif
else
let shell = &shell
call writefile(commands, file)
execute prefix . ' !' . shell . ' ' . file . ' &'
let async = 1
endif
endif
if async
let b:async_on_progress = 1
return 1
endif
endif
if s:on_windows()
execute prefix . ' !' . a:command
else
execute prefix . ' !clear && echo Executting && cat ' . g:sw_tmp . '/' . s:input_file() . ' && ' . a:command
endif
return 0
endfunction
function! s:get_profile(profile)
......@@ -42,15 +217,57 @@ function! s:get_profile(profile)
endfunction
function! s:input_file()
return 'sw-sql-' . g:sw_instance_id
return 'sw-sql-' . g:sw_instance_id . (sw#is_async() ? '-' . s:get_buff_unique_id() : '')
endfunction
function! s:output_file()
return 'sw-result-' . g:sw_instance_id
return 'sw-result-' . g:sw_instance_id . (sw#is_async() ? '-' . s:get_buff_unique_id() : '')
endfunction
function! s:async_input_file()
return 'sw-async-' . g:sw_instance_id . (sw#is_async() ? '-' . s:get_buff_unique_id() : '') . '.bat'
endfunction
function! sw#get_sql_result(touch_result)
let result = readfile(g:sw_tmp . '/' . s:output_file())
let touch_result = a:touch_result
if (touch_result && len(result) > 0)
if result[len(result) - 1] =~ '\v\c^\([0-9]+ row[s]?\)$'
let result[0] = result[len(result) - 1]
unlet result[len(result) - 1]
else
unlet result[0]
endif
endif
""let i = 0
""for row in result
"" if row == a:command
"" unlet result[i]
"" break
"" endif
"" let i = i + 1
""endfor
if (g:sw_show_command)
call add(result, "")
call add(result, '-----------------------------------------------------------------------------')
call add(result, ' Command executed: ' . a:command)
endif
return result
endfunction
" Executes an sql command{{{1
function! sw#execute_sql(profile, command, ...)
if sw#is_async()
if exists('b:async_on_progress')
if b:async_on_progress
throw 'There is a command in progress for this buffer. Please wait for it to finish.'
endif
endif
endif
execute "silent !echo '' >" . g:sw_tmp . '/' . s:output_file()
let delimiter = ''
if (exists('b:delimiter'))
......@@ -96,40 +313,19 @@ function! sw#execute_sql(profile, command, ...)
let g:sw_last_command = c
let lines = split(a:command, "\n")
call writefile(lines, g:sw_tmp . '/' . s:input_file())
call sw#do_shell(c)
redraw!
let result = readfile(g:sw_tmp . '/' . s:output_file())
let touch_result = 1
if a:0
let touch_result = a:1
endif
if (touch_result && len(result) > 0)
if result[len(result) - 1] =~ '\v\c^\([0-9]+ row[s]?\)$'
let result[0] = result[len(result) - 1]
unlet result[len(result) - 1]
else
unlet result[0]
endif
endif
""let i = 0
""for row in result
"" if row == a:command
"" unlet result[i]
"" break
"" endif
"" let i = i + 1
""endfor
if (g:sw_show_command)
call add(result, "")
call add(result, '-----------------------------------------------------------------------------')
call add(result, ' Command executed: ' . a:command)
endif
" If do_shell returns 0, it means that the command was not executed
" asynchroniously
if (!sw#do_shell(c))
redraw!
let touch_result = 1
if a:0
let touch_result = a:1
endif
return sw#get_sql_result(touch_result)
endif
return result
redraw!
return []
endfunction
" Exports as ods{{{1
......@@ -140,7 +336,6 @@ function! sw#export_ods(profile, command)
let location = input('Please select a destination file: ', '', 'file')
if (location != '')
let queries = sw#sql_split(a:command)
echomsg string(queries)
call writefile(['WbExport -type=' . format . ' -file=' . location . ';', queries[len(queries) - 1]], g:sw_tmp . '/' . s:input_file())
let c = g:sw_exe . s:get_profile(a:profile) . ' -displayResult=true -script=' . g:sw_tmp . '/' . s:input_file()
call sw#do_shell(c)
......@@ -311,9 +506,13 @@ endfunction
" Goes to a window identified by a buffer name{{{1
function! sw#goto_window(name)
let crt = bufname('%')
if bufwinnr(a:name) != -1
while bufname('%') != a:name
while bufname('%') != a:name && sw#session#buffer_name() != a:name
wincmd w
if bufname('%') == crt
return
endif
endwhile
endif
endfunction
......
......@@ -87,6 +87,8 @@ function! sw#autocomplete#extract_current_sql()
endif
endif
""let sql = s:eliminate_sql_comments(sql)
if sql =~ '\v\c<union>'
let sqls = split(sql, '\v\c<union[\s \t]*(all)?>')
for _sql in sqls
......@@ -109,25 +111,23 @@ function! s:execute_file(f)
endfor
endfunction
function! sw#autocomplete#set_cache_default()
call sw#autocomplete#cache()
function s:set_default()
let g:sw_autocomplete_default_tables = b:autocomplete_tables
let g:sw_autocomplete_default_procs = b:autocomplete_procs
let g:Str_sw_autocomplete_default_tables = string(g:sw_autocomplete_default_tables)
let g:Str_sw_autocomplete_default_procs = string(g:sw_autocomplete_default_procs)
endfunction
function! sw#autocomplete#cache()
if (!exists('b:profile'))
return
function! sw#autocomplete#set_cache_default()
call sw#autocomplete#cache()
if sw#is_async()
let b:__set_default = 1
else
call s:set_default()
endif
call sw#session#init_section()
let sql = "WbSchemaReport -file=" . g:sw_tmp . "/sw_report.xml -objects=% -types='TABLE,VIEW,SYSTEM VIEW,MATERIALIZED VIEW,TEMPORARY TABLE,SYNONYM' -stylesheet=" . s:script_path . "resources/wbreport2vim.xslt -xsltOutput=" . g:sw_tmp . "/sw_report.vim;\n"
let sql = sql . "WbExport -type=xml -file=" . g:sw_tmp . "/sw_procs.xml -stylesheet=" . s:script_path . "resources/wbprocedures2vim.xslt -lineEnding=lf -xsltOutput=" . g:sw_tmp . "/sw_procs.vim;\n"
let sql = sql . "WBListProcs;"
let result = sw#execute_sql(b:profile, sql)
endfunction
function! sw#autocomplete#got_result()
if !filereadable(g:sw_tmp . "/sw_report.xml")
throw "There is a problem clearing the autocomplete cache. Please check your connection"
endif
......@@ -138,6 +138,28 @@ function! sw#autocomplete#cache()
call sw#session#set_buffer_variable('autocomplete_procs', g:_procedures)
unlet g:_procedures
setlocal omnifunc=sw#autocomplete#perform
if exists('b:__set_default')
call s:set_default()
unlet b:__set_default
endif
echomsg "Autocomplete activated"
endfunction
function! sw#autocomplete#cache()
if (!exists('b:profile'))
return
endif
call sw#session#init_section()
let sql = "WbSchemaReport -file=" . g:sw_tmp . "/sw_report.xml -objects=% -types='TABLE,VIEW,SYSTEM VIEW,MATERIALIZED VIEW,TEMPORARY TABLE,SYNONYM' -stylesheet=" . s:script_path . "resources/wbreport2vim.xslt -xsltOutput=" . g:sw_tmp . "/sw_report.vim;\n"
let sql = sql . "WbExport -type=xml -file=" . g:sw_tmp . "/sw_procs.xml -stylesheet=" . s:script_path . "resources/wbprocedures2vim.xslt -lineEnding=lf -xsltOutput=" . g:sw_tmp . "/sw_procs.vim;\n"
let sql = sql . "WBListProcs;"
let b:on_async_result = 'sw#autocomplete#got_result'
let result = sw#execute_sql(b:profile, sql)
if !sw#is_async()
unlet b:on_async_result
call sw#autocomplete#got_result()
endif
endfunction
function! s:get_cache_tables()
......@@ -279,7 +301,6 @@ function! sw#autocomplete#perform(findstart, base)
elseif b:autocomplete_type == 'select' || b:autocomplete_type == 'update'
" If a select, first get its tables
let tables = s:get_tables(sql, [])
echomsg string(tables)
" If we returned an empty string, then no autocomplete
if string(tables) == ""
return []
......@@ -323,7 +344,7 @@ function! sw#autocomplete#perform(findstart, base)
" If we are between select and from or after where, then or in
" a using, return fields to autocomplete
if sql =~ '\v\cselect.*#cursor#.*from' || sql =~ '\v\cwhere.*#cursor#' || sql =~ '\v\cusing[\s\t ]*\([^\)]*#cursor#' || sql =~ '\v\cupdate.*<(set|where)>.*#cursor#'
if sql =~ '\v\cselect.*#cursor#.*from' || sql =~ '\v\c(where|group|having).*#cursor#' || sql =~ '\v\cusing[\s\t ]*\([^\)]*#cursor#' || sql =~ '\v\cupdate.*<(set|where)>.*#cursor#'
let result = []
for table in tables
for field in table['fields']
......@@ -345,6 +366,10 @@ function! sw#autocomplete#perform(findstart, base)
endfor
endfor
if len(result) == 0
return sw#autocomplete#all_objects(a:base)
endif
return result
else
" Otherwise, just return the tables autocomplete
......
......@@ -70,6 +70,7 @@ function! s:set_special_buffer(profile, connection)
call sw#session#set_buffer_variable('t1_shortcuts', 'Main shortcuts:')
call sw#session#set_buffer_variable('t2_shortcuts', 'Available shortcuts in the left panel:')
call sw#session#set_buffer_variable('t3_shortcuts', 'Available shortcuts in the right panel:')
call sw#session#autocommand('BufEnter', 'sw#check_async_result()')
if (a:connection != '')
call sw#session#set_buffer_variable('connection', a:connection)
......@@ -78,12 +79,57 @@ function! s:set_special_buffer(profile, connection)
call s:iterate('s:add_shortcut')
endfunction
" Change a tab{{{2
function! s:change_tab(command, shortcut, title)
let result = sw#execute_sql(b:profile, a:command)
wincmd t
function! s:get_panels()
return ['__DBExplorer__-' . b:profile, '__SQL__-' . b:profile, '__Info__-' . b:profile]
endfunction
function! s:set_values_to_all_buffers(keys, values)
let name = bufname('%')
for w in s:get_panels()
call sw#goto_window(w)
let i = 0
while i < len(a:keys)
execute "let b:" . a:keys[i] . " = a:values[i]"
let i = i + 1
endwhile
endfor
call sw#goto_window(name)
endfunction
function! s:unset_values_from_all_buffers(keys)
let name = bufname('%')
for w in s:get_panels()
call sw#goto_window(w)
for key in a:keys
if exists('b:' . key)
execute "unlet b:" . key
endif
endfor
endfor
call sw#goto_window(name)
endfunction
function! s:set_async_variables()
let name = bufname('%')
for w in s:get_panels()
call sw#goto_window(w)
if exists('b:async_on_progress')
call s:set_values_to_all_buffers(['async_on_progress'], [b:async_on_progress])
break
endif
endfor
call sw#goto_window(name)
endfunction
function! s:unset_async_variables()
call s:unset_values_from_all_buffers(['async_on_progress'])
endfunction
function! s:process_result_1(result, shortcut, title)
let result = a:result
call sw#goto_window('__Info__-' . b:profile)
call sw#session#set_buffer_variable('current_tab', a:shortcut)
wincmd b
call sw#goto_window('__SQL__-' . b:profile)
call sw#session#set_buffer_variable('current_tab', a:shortcut)
if (exists('b:last_cmd'))
call sw#session#unset_buffer_variable('last_cmd')
......@@ -91,7 +137,7 @@ function! s:change_tab(command, shortcut, title)
setlocal modifiable
normal! ggdG
setlocal nomodifiable
wincmd h
call sw#goto_window('__DBExplorer__-' . b:profile)
if (exists('b:mappings'))
for m in b:mappings
execute "silent! nunmap <buffer> " . m
......@@ -106,8 +152,7 @@ function! s:change_tab(command, shortcut, title)
normal! ggdd
setlocal nomodifiable
call s:set_info_buffer()
wincmd b
wincmd h
call sw#goto_window('__DBExplorer__-' . b:profile)
call sw#session#set_buffer_variable('mappings', [])
call sw#session#set_buffer_variable('shortcut', a:shortcut)
call s:iterate('s:find_tab_by_shortcut')
......@@ -122,20 +167,68 @@ function! s:change_tab(command, shortcut, title)
silent! call matchdelete(b:selected_row)
call sw#session#unset_buffer_variable('selected_row')
endif
endfunction
function! s:set_tmp_variables_1(title, shortcut)
call s:set_values_to_all_buffers(['on_async_result', 'on_async_kill', '__title', '__shortcut'], ['sw#dbexplorer#on_async_result_1', 'sw#dbexplorer#on_async_result_1', a:title, a:shortcut])
endfunction
function! s:change_panel(command, shortcut, title, tab_shortcut)
"if line('.') < 5
" echoerr "You have to select an object in the left panel"
" return
"endif
if (exists('b:selected_row'))
call matchdelete(b:selected_row)
function! s:unset_tmp_variables_1()
call s:unset_values_from_all_buffers(['on_async_result', 'on_async_kill', '__title', '__shortcut'])
endfunction
function! sw#dbexplorer#on_async_result_1()
let result = sw#get_sql_result(1)
call s:process_result_1(result, b:__shortcut, b:__title)
call s:unset_async_variables()
endfunction
function! sw#dbexplorer#on_async_result_2()
let result = sw#get_sql_result(1)
call s:process_result_2(result, b:__tab_shortcut, b:__shortcut, b:__cmd)
call s:unset_async_variables()
endfunction
function! sw#dbexplorer#on_async_kill_1()
call s:unset_tmp_variables_1()
call s:unset_async_variables()
call sw#goto_window('__DBExplorer__-' . b:profile)
setlocal modifiable
put ='Interrupted'
setlocal nomodifiable
endfunction
function! sw#dbexplorer#on_async_kill_2()
call s:unset_tmp_variables_2()
call s:unset_async_variables()
call sw#goto_window('__SQL__-' . b:profile)
setlocal modifiable
put ='Interrupted'
setlocal nomodifiable
endfunction
" Change a tab{{{2
function! s:change_tab(command, shortcut, title)
let result = sw#execute_sql(b:profile, a:command)
call s:set_async_variables()
call s:set_tmp_variables_1(a:title, a:shortcut)
if (len(result) != 0)
call s:unset_tmp_variables_1()
call s:process_result_1(result, a:shortcut, a:title)
else
if sw#is_async()
call sw#goto_window('__DBExplorer__-' . b:profile)
setlocal modifiable
normal ggdG
put ='Loading ' . a:title . '... Please wait.'
normal ggdd
setlocal nomodifiable
endif
endif
let object = substitute(getline('.'), '\v^([^ ]+) .*$', '\1', 'g')
call sw#session#set_buffer_variable('selected_row', matchadd('SWSelectedObject', '^' . object . ' .*$'))
let cmd = substitute(a:command, '\v\%object\%', object, 'g')
let result = sw#execute_sql(b:profile, cmd)
endfunction
function! s:process_result_2(result, tab_shortcut, shortcut, cmd)
let result = a:result
call sw#session#set_buffer_variable('shortcut', a:tab_shortcut)
call s:iterate('s:find_tab_by_shortcut')
if (exists('b:tab'))
......@@ -149,7 +242,7 @@ function! s:change_panel(command, shortcut, title, tab_shortcut)
let result = sw#hide_header(result)
endif
endif
wincmd b
call sw#goto_window('__SQL__-' . b:profile)
if (has_key(panel, 'filetype'))
execute 'set filetype=' . panel['filetype']
else
......@@ -159,8 +252,8 @@ function! s:change_panel(command, shortcut, title, tab_shortcut)
endif
endfor
endif
wincmd b
call sw#session#set_buffer_variable('last_cmd', cmd)
call sw#goto_window('__SQL__-' . b:profile)
call sw#session#set_buffer_variable('last_cmd', a:cmd)
setlocal modifiable
normal! ggdG
for line in result
......@@ -169,12 +262,49 @@ function! s:change_panel(command, shortcut, title, tab_shortcut)
normal! ggdd
setlocal nomodifiable
let pattern = '\v^.*-- AFTER(.*)$'
if cmd =~ pattern
let after = substitute(cmd, pattern, '\1', 'g')
if a:cmd =~ pattern
let after = substitute(a:cmd, pattern, '\1', 'g')
execute after
endif
endfunction
function! s:set_tmp_variables_2(tab_shortcut, shortcut, cmd)
call s:set_values_to_all_buffers(['__tab_shortcut', '__shortcut', '__cmd', 'on_async_result', 'on_async_kill'], [a:tab_shortcut, a:shortcut, a:cmd, 'sw#dbexplorer#on_async_result_2', 'sw#dbexplorer#on_async_kill_2'])
endfunction
function! s:unset_tmp_variables_2()
call s:unset_values_from_all_buffers(['__tab_shortcut', '__shortcut', '__cmd', 'on_async_result', 'on_async_kill'])
endfunction
function! s:change_panel(command, shortcut, title, tab_shortcut)
"if line('.') < 5
" echoerr "You have to select an object in the left panel"
" return
"endif
if (exists('b:selected_row'))
call matchdelete(b:selected_row)
endif
let object = substitute(getline('.'), '\v^([^ ]+) .*$', '\1', 'g')
call sw#session#set_buffer_variable('selected_row', matchadd('SWSelectedObject', '^' . object . ' .*$'))
let cmd = substitute(a:command, '\v\%object\%', object, 'g')
call s:set_tmp_variables_2(a:tab_shortcut, a:shortcut, cmd)
let result = sw#execute_sql(b:profile, cmd)
call s:set_async_variables()
if len(result) != 0
call s:unset_tmp_variables_2()
call s:process_result_2(result, a:tab_shortcut, a:shortcut, cmd)
else
if sw#is_async()
call sw#goto_window('__SQL__-' . b:profile)
setlocal modifiable
normal ggdG
put ='Loading ' . a:title . '... Please wait.'
normal ggdd
setlocal modifiable
endif
endif
endfunction
" Adds a shortcut from a tab to the current buffer{{{2
function! s:add_shortcut(tab)
execute "nnoremap <buffer> <silent> " . a:tab['shortcut'] . " :call <SID>change_tab(\"" . substitute(a:tab['command'], '"', "\\\\\"", 'g') . "\", \"" . a:tab['shortcut'] . "\", \"" . a:tab['title'] . "\")<cr>"
......@@ -195,7 +325,7 @@ endfunction
" Set the help buffer{{{2
function! s:set_info_buffer()
wincmd t
call sw#goto_window('__Info__-' . b:profile)
setlocal modifiable
normal! ggdG
put ='The current profile is ' . b:profile
......@@ -314,16 +444,16 @@ function! sw#dbexplorer#restore_from_session(...)
if exists('b:connection')
let connection = b:connection
endif
wincmd t
call sw#goto_window('__Info__-' . b:profile)
call sw#session#init_section()
call sw#session#check()
call s:set_special_buffer(b:profile, connection)
call s:set_highlights()
wincmd b
call sw#goto_window('__SQL__-' . b:profile)
call sw#session#init_section()
call sw#session#check()
call s:set_special_buffer(b:profile, connection)
wincmd h
call sw#goto_window('__DBExplorer__-' . b:profile)
call sw#session#init_section()
call sw#session#check()
call s:set_special_buffer(b:profile, connection)
......@@ -360,19 +490,24 @@ function! sw#dbexplorer#show_panel(profile, ...)
let connection = a:1
endif
let uid = sw#generate_unique_id()
execute "badd " . name
execute "buffer " . name
call s:set_special_buffer(a:profile, connection)
call sw#session#set_buffer_variable('unique_id', uid)
nnoremap <buffer> <silent> E :call sw#dbexplorer#export()<cr>
nnoremap <buffer> <silent> B :call <SID>open_in_new_buffer()<cr>
execute "silent! split __Info__-" . a:profile
resize 7
"let id = matchadd('SWHighlights', '\v^([^\(]+\([A-Za-z]+\)( \| )?)+$')
call s:set_special_buffer(a:profile, connection)
call sw#session#set_buffer_variable('unique_id', uid)
call s:set_highlights()
wincmd b
execute "silent! vsplit __DBExplorer__-" . a:profile
call s:set_special_buffer(a:profile, connection)
call sw#session#set_buffer_variable('unique_id', uid)
vertical resize 60
""call s:set_objects_buffer()
call s:iterate('s:get_first_tab')
......
......@@ -39,6 +39,16 @@ let s:obj_parameters = [{'name': 'searchValues', 'prompt': 'Search terms: ', 'ty
let s:data_parameters = [{'name': 'searchValue', 'prompt': 'Search terms: ', 'type': 'string', 'escape': 1, 'highlight': 1}, {'name': 'ignoreCase', 'prompt': 'Ignore case? [Y/N] ', 'type': 'boolean', 'default': g:sw_search_default_ignore_case, 'highlight_case': 1}, {'name': 'compareType', 'prompt': 'Possible values: equals | matches | startsWith | isNull. Compare type: ', 'type': 'select', 'default': g:sw_search_default_compare_types, 'options': ['equals', 'matches', 'startsWith', 'isNull']}, {'name': 'tables', 'prompt': 'Tables list: ', 'type': 'string', 'default': g:sw_search_default_tables}, {'name': 'types', 'prompt': 'Object types: ', 'type': 'string', 'default': g:sw_search_default_data_types, 'escape': 1}, {'name': 'excludeTables', 'prompt': 'Tables to exclude: ', 'type': 'string', 'continue_on_null': 1}, {'name': 'excludeLobs', 'prompt': 'Do you want to exclude lobs? [Y/N] ', 'type': 'boolean', 'default': g:sw_search_default_exclude_lobs}]
function! s:get_resultset_name()
let uid = ''
if exists('b:unique_id')
let uid = b:unique_id
elseif exists('b:r_unique_id')
let uid = b:r_unique_id
endif
return "__SQLResult__-" . b:profile . '__' . uid
endfunction
function! s:input_boolean(message, default_value)
let result = input(a:message, a:default_value)
if result == ''
......@@ -80,16 +90,8 @@ function! s:input_select(message, default_value, options)
return result
endfunction
function! sw#search#do(command, columns)
call sw#session#init_section()
if exists('b:feedback')
let feedback = b:feedback
call sw#session#unset_buffer_variable('feedback')
endif
let result = sw#execute_sql(b:profile, a:command, 0)
if exists('feedback')
call sw#session#set_buffer_variable('feedback', feedback)
endif
function! s:process_search_result(result, columns)
let result = a:result
if a:columns != ''
let _c = split(a:columns, ',')
let columns = []
......@@ -134,8 +136,11 @@ function! sw#search#do(command, columns)
let result = _r
endif
let __name = ''
if exists('b:max_results')
let name = "__SQLResult__-" . b:profile . '__' . b:unique_id
let __name = bufname('%')
let uid = b:unique_id
let name = s:get_resultset_name()
if (!bufexists(name))
let profile = b:profile
let s_below = &splitbelow
......@@ -147,6 +152,7 @@ function! sw#search#do(command, columns)
set nosplitbelow
endif
call sw#session#set_buffer_variable('state', 'resultsets')
call sw#session#set_buffer_variable('r_unique_id', uid)
endif
endif
let highlight = ''
......@@ -160,7 +166,12 @@ function! sw#search#do(command, columns)
let highlight = '\V' . highlight
endif
wincmd b
if bufwinnr('__SQL__-' . b:profile) != -1
call sw#goto_window('__SQL__-' . b:profile)
else
call sw#goto_window(s:get_resultset_name())
let __name = sw#find_buffer_by_unique_id(b:r_unique_id)
endif
if exists('b:match_id')
try
call matchdelete(b:match_id)
......@@ -187,6 +198,89 @@ function! sw#search#do(command, columns)
call sw#session#set_buffer_variable('match_id', matchadd('Search', highlight))
endif
setlocal nomodifiable
if __name != ''
call sw#goto_window(__name)
endif
endfunction
function! s:set_async_variables(columns)
let b:on_async_result = 'sw#search#on_async_result'
let b:on_async_kill = 'sw#search#on_async_kill'
let b:__columns = a:columns
endfunction
function! s:asynchronious(columns, set)
let name = sw#session#buffer_name()
if name == s:get_resultset_name()
let a_name = sw#find_buffer_by_unique_id(b:r_unique_id)
else
let a_name = s:get_resultset_name()
endif
if a:set
call s:set_async_variables(a:columns)
else
call s:unset_async_variables()
endif
call sw#goto_window(a_name)
if a:set
call s:set_async_variables(a:columns)
else
call s:unset_async_variables()
endif
call sw#goto_window(name)
endfunction
function! s:unset_async_variables()
if exists('b:on_async_result')
unlet b:on_async_result
endif
if exists('b:on_async_kill')
unlet b:on_async_kill
endif
if exists('b:__columns')
unlet b:__columns
endif
endfunction
function! sw#search#on_async_result()
let result = sw#get_sql_result(0)
let columns = g:sw_search_default_result_columns
if exists('b:__columns')
let columns = b:__columns
endif
call s:process_search_result(result, columns)
call s:asynchronious('', 0)
endfunction
function! sw#search#on_async_kill()
let name = s:get_resultset_name()
if bufexists(name)
call sw#goto_window(name)
setlocal modifiable
normal G
put ='Interrupted'
setlocal nomodifiable
endif
call s:asynchronious('', 0)
endfunction
function! sw#search#do(command, columns)
call sw#session#init_section()
if exists('b:feedback')
let feedback = b:feedback
call sw#session#unset_buffer_variable('feedback')
endif
call s:asynchronious(a:columns, 1)
let result = sw#execute_sql(b:profile, a:command, 0)
if exists('feedback')
call sw#session#set_buffer_variable('feedback', feedback)
endif
if len(result) > 0
call s:process_search_result(result, a:columns)
call s:asynchronious('', 0)
else
call s:process_search_result(['Searching...'], '')
endif
endfunction
function! sw#search#data_defaults(value)
......
......@@ -33,11 +33,19 @@ if !exists('g:sw_autocommands')
let g:sw_autocommands = {}
endif
function! sw#session#buffer_name()
let name = bufname('%')
if name =~ '\v^__'
return name
endif
return fnamemodify(name, ':p')
endfunction
function! s:key_name(...)
if a:0
let name = a:1
else
let name = bufname('%')
return sw#session#buffer_name()
endif
if name =~ '\v^__'
return name
......@@ -166,7 +174,7 @@ endfunction
function! sw#session#restore_sqlbuffer()
call sw#session#check()
wincmd b
call sw#goto_window(sw#sqlwindow#get_resultset_name())
call sw#session#check()
wincmd t
call sw#sqlwindow#goto_statement_buffer()
endfunction
......@@ -17,7 +17,7 @@
"
"============================================================================"
let s:pattern_resultset_start = '\v^([\-]+\+)+([\-]*)$'
let s:pattern_resultset_start = '\v^([\-]+\+?)+([\-]*)$'
let s:pattern_empty_line = '\v^[\r \s\t]*$'
let s:script_path = expand('<sfile>:p:h') . '/../../'
......@@ -27,6 +27,15 @@ function! s:check_sql_buffer()
endif
endfunction
function! sw#sqlwindow#goto_statement_buffer()
if (exists('b:r_unique_id'))
let b = sw#find_buffer_by_unique_id(b:r_unique_id)
if b != ''
call sw#goto_window(b)
endif
endif
endfunction
function! s:set_shortcuts(default_var, path)
if a:default_var == 'default'
let cmd = "so " . s:script_path . a:path
......@@ -65,6 +74,7 @@ function! s:do_open_buffer()
call sw#session#set_buffer_variable('feedback', g:sw_feedback)
call sw#session#set_buffer_variable('unique_id', sw#generate_unique_id())
call sw#session#autocommand('BufEnter', 'sw#sqlwindow#set_statement_shortcuts()')
call sw#session#autocommand('BufEnter', 'sw#check_async_result()')
call sw#sqlwindow#set_statement_shortcuts()
""normal gg
""put ='-- Current profile: ' . b:profile
......@@ -194,7 +204,7 @@ function! sw#sqlwindow#toggle_messages()
if b:state != 'resultsets' && b:state != 'messages'
return
endif
wincmd b
call sw#goto_window(sw#sqlwindow#get_resultset_name())
if b:state == 'resultsets'
call sw#session#set_buffer_variable('position', getpos('.'))
endif
......@@ -390,29 +400,18 @@ function! s:display_resultsets()
call sw#session#set_buffer_variable('state', 'resultsets')
endfunction
function! sw#sqlwindow#execute_sql(sql)
let w:auto_added1 = "-- auto\n"
let w:auto_added2 = "-- end auto\n"
call s:check_sql_buffer()
let _sql = a:sql
if (b:display_result_as != 'tab')
let _sql = w:auto_added1 . 'WbDisplay ' . b:display_result_as . "\n" . b:delimiter . "\n" . w:auto_added2 . _sql
endif
if (b:max_results != 0)
let _sql = w:auto_added1 . 'set maxrows = ' . b:max_results . "\n" . b:delimiter . "\n" . w:auto_added2 . _sql
endif
let result = sw#execute_sql(b:profile, _sql, 0)
function! s:process_result(result)
let result = a:result
let uid = b:unique_id
let name = "__SQLResult__-" . b:profile . '__' . b:unique_id
let profile = b:profile
if (bufexists(name))
wincmd b
call sw#goto_window(name)
setlocal modifiable
normal ggdG
else
let uid = b:unique_id
let s_below = &splitbelow
set splitbelow
execute "split " . name
......@@ -481,7 +480,48 @@ function! sw#sqlwindow#execute_sql(sql)
normal ggdd
setlocal nomodifiable
wincmd t
let b = sw#find_buffer_by_unique_id(b:r_unique_id)
if b != ''
call sw#goto_window(b)
endif
endfunction
function! sw#sqlwindow#on_async_result()
let result = sw#get_sql_result(0)
call s:process_result(result)
""call feedkeys(':echo ')
endfunction
function! sw#sqlwindow#on_async_kill()
let result = ['Interrupted asynchronious command...']
call s:process_result(result)
endfunction
function! sw#sqlwindow#execute_sql(sql)
let w:auto_added1 = "-- auto\n"
let w:auto_added2 = "-- end auto\n"
call s:check_sql_buffer()
let _sql = a:sql
if (b:display_result_as != 'tab')
let _sql = w:auto_added1 . 'WbDisplay ' . b:display_result_as . "\n" . b:delimiter . "\n" . w:auto_added2 . _sql
endif
if (b:max_results != 0)
let _sql = w:auto_added1 . 'set maxrows = ' . b:max_results . "\n" . b:delimiter . "\n" . w:auto_added2 . _sql
endif
let b:on_async_result = 'sw#sqlwindow#on_async_result'
let b:on_async_kill = 'sw#sqlwindow#on_async_kill'
let result = sw#execute_sql(b:profile, _sql, 0)
if len(result) != 0
unlet b:on_async_result
unlet b:on_async_kill
call s:process_result(result)
else
if sw#is_async()
call s:process_result(['Processing a command. Please wait...'])
endif
endif
endfunction
function! sw#sqlwindow#get_object_info()
......@@ -491,11 +531,11 @@ function! sw#sqlwindow#get_object_info()
let obj = expand('<cword>')
let sql = "desc " . obj
wincmd t
call sw#sqlwindow#goto_statement_buffer()
call sw#sqlwindow#execute_sql(sql)
endfunction
function! s:get_resultset_name()
function! sw#sqlwindow#get_resultset_name()
if exists('b:profile') && exists('b:unique_id')
return '__SQLResult__-' . b:profile . '__' . b:unique_id
endif
......@@ -510,7 +550,7 @@ function! sw#sqlwindow#close_all_result_sets()
let name = bufname('%')
let rs_name = ''
if exists('b:profile')
let rs_name = s:get_resultset_name()
let rs_name = sw#sqlwindow#get_resultset_name()
endif
for k in keys(g:sw_session)
if k =~ '\v^__SQLResult__' && k != rs_name
......@@ -555,7 +595,7 @@ function! sw#sqlwindow#check_hidden_results()
endif
normal ggdd
setlocal nomodifiable
wincmd t
call sw#sqlwindow#goto_statement_buffer()
endif
endif
endif
......@@ -569,6 +609,6 @@ function! sw#sqlwindow#get_object_source()
let obj = expand('<cword>')
let sql = 'WbGrepSource -searchValues="' . obj . '" -objects=' . obj . ' -types=* -useRegex=true;'
wincmd t
call sw#sqlwindow#goto_statement_buffer()
call sw#sqlwindow#execute_sql(sql)
endfunction
......@@ -140,7 +140,18 @@ if (!exists('g:extra_sw_tabs'))
let g:extra_sw_tabs = {}
endif
let g:sw_instance_id = strftime('%s')
if (!exists('g:sw_asynchronious'))
let g:sw_asynchronious = 0
if !exists('g:vim_exe')
let g:sw_vim_exe = 'vim'
endif
endif
"if !exists('g:sw_overwrite_current_command')
" let g:sw_overwrite_current_command = 0
"endif
let g:sw_instance_id = localtime()
if !exists('g:sw_dbexplorer_panel')
let file = expand('<sfile>:p:h') . '/../resources/dbexplorer.vim'
......@@ -190,6 +201,7 @@ command! SWSqlAutocomplete call sw#autocomplete#cache()
command! SWSqlAutocompleteSetDefault call sw#autocomplete#set_cache_default()
command! SWSqlAutocompleteWithDefault setlocal omnifunc=sw#autocomplete#perform
command! SWSqlBufferRestore call sw#session#restore_sqlbuffer()
command! -nargs=0 SWKillCurrentCommand call sw#kill_current_command()
augroup sw
autocmd sw BufDelete,BufWipeout * call sw#session#sync()
......
......@@ -8,4 +8,5 @@ imap <buffer> <C-@> <Esc>:SWSqlExecuteCurrent<cr>
nmap <buffer> <M-i> :SWSqlObjectInfo<cr>
nmap <buffer> <M-s> :SWSqlObjectSource<cr>
nmap <buffer> <M-m> <C-w>b:SWSqlToggleMessages<cr><C-w>t
nmap <buffer> <C-c> :SWKillCurrentCommand<cr>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册