blob: ef5ce2e6e21ea1a58e8aa0c375e3622d87cb2409 [file] [log] [blame]
Bram Moolenaarf193fff2006-04-27 00:02:13 +00001" Vim OMNI completion script for SQL
Bram Moolenaare2f98b92006-03-29 21:18:24 +00002" Language: SQL
Bram Moolenaar5c736222010-01-06 20:54:52 +01003" Maintainer: David Fishburn <dfishburn dot vim at gmail dot com>
Bram Moolenaar5e9b2fa2016-02-01 22:37:05 +01004" Version: 16.0
Bram Moolenaar01164a62017-11-02 22:58:42 +01005" Last Change: 2017 Oct 15
Bram Moolenaar34feacb2012-12-05 19:01:43 +01006" Homepage: http://www.vim.org/scripts/script.php?script_id=1572
Bram Moolenaarf193fff2006-04-27 00:02:13 +00007" Usage: For detailed help
Bram Moolenaardb7207e2012-02-22 17:30:19 +01008" ":help sql.txt"
9" or ":help ft-sql-omni"
Bram Moolenaarf193fff2006-04-27 00:02:13 +000010" or read $VIMRUNTIME/doc/sql.txt
Bram Moolenaare2f98b92006-03-29 21:18:24 +000011
Bram Moolenaar5c736222010-01-06 20:54:52 +010012" History
Bram Moolenaar34feacb2012-12-05 19:01:43 +010013"
Bram Moolenaarad3b3662013-05-17 18:14:19 +020014" TODO
15" - Jonas Enberg - if no table is found when using column completion
16" look backwards to a FROM clause and find the first table
17" and complete it.
18"
Bram Moolenaar5e9b2fa2016-02-01 22:37:05 +010019" Version 16.0 (Dec 2015)
20" - NF: If reseting the cache and table, procedure or view completion
21" had been used via dbext, have dbext delete or recreate the
22" dictionary so that new objects are picked up for the
23" next completion.
24"
Bram Moolenaarad3b3662013-05-17 18:14:19 +020025" Version 15.0 (May 2013)
26" - NF: Changed the SQL precached syntax items, omni_sql_precache_syntax_groups,
27" to use regular expressions to pick up extended syntax group names.
28" This requires an updated SyntaxComplete plugin version 13.0.
29" If the required versions have not been installed, previous
30" behaviour will not be impacted.
31"
Bram Moolenaar34feacb2012-12-05 19:01:43 +010032" Version 14.0 (Dec 2012)
33" - BF: Added check for cpo
34"
35" Version 13.0 (Dec 2012)
36" - NF: When completing column lists or drilling into a table
37" and g:omni_sql_include_owner is enabled, the
38" only the table name would be replaced with the column
39" list instead of the table name and owner (if specified).
40" - NF: When completing column lists using table aliases
41" and g:omni_sql_include_owner is enabled, account
42" for the owner name when looking up the table
43" list instead of the table name and owner (if specified).
44" - BF: When completing column lists or drilling into a table
45" and g:omni_sql_include_owner is enabled, the
46" column list could often not be found for the table.
47" - BF: When OMNI popped up, possibly the wrong word
48" would be replaced for column and column list options.
49"
50" Version 12.0 (Feb 2012)
Bram Moolenaardb7207e2012-02-22 17:30:19 +010051" - Partial column name completion did not work when a table
52" name or table alias was provided (Jonas Enberg).
53" - Improved the handling of column completion. First we match any
54" columns from a previous completion. If not matches are found, we
Bram Moolenaar34feacb2012-12-05 19:01:43 +010055" consider the partial name to be a table or table alias for the
Bram Moolenaardb7207e2012-02-22 17:30:19 +010056" query and attempt to match on it.
57"
Bram Moolenaar34feacb2012-12-05 19:01:43 +010058" Version 11.0 (Jan 2012)
Bram Moolenaardb7207e2012-02-22 17:30:19 +010059" Added g:omni_sql_default_compl_type variable
60" - You can specify which type of completion to default to
61" when pressing <C-X><C-O>. The entire list of available
62" choices can be found in the calls to sqlcomplete#Map in:
63" ftplugin/sql.vim
64"
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020065" Version 10.0
Bram Moolenaardb7207e2012-02-22 17:30:19 +010066" Updated PreCacheSyntax()
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020067" - Now returns a List of the syntax items it finds.
68" This allows other plugins / scripts to use this list for their own
69" purposes. In this case XPTemplate can use them for a Choose list.
70" - Verifies the parameters are the correct type and displays a
71" warning if not.
72" - Verifies the parameters are the correct type and displays a
73" warning if not.
Bram Moolenaardb7207e2012-02-22 17:30:19 +010074" Updated SQLCWarningMsg()
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020075" - Prepends warning message with SQLComplete so you know who issued
76" the warning.
Bram Moolenaardb7207e2012-02-22 17:30:19 +010077" Updated SQLCErrorMsg()
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020078" - Prepends error message with SQLComplete so you know who issued
79" the error.
Bram Moolenaardb7207e2012-02-22 17:30:19 +010080"
Bram Moolenaar34feacb2012-12-05 19:01:43 +010081" Version 9.0 (May 2010)
Bram Moolenaar00a927d2010-05-14 23:24:24 +020082" This change removes some of the support for tables with spaces in their
Bram Moolenaardb7207e2012-02-22 17:30:19 +010083" names in order to simplify the regexes used to pull out query table
Bram Moolenaar00a927d2010-05-14 23:24:24 +020084" aliases for more robust table name and column name code completion.
85" Full support for "table names with spaces" can be added in again
86" after 7.3.
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020087"
Bram Moolenaar00a927d2010-05-14 23:24:24 +020088" Version 8.0
Bram Moolenaardb7207e2012-02-22 17:30:19 +010089" Incorrectly re-executed the g:ftplugin_sql_omni_key_right and g:ftplugin_sql_omni_key_left
Bram Moolenaar00a927d2010-05-14 23:24:24 +020090" when drilling in and out of a column list for a table.
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020091"
Bram Moolenaar34feacb2012-12-05 19:01:43 +010092" Version 7.0 (Jan 2010)
Bram Moolenaar5c736222010-01-06 20:54:52 +010093" Better handling of object names
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020094"
Bram Moolenaar34feacb2012-12-05 19:01:43 +010095" Version 6.0 (Apr 2008)
Bram Moolenaar5c736222010-01-06 20:54:52 +010096" Supports object names with spaces "my table name"
97"
Bram Moolenaare2f98b92006-03-29 21:18:24 +000098" Set completion with CTRL-X CTRL-O to autoloaded function.
99" This check is in place in case this script is
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100100" sourced directly instead of using the autoload feature.
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000101if exists('&omnifunc')
102 " Do not set the option if already set since this
103 " results in an E117 warning.
104 if &omnifunc == ""
105 setlocal omnifunc=sqlcomplete#Complete
106 endif
107endif
108
109if exists('g:loaded_sql_completion')
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100110 finish
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000111endif
Bram Moolenaar5e9b2fa2016-02-01 22:37:05 +0100112let g:loaded_sql_completion = 160
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100113let s:keepcpo= &cpo
114set cpo&vim
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000115
116" Maintains filename of dictionary
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000117let s:sql_file_table = ""
118let s:sql_file_procedure = ""
119let s:sql_file_view = ""
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000120
121" Define various arrays to be used for caching
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000122let s:tbl_name = []
123let s:tbl_alias = []
124let s:tbl_cols = []
125let s:syn_list = []
126let s:syn_value = []
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100127
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000128" Used in conjunction with the syntaxcomplete plugin
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000129let s:save_inc = ""
130let s:save_exc = ""
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200131if !exists('g:omni_syntax_group_include_sql')
132 let g:omni_syntax_group_include_sql = ''
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000133endif
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200134if !exists('g:omni_syntax_group_exclude_sql')
135 let g:omni_syntax_group_exclude_sql = ''
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000136endif
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200137let s:save_inc = g:omni_syntax_group_include_sql
138let s:save_exc = g:omni_syntax_group_exclude_sql
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100139
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000140" Used with the column list
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000141let s:save_prev_table = ""
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000142
143" Default the option to verify table alias
144if !exists('g:omni_sql_use_tbl_alias')
145 let g:omni_sql_use_tbl_alias = 'a'
146endif
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000147" Default syntax items to precache
148if !exists('g:omni_sql_precache_syntax_groups')
149 let g:omni_sql_precache_syntax_groups = [
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200150 \ 'syntax\w*',
151 \ 'sqlKeyword\w*',
152 \ 'sqlFunction\w*',
153 \ 'sqlOption\w*',
154 \ 'sqlType\w*',
155 \ 'sqlStatement\w*'
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000156 \ ]
157endif
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000158" Set ignorecase to the ftplugin standard
159if !exists('g:omni_sql_ignorecase')
160 let g:omni_sql_ignorecase = &ignorecase
161endif
162" During table completion, should the table list also
163" include the owner name
164if !exists('g:omni_sql_include_owner')
165 let g:omni_sql_include_owner = 0
166 if exists('g:loaded_dbext')
167 if g:loaded_dbext >= 300
168 " New to dbext 3.00, by default the table lists include the owner
169 " name of the table. This is used when determining how much of
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100170 " whatever has been typed should be replaced as part of the
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000171 " code replacement.
172 let g:omni_sql_include_owner = 1
173 endif
174 endif
175endif
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100176" Default type of completion used when <C-X><C-O> is pressed
177if !exists('g:omni_sql_default_compl_type')
178 let g:omni_sql_default_compl_type = 'table'
179endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000180
181" This function is used for the 'omnifunc' option.
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100182" It is called twice by omni and it is responsible
183" for returning the completion list of items.
184" But it must also determine context of what to complete
185" and what to "replace" with the completion.
186" The a:base, is replaced directly with what the user
187" chooses from the choices.
188" The s:prepend provides context for the completion.
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000189function! sqlcomplete#Complete(findstart, base)
190
191 " Default to table name completion
192 let compl_type = 'table'
193 " Allow maps to specify what type of object completion they want
194 if exists('b:sql_compl_type')
195 let compl_type = b:sql_compl_type
196 endif
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100197 let begindot = 0
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000198
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000199 " First pass through this function determines how much of the line should
200 " be replaced by whatever is chosen from the completion list
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000201 if a:findstart
202 " Locate the start of the item, including "."
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000203 let line = getline('.')
204 let start = col('.') - 1
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000205 let lastword = -1
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000206 " Check if the first character is a ".", for column completion
207 if line[start - 1] == '.'
208 let begindot = 1
209 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000210 while start > 0
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100211 " Additional code was required to handle objects which
Bram Moolenaar5c736222010-01-06 20:54:52 +0100212 " can contain spaces like "my table name".
213 if line[start - 1] !~ '\(\w\|\.\)'
214 " If the previous character is not a period or word character
215 break
216 " elseif line[start - 1] =~ '\(\w\|\s\+\)'
217 " let start -= 1
218 elseif line[start - 1] =~ '\w'
219 " If the previous character is word character continue back
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000220 let start -= 1
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100221 elseif line[start - 1] =~ '\.' &&
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000222 \ compl_type =~ 'column\|table\|view\|procedure'
Bram Moolenaar5c736222010-01-06 20:54:52 +0100223 " If the previous character is a period and we are completing
224 " an object which can be specified with a period like this:
225 " table_name.column_name
226 " owner_name.table_name
227
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000228 " If lastword has already been set for column completion
229 " break from the loop, since we do not also want to pickup
230 " a table name if it was also supplied.
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100231 " Unless g:omni_sql_include_owner == 1, then we can
232 " include the ownername.
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100233 if lastword != -1 && compl_type == 'column'
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100234 \ && g:omni_sql_include_owner == 0
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000235 break
236 endif
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000237 " If column completion was specified stop at the "." if
238 " a . was specified, otherwise, replace all the way up
239 " to the owner name (if included).
240 if lastword == -1 && compl_type == 'column' && begindot == 1
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000241 let lastword = start
242 endif
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000243 " If omni_sql_include_owner = 0, do not include the table
244 " name as part of the substitution, so break here
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100245 if lastword == -1 &&
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100246 \ compl_type =~ '\<\(table\|view\|procedure\|column\|column_csv\)\>' &&
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000247 \ g:omni_sql_include_owner == 0
248 let lastword = start
249 break
250 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000251 let start -= 1
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000252 else
253 break
254 endif
255 endwhile
256
257 " Return the column of the last word, which is going to be changed.
258 " Remember the text that comes before it in s:prepended.
259 if lastword == -1
260 let s:prepended = ''
261 return start
262 endif
263 let s:prepended = strpart(line, start, lastword - start)
264 return lastword
265 endif
266
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000267 " Second pass through this function will determine what data to put inside
268 " of the completion list
269 " s:prepended is set by the first pass
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000270 let base = s:prepended . a:base
271
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000272 " Default the completion list to an empty list
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000273 let compl_list = []
274
275 " Default to table name completion
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100276 let compl_type = g:omni_sql_default_compl_type
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000277 " Allow maps to specify what type of object completion they want
278 if exists('b:sql_compl_type')
279 let compl_type = b:sql_compl_type
280 unlet b:sql_compl_type
281 endif
282
283 if compl_type == 'tableReset'
284 let compl_type = 'table'
285 let base = ''
286 endif
287
288 if compl_type == 'table' ||
289 \ compl_type == 'procedure' ||
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100290 \ compl_type == 'view'
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000291
292 " This type of completion relies upon the dbext.vim plugin
293 if s:SQLCCheck4dbext() == -1
294 return []
295 endif
296
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000297 " Allow the user to override the dbext plugin to specify whether
298 " the owner/creator should be included in the list
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000299 if g:loaded_dbext >= 300
300 let saveSetting = DB_listOption('dict_show_owner')
301 exec 'DBSetOption dict_show_owner='.(g:omni_sql_include_owner==1?'1':'0')
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000302 endif
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000303
304 let compl_type_uc = substitute(compl_type, '\w\+', '\u&', '')
Bram Moolenaar5c736222010-01-06 20:54:52 +0100305 " Same call below, no need to do it twice
306 " if s:sql_file_{compl_type} == ""
307 " let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc)
308 " endif
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000309 let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000310 if s:sql_file_{compl_type} != ""
311 if filereadable(s:sql_file_{compl_type})
312 let compl_list = readfile(s:sql_file_{compl_type})
313 endif
314 endif
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000315
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000316 if g:loaded_dbext > 300
317 exec 'DBSetOption dict_show_owner='.saveSetting
318 endif
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000319 elseif compl_type =~? 'column'
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000320
321 " This type of completion relies upon the dbext.vim plugin
322 if s:SQLCCheck4dbext() == -1
323 return []
324 endif
325
326 if base == ""
327 " The last time we displayed a column list we stored
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100328 " the table name. If the user selects a column list
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000329 " without a table name of alias present, assume they want
330 " the previous column list displayed.
331 let base = s:save_prev_table
332 endif
333
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000334 let owner = ''
335 let column = ''
336
337 if base =~ '\.'
338 " Check if the owner/creator has been specified
339 let owner = matchstr( base, '^\zs.*\ze\..*\..*' )
340 let table = matchstr( base, '^\(.*\.\)\?\zs.*\ze\..*' )
341 let column = matchstr( base, '.*\.\zs.*' )
342
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100343 if g:omni_sql_include_owner == 1 && owner == '' && table != '' && column != ''
344 let owner = table
345 let table = column
346 let column = ''
347 endif
348
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000349 " It is pretty well impossible to determine if the user
350 " has entered:
351 " owner.table
352 " table.column_prefix
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100353 " So there are a couple of things we can do to mitigate
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000354 " this issue.
355 " 1. Check if the dbext plugin has the option turned
356 " on to even allow owners
357 " 2. Based on 1, if the user is showing a table list
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100358 " and the DrillIntoTable (using <Right>) then
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000359 " this will be owner.table. In this case, we can
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100360 " check to see the table.column exists in the
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000361 " cached table list. If it does, then we have
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100362 " determined the user has actually chosen
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000363 " owner.table, not table.column_prefix.
364 let found = -1
365 if g:omni_sql_include_owner == 1 && owner == ''
366 if filereadable(s:sql_file_table)
367 let tbl_list = readfile(s:sql_file_table)
368 let found = index( tbl_list, ((table != '')?(table.'.'):'').column)
369 endif
370 endif
371 " If the table.column was found in the table list, we can safely assume
372 " the owner was not provided and shift the items appropriately.
373 " OR
374 " If the user has indicated not to use table owners at all and
375 " the base ends in a '.' we know they are not providing a column
376 " name, so we can shift the items appropriately.
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100377 " if found != -1 || (g:omni_sql_include_owner == 0 && base !~ '\.$')
378 " let owner = table
379 " let table = column
380 " let column = ''
381 " endif
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000382 else
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100383 " If no "." was provided and the user asked for
384 " column level completion, first attempt the match
385 " on any previous column lists. If the user asked
386 " for a list of columns comma separated, continue as usual.
387 if compl_type == 'column' && s:save_prev_table != ''
388 " The last time we displayed a column list we stored
389 " the table name. If the user selects a column list
390 " without a table name of alias present, assume they want
391 " the previous column list displayed.
392 let table = s:save_prev_table
393 let list_type = ''
394
395 let compl_list = s:SQLCGetColumns(table, list_type)
396 if ! empty(compl_list)
397 " If no column prefix has been provided and the table
398 " name was provided, append it to each of the items
399 " returned.
400 let compl_list = filter(deepcopy(compl_list), 'v:val=~"^'.base.'"' )
401
402 " If not empty, we have a match on columns
403 " return the list
404 if ! empty(compl_list)
405 return compl_list
406 endif
407 endif
408 endif
409 " Since no columns were found to match the base supplied
410 " assume the user is trying to complete the column list
411 " for a table (and or an alias to a table).
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000412 let table = base
413 endif
414
415 " Get anything after the . and consider this the table name
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100416 " If an owner has been specified, then we must consider the
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000417 " base to be a partial column name
418 " let base = matchstr( base, '^\(.*\.\)\?\zs.*' )
419
420 if table != ""
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000421 let s:save_prev_table = base
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000422 let list_type = ''
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000423
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000424 if compl_type == 'column_csv'
425 " Return one array element, with a comma separated
426 " list of values instead of multiple array entries
427 " for each column in the table.
428 let list_type = 'csv'
429 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000430
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100431 " If we are including the OWNER for the objects, then for
432 " table completion, if we have it, it should be included
433 " as there can be the same table names in a database yet
434 " with different owner names.
435 if g:omni_sql_include_owner == 1 && owner != '' && table != ''
436 let compl_list = s:SQLCGetColumns(owner.'.'.table, list_type)
437 else
438 let compl_list = s:SQLCGetColumns(table, list_type)
439 endif
440
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000441 if column != ''
442 " If no column prefix has been provided and the table
443 " name was provided, append it to each of the items
444 " returned.
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100445 let compl_list = map(compl_list, 'table.".".v:val')
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000446 if owner != ''
447 " If an owner has been provided append it to each of the
448 " items returned.
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100449 let compl_list = map(compl_list, 'owner.".".v:val')
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000450 endif
451 else
452 let base = ''
453 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000454
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000455 if compl_type == 'column_csv'
456 " Join the column array into 1 single element array
457 " but make the columns column separated
458 let compl_list = [join(compl_list, ', ')]
459 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000460 endif
461 elseif compl_type == 'resetCache'
462 " Reset all cached items
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100463 let s:tbl_name = []
464 let s:tbl_alias = []
465 let s:tbl_cols = []
466 let s:syn_list = []
467 let s:syn_value = []
Bram Moolenaar5e9b2fa2016-02-01 22:37:05 +0100468
469 if s:sql_file_table != ""
470 if g:loaded_dbext >= 2300
471 call DB_DictionaryDelete("table")
472 else
473 DBCompleteTables!
474 endif
475 endif
476 if s:sql_file_procedure != ""
477 if g:loaded_dbext >= 2300
478 call DB_DictionaryDelete("procedure")
479 else
480 DBCompleteProcedures!
481 endif
482 endif
483 if s:sql_file_view != ""
484 if g:loaded_dbext >= 2300
485 call DB_DictionaryDelete("view")
486 else
487 DBCompleteViews!
488 endif
489 endif
490
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100491 let s:sql_file_table = ""
492 let s:sql_file_procedure = ""
493 let s:sql_file_view = ""
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000494
495 let msg = "All SQL cached items have been removed."
496 call s:SQLCWarningMsg(msg)
497 " Leave time for the user to read the error message
498 :sleep 2
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000499 else
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000500 let compl_list = s:SQLCGetSyntaxList(compl_type)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000501 endif
502
503 if base != ''
Bram Moolenaar5c736222010-01-06 20:54:52 +0100504 " Filter the list based on the first few characters the user entered.
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100505 " Check if the text matches at the beginning
506 " \\(^.base.'\\)
507 " or
Bram Moolenaar5c736222010-01-06 20:54:52 +0100508 " Match to a owner.table or alias.column type match
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100509 " ^\\(\\w\\+\\.\\)\\?'.base.'\\)
Bram Moolenaar5c736222010-01-06 20:54:52 +0100510 " or
511 " Handle names with spaces "my table name"
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100512 " "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"'
513 "
Bram Moolenaar5c736222010-01-06 20:54:52 +0100514 let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"'
515 " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\)"'
516 " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\(\\.\\)\\?'.base.'\\)"'
517 " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\([^.]*\\)\\?'.base.'\\)"'
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000518 let compl_list = filter(deepcopy(compl_list), expr)
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100519
520 if empty(compl_list) && compl_type == 'table' && base =~ '\.$'
521 " It is possible we could be looking for column name completion
522 " and the user simply hit C-X C-O to lets try it as well
523 " since we had no hits with the tables.
524 " If the base ends with a . it is hard to know if we are
525 " completing table names or column names.
526 let list_type = ''
527
528 let compl_list = s:SQLCGetColumns(base, list_type)
529 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000530 endif
531
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000532 if exists('b:sql_compl_savefunc') && b:sql_compl_savefunc != ""
533 let &omnifunc = b:sql_compl_savefunc
534 endif
535
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100536 if empty(compl_list)
537 call s:SQLCWarningMsg( 'Could not find type['.compl_type.'] using prepend[.'.s:prepended.'] base['.a:base.']' )
538 endif
539
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000540 return compl_list
541endfunc
542
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000543function! sqlcomplete#PreCacheSyntax(...)
544 let syn_group_arr = []
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +0200545 let syn_items = []
546
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100547 if a:0 > 0
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +0200548 if type(a:1) != 3
549 call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']")
550 return ''
551 endif
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000552 let syn_group_arr = a:1
553 else
554 let syn_group_arr = g:omni_sql_precache_syntax_groups
555 endif
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000556 " For each group specified in the list, precache all
557 " the sytnax items.
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000558 if !empty(syn_group_arr)
559 for group_name in syn_group_arr
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +0200560 let syn_items = extend( syn_items, s:SQLCGetSyntaxList(group_name) )
561 endfor
562 endif
563
564 return syn_items
565endfunction
566
567function! sqlcomplete#ResetCacheSyntax(...)
568 let syn_group_arr = []
569
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100570 if a:0 > 0
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +0200571 if type(a:1) != 3
572 call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']")
573 return ''
574 endif
575 let syn_group_arr = a:1
576 else
577 let syn_group_arr = g:omni_sql_precache_syntax_groups
578 endif
579 " For each group specified in the list, precache all
580 " the sytnax items.
581 if !empty(syn_group_arr)
582 for group_name in syn_group_arr
583 let list_idx = index(s:syn_list, group_name, 0, &ignorecase)
584 if list_idx > -1
585 " Remove from list of groups
586 call remove( s:syn_list, list_idx )
587 " Remove from list of keywords
588 call remove( s:syn_value, list_idx )
589 endif
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000590 endfor
591 endif
592endfunction
593
594function! sqlcomplete#Map(type)
595 " Tell the SQL plugin what you want to complete
596 let b:sql_compl_type=a:type
597 " Record previous omnifunc, if the SQL completion
598 " is being used in conjunction with other filetype
599 " completion plugins
600 if &omnifunc != "" && &omnifunc != 'sqlcomplete#Complete'
601 " Record the previous omnifunc, the plugin
602 " will automatically set this back so that it
603 " does not interfere with other ftplugins settings
604 let b:sql_compl_savefunc=&omnifunc
605 endif
606 " Set the OMNI func for the SQL completion plugin
607 let &omnifunc='sqlcomplete#Complete'
608endfunction
609
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000610function! sqlcomplete#DrillIntoTable()
611 " If the omni popup window is visible
612 if pumvisible()
613 call sqlcomplete#Map('column')
614 " C-Y, makes the currently highlighted entry active
615 " and trigger the omni popup to be redisplayed
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200616 call feedkeys("\<C-Y>\<C-X>\<C-O>", 'n')
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000617 else
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200618 " If the popup is not visible, simple perform the normal
619 " key behaviour.
620 " Must use exec since they key must be preceeded by "\"
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100621 " or feedkeys will simply push each character of the string
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200622 " rather than the "key press".
623 exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_right.'", "n")'
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000624 endif
625 return ""
626endfunction
627
628function! sqlcomplete#DrillOutOfColumns()
629 " If the omni popup window is visible
630 if pumvisible()
631 call sqlcomplete#Map('tableReset')
632 " Trigger the omni popup to be redisplayed
633 call feedkeys("\<C-X>\<C-O>")
634 else
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200635 " If the popup is not visible, simple perform the normal
636 " key behaviour.
637 " Must use exec since they key must be preceeded by "\"
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100638 " or feedkeys will simply push each character of the string
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200639 " rather than the "key press".
640 exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_left.'", "n")'
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000641 endif
642 return ""
643endfunction
644
645function! s:SQLCWarningMsg(msg)
646 echohl WarningMsg
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100647 echomsg 'SQLComplete:'.a:msg
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000648 echohl None
649endfunction
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100650
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000651function! s:SQLCErrorMsg(msg)
652 echohl ErrorMsg
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100653 echomsg 'SQLComplete:'.a:msg
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000654 echohl None
655endfunction
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100656
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000657function! s:SQLCGetSyntaxList(syn_group)
658 let syn_group = a:syn_group
659 let compl_list = []
660
661 " Check if we have already cached the syntax list
662 let list_idx = index(s:syn_list, syn_group, 0, &ignorecase)
663 if list_idx > -1
664 " Return previously cached value
665 let compl_list = s:syn_value[list_idx]
666 else
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200667 let s:save_inc = g:omni_syntax_group_include_sql
668 let s:save_exc = g:omni_syntax_group_exclude_sql
669 let g:omni_syntax_group_include_sql = ''
670 let g:omni_syntax_group_exclude_sql = ''
671
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100672 " Request the syntax list items from the
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000673 " syntax completion plugin
674 if syn_group == 'syntax'
675 " Handle this special case. This allows the user
676 " to indicate they want all the syntax items available,
677 " so do not specify a specific include list.
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200678 let syn_value = syntaxcomplete#OmniSyntaxList()
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000679 else
680 " The user has specified a specific syntax group
681 let g:omni_syntax_group_include_sql = syn_group
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200682 let syn_value = syntaxcomplete#OmniSyntaxList(syn_group)
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000683 endif
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000684 let g:omni_syntax_group_include_sql = s:save_inc
685 let g:omni_syntax_group_exclude_sql = s:save_exc
686 " Cache these values for later use
687 let s:syn_list = add( s:syn_list, syn_group )
688 let s:syn_value = add( s:syn_value, syn_value )
689 let compl_list = syn_value
690 endif
691
692 return compl_list
693endfunction
694
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000695function! s:SQLCCheck4dbext()
696 if !exists('g:loaded_dbext')
697 let msg = "The dbext plugin must be loaded for dynamic SQL completion"
698 call s:SQLCErrorMsg(msg)
699 " Leave time for the user to read the error message
700 :sleep 2
701 return -1
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000702 elseif g:loaded_dbext < 600
703 let msg = "The dbext plugin must be at least version 5.30 " .
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000704 \ " for dynamic SQL completion"
705 call s:SQLCErrorMsg(msg)
706 " Leave time for the user to read the error message
707 :sleep 2
708 return -1
709 endif
710 return 1
711endfunction
712
713function! s:SQLCAddAlias(table_name, table_alias, cols)
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000714 " Strip off the owner if included
715 let table_name = matchstr(a:table_name, '\%(.\{-}\.\)\?\zs\(.*\)' )
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000716 let table_alias = a:table_alias
717 let cols = a:cols
718
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100719 if g:omni_sql_use_tbl_alias != 'n'
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000720 if table_alias == ''
721 if 'da' =~? g:omni_sql_use_tbl_alias
722 if table_name =~ '_'
723 " Treat _ as separators since people often use these
724 " for word separators
725 let save_keyword = &iskeyword
726 setlocal iskeyword-=_
727
728 " Get the first letter of each word
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100729 " [[:alpha:]] is used instead of \w
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000730 " to catch extended accented characters
731 "
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100732 let table_alias = substitute(
733 \ table_name,
734 \ '\<[[:alpha:]]\+\>_\?',
735 \ '\=strpart(submatch(0), 0, 1)',
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000736 \ 'g'
737 \ )
738 " Restore original value
739 let &iskeyword = save_keyword
740 elseif table_name =~ '\u\U'
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000741 let table_alias = substitute(
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000742 \ table_name, '\(\u\)\U*', '\1', 'g')
743 else
744 let table_alias = strpart(table_name, 0, 1)
745 endif
746 endif
747 endif
748 if table_alias != ''
749 " Following a word character, make sure there is a . and no spaces
750 let table_alias = substitute(table_alias, '\w\zs\.\?\s*$', '.', '')
751 if 'a' =~? g:omni_sql_use_tbl_alias && a:table_alias == ''
752 let table_alias = inputdialog("Enter table alias:", table_alias)
753 endif
754 endif
755 if table_alias != ''
756 let cols = substitute(cols, '\<\w', table_alias.'&', 'g')
757 endif
758 endif
759
760 return cols
761endfunction
762
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100763function! s:SQLCGetObjectOwner(object)
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000764 " The owner regex matches a word at the start of the string which is
765 " followed by a dot, but doesn't include the dot in the result.
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000766 " ^ - from beginning of line
767 " \("\|\[\)\? - ignore any quotes
768 " \zs - start the match now
769 " .\{-} - get owner name
770 " \ze - end the match
771 " \("\|\[\)\? - ignore any quotes
772 " \. - must by followed by a .
773 " let owner = matchstr( a:object, '^\s*\zs.*\ze\.' )
774 let owner = matchstr( a:object, '^\("\|\[\)\?\zs\.\{-}\ze\("\|\]\)\?\.' )
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000775 return owner
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100776endfunction
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000777
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000778function! s:SQLCGetColumns(table_name, list_type)
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100779 if a:table_name =~ '\.'
780 " Check if the owner/creator has been specified
781 let owner = matchstr( a:table_name, '^\zs.*\ze\..*\..*' )
782 let table = matchstr( a:table_name, '^\(.*\.\)\?\zs.*\ze\..*' )
783 let column = matchstr( a:table_name, '.*\.\zs.*' )
784
785 if g:omni_sql_include_owner == 1 && owner == '' && table != '' && column != ''
786 let owner = table
787 let table = column
788 let column = ''
789 endif
790 else
791 let owner = ''
792 let table = matchstr(a:table_name, '^["\[\]a-zA-Z0-9_ ]\+\ze\.\?')
793 let column = ''
794 endif
795
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000796 " Check if the table name was provided as part of the column name
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100797 " let table_name = matchstr(a:table_name, '^["\[\]a-zA-Z0-9_ ]\+\ze\.\?')
798 let table_name = table
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000799 let table_cols = []
800 let table_alias = ''
801 let move_to_top = 1
802
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000803 let table_name = substitute(table_name, '\s*\(.\{-}\)\s*$', '\1', 'g')
804
805 " If the table name was given as:
806 " where c.
807 let table_name = substitute(table_name, '^\c\(WHERE\|AND\|OR\)\s\+', '', '')
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000808 if g:loaded_dbext >= 300
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000809 let saveSettingAlias = DB_listOption('use_tbl_alias')
810 exec 'DBSetOption use_tbl_alias=n'
811 endif
812
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000813 let table_name_stripped = substitute(table_name, '["\[\]]*', '', 'g')
814
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000815 " Check if we have already cached the column list for this table
816 " by its name
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000817 let list_idx = index(s:tbl_name, table_name_stripped, 0, &ignorecase)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000818 if list_idx > -1
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000819 let table_cols = split(s:tbl_cols[list_idx], '\n')
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000820 else
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100821 " Check if we have already cached the column list for this table
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000822 " by its alias, assuming the table_name provided was actually
823 " the alias for the table instead
824 " select *
825 " from area a
826 " where a.
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000827 let list_idx = index(s:tbl_alias, table_name_stripped, 0, &ignorecase)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000828 if list_idx > -1
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000829 let table_alias = table_name_stripped
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000830 let table_name = s:tbl_name[list_idx]
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000831 let table_cols = split(s:tbl_cols[list_idx], '\n')
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000832 endif
833 endif
834
835 " If we have not found a cached copy of the table
836 " And the table ends in a "." or we are looking for a column list
837 " if list_idx == -1 && (a:table_name =~ '\.' || b:sql_compl_type =~ 'column')
838 " if list_idx == -1 && (a:table_name =~ '\.' || a:list_type =~ 'csv')
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100839 if list_idx == -1
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000840 let saveY = @y
841 let saveSearch = @/
842 let saveWScan = &wrapscan
843 let curline = line(".")
844 let curcol = col(".")
845
846 " Do not let searchs wrap
847 setlocal nowrapscan
848 " If . was entered, look at the word just before the .
849 " We are looking for something like this:
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100850 " select *
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000851 " from customer c
852 " where c.
853 " So when . is pressed, we need to find 'c'
854 "
855
856 " Search backwards to the beginning of the statement
857 " and do NOT wrap
858 " exec 'silent! normal! v?\<\(select\|update\|delete\|;\)\>'."\n".'"yy'
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200859 exec 'silent! normal! ?\<\c\(select\|update\|delete\|;\)\>'."\n"
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000860
861 " Start characterwise visual mode
862 " Advance right one character
Bram Moolenaar01164a62017-11-02 22:58:42 +0100863 " Search forward until one of the following:
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000864 " 1. Another select/update/delete statement
865 " 2. A ; at the end of a line (the delimiter)
866 " 3. The end of the file (incase no delimiter)
867 " Yank the visually selected text into the "y register.
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200868 exec 'silent! normal! vl/\c\(\<select\>\|\<update\>\|\<delete\>\|;\s*$\|\%$\)'."\n".'"yy'
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000869
870 let query = @y
871 let query = substitute(query, "\n", ' ', 'g')
872 let found = 0
873
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200874 " if query =~? '^\c\(select\)'
875 if query =~? '^\(select\|update\|delete\)'
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000876 let found = 1
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100877 " \(\(\<\w\+\>\)\.\)\? -
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200878 " '\c\(from\|join\|,\).\{-}' - Starting at the from clause (case insensitive)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000879 " '\zs\(\(\<\w\+\>\)\.\)\?' - Get the owner name (optional)
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100880 " '\<\w\+\>\ze' - Get the table name
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000881 " '\s\+\<'.table_name.'\>' - Followed by the alias
882 " '\s*\.\@!.*' - Cannot be followed by a .
883 " '\(\<where\>\|$\)' - Must be followed by a WHERE clause
884 " '.*' - Exclude the rest of the line in the match
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100885 " let table_name_new = matchstr(@y,
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200886 " \ '\c\(from\|join\|,\).\{-}'.
887 " \ '\zs\(\("\|\[\)\?.\{-}\("\|\]\)\.\)\?'.
888 " \ '\("\|\[\)\?.\{-}\("\|\]\)\?\ze'.
889 " \ '\s\+\%(as\s\+\)\?\<'.
890 " \ matchstr(table_name, '.\{-}\ze\.\?$').
891 " \ '\>'.
892 " \ '\s*\.\@!.*'.
893 " \ '\(\<where\>\|$\)'.
894 " \ '.*'
895 " \ )
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100896 "
897 "
898 " ''\c\(\<from\>\|\<join\>\|,\)\s*' - Starting at the from clause (case insensitive)
899 " '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?' - Get the owner name (optional)
900 " '\("\|\[\)\?\w\+\("\|\]\)\?\ze' - Get the table name
901 " '\s\+\%(as\s\+\)\?\<'.matchstr(table_name, '.\{-}\ze\.\?$').'\>' - Followed by the alias
902 " '\s*\.\@!.*' - Cannot be followed by a .
903 " '\(\<where\>\|$\)' - Must be followed by a WHERE clause
904 " '.*' - Exclude the rest of the line in the match
905 let table_name_new = matchstr(@y,
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200906 \ '\c\(\<from\>\|\<join\>\|,\)\s*'.
907 \ '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?'.
908 \ '\("\|\[\)\?\w\+\("\|\]\)\?\ze'.
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000909 \ '\s\+\%(as\s\+\)\?\<'.
910 \ matchstr(table_name, '.\{-}\ze\.\?$').
911 \ '\>'.
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000912 \ '\s*\.\@!.*'.
913 \ '\(\<where\>\|$\)'.
914 \ '.*'
915 \ )
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000916
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000917 if table_name_new != ''
918 let table_alias = table_name
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100919 if g:omni_sql_include_owner == 1
920 let table_name = matchstr( table_name_new, '^\zs\(.\{-}\.\)\?\(.\{-}\.\)\?.*\ze' )
921 else
922 " let table_name = matchstr( table_name_new, '^\(.*\.\)\?\zs.*\ze' )
923 let table_name = matchstr( table_name_new, '^\(.\{-}\.\)\?\zs\(.\{-}\.\)\?.*\ze' )
924 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000925
926 let list_idx = index(s:tbl_name, table_name, 0, &ignorecase)
927 if list_idx > -1
928 let table_cols = split(s:tbl_cols[list_idx])
929 let s:tbl_name[list_idx] = table_name
930 let s:tbl_alias[list_idx] = table_alias
931 else
932 let list_idx = index(s:tbl_alias, table_name, 0, &ignorecase)
933 if list_idx > -1
934 let table_cols = split(s:tbl_cols[list_idx])
935 let s:tbl_name[list_idx] = table_name
936 let s:tbl_alias[list_idx] = table_alias
937 endif
938 endif
939
940 endif
941 else
942 " Simply assume it is a table name provided with a . on the end
943 let found = 1
944 endif
945
946 let @y = saveY
947 let @/ = saveSearch
948 let &wrapscan = saveWScan
949
950 " Return to previous location
951 call cursor(curline, curcol)
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100952
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000953 if found == 0
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000954 if g:loaded_dbext > 300
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000955 exec 'DBSetOption use_tbl_alias='.saveSettingAlias
956 endif
957
958 " Not a SQL statement, do not display a list
959 return []
960 endif
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100961 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000962
963 if empty(table_cols)
964 " Specify silent mode, no messages to the user (tbl, 1)
965 " Specify do not comma separate (tbl, 1, 1)
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100966 " let table_cols_str = DB_getListColumn(table_name, 1, 1)
967 let table_cols_str = DB_getListColumn((owner!=''?owner.'.':'').table_name, 1, 1)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000968
969 if table_cols_str != ""
970 let s:tbl_name = add( s:tbl_name, table_name )
971 let s:tbl_alias = add( s:tbl_alias, table_alias )
972 let s:tbl_cols = add( s:tbl_cols, table_cols_str )
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000973 let table_cols = split(table_cols_str, '\n')
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000974 endif
975
976 endif
977
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000978 if g:loaded_dbext > 300
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000979 exec 'DBSetOption use_tbl_alias='.saveSettingAlias
980 endif
981
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000982 " If the user has asked for a comma separate list of column
983 " values, ask the user if they want to prepend each column
984 " with a tablename alias.
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000985 if a:list_type == 'csv' && !empty(table_cols)
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000986 let cols = join(table_cols, ', ')
987 let cols = s:SQLCAddAlias(table_name, table_alias, cols)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000988 let table_cols = [cols]
989 endif
990
991 return table_cols
992endfunction
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100993" Restore:
994let &cpo= s:keepcpo
995unlet s:keepcpo
996" vim: ts=4 fdm=marker