Merge branch 'vim-with-runtime' into feat/quickfix-title
[vim_extended.git] / runtime / autoload / sqlcomplete.vim
blob2d88862a137da7fdbcd1c46ee8cb16ee80aa1669
1 " Vim OMNI completion script for SQL
2 " Language:    SQL
3 " Maintainer:  David Fishburn <dfishburn dot vim at gmail dot com>
4 " Version:     9.0
5 " Last Change: 2010 Apr 20
6 " Usage:       For detailed help
7 "              ":help sql.txt" 
8 "              or ":help ft-sql-omni" 
9 "              or read $VIMRUNTIME/doc/sql.txt
11 " History
12 " Version 9.0
13 "     This change removes some of the support for tables with spaces in their
14 "     names in order to simplify the regexes used to pull out query table 
15 "     aliases for more robust table name and column name code completion.
16 "     Full support for "table names with spaces" can be added in again
17 "     after 7.3.
18 " Version 8.0
19 "     Incorrectly re-executed the g:ftplugin_sql_omni_key_right and g:ftplugin_sql_omni_key_left 
20 "     when drilling in and out of a column list for a table.
21 " Version 7.0
22 "     Better handling of object names
23 " Version 6.0
24 "     Supports object names with spaces "my table name"
26 " Set completion with CTRL-X CTRL-O to autoloaded function.
27 " This check is in place in case this script is
28 " sourced directly instead of using the autoload feature. 
29 if exists('&omnifunc')
30     " Do not set the option if already set since this
31     " results in an E117 warning.
32     if &omnifunc == ""
33         setlocal omnifunc=sqlcomplete#Complete
34     endif
35 endif
37 if exists('g:loaded_sql_completion')
38     finish 
39 endif
40 let g:loaded_sql_completion = 70
42 " Maintains filename of dictionary
43 let s:sql_file_table        = ""
44 let s:sql_file_procedure    = ""
45 let s:sql_file_view         = ""
47 " Define various arrays to be used for caching
48 let s:tbl_name              = []
49 let s:tbl_alias             = []
50 let s:tbl_cols              = []
51 let s:syn_list              = []
52 let s:syn_value             = []
54 " Used in conjunction with the syntaxcomplete plugin
55 let s:save_inc              = ""
56 let s:save_exc              = ""
57 if exists('g:omni_syntax_group_include_sql')
58     let s:save_inc = g:omni_syntax_group_include_sql
59 endif
60 if exists('g:omni_syntax_group_exclude_sql')
61     let s:save_exc = g:omni_syntax_group_exclude_sql
62 endif
64 " Used with the column list
65 let s:save_prev_table       = ""
67 " Default the option to verify table alias
68 if !exists('g:omni_sql_use_tbl_alias')
69     let g:omni_sql_use_tbl_alias = 'a'
70 endif
71 " Default syntax items to precache
72 if !exists('g:omni_sql_precache_syntax_groups')
73     let g:omni_sql_precache_syntax_groups = [
74                 \ 'syntax',
75                 \ 'sqlKeyword',
76                 \ 'sqlFunction',
77                 \ 'sqlOption',
78                 \ 'sqlType',
79                 \ 'sqlStatement'
80                 \ ]
81 endif
82 " Set ignorecase to the ftplugin standard
83 if !exists('g:omni_sql_ignorecase')
84     let g:omni_sql_ignorecase = &ignorecase
85 endif
86 " During table completion, should the table list also
87 " include the owner name
88 if !exists('g:omni_sql_include_owner')
89     let g:omni_sql_include_owner = 0
90     if exists('g:loaded_dbext')
91         if g:loaded_dbext >= 300
92             " New to dbext 3.00, by default the table lists include the owner
93             " name of the table.  This is used when determining how much of
94             " whatever has been typed should be replaced as part of the 
95             " code replacement.
96             let g:omni_sql_include_owner = 1
97         endif
98     endif
99 endif
101 " This function is used for the 'omnifunc' option.
102 function! sqlcomplete#Complete(findstart, base)
104     " Default to table name completion
105     let compl_type = 'table'
106     " Allow maps to specify what type of object completion they want
107     if exists('b:sql_compl_type')
108         let compl_type = b:sql_compl_type
109     endif
111     " First pass through this function determines how much of the line should
112     " be replaced by whatever is chosen from the completion list
113     if a:findstart
114         " Locate the start of the item, including "."
115         let line     = getline('.')
116         let start    = col('.') - 1
117         let lastword = -1
118         let begindot = 0
119         " Check if the first character is a ".", for column completion
120         if line[start - 1] == '.'
121             let begindot = 1
122         endif
123         while start > 0
124             " Additional code was required to handle objects which 
125             " can contain spaces like "my table name".
126             if line[start - 1] !~ '\(\w\|\.\)'
127                 " If the previous character is not a period or word character
128                 break
129             " elseif line[start - 1] =~ '\(\w\|\s\+\)'
130             "     let start -= 1
131             elseif line[start - 1] =~ '\w'
132                 " If the previous character is word character continue back
133                 let start -= 1
134             elseif line[start - 1] =~ '\.' && 
135                         \ compl_type =~ 'column\|table\|view\|procedure'
136                 " If the previous character is a period and we are completing
137                 " an object which can be specified with a period like this:
138                 "     table_name.column_name
139                 "     owner_name.table_name
141                 " If lastword has already been set for column completion
142                 " break from the loop, since we do not also want to pickup
143                 " a table name if it was also supplied.
144                 if lastword != -1 && compl_type == 'column' 
145                     break
146                 endif
147                 " If column completion was specified stop at the "." if
148                 " a . was specified, otherwise, replace all the way up
149                 " to the owner name (if included).
150                 if lastword == -1 && compl_type == 'column' && begindot == 1
151                     let lastword = start
152                 endif
153                 " If omni_sql_include_owner = 0, do not include the table
154                 " name as part of the substitution, so break here
155                 if lastword == -1 && 
156                             \ compl_type =~ 'table\|view\|procedure\column_csv' && 
157                             \ g:omni_sql_include_owner == 0
158                     let lastword = start
159                     break
160                 endif
161                 let start -= 1
162             else
163                 break
164             endif
165         endwhile
167         " Return the column of the last word, which is going to be changed.
168         " Remember the text that comes before it in s:prepended.
169         if lastword == -1
170             let s:prepended = ''
171             return start
172         endif
173         let s:prepended = strpart(line, start, lastword - start)
174         return lastword
175     endif
177     " Second pass through this function will determine what data to put inside
178     " of the completion list
179     " s:prepended is set by the first pass
180     let base = s:prepended . a:base
182     " Default the completion list to an empty list
183     let compl_list = []
185     " Default to table name completion
186     let compl_type = 'table'
187     " Allow maps to specify what type of object completion they want
188     if exists('b:sql_compl_type')
189         let compl_type = b:sql_compl_type
190         unlet b:sql_compl_type
191     endif
193     if compl_type == 'tableReset'
194         let compl_type = 'table'
195         let base = ''
196     endif
198     if compl_type == 'table' ||
199                 \ compl_type == 'procedure' ||
200                 \ compl_type == 'view' 
202         " This type of completion relies upon the dbext.vim plugin
203         if s:SQLCCheck4dbext() == -1
204             return []
205         endif
207         " Allow the user to override the dbext plugin to specify whether
208         " the owner/creator should be included in the list
209         if g:loaded_dbext >= 300
210             let saveSetting = DB_listOption('dict_show_owner')
211             exec 'DBSetOption dict_show_owner='.(g:omni_sql_include_owner==1?'1':'0')
212         endif
214         let compl_type_uc = substitute(compl_type, '\w\+', '\u&', '')
215         " Same call below, no need to do it twice
216         " if s:sql_file_{compl_type} == ""
217         "     let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc)
218         " endif
219         let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc)
220         if s:sql_file_{compl_type} != ""
221             if filereadable(s:sql_file_{compl_type})
222                 let compl_list = readfile(s:sql_file_{compl_type})
223             endif
224         endif
226         if g:loaded_dbext > 300
227             exec 'DBSetOption dict_show_owner='.saveSetting
228         endif
229     elseif compl_type =~? 'column'
231         " This type of completion relies upon the dbext.vim plugin
232         if s:SQLCCheck4dbext() == -1
233             return []
234         endif
236         if base == ""
237             " The last time we displayed a column list we stored
238             " the table name.  If the user selects a column list 
239             " without a table name of alias present, assume they want
240             " the previous column list displayed.
241             let base = s:save_prev_table
242         endif
244         let owner  = ''
245         let column = ''
247         if base =~ '\.'
248             " Check if the owner/creator has been specified
249             let owner  = matchstr( base, '^\zs.*\ze\..*\..*' )
250             let table  = matchstr( base, '^\(.*\.\)\?\zs.*\ze\..*' )
251             let column = matchstr( base, '.*\.\zs.*' )
253             " It is pretty well impossible to determine if the user
254             " has entered:
255             "    owner.table
256             "    table.column_prefix
257             " So there are a couple of things we can do to mitigate 
258             " this issue.
259             "    1.  Check if the dbext plugin has the option turned
260             "        on to even allow owners
261             "    2.  Based on 1, if the user is showing a table list
262             "        and the DrillIntoTable (using <Right>) then 
263             "        this will be owner.table.  In this case, we can
264             "        check to see the table.column exists in the 
265             "        cached table list.  If it does, then we have
266             "        determined the user has actually chosen 
267             "        owner.table, not table.column_prefix.
268             let found = -1
269             if g:omni_sql_include_owner == 1 && owner == ''
270                 if filereadable(s:sql_file_table)
271                     let tbl_list = readfile(s:sql_file_table)
272                     let found    = index( tbl_list, ((table != '')?(table.'.'):'').column)
273                 endif
274             endif
275             " If the table.column was found in the table list, we can safely assume
276             " the owner was not provided and shift the items appropriately.
277             " OR
278             " If the user has indicated not to use table owners at all and
279             " the base ends in a '.' we know they are not providing a column
280             " name, so we can shift the items appropriately.
281             if found != -1 || (g:omni_sql_include_owner == 0 && base !~ '\.$')
282                 let owner  = table
283                 let table  = column
284                 let column = ''
285             endif
286         else
287             let table  = base
288         endif
290         " Get anything after the . and consider this the table name
291         " If an owner has been specified, then we must consider the 
292         " base to be a partial column name
293         " let base  = matchstr( base, '^\(.*\.\)\?\zs.*' )
295         if table != ""
296             let s:save_prev_table = base
297             let list_type         = ''
299             if compl_type == 'column_csv'
300                 " Return one array element, with a comma separated
301                 " list of values instead of multiple array entries
302                 " for each column in the table.
303                 let list_type     = 'csv'
304             endif
306             let compl_list  = s:SQLCGetColumns(table, list_type)
307             if column != ''
308                 " If no column prefix has been provided and the table
309                 " name was provided, append it to each of the items
310                 " returned.
311                 let compl_list = map(compl_list, "table.'.'.v:val")
312                 if owner != ''
313                     " If an owner has been provided append it to each of the
314                     " items returned.
315                     let compl_list = map(compl_list, "owner.'.'.v:val")
316                 endif
317             else
318                 let base = ''
319             endif
321             if compl_type == 'column_csv'
322                 " Join the column array into 1 single element array
323                 " but make the columns column separated
324                 let compl_list        = [join(compl_list, ', ')]
325             endif
326         endif
327     elseif compl_type == 'resetCache'
328         " Reset all cached items
329         let s:tbl_name  = []
330         let s:tbl_alias = []
331         let s:tbl_cols  = []
332         let s:syn_list  = []
333         let s:syn_value = []
335         let msg = "All SQL cached items have been removed."
336         call s:SQLCWarningMsg(msg)
337         " Leave time for the user to read the error message
338         :sleep 2
339     else
340         let compl_list = s:SQLCGetSyntaxList(compl_type)
341     endif
343     if base != ''
344         " Filter the list based on the first few characters the user entered.
345         " Check if the text matches at the beginning 
346         " or 
347         " Match to a owner.table or alias.column type match
348         " or
349         " Handle names with spaces "my table name"
350         let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"'
351         " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\)"'
352         " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\(\\.\\)\\?'.base.'\\)"'
353         " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\([^.]*\\)\\?'.base.'\\)"'
354         let compl_list = filter(deepcopy(compl_list), expr)
355     endif
357     if exists('b:sql_compl_savefunc') && b:sql_compl_savefunc != ""
358         let &omnifunc = b:sql_compl_savefunc
359     endif
361     return compl_list
362 endfunc
364 function! sqlcomplete#PreCacheSyntax(...)
365     let syn_group_arr = []
366     if a:0 > 0 
367         let syn_group_arr = a:1
368     else
369         let syn_group_arr = g:omni_sql_precache_syntax_groups
370     endif
371     " For each group specified in the list, precache all
372     " the sytnax items.
373     if !empty(syn_group_arr)
374         for group_name in syn_group_arr
375             call s:SQLCGetSyntaxList(group_name)
376         endfor
377     endif
378 endfunction
380 function! sqlcomplete#Map(type)
381     " Tell the SQL plugin what you want to complete
382     let b:sql_compl_type=a:type
383     " Record previous omnifunc, if the SQL completion
384     " is being used in conjunction with other filetype
385     " completion plugins
386     if &omnifunc != "" && &omnifunc != 'sqlcomplete#Complete'
387         " Record the previous omnifunc, the plugin
388         " will automatically set this back so that it
389         " does not interfere with other ftplugins settings
390         let b:sql_compl_savefunc=&omnifunc
391     endif
392     " Set the OMNI func for the SQL completion plugin
393     let &omnifunc='sqlcomplete#Complete'
394 endfunction
396 function! sqlcomplete#DrillIntoTable()
397     " If the omni popup window is visible
398     if pumvisible()
399         call sqlcomplete#Map('column')
400         " C-Y, makes the currently highlighted entry active
401         " and trigger the omni popup to be redisplayed
402         call feedkeys("\<C-Y>\<C-X>\<C-O>", 'n')
403     else
404         " If the popup is not visible, simple perform the normal
405         " key behaviour.
406         " Must use exec since they key must be preceeded by "\"
407         " or feedkeys will simply push each character of the string 
408         " rather than the "key press".
409         exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_right.'", "n")'
410     endif
411     return ""
412 endfunction
414 function! sqlcomplete#DrillOutOfColumns()
415     " If the omni popup window is visible
416     if pumvisible()
417         call sqlcomplete#Map('tableReset')
418         " Trigger the omni popup to be redisplayed
419         call feedkeys("\<C-X>\<C-O>")
420     else
421         " If the popup is not visible, simple perform the normal
422         " key behaviour.
423         " Must use exec since they key must be preceeded by "\"
424         " or feedkeys will simply push each character of the string 
425         " rather than the "key press".
426         exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_left.'", "n")'
427     endif
428     return ""
429 endfunction
431 function! s:SQLCWarningMsg(msg)
432     echohl WarningMsg
433     echomsg a:msg 
434     echohl None
435 endfunction
436       
437 function! s:SQLCErrorMsg(msg)
438     echohl ErrorMsg
439     echomsg a:msg 
440     echohl None
441 endfunction
442       
443 function! s:SQLCGetSyntaxList(syn_group)
444     let syn_group  = a:syn_group
445     let compl_list = []
447     " Check if we have already cached the syntax list
448     let list_idx = index(s:syn_list, syn_group, 0, &ignorecase)
449     if list_idx > -1
450         " Return previously cached value
451         let compl_list = s:syn_value[list_idx]
452     else
453         " Request the syntax list items from the 
454         " syntax completion plugin
455         if syn_group == 'syntax'
456             " Handle this special case.  This allows the user
457             " to indicate they want all the syntax items available,
458             " so do not specify a specific include list.
459             let g:omni_syntax_group_include_sql = ''
460         else
461             " The user has specified a specific syntax group
462             let g:omni_syntax_group_include_sql = syn_group
463         endif
464         let g:omni_syntax_group_exclude_sql = ''
465         let syn_value                       = OmniSyntaxList()
466         let g:omni_syntax_group_include_sql = s:save_inc
467         let g:omni_syntax_group_exclude_sql = s:save_exc
468         " Cache these values for later use
469         let s:syn_list  = add( s:syn_list,  syn_group )
470         let s:syn_value = add( s:syn_value, syn_value )
471         let compl_list  = syn_value
472     endif
474     return compl_list
475 endfunction
477 function! s:SQLCCheck4dbext()
478     if !exists('g:loaded_dbext')
479         let msg = "The dbext plugin must be loaded for dynamic SQL completion"
480         call s:SQLCErrorMsg(msg)
481         " Leave time for the user to read the error message
482         :sleep 2
483         return -1
484     elseif g:loaded_dbext < 600
485         let msg = "The dbext plugin must be at least version 5.30 " .
486                     \ " for dynamic SQL completion"
487         call s:SQLCErrorMsg(msg)
488         " Leave time for the user to read the error message
489         :sleep 2
490         return -1
491     endif
492     return 1
493 endfunction
495 function! s:SQLCAddAlias(table_name, table_alias, cols)
496     " Strip off the owner if included
497     let table_name  = matchstr(a:table_name, '\%(.\{-}\.\)\?\zs\(.*\)' )
498     let table_alias = a:table_alias
499     let cols        = a:cols
501     if g:omni_sql_use_tbl_alias != 'n' 
502         if table_alias == ''
503             if 'da' =~? g:omni_sql_use_tbl_alias
504                 if table_name =~ '_'
505                     " Treat _ as separators since people often use these
506                     " for word separators
507                     let save_keyword = &iskeyword
508                     setlocal iskeyword-=_
510                     " Get the first letter of each word
511                     " [[:alpha:]] is used instead of \w 
512                     " to catch extended accented characters
513                     "
514                     let table_alias = substitute( 
515                                 \ table_name, 
516                                 \ '\<[[:alpha:]]\+\>_\?', 
517                                 \ '\=strpart(submatch(0), 0, 1)', 
518                                 \ 'g'
519                                 \ )
520                     " Restore original value
521                     let &iskeyword = save_keyword
522                 elseif table_name =~ '\u\U'
523                     let table_alias = substitute(
524                                 \ table_name, '\(\u\)\U*', '\1', 'g')
525                 else
526                     let table_alias = strpart(table_name, 0, 1)
527                 endif
528             endif
529         endif
530         if table_alias != ''
531             " Following a word character, make sure there is a . and no spaces
532             let table_alias = substitute(table_alias, '\w\zs\.\?\s*$', '.', '')
533             if 'a' =~? g:omni_sql_use_tbl_alias && a:table_alias == ''
534                 let table_alias = inputdialog("Enter table alias:", table_alias)
535             endif
536         endif
537         if table_alias != ''
538             let cols = substitute(cols, '\<\w', table_alias.'&', 'g')
539         endif
540     endif
542     return cols
543 endfunction
545 function! s:SQLCGetObjectOwner(object) 
546     " The owner regex matches a word at the start of the string which is
547     " followed by a dot, but doesn't include the dot in the result.
548     " ^           - from beginning of line
549     " \("\|\[\)\? - ignore any quotes
550     " \zs         - start the match now
551     " .\{-}       - get owner name
552     " \ze         - end the match
553     " \("\|\[\)\? - ignore any quotes
554     " \.          - must by followed by a .
555     " let owner = matchstr( a:object, '^\s*\zs.*\ze\.' )
556     let owner = matchstr( a:object, '^\("\|\[\)\?\zs\.\{-}\ze\("\|\]\)\?\.' )
557     return owner
558 endfunction 
560 function! s:SQLCGetColumns(table_name, list_type)
561     " Check if the table name was provided as part of the column name
562     let table_name   = matchstr(a:table_name, '^["\[\]a-zA-Z0-9_ ]\+\ze\.\?')
563     let table_cols   = []
564     let table_alias  = ''
565     let move_to_top  = 1
567     let table_name   = substitute(table_name, '\s*\(.\{-}\)\s*$', '\1', 'g')
569     " If the table name was given as:
570     "     where c.
571     let table_name   = substitute(table_name, '^\c\(WHERE\|AND\|OR\)\s\+', '', '')
572     if g:loaded_dbext >= 300
573         let saveSettingAlias = DB_listOption('use_tbl_alias')
574         exec 'DBSetOption use_tbl_alias=n'
575     endif
577     let table_name_stripped = substitute(table_name, '["\[\]]*', '', 'g')
579     " Check if we have already cached the column list for this table
580     " by its name
581     let list_idx = index(s:tbl_name, table_name_stripped, 0, &ignorecase)
582     if list_idx > -1
583         let table_cols = split(s:tbl_cols[list_idx], '\n')
584     else
585         " Check if we have already cached the column list for this table 
586         " by its alias, assuming the table_name provided was actually
587         " the alias for the table instead
588         "     select *
589         "       from area a
590         "      where a.
591         let list_idx = index(s:tbl_alias, table_name_stripped, 0, &ignorecase)
592         if list_idx > -1
593             let table_alias = table_name_stripped
594             let table_name  = s:tbl_name[list_idx]
595             let table_cols  = split(s:tbl_cols[list_idx], '\n')
596         endif
597     endif
599     " If we have not found a cached copy of the table
600     " And the table ends in a "." or we are looking for a column list
601     " if list_idx == -1 && (a:table_name =~ '\.' || b:sql_compl_type =~ 'column')
602     " if list_idx == -1 && (a:table_name =~ '\.' || a:list_type =~ 'csv')
603     if list_idx == -1 
604          let saveY      = @y
605          let saveSearch = @/
606          let saveWScan  = &wrapscan
607          let curline    = line(".")
608          let curcol     = col(".")
610          " Do not let searchs wrap
611          setlocal nowrapscan
612          " If . was entered, look at the word just before the .
613          " We are looking for something like this:
614          "    select * 
615          "      from customer c
616          "     where c.
617          " So when . is pressed, we need to find 'c'
618          "
620          " Search backwards to the beginning of the statement
621          " and do NOT wrap
622          " exec 'silent! normal! v?\<\(select\|update\|delete\|;\)\>'."\n".'"yy'
623          exec 'silent! normal! ?\<\c\(select\|update\|delete\|;\)\>'."\n"
625          " Start characterwise visual mode
626          " Advance right one character
627          " Search foward until one of the following:
628          "     1.  Another select/update/delete statement
629          "     2.  A ; at the end of a line (the delimiter)
630          "     3.  The end of the file (incase no delimiter)
631          " Yank the visually selected text into the "y register.
632          exec 'silent! normal! vl/\c\(\<select\>\|\<update\>\|\<delete\>\|;\s*$\|\%$\)'."\n".'"yy'
634          let query = @y
635          let query = substitute(query, "\n", ' ', 'g')
636          let found = 0
638          " if query =~? '^\c\(select\)'
639          if query =~? '^\(select\|update\|delete\)'
640              let found = 1
641              "  \(\(\<\w\+\>\)\.\)\?   - 
642              " '\c\(from\|join\|,\).\{-}'  - Starting at the from clause (case insensitive)
643              " '\zs\(\(\<\w\+\>\)\.\)\?' - Get the owner name (optional)
644              " '\<\w\+\>\ze' - Get the table name 
645              " '\s\+\<'.table_name.'\>' - Followed by the alias
646              " '\s*\.\@!.*'  - Cannot be followed by a .
647              " '\(\<where\>\|$\)' - Must be followed by a WHERE clause
648              " '.*'  - Exclude the rest of the line in the match
649              " let table_name_new = matchstr(@y, 
650              "             \ '\c\(from\|join\|,\).\{-}'.
651              "             \ '\zs\(\("\|\[\)\?.\{-}\("\|\]\)\.\)\?'.
652              "             \ '\("\|\[\)\?.\{-}\("\|\]\)\?\ze'.
653              "             \ '\s\+\%(as\s\+\)\?\<'.
654              "             \ matchstr(table_name, '.\{-}\ze\.\?$').
655              "             \ '\>'.
656              "             \ '\s*\.\@!.*'.
657              "             \ '\(\<where\>\|$\)'.
658              "             \ '.*'
659              "             \ )
660              let table_name_new = matchstr(@y, 
661                          \ '\c\(\<from\>\|\<join\>\|,\)\s*'.
662                          \ '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?'.
663                          \ '\("\|\[\)\?\w\+\("\|\]\)\?\ze'.
664                          \ '\s\+\%(as\s\+\)\?\<'.
665                          \ matchstr(table_name, '.\{-}\ze\.\?$').
666                          \ '\>'.
667                          \ '\s*\.\@!.*'.
668                          \ '\(\<where\>\|$\)'.
669                          \ '.*'
670                          \ )
672              if table_name_new != ''
673                  let table_alias = table_name
674                  let table_name  = matchstr( table_name_new, '^\(.*\.\)\?\zs.*\ze' )
676                  let list_idx = index(s:tbl_name, table_name, 0, &ignorecase)
677                  if list_idx > -1
678                      let table_cols  = split(s:tbl_cols[list_idx])
679                      let s:tbl_name[list_idx]  = table_name
680                      let s:tbl_alias[list_idx] = table_alias
681                  else
682                      let list_idx = index(s:tbl_alias, table_name, 0, &ignorecase)
683                      if list_idx > -1
684                          let table_cols = split(s:tbl_cols[list_idx])
685                          let s:tbl_name[list_idx]  = table_name
686                          let s:tbl_alias[list_idx] = table_alias
687                      endif
688                  endif
690              endif
691          else
692              " Simply assume it is a table name provided with a . on the end
693              let found = 1
694          endif
696          let @y        = saveY
697          let @/        = saveSearch
698          let &wrapscan = saveWScan
700          " Return to previous location
701          call cursor(curline, curcol)
702          
703          if found == 0
704              if g:loaded_dbext > 300
705                  exec 'DBSetOption use_tbl_alias='.saveSettingAlias
706              endif
708              " Not a SQL statement, do not display a list
709              return []
710          endif
711     endif 
713     if empty(table_cols)
714         " Specify silent mode, no messages to the user (tbl, 1)
715         " Specify do not comma separate (tbl, 1, 1)
716         let table_cols_str = DB_getListColumn(table_name, 1, 1)
718         if table_cols_str != ""
719             let s:tbl_name  = add( s:tbl_name,  table_name )
720             let s:tbl_alias = add( s:tbl_alias, table_alias )
721             let s:tbl_cols  = add( s:tbl_cols,  table_cols_str )
722             let table_cols  = split(table_cols_str, '\n')
723         endif
725     endif
727     if g:loaded_dbext > 300
728         exec 'DBSetOption use_tbl_alias='.saveSettingAlias
729     endif
731     " If the user has asked for a comma separate list of column
732     " values, ask the user if they want to prepend each column
733     " with a tablename alias.
734     if a:list_type == 'csv' && !empty(table_cols)
735         let cols       = join(table_cols, ', ')
736         let cols       = s:SQLCAddAlias(table_name, table_alias, cols)
737         let table_cols = [cols]
738     endif
740     return table_cols
741 endfunction