sqlwindow.vim 25.7 KB
Newer Older
C
Cosmin Popescu 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
"============================================================================"
"
"  Vim SQL Workbench/J Implementation
"
"  Copyright (c) Cosmin Popescu
"
"  Author:      Cosmin Popescu <cosminadrianpopescu at gmail dot com>
"  Version:     1.00 (2015-01-08)
"  Requires:    Vim 7
"  License:     GPL
"
"  Description:
"
"  Provides SQL database access to any DBMS supported by SQL Workbench/J. The
"  only dependency is SQL Workbench/J. Also includes powefull intellisense
"  autocomplete based on the current selected database
"
"============================================================================"

C
Cosmin Popescu 已提交
20 21 22
let s:pattern_resultset_start = '\v^([\-]+\+?)+([\-]*)-$'
let s:pattern_resultset_title = '\v^RESULTSET ([0-9]+)( \()?.*$'
let s:pattern_no_results = '\v^Query returned [0-9]+ rows?$'
C
Cosmin Popescu 已提交
23
let s:pattern_empty_line = '\v^[\r \s\t]*$'
C
Cosmin Popescu 已提交
24
let s:pattern_ignore_line = '\v\c^#IGNORE#$'
C
Cosmin Popescu 已提交
25 26 27
let s:script_path = expand('<sfile>:p:h') . '/../../'

function! s:check_sql_buffer()
C
Cosmin Popescu 已提交
28
    if (!exists('b:port'))
C
Cosmin Popescu 已提交
29 30
        call sw#display_error("The current buffer is not an SQL Workbench buffer. Open it using the SWOpenSQL command.")
        return 0
C
Cosmin Popescu 已提交
31
    endif
C
Cosmin Popescu 已提交
32
    return 1
C
Cosmin Popescu 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
endfunction

function! s:set_shortcuts(default_var, path)
    if a:default_var == 'default'
        let cmd = "so " . s:script_path . a:path
        execute cmd
    else
        so a:default_var
    endif
endfunction

function! sw#sqlwindow#set_statement_shortcuts()
    call s:set_shortcuts(g:sw_shortcuts_sql_buffer_statement, "resources/shortcuts_sql_buffer_statement.vim")
    call sw#sqlwindow#check_hidden_results()
endfunction

function! sw#sqlwindow#set_results_shortcuts()
    call s:set_shortcuts(g:sw_shortcuts_sql_results, "resources/shortcuts_sql_results.vim")
endfunction

C
Cosmin Popescu 已提交
53 54 55 56
function! s:switch_to_results_tab()
    if !g:sw_switch_to_results_tab
        wincmd t
    endif
C
Cosmin Popescu 已提交
57 58
endfunction

C
Cosmin Popescu 已提交
59 60 61
function! sw#sqlwindow#check_results()
    let results = sw#server#fetch_result()
    if results != ''
C
Cosmin Popescu 已提交
62 63
        call s:display_resultsets(results, 1)
        call s:switch_to_results_tab()
C
Cosmin Popescu 已提交
64
    endif
C
Cosmin Popescu 已提交
65 66
endfunction

C
Cosmin Popescu 已提交
67 68 69 70 71 72 73 74 75 76 77 78 79 80
function! sw#sqlwindow#auto_commands(when)
    let i = 1
    let pattern = '\v\c^-- ' . a:when . '[ \t]*(.*)$'
    let sql = ''
    while i < line('$')
        let line = getline(i)
        if line =~ pattern
            let command = substitute(line, pattern, '\1', 'g')
            if command =~ '\v\c^:'
                execute substitute(command, '\v\c^:', '', 'g')
            else
                let sql = sql . (sql == '' ? '' : ";\n") . command
            endif
        endif
C
Cosmin Popescu 已提交
81 82 83
        let i = i + 1
    endwhile

C
Cosmin Popescu 已提交
84 85 86 87
    if sql != ''
        echomsg "Executing automatic commands"
        call sw#sqlwindow#execute_sql(0, sql)
    endif
C
Cosmin Popescu 已提交
88 89
endfunction

C
Cosmin Popescu 已提交
90 91 92 93 94 95 96 97 98
function! s:do_open_buffer(port)
    call sw#session#set_buffer_variable('delimiter', g:sw_delimiter)
    call sw#session#set_buffer_variable('unique_id', sw#generate_unique_id())
    call sw#session#set_buffer_variable('port', a:port)
    ""call sw#session#autocommand('BufEnter', 'sw#sqlwindow#set_statement_shortcuts()')
    call sw#session#autocommand('BufEnter', 'sw#sqlwindow#check_results()')
    ""call sw#session#autocommand('BufUnload', 'sw#sqlwindow#auto_commands("after")')
    call sw#sqlwindow#set_statement_shortcuts()
    call sw#sqlwindow#auto_commands('before')
C
Cosmin Popescu 已提交
99 100
endfunction

C
Cosmin Popescu 已提交
101 102 103 104 105
function! sw#sqlwindow#open_buffer(port, file, command)
    execute a:command . " " . a:file
    call sw#session#init_section()
    call sw#session#set_buffer_variable('port', a:port)
    call s:do_open_buffer(a:port)
C
Cosmin Popescu 已提交
106 107 108
endfunction

function! sw#sqlwindow#set_delimiter(new_del)
C
Cosmin Popescu 已提交
109 110 111
    if (!s:check_sql_buffer())
        return 
    endif
C
Cosmin Popescu 已提交
112
    if exists('b:port')
C
Cosmin Popescu 已提交
113 114
        sw#display_error('You cannot change the delimier in server mode. This happens because SQL Workbench does now know another delimiter during console mode. You can only change the delimiter in batch mode (see the documentation). So, if you want to change the delimiter, please open the buffer in batch mode.')
        return 
C
Cosmin Popescu 已提交
115
    endif
C
Cosmin Popescu 已提交
116 117 118 119
    call sw#session#set_buffer_variable('delimiter', a:new_del)
endfunction

function! sw#sqlwindow#export_last()
C
Cosmin Popescu 已提交
120
    call sw#export_ods(g:sw_last_sql_query)
C
Cosmin Popescu 已提交
121 122 123
endfunction

function! sw#sqlwindow#extract_current_sql(...)
C
Cosmin Popescu 已提交
124
    let lines = getbufline(bufname(bufnr('%')), 1, '$')
C
Cosmin Popescu 已提交
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
    let pos = getpos('.')
    let n = pos[2] - 2
    let m = n + 1
    let i = pos[1] - 1
    if n < 0
        let lines[i] = '#CURSOR#' . lines[i]
    else
        let cmd = 'let lines[' . i . '] = lines[' . i . '][0:' . n . '] . "#CURSOR#" . lines[' . i . '][' . m . ':]' 
        execute cmd
    endif

    let s = ''
    for line in lines
        let s = s . line . "\n"
    endfor

C
Cosmin Popescu 已提交
141 142 143 144
    if !exists('b:delimiter')
        call sw#display_error("The buffer is not connected to a server. Please use SWSqlConectToServer before running queries")
        return ''
    endif
C
Cosmin Popescu 已提交
145 146 147 148 149 150 151 152 153
    let sqls = sw#sql_split(s, b:delimiter)
    for sql in sqls
        if sql =~ '#CURSOR#'
            if (!a:0 || (a:0 && !a:1))
                let sql = substitute(sql, '#CURSOR#', '', 'g')
            endif
            return sql
        endif
    endfor
C
Cosmin Popescu 已提交
154
    call sw#display_error("Could not identify the current query")
C
Cosmin Popescu 已提交
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
    return ""
endfunction

function! sw#sqlwindow#extract_selected_sql()
    let z_save = @z
    normal gv"zy
    let sql = @z
    let @z = z_save
    return sql
endfunction

function! sw#sqlwindow#extract_all_sql()
    let pos = getpos('.')
    let z_save = @z
    normal ggVG"zy
    let sql = @z
    let @z = z_save
    call setpos('.', pos)
    return sql
endfunction

function! sw#sqlwindow#toggle_messages()
C
Cosmin Popescu 已提交
177
    if (!(exists('b:resultsets')))
C
Cosmin Popescu 已提交
178 179 180 181 182
        return 
    endif
    if b:state != 'resultsets' && b:state != 'messages'
        return 
    endif
183
    call sw#goto_window(sw#sqlwindow#get_resultset_name())
C
Cosmin Popescu 已提交
184 185 186
    if bufname('%') != sw#sqlwindow#get_resultset_name()
        return
    endif
C
Cosmin Popescu 已提交
187 188 189
    if b:state == 'resultsets'
        call sw#session#set_buffer_variable('position', getpos('.'))
    endif
C
Cosmin Popescu 已提交
190 191
    call sw#session#set_buffer_variable('state', b:state == 'resultsets' ? 'messages' : 'resultsets')
    call s:display_resultsets('', 1)
C
Cosmin Popescu 已提交
192 193 194 195 196 197
endfunction

function! sw#sqlwindow#toggle_display()
    if (!exists('b:resultsets') || !exists('b:state'))
        return 
    endif
C
Cosmin Popescu 已提交
198 199
    if getline('.') == ''
        return
C
Cosmin Popescu 已提交
200
    endif
C
Cosmin Popescu 已提交
201 202 203 204
    if b:state == 'form'
        call sw#session#set_buffer_variable('state', 'resultsets')
    elseif b:state == 'resultsets'
        call sw#session#set_buffer_variable('state', 'form')
C
Cosmin Popescu 已提交
205 206 207
    endif
    let line = line('.')
    
C
Cosmin Popescu 已提交
208 209 210 211 212 213
    ""if (line <= 3 || getline('.') =~ s:pattern_empty_line || getline('.') == '')
    ""    call sw#display_error("You have to be on a row in a resultset")
    ""    return
    ""endif
    if b:state == 'form' || b:state == 'resultsets'
        call s:display_resultsets('', 1)
C
Cosmin Popescu 已提交
214 215 216
    endif
endfunction

C
Cosmin Popescu 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
function! s:get_n_resultset()
    let resultset_start = s:get_resultset_start(s:pattern_resultset_title)
    if resultset_start == -1
        call sw#display_error('Could not identify the resultset')
        return
    endif

    return substitute(getline(resultset_start), s:pattern_resultset_title, '\1', 'g') - 1
endfunction

function! s:get_idx(idx, n)
    let n = s:get_n_resultset()
    let idx = a:idx

    if !(idx =~ '\v^[0-9]+$')
        let idx = index(b:resultsets[a:n].header, idx)
    endif

    return idx
endfunction

function! s:get_column(column, n)
    let column = a:column
    if column =~ '\v^[0-9]+$'
        let column = b:resultsets[a:n].header[column]
    endif

    return column
endfunction

function! sw#sqlwindow#show_column(idx, show_results)
    let n = s:get_n_resultset()
    if (n == -1)
        return
    endif

    let a_idx = s:get_idx(a:idx, n)

    let idx = index(b:resultsets[n].hidden_columns, a_idx)
    if idx != -1
        call remove(b:resultsets[n].hidden_columns, idx)
    endif

    
    if a:show_results
        call s:display_resultsets('', 1)
    endif
endfunction

function! sw#sqlwindow#hide_column(idx, show_results)
    let n = s:get_n_resultset()
    if (n == -1)
        return
    endif
    
    let idx = s:get_idx(a:idx, n)

    let n_columns = len(split(b:resultsets[n].lines[b:resultsets[n].resultset_start], '+'))
    if idx < 0 || idx >= n_columns
        call sw#display_error("The index is out of range")
        return
    endif

    if n_columns == 1
        call sw#display_error("Just one column in the resultset.")
        return
    endif

    call add(b:resultsets[n].hidden_columns, idx)
C
Cosmin Popescu 已提交
286
    call sort(b:resultsets[n].hidden_columns)
C
Cosmin Popescu 已提交
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343

    if a:show_results
        call s:display_resultsets('', 1)
    endif
endfunction

function! sw#sqlwindow#unfilter_column(column)
    let n = s:get_n_resultset()
    if n == -1
        return
    endif

    let column = s:get_column(a:column, n)
    unlet b:resultsets[n].filters[column]

    call s:display_resultsets('', 1)
endfunction

function! sw#sqlwindow#filter_column(column)
    let n = s:get_n_resultset()
    if n == -1
        return
    endif

    let filter = input('Please input the filter value: ')
    if filter != ''
        let column = s:get_column(a:column, n)
        let b:resultsets[n].filters[column] = filter

        call s:display_resultsets('', 1)
    endif
endfunction

function! sw#sqlwindow#remove_all_filters()
    let n = s:get_n_resultset()
    if n == -1
        return
    endif

    let b:resultsets[n].filters = {}
    call s:display_resultsets('', 1)
endfunction

function! sw#sqlwindow#show_all_columns()
    let n = s:get_n_resultset()
    if (n == -1)
        return
    endif
    let b:resultsets[n].hidden_columns = []
    call s:display_resultsets('', 1)
endfunction

function! sw#sqlwindow#show_only_column(column)
    let n = s:get_n_resultset()
    if (n == -1)
        return
    endif
C
Cosmin Popescu 已提交
344 345 346 347
    if index(b:resultsets[n].header, a:column) == -1
        call sw#display_error("The column does not exists")
        return
    endif
C
Cosmin Popescu 已提交
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
    for column in b:resultsets[n].header
        if column != a:column
            call sw#sqlwindow#hide_column(column, 0)
        endif
    endfor

    call s:display_resultsets('', 1)
endfunction

function! sw#sqlwindow#complete_columns(ArgLead, CmdLine, CursorPos)
    let n = s:get_n_resultset()
    if n == -1
        return []
    endif

    let result = []

    for column in b:resultsets[n].header
        if column =~ '^' . a:ArgLead
            call add(result, column)
        endif
    endfor

    return result
endfunction

function! sw#sqlwindow#show_only_columns(columns)
    let n = s:get_n_resultset()
    if n == -1
        return
    endif

    for column in b:resultsets[n].header
        if index(a:columns, column) == -1
            call sw#sqlwindow#hide_column(column, 0)
        endif
    endfor

    call s:display_resultsets('', 1)
endfunction

C
Cosmin Popescu 已提交
389
function! sw#sqlwindow#display_as_form()
C
Cosmin Popescu 已提交
390 391 392 393 394 395
    let row_limits = s:get_row_limits()
    if len(row_limits) == 0
        call sw#session#set_buffer_variable('state', 'resultsets')
        call sw#session#unset_buffer_variable('position')
        return
    endif
C
Cosmin Popescu 已提交
396 397 398
    let resultset_start = s:get_resultset_start()
    call sw#session#set_buffer_variable('position', getpos('.'))

C
Cosmin Popescu 已提交
399
    let _columns = split(getline(resultset_start - 1), '|')
C
Cosmin Popescu 已提交
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
    let s_len = 0
    let columns = []
    for column in _columns
        let column = substitute(column, '\v^[ ]?([^ ]+)[ ]+$', '\1', 'g')
        call add(columns, column)
        if strlen(column) > s_len
            let s_len = strlen(column) + 1
        endif
    endfor

    let lines = []

    let n = 0
    let k = 0
    for column in columns
        let line = column
        let i = strlen(line)
        while i < s_len
            let line = line . ' '
            let i = i + 1
        endwhile

        let line = line . ': '

        if column == columns[len(columns) - 1]
C
Cosmin Popescu 已提交
425
            let m = n + strlen(getline(row_limits[0])) - n
C
Cosmin Popescu 已提交
426 427 428 429 430 431
        else
            let m = n + strlen(_columns[k]) - 1
            if (k > 0)
                let m = m - 1
            endif
        endif
C
Cosmin Popescu 已提交
432
        let cmd = "let line = line . getline(row_limits[0])[" . n . ":" . m . "]"
C
Cosmin Popescu 已提交
433
        execute cmd
C
Cosmin Popescu 已提交
434 435 436
        let i = row_limits[0] + 1
        while i <= row_limits[1]
            let cmd = "let txt = getline(i)[" . n . ":" . m . "]"
C
Cosmin Popescu 已提交
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
            execute cmd
            
            if !(txt =~ s:pattern_empty_line)
                call add(lines, line)
                let line = ''
                let j = 0
                while j < s_len
                    let line = line . ' '
                    let j = j + 1
                endwhile
                let line = line . ': '
                let line = line . txt
            endif
            let i = i + 1
        endwhile
        let n = m + 3
        let k = k + 1
        let line = substitute(line, '\v^([^:]+):[ ]*([0-9]+)[ ]*$', '\1: \2', 'g')
        call add(lines, line)
    endfor
C
Cosmin Popescu 已提交
457
    call sw#put_lines_in_buffer(lines)
C
Cosmin Popescu 已提交
458 459
endfunction

C
Cosmin Popescu 已提交
460 461 462 463 464
function! s:get_resultset_start(...)
    let pattern = s:pattern_resultset_start
    if a:0
        let pattern = a:1
    endif
C
Cosmin Popescu 已提交
465 466
    let resultset_start = line('.')
    while resultset_start > 1
C
Cosmin Popescu 已提交
467
        if getline(resultset_start) =~ pattern
C
Cosmin Popescu 已提交
468 469 470 471 472
            break
        endif
        let resultset_start = resultset_start - 1
    endwhile

C
Cosmin Popescu 已提交
473 474 475
    if !(getline(resultset_start) =~ pattern)
        call sw#display_error("Could not indentify the resultset")
        return -1
C
Cosmin Popescu 已提交
476 477 478 479 480 481 482
    endif

    return resultset_start
endfunction

function! s:get_row_limits()
    let resultset_start = s:get_resultset_start()
C
Cosmin Popescu 已提交
483 484 485 486
    if resultset_start == -1
        return []
    endif

C
Cosmin Popescu 已提交
487 488
    let row_start = line('.')
    let row_end = line('.') + 1
C
Cosmin Popescu 已提交
489
    let columns = split(getline(resultset_start - 1), '|')
C
Cosmin Popescu 已提交
490 491 492

    while (row_start > resultset_start)
        let n = 0
C
Cosmin Popescu 已提交
493 494 495 496 497
        let line = getline(row_start)
        if line =~ s:pattern_no_results
            call sw#display_error("You are not on a resultset row.")
            return []
        endif
C
Cosmin Popescu 已提交
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
        let stop = 0
        for column in columns
            if line[n + strlen(column)] == '|'
                let stop = 1
                break
            endif
            let n = n + strlen(column) + 1
        endfor
        if (stop)
            break
        endif
        if line =~ s:pattern_resultset_start
            let row_start = row_start + 1
            break
        endif
        let row_start = row_start - 1
    endwhile

C
Cosmin Popescu 已提交
516
    while (row_end < line('$'))
C
Cosmin Popescu 已提交
517
        let n = 0
C
Cosmin Popescu 已提交
518
        let line = getline(row_end)
C
Cosmin Popescu 已提交
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
        let stop = 0
        for column in columns
            if line[n + strlen(column)] == '|'
                let stop = 1
                break
            endif
            let n = n + strlen(column) + 1
        endfor
        if (stop)
            let row_end = row_end - 1
            break
        endif
        
        if (line =~ s:pattern_empty_line || line == '')
            let row_end = row_end - 1
            break
        endif
        let row_end = row_end + 1
    endwhile

    return [row_start, row_end]
endfunction

C
Cosmin Popescu 已提交
542
function! s:open_resultset_window()
C
Cosmin Popescu 已提交
543
    let name = sw#sqlwindow#get_resultset_name()
C
Cosmin Popescu 已提交
544

C
Cosmin Popescu 已提交
545
    if (!bufexists(name))
C
Cosmin Popescu 已提交
546 547 548 549
        let s_below = &splitbelow
        set splitbelow
        execute "split " . name
        call sw#session#init_section()
C
Cosmin Popescu 已提交
550
        call sw#set_special_buffer()
C
Cosmin Popescu 已提交
551 552 553 554 555 556
        call sw#sqlwindow#set_results_shortcuts()
        if !s_below
            set nosplitbelow
        endif
    endif

C
Cosmin Popescu 已提交
557 558 559 560 561
    call sw#goto_window(name)

    return bufname('%') == name
endfunction

C
Cosmin Popescu 已提交
562 563
function! s:split_into_columns(resultset)
    let columns_length = split(a:resultset.lines[a:resultset.resultset_start], '+')
C
Cosmin Popescu 已提交
564
    if len(columns_length) <= 0
C
Cosmin Popescu 已提交
565
        return a:resultset.lines
C
Cosmin Popescu 已提交
566 567
    endif

C
Cosmin Popescu 已提交
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
    let result = []
    let i = 0
    for line in a:resultset.lines
        let matches = []
        call add(matches, line)
        if i > a:resultset.resultset_start - 2 && line != ''
            for c in columns_length
                let pattern = '\v^(.{' . len(c) . '}).?(.*)$'
                let match = substitute(line, pattern, '\1', 'g')
                call add(matches, match)
                let line = substitute(line, pattern, '\2', 'g')
            endfor

        endif

        call add(result, matches)
        let i += 1
C
Cosmin Popescu 已提交
585 586
    endfor

C
Cosmin Popescu 已提交
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
    return result
endfunction

function! s:print_line(line_idx, n_resultset, do_filter)
    let resultset = b:resultsets[a:n_resultset]

    let line = resultset.lines[a:line_idx]

    if a:line_idx <= resultset.resultset_start - 2
        return line
    endif

    let delimiter = line =~ s:pattern_resultset_start ? '+' : '|'
    let result = ''

    if (len(resultset.hidden_columns) > 0 || len(resultset.filters) > 0)
        if !exists('resultset.columns')
            let resultset.columns = s:split_into_columns(resultset)
        endif
    else
        return line
C
Cosmin Popescu 已提交
608
    endif
C
Cosmin Popescu 已提交
609 610 611 612 613

    if len(resultset.columns[a:line_idx]) <= 1
        return line
    endif

C
Cosmin Popescu 已提交
614
    let i = 1
C
Cosmin Popescu 已提交
615 616
    while i < len(resultset.columns[a:line_idx])
        if a:do_filter
C
Cosmin Popescu 已提交
617
            let column = s:get_column(i - 1, a:n_resultset)
C
Cosmin Popescu 已提交
618 619
            if has_key(resultset.filters, column)
                let filter = resultset.filters[column]
C
Cosmin Popescu 已提交
620 621
                let filter_in = 1
                if filter =~ '\v^[\>\<\=]{1,2}'
C
Cosmin Popescu 已提交
622
                    let filter_in = eval(resultset.columns[a:line_idx][i] . filter)
C
Cosmin Popescu 已提交
623
                else
C
Cosmin Popescu 已提交
624
                    let filter_in = resultset.columns[a:line_idx][i] =~ filter
C
Cosmin Popescu 已提交
625 626 627 628 629 630
                endif
                if !filter_in
                    return '#IGNORE#'
                endif
            endif
        endif
C
Cosmin Popescu 已提交
631 632 633
        if index(resultset.hidden_columns, i - 1) == -1 && a:line_idx >= resultset.resultset_start - 1
            let result .= resultset.columns[a:line_idx][i]
            if i - 1 < len(resultset.columns[a:line_idx]) - 1
C
Cosmin Popescu 已提交
634 635 636 637 638 639 640 641 642 643
                let result .= delimiter
            endif
        endif

        let i += 1
    endwhile

    if result == ''
        let result = '#IGNORE#'
    endif
C
Cosmin Popescu 已提交
644
    return substitute(result, '\v^(.*)[+|]$', '\1', 'g')
C
Cosmin Popescu 已提交
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
endfunction

function! s:add_hidden_columns(n)
    let result = ''
    for c in b:resultsets[a:n].hidden_columns
        let result .= (result == '' ? '' : ', ') .  b:resultsets[a:n].header[c]
    endfor

    return result
endfunction

function! s:add_filters(n)
    let result = ''
    for column in keys(b:resultsets[a:n].filters)
        let result .= (result == '' ? '' : ', ') . column . ' ' . b:resultsets[a:n].filters[column]
    endfor

    return result
endfunction

C
Cosmin Popescu 已提交
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
function! s:output_content(content)
    call sw#put_text_in_buffer(a:content)
endfunction

function! s:build_header(n)
    let n = a:n
    let header = 'RESULTSET ' . string(n)
    let hidden_columns = s:add_hidden_columns(len(b:resultsets) - n)
    if hidden_columns != ''
        let header .= " (Hidden columns: " . hidden_columns . ")"
    endif
    let filters = s:add_filters(len(b:resultsets) - n)
    if (filters != '')
        let header .= " (Filters: " . filters . ")"
    endif
    let header .= "\n============\n"

    return header
endfunction

function! s:display_messages()
C
Cosmin Popescu 已提交
686 687 688 689
    let messages = ''
    let n = len(b:resultsets)
    call reverse(b:resultsets)
    for resultset in b:resultsets
C
Cosmin Popescu 已提交
690
        let messages .= s:build_header(n)
C
Cosmin Popescu 已提交
691 692 693
        for line in resultset.messages
            let messages .= line . "\n"
        endfor
C
Cosmin Popescu 已提交
694 695 696 697 698 699 700 701 702 703 704
        let n = n - 1
    endfor
    call reverse(b:resultsets)
    call s:output_content(messages)
endfunction

function! s:display_resultsets_continous()
    let lines = ''
    let n = len(b:resultsets)
    call reverse(b:resultsets)
    for resultset in b:resultsets
C
Cosmin Popescu 已提交
705
        if len(resultset.lines) > 0
C
Cosmin Popescu 已提交
706
            let lines .= s:build_header(n)
C
Cosmin Popescu 已提交
707 708 709
        endif
        let i = 0
        for line in resultset.lines
C
Cosmin Popescu 已提交
710
            let row = s:print_line(i, len(b:resultsets) - n, i > resultset.resultset_start)
C
Cosmin Popescu 已提交
711 712 713 714 715 716 717 718
            if !(row =~ s:pattern_ignore_line)
                let lines .= row . "\n"
            endif
            let i += 1
        endfor
        let n = n - 1
    endfor
    call reverse(b:resultsets)
C
Cosmin Popescu 已提交
719
    call s:output_content(lines)
C
Cosmin Popescu 已提交
720 721 722 723 724 725 726 727 728 729 730 731 732
endfunction

function! s:display_resultsets(result, ...)
    if (!s:open_resultset_window())
        call sw#display_error('Result set cannot be selected. Probably is hidden')
        return
    endif
    call s:process_result(a:result)
    let continous = 0
    if a:0
        let continous = a:1
    endif
    if b:state == 'form'
C
Cosmin Popescu 已提交
733
        call sw#sqlwindow#display_as_form()
C
Cosmin Popescu 已提交
734
    elseif continous
C
Cosmin Popescu 已提交
735 736 737 738 739 740 741 742 743 744 745 746
        if b:state == 'messages'
            call s:display_messages()
        elseif b:state == 'resultsets'
            call s:display_resultsets_continous()
        endif
        if g:sw_highlight_resultsets
            set filetype=sw
        endif
        setlocal foldmethod=expr
        setlocal foldexpr=sw#sqlwindow#folding(v:lnum)
        ""normal zMggjza
        normal zR
C
Cosmin Popescu 已提交
747 748 749 750 751 752 753 754 755 756 757 758
    else
        call s:display_resultsets_separate()
    endif

    if (exists('b:position') && b:state == 'resultsets')
        call setpos('.', b:position)
    endif
endfunction

function! s:process_result(result)
    if a:result == ''
        return
C
Cosmin Popescu 已提交
759
    endif
C
Cosmin Popescu 已提交
760 761 762 763
    let result = split(a:result, "\n")

    if !exists('b:resultsets')
        call sw#session#set_buffer_variable('resultsets', [])
C
Cosmin Popescu 已提交
764 765 766 767
    endif

    let i = 0
    let mode = 'message'
C
Cosmin Popescu 已提交
768
    let pattern = '\v\c^[\=]+$'
C
Cosmin Popescu 已提交
769 770
    call add(b:resultsets, {'messages': [], 'lines': [], 'hidden_columns': [], 'resultset_start': 0, 'header': [], 'filters': {}})
    let n = len(b:resultsets) - 1
C
Cosmin Popescu 已提交
771
    while i < len(result)
C
Cosmin Popescu 已提交
772 773
        if result[i] =~ pattern
            let mode = 'resultset'
C
Cosmin Popescu 已提交
774 775 776 777
        endif
        
        if (mode == 'resultset' && (result[i] =~ s:pattern_empty_line || result[i] == ''))
            let mode = 'message'
C
Cosmin Popescu 已提交
778
            call add(b:resultsets[n].lines, '')
C
Cosmin Popescu 已提交
779
        endif
C
Cosmin Popescu 已提交
780
        if (mode == 'resultset' && !(result[i] =~ pattern))
C
Cosmin Popescu 已提交
781
            call add(b:resultsets[n].lines, result[i])
C
Cosmin Popescu 已提交
782
        elseif mode == 'message'
C
Cosmin Popescu 已提交
783 784 785 786
            call add(b:resultsets[n].messages, substitute(result[i], "\r", '', 'g'))
        endif
        if mode == 'resultset' && result[i] =~ s:pattern_resultset_start
            let b:resultsets[n].resultset_start = len(b:resultsets[n].lines) - 1
C
Cosmin Popescu 已提交
787 788 789 790
        endif
        let i = i + 1
    endwhile

C
Cosmin Popescu 已提交
791 792 793 794
    if len(b:resultsets[n].lines) > 0
        let header = split(b:resultsets[n].lines[b:resultsets[n].resultset_start - 1], '|')
        for h in header
            call add(b:resultsets[n].header, substitute(h, '\v^[ ]*([^ ].*[^ ])[ ]*$', '\1', 'g'))
C
Cosmin Popescu 已提交
795 796 797
        endfor
    endif

C
Cosmin Popescu 已提交
798
    call sw#session#set_buffer_variable('state', len(b:resultsets[n].lines) > 0 ? 'resultsets' : 'messages')
C
Cosmin Popescu 已提交
799
    echomsg "Command completed"
800 801
endfunction

C
Cosmin Popescu 已提交
802
function! sw#sqlwindow#execute_sql(wait_result, sql)
803 804 805
    let w:auto_added1 = "-- auto\n"
    let w:auto_added2 = "-- end auto\n"

C
Cosmin Popescu 已提交
806 807 808
    if (!s:check_sql_buffer())
        return 
    endif
809
    let _sql = a:sql
C
Cosmin Popescu 已提交
810
    if !exists('b:no_variables') && g:sw_use_old_sw
C
Cosmin Popescu 已提交
811 812 813 814 815 816 817 818
        let vars = sw#variables#extract(_sql)
        if len(vars) > 0
            for var in vars
                let value = sw#variables#get(var)
                if value != ''
                    let _sql = w:auto_added1 . 'wbvardef ' . var . ' = ' . value . "\n" . b:delimiter . "\n" . w:auto_added2 . _sql
                endif
            endfor
C
Cosmin Popescu 已提交
819
            let _sql = substitute(_sql, g:parameters_pattern, g:sw_p_prefix . '\1' . g:sw_p_suffix, 'g')
C
Cosmin Popescu 已提交
820 821
        endif
    endif
C
Cosmin Popescu 已提交
822 823 824
    let b:on_async_result = 'sw#sqlwindow#check_results'
    echomsg "Processing a command. Please wait..."
    let result = sw#execute_sql(_sql, a:wait_result)
825

C
Cosmin Popescu 已提交
826
    if result != ''
C
Cosmin Popescu 已提交
827 828
        call s:display_resultsets(result, 1)
        call s:switch_to_results_tab()
829
    endif
C
Cosmin Popescu 已提交
830 831 832
endfunction

function! sw#sqlwindow#get_object_info()
C
Cosmin Popescu 已提交
833
    if (!exists('b:port'))
C
Cosmin Popescu 已提交
834 835 836 837 838
        return
    endif

    let obj = expand('<cword>')
    let sql = "desc " . obj
C
Cosmin Popescu 已提交
839
    call sw#sqlwindow#execute_sql(0, sql)
C
Cosmin Popescu 已提交
840 841
endfunction

842
function! sw#sqlwindow#get_resultset_name()
C
Cosmin Popescu 已提交
843
    return '__SQLResult__'
C
Cosmin Popescu 已提交
844 845 846 847 848 849 850 851
endfunction

function! sw#sqlwindow#close_all_result_sets()
    if bufname('%') =~ '\v__SQLResult__'
        return
    endif
    if exists('g:sw_session')
        let name = bufname('%')
C
Cosmin Popescu 已提交
852
        let rs_name = sw#sqlwindow#get_resultset_name()
C
Cosmin Popescu 已提交
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
        for k in keys(g:sw_session)
            if k =~ '\v^__SQLResult__' && k != rs_name
                if bufwinnr(k) != -1
                    call sw#goto_window(k)
                    call sw#session#set_buffer_variable('hidden', 1)
                    hide
                    call sw#goto_window(name)
                endif
            endif
        endfor
    endif
endfunction

function! sw#sqlwindow#check_hidden_results()
    if exists('g:sw_session')
C
Cosmin Popescu 已提交
868
        let name = sw#sqlwindow#get_resultset_name()
C
Cosmin Popescu 已提交
869 870 871 872 873 874 875 876 877 878 879
        if bufwinnr(name) != -1
            return
        endif
        if has_key(g:sw_session, name)
            if has_key(g:sw_session[name], 'hidden')
                if g:sw_session[name]['hidden']
                    let s_below = &splitbelow
                    set splitbelow
                    execute "split " . name
                    call sw#session#reload_from_cache()
                    call sw#session#unset_buffer_variable('hidden')
C
Cosmin Popescu 已提交
880
                    call sw#set_special_buffer()
C
Cosmin Popescu 已提交
881
                    call sw#sqlwindow#set_results_shortcuts()
C
Cosmin Popescu 已提交
882
                    ""call sw#session#autocommand('BufEnter', 'sw#sqlwindow#set_results_shortcuts()')
C
Cosmin Popescu 已提交
883 884 885
                    if !s_below
                        set nosplitbelow
                    endif
C
Cosmin Popescu 已提交
886
                    call s:display_resultsets('', 1)
C
Cosmin Popescu 已提交
887 888 889 890 891 892 893
                endif
            endif
        endif
    endif
endfunction

function! sw#sqlwindow#get_object_source()
C
Cosmin Popescu 已提交
894
    if (!exists('b:port'))
C
Cosmin Popescu 已提交
895 896 897 898 899
        return
    endif

    let obj = expand('<cword>')
    let sql = 'WbGrepSource -searchValues="' . obj . '" -objects=' . obj . ' -types=* -useRegex=true;'
C
Cosmin Popescu 已提交
900
    call sw#sqlwindow#execute_sql(0, sql)
C
Cosmin Popescu 已提交
901
endfunction
C
Cosmin Popescu 已提交
902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918

function! sw#sqlwindow#folding(lnum)
    if (a:lnum == 1)
        let b:fold_level = 0
    endif
    if getline(a:lnum) =~ '\v^[\=]+$'
        let b:fold_level += 1
        return '>' . b:fold_level
    endif
    if getline(a:lnum) =~ '\v^$'
        let result = '<' . b:fold_level
        let b:fold_level -= 1
        return result
    endif

    return -1
endfunction