1f193fffdSBram Moolenaar" Vim OMNI completion script for SQL
2e2f98b95SBram Moolenaar" Language:    SQL
35c73622aSBram Moolenaar" Maintainer:  David Fishburn <dfishburn dot vim at gmail dot com>
4*f9d5ca1dSBram Moolenaar" Version:     10.0
5*f9d5ca1dSBram Moolenaar" Last Change: 2010 Jun 11
6f193fffdSBram Moolenaar" Usage:       For detailed help
7f193fffdSBram Moolenaar"              ":help sql.txt"
8f193fffdSBram Moolenaar"              or ":help ft-sql-omni"
9f193fffdSBram Moolenaar"              or read $VIMRUNTIME/doc/sql.txt
10e2f98b95SBram Moolenaar
115c73622aSBram Moolenaar" History
12*f9d5ca1dSBram Moolenaar" Version 10.0
13*f9d5ca1dSBram Moolenaar"     Updated PreCacheSyntax()
14*f9d5ca1dSBram Moolenaar"         - Now returns a List of the syntax items it finds.
15*f9d5ca1dSBram Moolenaar"           This allows other plugins / scripts to use this list for their own
16*f9d5ca1dSBram Moolenaar"           purposes.  In this case XPTemplate can use them for a Choose list.
17*f9d5ca1dSBram Moolenaar"         - Verifies the parameters are the correct type and displays a
18*f9d5ca1dSBram Moolenaar"           warning if not.
19*f9d5ca1dSBram Moolenaar"         - Verifies the parameters are the correct type and displays a
20*f9d5ca1dSBram Moolenaar"           warning if not.
21*f9d5ca1dSBram Moolenaar"     Updated SQLCWarningMsg()
22*f9d5ca1dSBram Moolenaar"         - Prepends warning message with SQLComplete so you know who issued
23*f9d5ca1dSBram Moolenaar"           the warning.
24*f9d5ca1dSBram Moolenaar"     Updated SQLCErrorMsg()
25*f9d5ca1dSBram Moolenaar"         - Prepends error message with SQLComplete so you know who issued
26*f9d5ca1dSBram Moolenaar"           the error.
27*f9d5ca1dSBram Moolenaar"
2800a927d6SBram Moolenaar" Version 9.0
2900a927d6SBram Moolenaar"     This change removes some of the support for tables with spaces in their
3000a927d6SBram Moolenaar"     names in order to simplify the regexes used to pull out query table
3100a927d6SBram Moolenaar"     aliases for more robust table name and column name code completion.
3200a927d6SBram Moolenaar"     Full support for "table names with spaces" can be added in again
3300a927d6SBram Moolenaar"     after 7.3.
34*f9d5ca1dSBram Moolenaar"
3500a927d6SBram Moolenaar" Version 8.0
3600a927d6SBram Moolenaar"     Incorrectly re-executed the g:ftplugin_sql_omni_key_right and g:ftplugin_sql_omni_key_left
3700a927d6SBram Moolenaar"     when drilling in and out of a column list for a table.
38*f9d5ca1dSBram Moolenaar"
395c73622aSBram Moolenaar" Version 7.0
405c73622aSBram Moolenaar"     Better handling of object names
41*f9d5ca1dSBram Moolenaar"
425c73622aSBram Moolenaar" Version 6.0
435c73622aSBram Moolenaar"     Supports object names with spaces "my table name"
445c73622aSBram Moolenaar"
45e2f98b95SBram Moolenaar" Set completion with CTRL-X CTRL-O to autoloaded function.
46e2f98b95SBram Moolenaar" This check is in place in case this script is
47e2f98b95SBram Moolenaar" sourced directly instead of using the autoload feature.
48e2f98b95SBram Moolenaarif exists('&omnifunc')
49e2f98b95SBram Moolenaar    " Do not set the option if already set since this
50e2f98b95SBram Moolenaar    " results in an E117 warning.
51e2f98b95SBram Moolenaar    if &omnifunc == ""
52e2f98b95SBram Moolenaar        setlocal omnifunc=sqlcomplete#Complete
53e2f98b95SBram Moolenaar    endif
54e2f98b95SBram Moolenaarendif
55e2f98b95SBram Moolenaar
56e2f98b95SBram Moolenaarif exists('g:loaded_sql_completion')
57e2f98b95SBram Moolenaar    finish
58e2f98b95SBram Moolenaarendif
59*f9d5ca1dSBram Moolenaarlet g:loaded_sql_completion = 100
60e2f98b95SBram Moolenaar
61e2f98b95SBram Moolenaar" Maintains filename of dictionary
62e2f98b95SBram Moolenaarlet s:sql_file_table        = ""
63e2f98b95SBram Moolenaarlet s:sql_file_procedure    = ""
64e2f98b95SBram Moolenaarlet s:sql_file_view         = ""
65e2f98b95SBram Moolenaar
66e2f98b95SBram Moolenaar" Define various arrays to be used for caching
67e2f98b95SBram Moolenaarlet s:tbl_name              = []
68e2f98b95SBram Moolenaarlet s:tbl_alias             = []
69e2f98b95SBram Moolenaarlet s:tbl_cols              = []
70e2f98b95SBram Moolenaarlet s:syn_list              = []
71e2f98b95SBram Moolenaarlet s:syn_value             = []
72e2f98b95SBram Moolenaar
73e2f98b95SBram Moolenaar" Used in conjunction with the syntaxcomplete plugin
74e2f98b95SBram Moolenaarlet s:save_inc              = ""
75e2f98b95SBram Moolenaarlet s:save_exc              = ""
76e2f98b95SBram Moolenaarif exists('g:omni_syntax_group_include_sql')
77e2f98b95SBram Moolenaar    let s:save_inc = g:omni_syntax_group_include_sql
78e2f98b95SBram Moolenaarendif
79e2f98b95SBram Moolenaarif exists('g:omni_syntax_group_exclude_sql')
80e2f98b95SBram Moolenaar    let s:save_exc = g:omni_syntax_group_exclude_sql
81e2f98b95SBram Moolenaarendif
82e2f98b95SBram Moolenaar
83e2f98b95SBram Moolenaar" Used with the column list
84e2f98b95SBram Moolenaarlet s:save_prev_table       = ""
85e2f98b95SBram Moolenaar
86e2f98b95SBram Moolenaar" Default the option to verify table alias
87e2f98b95SBram Moolenaarif !exists('g:omni_sql_use_tbl_alias')
88e2f98b95SBram Moolenaar    let g:omni_sql_use_tbl_alias = 'a'
89e2f98b95SBram Moolenaarendif
90910f66f9SBram Moolenaar" Default syntax items to precache
91910f66f9SBram Moolenaarif !exists('g:omni_sql_precache_syntax_groups')
92910f66f9SBram Moolenaar    let g:omni_sql_precache_syntax_groups = [
93910f66f9SBram Moolenaar                \ 'syntax',
94910f66f9SBram Moolenaar                \ 'sqlKeyword',
95910f66f9SBram Moolenaar                \ 'sqlFunction',
96910f66f9SBram Moolenaar                \ 'sqlOption',
97910f66f9SBram Moolenaar                \ 'sqlType',
98910f66f9SBram Moolenaar                \ 'sqlStatement'
99910f66f9SBram Moolenaar                \ ]
100910f66f9SBram Moolenaarendif
101eb3593b3SBram Moolenaar" Set ignorecase to the ftplugin standard
102eb3593b3SBram Moolenaarif !exists('g:omni_sql_ignorecase')
103eb3593b3SBram Moolenaar    let g:omni_sql_ignorecase = &ignorecase
104eb3593b3SBram Moolenaarendif
105eb3593b3SBram Moolenaar" During table completion, should the table list also
106eb3593b3SBram Moolenaar" include the owner name
107eb3593b3SBram Moolenaarif !exists('g:omni_sql_include_owner')
108eb3593b3SBram Moolenaar    let g:omni_sql_include_owner = 0
109eb3593b3SBram Moolenaar    if exists('g:loaded_dbext')
110eb3593b3SBram Moolenaar        if g:loaded_dbext >= 300
111eb3593b3SBram Moolenaar            " New to dbext 3.00, by default the table lists include the owner
112eb3593b3SBram Moolenaar            " name of the table.  This is used when determining how much of
113eb3593b3SBram Moolenaar            " whatever has been typed should be replaced as part of the
114eb3593b3SBram Moolenaar            " code replacement.
115eb3593b3SBram Moolenaar            let g:omni_sql_include_owner = 1
116eb3593b3SBram Moolenaar        endif
117eb3593b3SBram Moolenaar    endif
118eb3593b3SBram Moolenaarendif
119e2f98b95SBram Moolenaar
120e2f98b95SBram Moolenaar" This function is used for the 'omnifunc' option.
121e2f98b95SBram Moolenaarfunction! sqlcomplete#Complete(findstart, base)
122e2f98b95SBram Moolenaar
123e2f98b95SBram Moolenaar    " Default to table name completion
124e2f98b95SBram Moolenaar    let compl_type = 'table'
125e2f98b95SBram Moolenaar    " Allow maps to specify what type of object completion they want
126e2f98b95SBram Moolenaar    if exists('b:sql_compl_type')
127e2f98b95SBram Moolenaar        let compl_type = b:sql_compl_type
128e2f98b95SBram Moolenaar    endif
129e2f98b95SBram Moolenaar
130910f66f9SBram Moolenaar    " First pass through this function determines how much of the line should
131910f66f9SBram Moolenaar    " be replaced by whatever is chosen from the completion list
132e2f98b95SBram Moolenaar    if a:findstart
133e2f98b95SBram Moolenaar        " Locate the start of the item, including "."
134e2f98b95SBram Moolenaar        let line     = getline('.')
135e2f98b95SBram Moolenaar        let start    = col('.') - 1
136e2f98b95SBram Moolenaar        let lastword = -1
137f193fffdSBram Moolenaar        let begindot = 0
138f193fffdSBram Moolenaar        " Check if the first character is a ".", for column completion
139f193fffdSBram Moolenaar        if line[start - 1] == '.'
140f193fffdSBram Moolenaar            let begindot = 1
141f193fffdSBram Moolenaar        endif
142e2f98b95SBram Moolenaar        while start > 0
1435c73622aSBram Moolenaar            " Additional code was required to handle objects which
1445c73622aSBram Moolenaar            " can contain spaces like "my table name".
1455c73622aSBram Moolenaar            if line[start - 1] !~ '\(\w\|\.\)'
1465c73622aSBram Moolenaar                " If the previous character is not a period or word character
1475c73622aSBram Moolenaar                break
1485c73622aSBram Moolenaar            " elseif line[start - 1] =~ '\(\w\|\s\+\)'
1495c73622aSBram Moolenaar            "     let start -= 1
1505c73622aSBram Moolenaar            elseif line[start - 1] =~ '\w'
1515c73622aSBram Moolenaar                " If the previous character is word character continue back
152e2f98b95SBram Moolenaar                let start -= 1
153eb3593b3SBram Moolenaar            elseif line[start - 1] =~ '\.' &&
154eb3593b3SBram Moolenaar                        \ compl_type =~ 'column\|table\|view\|procedure'
1555c73622aSBram Moolenaar                " If the previous character is a period and we are completing
1565c73622aSBram Moolenaar                " an object which can be specified with a period like this:
1575c73622aSBram Moolenaar                "     table_name.column_name
1585c73622aSBram Moolenaar                "     owner_name.table_name
1595c73622aSBram Moolenaar
160eb3593b3SBram Moolenaar                " If lastword has already been set for column completion
161eb3593b3SBram Moolenaar                " break from the loop, since we do not also want to pickup
162eb3593b3SBram Moolenaar                " a table name if it was also supplied.
163f193fffdSBram Moolenaar                if lastword != -1 && compl_type == 'column'
164eb3593b3SBram Moolenaar                    break
165eb3593b3SBram Moolenaar                endif
166f193fffdSBram Moolenaar                " If column completion was specified stop at the "." if
167f193fffdSBram Moolenaar                " a . was specified, otherwise, replace all the way up
168f193fffdSBram Moolenaar                " to the owner name (if included).
169f193fffdSBram Moolenaar                if lastword == -1 && compl_type == 'column' && begindot == 1
170e2f98b95SBram Moolenaar                    let lastword = start
171e2f98b95SBram Moolenaar                endif
172eb3593b3SBram Moolenaar                " If omni_sql_include_owner = 0, do not include the table
173eb3593b3SBram Moolenaar                " name as part of the substitution, so break here
174eb3593b3SBram Moolenaar                if lastword == -1 &&
175f193fffdSBram Moolenaar                            \ compl_type =~ 'table\|view\|procedure\column_csv' &&
176eb3593b3SBram Moolenaar                            \ g:omni_sql_include_owner == 0
177eb3593b3SBram Moolenaar                    let lastword = start
178eb3593b3SBram Moolenaar                    break
179eb3593b3SBram Moolenaar                endif
180e2f98b95SBram Moolenaar                let start -= 1
181e2f98b95SBram Moolenaar            else
182e2f98b95SBram Moolenaar                break
183e2f98b95SBram Moolenaar            endif
184e2f98b95SBram Moolenaar        endwhile
185e2f98b95SBram Moolenaar
186e2f98b95SBram Moolenaar        " Return the column of the last word, which is going to be changed.
187e2f98b95SBram Moolenaar        " Remember the text that comes before it in s:prepended.
188e2f98b95SBram Moolenaar        if lastword == -1
189e2f98b95SBram Moolenaar            let s:prepended = ''
190e2f98b95SBram Moolenaar            return start
191e2f98b95SBram Moolenaar        endif
192e2f98b95SBram Moolenaar        let s:prepended = strpart(line, start, lastword - start)
193e2f98b95SBram Moolenaar        return lastword
194e2f98b95SBram Moolenaar    endif
195e2f98b95SBram Moolenaar
196910f66f9SBram Moolenaar    " Second pass through this function will determine what data to put inside
197910f66f9SBram Moolenaar    " of the completion list
198910f66f9SBram Moolenaar    " s:prepended is set by the first pass
199e2f98b95SBram Moolenaar    let base = s:prepended . a:base
200e2f98b95SBram Moolenaar
201910f66f9SBram Moolenaar    " Default the completion list to an empty list
202e2f98b95SBram Moolenaar    let compl_list = []
203e2f98b95SBram Moolenaar
204e2f98b95SBram Moolenaar    " Default to table name completion
205e2f98b95SBram Moolenaar    let compl_type = 'table'
206e2f98b95SBram Moolenaar    " Allow maps to specify what type of object completion they want
207e2f98b95SBram Moolenaar    if exists('b:sql_compl_type')
208e2f98b95SBram Moolenaar        let compl_type = b:sql_compl_type
209e2f98b95SBram Moolenaar        unlet b:sql_compl_type
210e2f98b95SBram Moolenaar    endif
211e2f98b95SBram Moolenaar
212e2f98b95SBram Moolenaar    if compl_type == 'tableReset'
213e2f98b95SBram Moolenaar        let compl_type = 'table'
214e2f98b95SBram Moolenaar        let base = ''
215e2f98b95SBram Moolenaar    endif
216e2f98b95SBram Moolenaar
217e2f98b95SBram Moolenaar    if compl_type == 'table' ||
218e2f98b95SBram Moolenaar                \ compl_type == 'procedure' ||
219e2f98b95SBram Moolenaar                \ compl_type == 'view'
220e2f98b95SBram Moolenaar
221e2f98b95SBram Moolenaar        " This type of completion relies upon the dbext.vim plugin
222e2f98b95SBram Moolenaar        if s:SQLCCheck4dbext() == -1
223e2f98b95SBram Moolenaar            return []
224e2f98b95SBram Moolenaar        endif
225e2f98b95SBram Moolenaar
22683e138c6SBram Moolenaar        " Allow the user to override the dbext plugin to specify whether
22783e138c6SBram Moolenaar        " the owner/creator should be included in the list
2288c8de839SBram Moolenaar        if g:loaded_dbext >= 300
2298c8de839SBram Moolenaar            let saveSetting = DB_listOption('dict_show_owner')
2308c8de839SBram Moolenaar            exec 'DBSetOption dict_show_owner='.(g:omni_sql_include_owner==1?'1':'0')
231e2f98b95SBram Moolenaar        endif
23283e138c6SBram Moolenaar
23383e138c6SBram Moolenaar        let compl_type_uc = substitute(compl_type, '\w\+', '\u&', '')
2345c73622aSBram Moolenaar        " Same call below, no need to do it twice
2355c73622aSBram Moolenaar        " if s:sql_file_{compl_type} == ""
2365c73622aSBram Moolenaar        "     let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc)
2375c73622aSBram Moolenaar        " endif
23883e138c6SBram Moolenaar        let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc)
239e2f98b95SBram Moolenaar        if s:sql_file_{compl_type} != ""
240e2f98b95SBram Moolenaar            if filereadable(s:sql_file_{compl_type})
241e2f98b95SBram Moolenaar                let compl_list = readfile(s:sql_file_{compl_type})
242e2f98b95SBram Moolenaar            endif
243e2f98b95SBram Moolenaar        endif
24483e138c6SBram Moolenaar
2458c8de839SBram Moolenaar        if g:loaded_dbext > 300
2468c8de839SBram Moolenaar            exec 'DBSetOption dict_show_owner='.saveSetting
2478c8de839SBram Moolenaar        endif
24883e138c6SBram Moolenaar    elseif compl_type =~? 'column'
249e2f98b95SBram Moolenaar
250e2f98b95SBram Moolenaar        " This type of completion relies upon the dbext.vim plugin
251e2f98b95SBram Moolenaar        if s:SQLCCheck4dbext() == -1
252e2f98b95SBram Moolenaar            return []
253e2f98b95SBram Moolenaar        endif
254e2f98b95SBram Moolenaar
255e2f98b95SBram Moolenaar        if base == ""
256e2f98b95SBram Moolenaar            " The last time we displayed a column list we stored
257e2f98b95SBram Moolenaar            " the table name.  If the user selects a column list
258e2f98b95SBram Moolenaar            " without a table name of alias present, assume they want
259e2f98b95SBram Moolenaar            " the previous column list displayed.
260e2f98b95SBram Moolenaar            let base = s:save_prev_table
261e2f98b95SBram Moolenaar        endif
262e2f98b95SBram Moolenaar
26383e138c6SBram Moolenaar        let owner  = ''
26483e138c6SBram Moolenaar        let column = ''
26583e138c6SBram Moolenaar
26683e138c6SBram Moolenaar        if base =~ '\.'
26783e138c6SBram Moolenaar            " Check if the owner/creator has been specified
26883e138c6SBram Moolenaar            let owner  = matchstr( base, '^\zs.*\ze\..*\..*' )
26983e138c6SBram Moolenaar            let table  = matchstr( base, '^\(.*\.\)\?\zs.*\ze\..*' )
27083e138c6SBram Moolenaar            let column = matchstr( base, '.*\.\zs.*' )
27183e138c6SBram Moolenaar
27283e138c6SBram Moolenaar            " It is pretty well impossible to determine if the user
27383e138c6SBram Moolenaar            " has entered:
27483e138c6SBram Moolenaar            "    owner.table
27583e138c6SBram Moolenaar            "    table.column_prefix
27683e138c6SBram Moolenaar            " So there are a couple of things we can do to mitigate
27783e138c6SBram Moolenaar            " this issue.
27883e138c6SBram Moolenaar            "    1.  Check if the dbext plugin has the option turned
27983e138c6SBram Moolenaar            "        on to even allow owners
28083e138c6SBram Moolenaar            "    2.  Based on 1, if the user is showing a table list
28100a927d6SBram Moolenaar            "        and the DrillIntoTable (using <Right>) then
28283e138c6SBram Moolenaar            "        this will be owner.table.  In this case, we can
28383e138c6SBram Moolenaar            "        check to see the table.column exists in the
28483e138c6SBram Moolenaar            "        cached table list.  If it does, then we have
28583e138c6SBram Moolenaar            "        determined the user has actually chosen
28683e138c6SBram Moolenaar            "        owner.table, not table.column_prefix.
28783e138c6SBram Moolenaar            let found = -1
28883e138c6SBram Moolenaar            if g:omni_sql_include_owner == 1 && owner == ''
28983e138c6SBram Moolenaar                if filereadable(s:sql_file_table)
29083e138c6SBram Moolenaar                    let tbl_list = readfile(s:sql_file_table)
29183e138c6SBram Moolenaar                    let found    = index( tbl_list, ((table != '')?(table.'.'):'').column)
29283e138c6SBram Moolenaar                endif
29383e138c6SBram Moolenaar            endif
29483e138c6SBram Moolenaar            " If the table.column was found in the table list, we can safely assume
29583e138c6SBram Moolenaar            " the owner was not provided and shift the items appropriately.
29683e138c6SBram Moolenaar            " OR
29783e138c6SBram Moolenaar            " If the user has indicated not to use table owners at all and
29883e138c6SBram Moolenaar            " the base ends in a '.' we know they are not providing a column
29983e138c6SBram Moolenaar            " name, so we can shift the items appropriately.
30083e138c6SBram Moolenaar            if found != -1 || (g:omni_sql_include_owner == 0 && base !~ '\.$')
30183e138c6SBram Moolenaar                let owner  = table
30283e138c6SBram Moolenaar                let table  = column
30383e138c6SBram Moolenaar                let column = ''
30483e138c6SBram Moolenaar            endif
30583e138c6SBram Moolenaar        else
30683e138c6SBram Moolenaar            let table  = base
30783e138c6SBram Moolenaar        endif
30883e138c6SBram Moolenaar
30983e138c6SBram Moolenaar        " Get anything after the . and consider this the table name
31083e138c6SBram Moolenaar        " If an owner has been specified, then we must consider the
31183e138c6SBram Moolenaar        " base to be a partial column name
31283e138c6SBram Moolenaar        " let base  = matchstr( base, '^\(.*\.\)\?\zs.*' )
31383e138c6SBram Moolenaar
31483e138c6SBram Moolenaar        if table != ""
315e2f98b95SBram Moolenaar            let s:save_prev_table = base
31683e138c6SBram Moolenaar            let list_type         = ''
31783e138c6SBram Moolenaar
31883e138c6SBram Moolenaar            if compl_type == 'column_csv'
31983e138c6SBram Moolenaar                " Return one array element, with a comma separated
32083e138c6SBram Moolenaar                " list of values instead of multiple array entries
32183e138c6SBram Moolenaar                " for each column in the table.
32283e138c6SBram Moolenaar                let list_type     = 'csv'
32383e138c6SBram Moolenaar            endif
32483e138c6SBram Moolenaar
32583e138c6SBram Moolenaar            let compl_list  = s:SQLCGetColumns(table, list_type)
32683e138c6SBram Moolenaar            if column != ''
32783e138c6SBram Moolenaar                " If no column prefix has been provided and the table
32883e138c6SBram Moolenaar                " name was provided, append it to each of the items
32983e138c6SBram Moolenaar                " returned.
33083e138c6SBram Moolenaar                let compl_list = map(compl_list, "table.'.'.v:val")
33183e138c6SBram Moolenaar                if owner != ''
33283e138c6SBram Moolenaar                    " If an owner has been provided append it to each of the
33383e138c6SBram Moolenaar                    " items returned.
33483e138c6SBram Moolenaar                    let compl_list = map(compl_list, "owner.'.'.v:val")
33583e138c6SBram Moolenaar                endif
33683e138c6SBram Moolenaar            else
337e2f98b95SBram Moolenaar                let base = ''
338e2f98b95SBram Moolenaar            endif
339e2f98b95SBram Moolenaar
34083e138c6SBram Moolenaar            if compl_type == 'column_csv'
341e2f98b95SBram Moolenaar                " Join the column array into 1 single element array
342e2f98b95SBram Moolenaar                " but make the columns column separated
343e2f98b95SBram Moolenaar                let compl_list        = [join(compl_list, ', ')]
34483e138c6SBram Moolenaar            endif
345e2f98b95SBram Moolenaar        endif
346e2f98b95SBram Moolenaar    elseif compl_type == 'resetCache'
347e2f98b95SBram Moolenaar        " Reset all cached items
348e2f98b95SBram Moolenaar        let s:tbl_name  = []
349e2f98b95SBram Moolenaar        let s:tbl_alias = []
350e2f98b95SBram Moolenaar        let s:tbl_cols  = []
351e2f98b95SBram Moolenaar        let s:syn_list  = []
352e2f98b95SBram Moolenaar        let s:syn_value = []
353f193fffdSBram Moolenaar
354f193fffdSBram Moolenaar        let msg = "All SQL cached items have been removed."
355f193fffdSBram Moolenaar        call s:SQLCWarningMsg(msg)
356f193fffdSBram Moolenaar        " Leave time for the user to read the error message
357f193fffdSBram Moolenaar        :sleep 2
358e2f98b95SBram Moolenaar    else
359910f66f9SBram Moolenaar        let compl_list = s:SQLCGetSyntaxList(compl_type)
360e2f98b95SBram Moolenaar    endif
361e2f98b95SBram Moolenaar
362e2f98b95SBram Moolenaar    if base != ''
3635c73622aSBram Moolenaar        " Filter the list based on the first few characters the user entered.
3645c73622aSBram Moolenaar        " Check if the text matches at the beginning
3655c73622aSBram Moolenaar        " or
3665c73622aSBram Moolenaar        " Match to a owner.table or alias.column type match
3675c73622aSBram Moolenaar        " or
3685c73622aSBram Moolenaar        " Handle names with spaces "my table name"
3695c73622aSBram Moolenaar        let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"'
3705c73622aSBram Moolenaar        " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\)"'
3715c73622aSBram Moolenaar        " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\(\\.\\)\\?'.base.'\\)"'
3725c73622aSBram Moolenaar        " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\([^.]*\\)\\?'.base.'\\)"'
373eb3593b3SBram Moolenaar        let compl_list = filter(deepcopy(compl_list), expr)
374e2f98b95SBram Moolenaar    endif
375e2f98b95SBram Moolenaar
376910f66f9SBram Moolenaar    if exists('b:sql_compl_savefunc') && b:sql_compl_savefunc != ""
377910f66f9SBram Moolenaar        let &omnifunc = b:sql_compl_savefunc
378910f66f9SBram Moolenaar    endif
379910f66f9SBram Moolenaar
380e2f98b95SBram Moolenaar    return compl_list
381e2f98b95SBram Moolenaarendfunc
382e2f98b95SBram Moolenaar
383910f66f9SBram Moolenaarfunction! sqlcomplete#PreCacheSyntax(...)
384910f66f9SBram Moolenaar    let syn_group_arr = []
385*f9d5ca1dSBram Moolenaar    let syn_items     = []
386*f9d5ca1dSBram Moolenaar
387910f66f9SBram Moolenaar    if a:0 > 0
388*f9d5ca1dSBram Moolenaar        if type(a:1) != 3
389*f9d5ca1dSBram Moolenaar            call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']")
390*f9d5ca1dSBram Moolenaar            return ''
391*f9d5ca1dSBram Moolenaar        endif
392910f66f9SBram Moolenaar        let syn_group_arr = a:1
393910f66f9SBram Moolenaar    else
394910f66f9SBram Moolenaar        let syn_group_arr = g:omni_sql_precache_syntax_groups
395910f66f9SBram Moolenaar    endif
39683e138c6SBram Moolenaar    " For each group specified in the list, precache all
39783e138c6SBram Moolenaar    " the sytnax items.
398910f66f9SBram Moolenaar    if !empty(syn_group_arr)
399910f66f9SBram Moolenaar        for group_name in syn_group_arr
400*f9d5ca1dSBram Moolenaar            let syn_items = extend( syn_items, s:SQLCGetSyntaxList(group_name) )
401*f9d5ca1dSBram Moolenaar        endfor
402*f9d5ca1dSBram Moolenaar    endif
403*f9d5ca1dSBram Moolenaar
404*f9d5ca1dSBram Moolenaar    return syn_items
405*f9d5ca1dSBram Moolenaarendfunction
406*f9d5ca1dSBram Moolenaar
407*f9d5ca1dSBram Moolenaarfunction! sqlcomplete#ResetCacheSyntax(...)
408*f9d5ca1dSBram Moolenaar    let syn_group_arr = []
409*f9d5ca1dSBram Moolenaar
410*f9d5ca1dSBram Moolenaar    if a:0 > 0
411*f9d5ca1dSBram Moolenaar        if type(a:1) != 3
412*f9d5ca1dSBram Moolenaar            call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']")
413*f9d5ca1dSBram Moolenaar            return ''
414*f9d5ca1dSBram Moolenaar        endif
415*f9d5ca1dSBram Moolenaar        let syn_group_arr = a:1
416*f9d5ca1dSBram Moolenaar    else
417*f9d5ca1dSBram Moolenaar        let syn_group_arr = g:omni_sql_precache_syntax_groups
418*f9d5ca1dSBram Moolenaar    endif
419*f9d5ca1dSBram Moolenaar    " For each group specified in the list, precache all
420*f9d5ca1dSBram Moolenaar    " the sytnax items.
421*f9d5ca1dSBram Moolenaar    if !empty(syn_group_arr)
422*f9d5ca1dSBram Moolenaar        for group_name in syn_group_arr
423*f9d5ca1dSBram Moolenaar            let list_idx = index(s:syn_list, group_name, 0, &ignorecase)
424*f9d5ca1dSBram Moolenaar            if list_idx > -1
425*f9d5ca1dSBram Moolenaar                " Remove from list of groups
426*f9d5ca1dSBram Moolenaar                call remove( s:syn_list, list_idx )
427*f9d5ca1dSBram Moolenaar                " Remove from list of keywords
428*f9d5ca1dSBram Moolenaar                call remove( s:syn_value, list_idx )
429*f9d5ca1dSBram Moolenaar            endif
430910f66f9SBram Moolenaar        endfor
431910f66f9SBram Moolenaar    endif
432910f66f9SBram Moolenaarendfunction
433910f66f9SBram Moolenaar
434910f66f9SBram Moolenaarfunction! sqlcomplete#Map(type)
435910f66f9SBram Moolenaar    " Tell the SQL plugin what you want to complete
436910f66f9SBram Moolenaar    let b:sql_compl_type=a:type
437910f66f9SBram Moolenaar    " Record previous omnifunc, if the SQL completion
438910f66f9SBram Moolenaar    " is being used in conjunction with other filetype
439910f66f9SBram Moolenaar    " completion plugins
440910f66f9SBram Moolenaar    if &omnifunc != "" && &omnifunc != 'sqlcomplete#Complete'
441910f66f9SBram Moolenaar        " Record the previous omnifunc, the plugin
442910f66f9SBram Moolenaar        " will automatically set this back so that it
443910f66f9SBram Moolenaar        " does not interfere with other ftplugins settings
444910f66f9SBram Moolenaar        let b:sql_compl_savefunc=&omnifunc
445910f66f9SBram Moolenaar    endif
446910f66f9SBram Moolenaar    " Set the OMNI func for the SQL completion plugin
447910f66f9SBram Moolenaar    let &omnifunc='sqlcomplete#Complete'
448910f66f9SBram Moolenaarendfunction
449910f66f9SBram Moolenaar
450f193fffdSBram Moolenaarfunction! sqlcomplete#DrillIntoTable()
451f193fffdSBram Moolenaar    " If the omni popup window is visible
452f193fffdSBram Moolenaar    if pumvisible()
453f193fffdSBram Moolenaar        call sqlcomplete#Map('column')
454f193fffdSBram Moolenaar        " C-Y, makes the currently highlighted entry active
455f193fffdSBram Moolenaar        " and trigger the omni popup to be redisplayed
45600a927d6SBram Moolenaar        call feedkeys("\<C-Y>\<C-X>\<C-O>", 'n')
457f193fffdSBram Moolenaar    else
458f193fffdSBram Moolenaar	" If the popup is not visible, simple perform the normal
45900a927d6SBram Moolenaar	" key behaviour.
46000a927d6SBram Moolenaar	" Must use exec since they key must be preceeded by "\"
46100a927d6SBram Moolenaar	" or feedkeys will simply push each character of the string
46200a927d6SBram Moolenaar	" rather than the "key press".
46300a927d6SBram Moolenaar        exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_right.'", "n")'
464f193fffdSBram Moolenaar    endif
465f193fffdSBram Moolenaar    return ""
466f193fffdSBram Moolenaarendfunction
467f193fffdSBram Moolenaar
468f193fffdSBram Moolenaarfunction! sqlcomplete#DrillOutOfColumns()
469f193fffdSBram Moolenaar    " If the omni popup window is visible
470f193fffdSBram Moolenaar    if pumvisible()
471f193fffdSBram Moolenaar        call sqlcomplete#Map('tableReset')
472f193fffdSBram Moolenaar        " Trigger the omni popup to be redisplayed
473f193fffdSBram Moolenaar        call feedkeys("\<C-X>\<C-O>")
474f193fffdSBram Moolenaar    else
475f193fffdSBram Moolenaar	" If the popup is not visible, simple perform the normal
47600a927d6SBram Moolenaar	" key behaviour.
47700a927d6SBram Moolenaar	" Must use exec since they key must be preceeded by "\"
47800a927d6SBram Moolenaar	" or feedkeys will simply push each character of the string
47900a927d6SBram Moolenaar	" rather than the "key press".
48000a927d6SBram Moolenaar        exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_left.'", "n")'
481f193fffdSBram Moolenaar    endif
482f193fffdSBram Moolenaar    return ""
483f193fffdSBram Moolenaarendfunction
484f193fffdSBram Moolenaar
485f193fffdSBram Moolenaarfunction! s:SQLCWarningMsg(msg)
486f193fffdSBram Moolenaar    echohl WarningMsg
487*f9d5ca1dSBram Moolenaar    echomsg 'SQLComplete:'.a:msg
488f193fffdSBram Moolenaar    echohl None
489f193fffdSBram Moolenaarendfunction
490f193fffdSBram Moolenaar
491f193fffdSBram Moolenaarfunction! s:SQLCErrorMsg(msg)
492f193fffdSBram Moolenaar    echohl ErrorMsg
493*f9d5ca1dSBram Moolenaar    echomsg 'SQLComplete:'.a:msg
494f193fffdSBram Moolenaar    echohl None
495f193fffdSBram Moolenaarendfunction
496f193fffdSBram Moolenaar
497910f66f9SBram Moolenaarfunction! s:SQLCGetSyntaxList(syn_group)
498910f66f9SBram Moolenaar    let syn_group  = a:syn_group
499910f66f9SBram Moolenaar    let compl_list = []
500910f66f9SBram Moolenaar
501910f66f9SBram Moolenaar    " Check if we have already cached the syntax list
502910f66f9SBram Moolenaar    let list_idx = index(s:syn_list, syn_group, 0, &ignorecase)
503910f66f9SBram Moolenaar    if list_idx > -1
504910f66f9SBram Moolenaar        " Return previously cached value
505910f66f9SBram Moolenaar        let compl_list = s:syn_value[list_idx]
506910f66f9SBram Moolenaar    else
507910f66f9SBram Moolenaar        " Request the syntax list items from the
508910f66f9SBram Moolenaar        " syntax completion plugin
509910f66f9SBram Moolenaar        if syn_group == 'syntax'
510910f66f9SBram Moolenaar            " Handle this special case.  This allows the user
511910f66f9SBram Moolenaar            " to indicate they want all the syntax items available,
512910f66f9SBram Moolenaar            " so do not specify a specific include list.
513910f66f9SBram Moolenaar            let g:omni_syntax_group_include_sql = ''
514910f66f9SBram Moolenaar        else
515910f66f9SBram Moolenaar            " The user has specified a specific syntax group
516910f66f9SBram Moolenaar            let g:omni_syntax_group_include_sql = syn_group
517910f66f9SBram Moolenaar        endif
518910f66f9SBram Moolenaar        let g:omni_syntax_group_exclude_sql = ''
519*f9d5ca1dSBram Moolenaar        let syn_value                       = syntaxcomplete#OmniSyntaxList()
520910f66f9SBram Moolenaar        let g:omni_syntax_group_include_sql = s:save_inc
521910f66f9SBram Moolenaar        let g:omni_syntax_group_exclude_sql = s:save_exc
522910f66f9SBram Moolenaar        " Cache these values for later use
523910f66f9SBram Moolenaar        let s:syn_list  = add( s:syn_list,  syn_group )
524910f66f9SBram Moolenaar        let s:syn_value = add( s:syn_value, syn_value )
525910f66f9SBram Moolenaar        let compl_list  = syn_value
526910f66f9SBram Moolenaar    endif
527910f66f9SBram Moolenaar
528910f66f9SBram Moolenaar    return compl_list
529910f66f9SBram Moolenaarendfunction
530910f66f9SBram Moolenaar
531e2f98b95SBram Moolenaarfunction! s:SQLCCheck4dbext()
532e2f98b95SBram Moolenaar    if !exists('g:loaded_dbext')
533e2f98b95SBram Moolenaar        let msg = "The dbext plugin must be loaded for dynamic SQL completion"
534e2f98b95SBram Moolenaar        call s:SQLCErrorMsg(msg)
535e2f98b95SBram Moolenaar        " Leave time for the user to read the error message
536e2f98b95SBram Moolenaar        :sleep 2
537e2f98b95SBram Moolenaar        return -1
5388c8de839SBram Moolenaar    elseif g:loaded_dbext < 600
5398c8de839SBram Moolenaar        let msg = "The dbext plugin must be at least version 5.30 " .
540e2f98b95SBram Moolenaar                    \ " for dynamic SQL completion"
541e2f98b95SBram Moolenaar        call s:SQLCErrorMsg(msg)
542e2f98b95SBram Moolenaar        " Leave time for the user to read the error message
543e2f98b95SBram Moolenaar        :sleep 2
544e2f98b95SBram Moolenaar        return -1
545e2f98b95SBram Moolenaar    endif
546e2f98b95SBram Moolenaar    return 1
547e2f98b95SBram Moolenaarendfunction
548e2f98b95SBram Moolenaar
549e2f98b95SBram Moolenaarfunction! s:SQLCAddAlias(table_name, table_alias, cols)
550f193fffdSBram Moolenaar    " Strip off the owner if included
551f193fffdSBram Moolenaar    let table_name  = matchstr(a:table_name, '\%(.\{-}\.\)\?\zs\(.*\)' )
552e2f98b95SBram Moolenaar    let table_alias = a:table_alias
553e2f98b95SBram Moolenaar    let cols        = a:cols
554e2f98b95SBram Moolenaar
555e2f98b95SBram Moolenaar    if g:omni_sql_use_tbl_alias != 'n'
556e2f98b95SBram Moolenaar        if table_alias == ''
557e2f98b95SBram Moolenaar            if 'da' =~? g:omni_sql_use_tbl_alias
558e2f98b95SBram Moolenaar                if table_name =~ '_'
559e2f98b95SBram Moolenaar                    " Treat _ as separators since people often use these
560e2f98b95SBram Moolenaar                    " for word separators
561e2f98b95SBram Moolenaar                    let save_keyword = &iskeyword
562e2f98b95SBram Moolenaar                    setlocal iskeyword-=_
563e2f98b95SBram Moolenaar
564e2f98b95SBram Moolenaar                    " Get the first letter of each word
565e2f98b95SBram Moolenaar                    " [[:alpha:]] is used instead of \w
566e2f98b95SBram Moolenaar                    " to catch extended accented characters
567e2f98b95SBram Moolenaar                    "
568e2f98b95SBram Moolenaar                    let table_alias = substitute(
569e2f98b95SBram Moolenaar                                \ table_name,
570e2f98b95SBram Moolenaar                                \ '\<[[:alpha:]]\+\>_\?',
571e2f98b95SBram Moolenaar                                \ '\=strpart(submatch(0), 0, 1)',
572e2f98b95SBram Moolenaar                                \ 'g'
573e2f98b95SBram Moolenaar                                \ )
574e2f98b95SBram Moolenaar                    " Restore original value
575e2f98b95SBram Moolenaar                    let &iskeyword = save_keyword
576e2f98b95SBram Moolenaar                elseif table_name =~ '\u\U'
577f193fffdSBram Moolenaar                    let table_alias = substitute(
578e2f98b95SBram Moolenaar                                \ table_name, '\(\u\)\U*', '\1', 'g')
579e2f98b95SBram Moolenaar                else
580e2f98b95SBram Moolenaar                    let table_alias = strpart(table_name, 0, 1)
581e2f98b95SBram Moolenaar                endif
582e2f98b95SBram Moolenaar            endif
583e2f98b95SBram Moolenaar        endif
584e2f98b95SBram Moolenaar        if table_alias != ''
585e2f98b95SBram Moolenaar            " Following a word character, make sure there is a . and no spaces
586e2f98b95SBram Moolenaar            let table_alias = substitute(table_alias, '\w\zs\.\?\s*$', '.', '')
587e2f98b95SBram Moolenaar            if 'a' =~? g:omni_sql_use_tbl_alias && a:table_alias == ''
588e2f98b95SBram Moolenaar                let table_alias = inputdialog("Enter table alias:", table_alias)
589e2f98b95SBram Moolenaar            endif
590e2f98b95SBram Moolenaar        endif
591e2f98b95SBram Moolenaar        if table_alias != ''
592e2f98b95SBram Moolenaar            let cols = substitute(cols, '\<\w', table_alias.'&', 'g')
593e2f98b95SBram Moolenaar        endif
594e2f98b95SBram Moolenaar    endif
595e2f98b95SBram Moolenaar
596e2f98b95SBram Moolenaar    return cols
597e2f98b95SBram Moolenaarendfunction
598e2f98b95SBram Moolenaar
59983e138c6SBram Moolenaarfunction! s:SQLCGetObjectOwner(object)
60083e138c6SBram Moolenaar    " The owner regex matches a word at the start of the string which is
60183e138c6SBram Moolenaar    " followed by a dot, but doesn't include the dot in the result.
60283e138c6SBram Moolenaar    " ^           - from beginning of line
6038c8de839SBram Moolenaar    " \("\|\[\)\? - ignore any quotes
60483e138c6SBram Moolenaar    " \zs         - start the match now
6058c8de839SBram Moolenaar    " .\{-}       - get owner name
60683e138c6SBram Moolenaar    " \ze         - end the match
6078c8de839SBram Moolenaar    " \("\|\[\)\? - ignore any quotes
60883e138c6SBram Moolenaar    " \.          - must by followed by a .
6098c8de839SBram Moolenaar    " let owner = matchstr( a:object, '^\s*\zs.*\ze\.' )
6108c8de839SBram Moolenaar    let owner = matchstr( a:object, '^\("\|\[\)\?\zs\.\{-}\ze\("\|\]\)\?\.' )
61183e138c6SBram Moolenaar    return owner
61283e138c6SBram Moolenaarendfunction
61383e138c6SBram Moolenaar
614e2f98b95SBram Moolenaarfunction! s:SQLCGetColumns(table_name, list_type)
61583e138c6SBram Moolenaar    " Check if the table name was provided as part of the column name
6168c8de839SBram Moolenaar    let table_name   = matchstr(a:table_name, '^["\[\]a-zA-Z0-9_ ]\+\ze\.\?')
617e2f98b95SBram Moolenaar    let table_cols   = []
618e2f98b95SBram Moolenaar    let table_alias  = ''
619e2f98b95SBram Moolenaar    let move_to_top  = 1
620e2f98b95SBram Moolenaar
6218c8de839SBram Moolenaar    let table_name   = substitute(table_name, '\s*\(.\{-}\)\s*$', '\1', 'g')
6228c8de839SBram Moolenaar
6238c8de839SBram Moolenaar    " If the table name was given as:
6248c8de839SBram Moolenaar    "     where c.
6258c8de839SBram Moolenaar    let table_name   = substitute(table_name, '^\c\(WHERE\|AND\|OR\)\s\+', '', '')
626eb3593b3SBram Moolenaar    if g:loaded_dbext >= 300
627e2f98b95SBram Moolenaar        let saveSettingAlias = DB_listOption('use_tbl_alias')
628e2f98b95SBram Moolenaar        exec 'DBSetOption use_tbl_alias=n'
629e2f98b95SBram Moolenaar    endif
630e2f98b95SBram Moolenaar
6318c8de839SBram Moolenaar    let table_name_stripped = substitute(table_name, '["\[\]]*', '', 'g')
6328c8de839SBram Moolenaar
633e2f98b95SBram Moolenaar    " Check if we have already cached the column list for this table
634e2f98b95SBram Moolenaar    " by its name
6358c8de839SBram Moolenaar    let list_idx = index(s:tbl_name, table_name_stripped, 0, &ignorecase)
636e2f98b95SBram Moolenaar    if list_idx > -1
6378c8de839SBram Moolenaar        let table_cols = split(s:tbl_cols[list_idx], '\n')
638e2f98b95SBram Moolenaar    else
639e2f98b95SBram Moolenaar        " Check if we have already cached the column list for this table
640e2f98b95SBram Moolenaar        " by its alias, assuming the table_name provided was actually
641e2f98b95SBram Moolenaar        " the alias for the table instead
642e2f98b95SBram Moolenaar        "     select *
643e2f98b95SBram Moolenaar        "       from area a
644e2f98b95SBram Moolenaar        "      where a.
6458c8de839SBram Moolenaar        let list_idx = index(s:tbl_alias, table_name_stripped, 0, &ignorecase)
646e2f98b95SBram Moolenaar        if list_idx > -1
6478c8de839SBram Moolenaar            let table_alias = table_name_stripped
648e2f98b95SBram Moolenaar            let table_name  = s:tbl_name[list_idx]
6498c8de839SBram Moolenaar            let table_cols  = split(s:tbl_cols[list_idx], '\n')
650e2f98b95SBram Moolenaar        endif
651e2f98b95SBram Moolenaar    endif
652e2f98b95SBram Moolenaar
653e2f98b95SBram Moolenaar    " If we have not found a cached copy of the table
654e2f98b95SBram Moolenaar    " And the table ends in a "." or we are looking for a column list
655e2f98b95SBram Moolenaar    " if list_idx == -1 && (a:table_name =~ '\.' || b:sql_compl_type =~ 'column')
656e2f98b95SBram Moolenaar    " if list_idx == -1 && (a:table_name =~ '\.' || a:list_type =~ 'csv')
657e2f98b95SBram Moolenaar    if list_idx == -1
658e2f98b95SBram Moolenaar         let saveY      = @y
659e2f98b95SBram Moolenaar         let saveSearch = @/
660e2f98b95SBram Moolenaar         let saveWScan  = &wrapscan
661e2f98b95SBram Moolenaar         let curline    = line(".")
662e2f98b95SBram Moolenaar         let curcol     = col(".")
663e2f98b95SBram Moolenaar
664e2f98b95SBram Moolenaar         " Do not let searchs wrap
665e2f98b95SBram Moolenaar         setlocal nowrapscan
666e2f98b95SBram Moolenaar         " If . was entered, look at the word just before the .
667e2f98b95SBram Moolenaar         " We are looking for something like this:
668e2f98b95SBram Moolenaar         "    select *
669e2f98b95SBram Moolenaar         "      from customer c
670e2f98b95SBram Moolenaar         "     where c.
671e2f98b95SBram Moolenaar         " So when . is pressed, we need to find 'c'
672e2f98b95SBram Moolenaar         "
673e2f98b95SBram Moolenaar
674e2f98b95SBram Moolenaar         " Search backwards to the beginning of the statement
675e2f98b95SBram Moolenaar         " and do NOT wrap
676e2f98b95SBram Moolenaar         " exec 'silent! normal! v?\<\(select\|update\|delete\|;\)\>'."\n".'"yy'
67700a927d6SBram Moolenaar         exec 'silent! normal! ?\<\c\(select\|update\|delete\|;\)\>'."\n"
678e2f98b95SBram Moolenaar
679e2f98b95SBram Moolenaar         " Start characterwise visual mode
680e2f98b95SBram Moolenaar         " Advance right one character
681e2f98b95SBram Moolenaar         " Search foward until one of the following:
682e2f98b95SBram Moolenaar         "     1.  Another select/update/delete statement
683e2f98b95SBram Moolenaar         "     2.  A ; at the end of a line (the delimiter)
684e2f98b95SBram Moolenaar         "     3.  The end of the file (incase no delimiter)
685e2f98b95SBram Moolenaar         " Yank the visually selected text into the "y register.
68600a927d6SBram Moolenaar         exec 'silent! normal! vl/\c\(\<select\>\|\<update\>\|\<delete\>\|;\s*$\|\%$\)'."\n".'"yy'
687e2f98b95SBram Moolenaar
688e2f98b95SBram Moolenaar         let query = @y
689e2f98b95SBram Moolenaar         let query = substitute(query, "\n", ' ', 'g')
690e2f98b95SBram Moolenaar         let found = 0
691e2f98b95SBram Moolenaar
69200a927d6SBram Moolenaar         " if query =~? '^\c\(select\)'
69300a927d6SBram Moolenaar         if query =~? '^\(select\|update\|delete\)'
694e2f98b95SBram Moolenaar             let found = 1
695e2f98b95SBram Moolenaar             "  \(\(\<\w\+\>\)\.\)\?   -
69600a927d6SBram Moolenaar             " '\c\(from\|join\|,\).\{-}'  - Starting at the from clause (case insensitive)
697e2f98b95SBram Moolenaar             " '\zs\(\(\<\w\+\>\)\.\)\?' - Get the owner name (optional)
698e2f98b95SBram Moolenaar             " '\<\w\+\>\ze' - Get the table name
699e2f98b95SBram Moolenaar             " '\s\+\<'.table_name.'\>' - Followed by the alias
700e2f98b95SBram Moolenaar             " '\s*\.\@!.*'  - Cannot be followed by a .
701e2f98b95SBram Moolenaar             " '\(\<where\>\|$\)' - Must be followed by a WHERE clause
702e2f98b95SBram Moolenaar             " '.*'  - Exclude the rest of the line in the match
70300a927d6SBram Moolenaar             " let table_name_new = matchstr(@y,
70400a927d6SBram Moolenaar             "             \ '\c\(from\|join\|,\).\{-}'.
70500a927d6SBram Moolenaar             "             \ '\zs\(\("\|\[\)\?.\{-}\("\|\]\)\.\)\?'.
70600a927d6SBram Moolenaar             "             \ '\("\|\[\)\?.\{-}\("\|\]\)\?\ze'.
70700a927d6SBram Moolenaar             "             \ '\s\+\%(as\s\+\)\?\<'.
70800a927d6SBram Moolenaar             "             \ matchstr(table_name, '.\{-}\ze\.\?$').
70900a927d6SBram Moolenaar             "             \ '\>'.
71000a927d6SBram Moolenaar             "             \ '\s*\.\@!.*'.
71100a927d6SBram Moolenaar             "             \ '\(\<where\>\|$\)'.
71200a927d6SBram Moolenaar             "             \ '.*'
71300a927d6SBram Moolenaar             "             \ )
714e2f98b95SBram Moolenaar             let table_name_new = matchstr(@y,
71500a927d6SBram Moolenaar                         \ '\c\(\<from\>\|\<join\>\|,\)\s*'.
71600a927d6SBram Moolenaar                         \ '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?'.
71700a927d6SBram Moolenaar                         \ '\("\|\[\)\?\w\+\("\|\]\)\?\ze'.
718f193fffdSBram Moolenaar                         \ '\s\+\%(as\s\+\)\?\<'.
719f193fffdSBram Moolenaar                         \ matchstr(table_name, '.\{-}\ze\.\?$').
720f193fffdSBram Moolenaar                         \ '\>'.
721e2f98b95SBram Moolenaar                         \ '\s*\.\@!.*'.
722e2f98b95SBram Moolenaar                         \ '\(\<where\>\|$\)'.
723e2f98b95SBram Moolenaar                         \ '.*'
724e2f98b95SBram Moolenaar                         \ )
7258c8de839SBram Moolenaar
726e2f98b95SBram Moolenaar             if table_name_new != ''
727e2f98b95SBram Moolenaar                 let table_alias = table_name
72800a927d6SBram Moolenaar                 let table_name  = matchstr( table_name_new, '^\(.*\.\)\?\zs.*\ze' )
729e2f98b95SBram Moolenaar
730e2f98b95SBram Moolenaar                 let list_idx = index(s:tbl_name, table_name, 0, &ignorecase)
731e2f98b95SBram Moolenaar                 if list_idx > -1
732e2f98b95SBram Moolenaar                     let table_cols  = split(s:tbl_cols[list_idx])
733e2f98b95SBram Moolenaar                     let s:tbl_name[list_idx]  = table_name
734e2f98b95SBram Moolenaar                     let s:tbl_alias[list_idx] = table_alias
735e2f98b95SBram Moolenaar                 else
736e2f98b95SBram Moolenaar                     let list_idx = index(s:tbl_alias, table_name, 0, &ignorecase)
737e2f98b95SBram Moolenaar                     if list_idx > -1
738e2f98b95SBram Moolenaar                         let table_cols = split(s:tbl_cols[list_idx])
739e2f98b95SBram Moolenaar                         let s:tbl_name[list_idx]  = table_name
740e2f98b95SBram Moolenaar                         let s:tbl_alias[list_idx] = table_alias
741e2f98b95SBram Moolenaar                     endif
742e2f98b95SBram Moolenaar                 endif
743e2f98b95SBram Moolenaar
744e2f98b95SBram Moolenaar             endif
745e2f98b95SBram Moolenaar         else
746e2f98b95SBram Moolenaar             " Simply assume it is a table name provided with a . on the end
747e2f98b95SBram Moolenaar             let found = 1
748e2f98b95SBram Moolenaar         endif
749e2f98b95SBram Moolenaar
750e2f98b95SBram Moolenaar         let @y        = saveY
751e2f98b95SBram Moolenaar         let @/        = saveSearch
752e2f98b95SBram Moolenaar         let &wrapscan = saveWScan
753e2f98b95SBram Moolenaar
754e2f98b95SBram Moolenaar         " Return to previous location
755e2f98b95SBram Moolenaar         call cursor(curline, curcol)
756e2f98b95SBram Moolenaar
757e2f98b95SBram Moolenaar         if found == 0
758eb3593b3SBram Moolenaar             if g:loaded_dbext > 300
759e2f98b95SBram Moolenaar                 exec 'DBSetOption use_tbl_alias='.saveSettingAlias
760e2f98b95SBram Moolenaar             endif
761e2f98b95SBram Moolenaar
762e2f98b95SBram Moolenaar             " Not a SQL statement, do not display a list
763e2f98b95SBram Moolenaar             return []
764e2f98b95SBram Moolenaar         endif
765e2f98b95SBram Moolenaar    endif
766e2f98b95SBram Moolenaar
767e2f98b95SBram Moolenaar    if empty(table_cols)
768e2f98b95SBram Moolenaar        " Specify silent mode, no messages to the user (tbl, 1)
769e2f98b95SBram Moolenaar        " Specify do not comma separate (tbl, 1, 1)
770e2f98b95SBram Moolenaar        let table_cols_str = DB_getListColumn(table_name, 1, 1)
771e2f98b95SBram Moolenaar
772e2f98b95SBram Moolenaar        if table_cols_str != ""
773e2f98b95SBram Moolenaar            let s:tbl_name  = add( s:tbl_name,  table_name )
774e2f98b95SBram Moolenaar            let s:tbl_alias = add( s:tbl_alias, table_alias )
775e2f98b95SBram Moolenaar            let s:tbl_cols  = add( s:tbl_cols,  table_cols_str )
7768c8de839SBram Moolenaar            let table_cols  = split(table_cols_str, '\n')
777e2f98b95SBram Moolenaar        endif
778e2f98b95SBram Moolenaar
779e2f98b95SBram Moolenaar    endif
780e2f98b95SBram Moolenaar
781eb3593b3SBram Moolenaar    if g:loaded_dbext > 300
782e2f98b95SBram Moolenaar        exec 'DBSetOption use_tbl_alias='.saveSettingAlias
783e2f98b95SBram Moolenaar    endif
784e2f98b95SBram Moolenaar
785f193fffdSBram Moolenaar    " If the user has asked for a comma separate list of column
786f193fffdSBram Moolenaar    " values, ask the user if they want to prepend each column
787f193fffdSBram Moolenaar    " with a tablename alias.
788e2f98b95SBram Moolenaar    if a:list_type == 'csv' && !empty(table_cols)
789e2f98b95SBram Moolenaar        let cols       = join(table_cols, ', ')
790e2f98b95SBram Moolenaar        let cols       = s:SQLCAddAlias(table_name, table_alias, cols)
791e2f98b95SBram Moolenaar        let table_cols = [cols]
792e2f98b95SBram Moolenaar    endif
793e2f98b95SBram Moolenaar
794e2f98b95SBram Moolenaar    return table_cols
795e2f98b95SBram Moolenaarendfunction
796