blob: 9326c15bb3e5e105f31c289dd45e397284fd33d1 [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 Moolenaarad3b3662013-05-17 18:14:19 +02004" Version: 15.0
5" Last Change: 2013 May 13
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"
19" Version 15.0 (May 2013)
20" - NF: Changed the SQL precached syntax items, omni_sql_precache_syntax_groups,
21" to use regular expressions to pick up extended syntax group names.
22" This requires an updated SyntaxComplete plugin version 13.0.
23" If the required versions have not been installed, previous
24" behaviour will not be impacted.
25"
Bram Moolenaar34feacb2012-12-05 19:01:43 +010026" Version 14.0 (Dec 2012)
27" - BF: Added check for cpo
28"
29" Version 13.0 (Dec 2012)
30" - NF: When completing column lists or drilling into a table
31" and g:omni_sql_include_owner is enabled, the
32" only the table name would be replaced with the column
33" list instead of the table name and owner (if specified).
34" - NF: When completing column lists using table aliases
35" and g:omni_sql_include_owner is enabled, account
36" for the owner name when looking up the table
37" list instead of the table name and owner (if specified).
38" - BF: When completing column lists or drilling into a table
39" and g:omni_sql_include_owner is enabled, the
40" column list could often not be found for the table.
41" - BF: When OMNI popped up, possibly the wrong word
42" would be replaced for column and column list options.
43"
44" Version 12.0 (Feb 2012)
Bram Moolenaardb7207e2012-02-22 17:30:19 +010045" - Partial column name completion did not work when a table
46" name or table alias was provided (Jonas Enberg).
47" - Improved the handling of column completion. First we match any
48" columns from a previous completion. If not matches are found, we
Bram Moolenaar34feacb2012-12-05 19:01:43 +010049" consider the partial name to be a table or table alias for the
Bram Moolenaardb7207e2012-02-22 17:30:19 +010050" query and attempt to match on it.
51"
Bram Moolenaar34feacb2012-12-05 19:01:43 +010052" Version 11.0 (Jan 2012)
Bram Moolenaardb7207e2012-02-22 17:30:19 +010053" Added g:omni_sql_default_compl_type variable
54" - You can specify which type of completion to default to
55" when pressing <C-X><C-O>. The entire list of available
56" choices can be found in the calls to sqlcomplete#Map in:
57" ftplugin/sql.vim
58"
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020059" Version 10.0
Bram Moolenaardb7207e2012-02-22 17:30:19 +010060" Updated PreCacheSyntax()
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020061" - Now returns a List of the syntax items it finds.
62" This allows other plugins / scripts to use this list for their own
63" purposes. In this case XPTemplate can use them for a Choose list.
64" - Verifies the parameters are the correct type and displays a
65" warning if not.
66" - Verifies the parameters are the correct type and displays a
67" warning if not.
Bram Moolenaardb7207e2012-02-22 17:30:19 +010068" Updated SQLCWarningMsg()
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020069" - Prepends warning message with SQLComplete so you know who issued
70" the warning.
Bram Moolenaardb7207e2012-02-22 17:30:19 +010071" Updated SQLCErrorMsg()
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020072" - Prepends error message with SQLComplete so you know who issued
73" the error.
Bram Moolenaardb7207e2012-02-22 17:30:19 +010074"
Bram Moolenaar34feacb2012-12-05 19:01:43 +010075" Version 9.0 (May 2010)
Bram Moolenaar00a927d2010-05-14 23:24:24 +020076" This change removes some of the support for tables with spaces in their
Bram Moolenaardb7207e2012-02-22 17:30:19 +010077" names in order to simplify the regexes used to pull out query table
Bram Moolenaar00a927d2010-05-14 23:24:24 +020078" aliases for more robust table name and column name code completion.
79" Full support for "table names with spaces" can be added in again
80" after 7.3.
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020081"
Bram Moolenaar00a927d2010-05-14 23:24:24 +020082" Version 8.0
Bram Moolenaardb7207e2012-02-22 17:30:19 +010083" Incorrectly re-executed the g:ftplugin_sql_omni_key_right and g:ftplugin_sql_omni_key_left
Bram Moolenaar00a927d2010-05-14 23:24:24 +020084" when drilling in and out of a column list for a table.
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020085"
Bram Moolenaar34feacb2012-12-05 19:01:43 +010086" Version 7.0 (Jan 2010)
Bram Moolenaar5c736222010-01-06 20:54:52 +010087" Better handling of object names
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +020088"
Bram Moolenaar34feacb2012-12-05 19:01:43 +010089" Version 6.0 (Apr 2008)
Bram Moolenaar5c736222010-01-06 20:54:52 +010090" Supports object names with spaces "my table name"
91"
Bram Moolenaare2f98b92006-03-29 21:18:24 +000092" Set completion with CTRL-X CTRL-O to autoloaded function.
93" This check is in place in case this script is
Bram Moolenaardb7207e2012-02-22 17:30:19 +010094" sourced directly instead of using the autoload feature.
Bram Moolenaare2f98b92006-03-29 21:18:24 +000095if exists('&omnifunc')
96 " Do not set the option if already set since this
97 " results in an E117 warning.
98 if &omnifunc == ""
99 setlocal omnifunc=sqlcomplete#Complete
100 endif
101endif
102
103if exists('g:loaded_sql_completion')
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100104 finish
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000105endif
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200106let g:loaded_sql_completion = 150
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100107let s:keepcpo= &cpo
108set cpo&vim
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000109
110" Maintains filename of dictionary
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000111let s:sql_file_table = ""
112let s:sql_file_procedure = ""
113let s:sql_file_view = ""
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000114
115" Define various arrays to be used for caching
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000116let s:tbl_name = []
117let s:tbl_alias = []
118let s:tbl_cols = []
119let s:syn_list = []
120let s:syn_value = []
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100121
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000122" Used in conjunction with the syntaxcomplete plugin
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000123let s:save_inc = ""
124let s:save_exc = ""
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200125if !exists('g:omni_syntax_group_include_sql')
126 let g:omni_syntax_group_include_sql = ''
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000127endif
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200128if !exists('g:omni_syntax_group_exclude_sql')
129 let g:omni_syntax_group_exclude_sql = ''
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000130endif
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200131let s:save_inc = g:omni_syntax_group_include_sql
132let s:save_exc = g:omni_syntax_group_exclude_sql
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100133
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000134" Used with the column list
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000135let s:save_prev_table = ""
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000136
137" Default the option to verify table alias
138if !exists('g:omni_sql_use_tbl_alias')
139 let g:omni_sql_use_tbl_alias = 'a'
140endif
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000141" Default syntax items to precache
142if !exists('g:omni_sql_precache_syntax_groups')
143 let g:omni_sql_precache_syntax_groups = [
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200144 \ 'syntax\w*',
145 \ 'sqlKeyword\w*',
146 \ 'sqlFunction\w*',
147 \ 'sqlOption\w*',
148 \ 'sqlType\w*',
149 \ 'sqlStatement\w*'
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000150 \ ]
151endif
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000152" Set ignorecase to the ftplugin standard
153if !exists('g:omni_sql_ignorecase')
154 let g:omni_sql_ignorecase = &ignorecase
155endif
156" During table completion, should the table list also
157" include the owner name
158if !exists('g:omni_sql_include_owner')
159 let g:omni_sql_include_owner = 0
160 if exists('g:loaded_dbext')
161 if g:loaded_dbext >= 300
162 " New to dbext 3.00, by default the table lists include the owner
163 " name of the table. This is used when determining how much of
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100164 " whatever has been typed should be replaced as part of the
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000165 " code replacement.
166 let g:omni_sql_include_owner = 1
167 endif
168 endif
169endif
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100170" Default type of completion used when <C-X><C-O> is pressed
171if !exists('g:omni_sql_default_compl_type')
172 let g:omni_sql_default_compl_type = 'table'
173endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000174
175" This function is used for the 'omnifunc' option.
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100176" It is called twice by omni and it is responsible
177" for returning the completion list of items.
178" But it must also determine context of what to complete
179" and what to "replace" with the completion.
180" The a:base, is replaced directly with what the user
181" chooses from the choices.
182" The s:prepend provides context for the completion.
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000183function! sqlcomplete#Complete(findstart, base)
184
185 " Default to table name completion
186 let compl_type = 'table'
187 " Allow maps to specify what type of object completion they want
188 if exists('b:sql_compl_type')
189 let compl_type = b:sql_compl_type
190 endif
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100191 let begindot = 0
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000192
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000193 " First pass through this function determines how much of the line should
194 " be replaced by whatever is chosen from the completion list
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000195 if a:findstart
196 " Locate the start of the item, including "."
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000197 let line = getline('.')
198 let start = col('.') - 1
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000199 let lastword = -1
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000200 " Check if the first character is a ".", for column completion
201 if line[start - 1] == '.'
202 let begindot = 1
203 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000204 while start > 0
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100205 " Additional code was required to handle objects which
Bram Moolenaar5c736222010-01-06 20:54:52 +0100206 " can contain spaces like "my table name".
207 if line[start - 1] !~ '\(\w\|\.\)'
208 " If the previous character is not a period or word character
209 break
210 " elseif line[start - 1] =~ '\(\w\|\s\+\)'
211 " let start -= 1
212 elseif line[start - 1] =~ '\w'
213 " If the previous character is word character continue back
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000214 let start -= 1
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100215 elseif line[start - 1] =~ '\.' &&
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000216 \ compl_type =~ 'column\|table\|view\|procedure'
Bram Moolenaar5c736222010-01-06 20:54:52 +0100217 " If the previous character is a period and we are completing
218 " an object which can be specified with a period like this:
219 " table_name.column_name
220 " owner_name.table_name
221
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000222 " If lastword has already been set for column completion
223 " break from the loop, since we do not also want to pickup
224 " a table name if it was also supplied.
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100225 " Unless g:omni_sql_include_owner == 1, then we can
226 " include the ownername.
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100227 if lastword != -1 && compl_type == 'column'
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100228 \ && g:omni_sql_include_owner == 0
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000229 break
230 endif
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000231 " If column completion was specified stop at the "." if
232 " a . was specified, otherwise, replace all the way up
233 " to the owner name (if included).
234 if lastword == -1 && compl_type == 'column' && begindot == 1
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000235 let lastword = start
236 endif
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000237 " If omni_sql_include_owner = 0, do not include the table
238 " name as part of the substitution, so break here
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100239 if lastword == -1 &&
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100240 \ compl_type =~ '\<\(table\|view\|procedure\|column\|column_csv\)\>' &&
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000241 \ g:omni_sql_include_owner == 0
242 let lastword = start
243 break
244 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000245 let start -= 1
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000246 else
247 break
248 endif
249 endwhile
250
251 " Return the column of the last word, which is going to be changed.
252 " Remember the text that comes before it in s:prepended.
253 if lastword == -1
254 let s:prepended = ''
255 return start
256 endif
257 let s:prepended = strpart(line, start, lastword - start)
258 return lastword
259 endif
260
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000261 " Second pass through this function will determine what data to put inside
262 " of the completion list
263 " s:prepended is set by the first pass
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000264 let base = s:prepended . a:base
265
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000266 " Default the completion list to an empty list
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000267 let compl_list = []
268
269 " Default to table name completion
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100270 let compl_type = g:omni_sql_default_compl_type
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000271 " Allow maps to specify what type of object completion they want
272 if exists('b:sql_compl_type')
273 let compl_type = b:sql_compl_type
274 unlet b:sql_compl_type
275 endif
276
277 if compl_type == 'tableReset'
278 let compl_type = 'table'
279 let base = ''
280 endif
281
282 if compl_type == 'table' ||
283 \ compl_type == 'procedure' ||
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100284 \ compl_type == 'view'
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000285
286 " This type of completion relies upon the dbext.vim plugin
287 if s:SQLCCheck4dbext() == -1
288 return []
289 endif
290
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000291 " Allow the user to override the dbext plugin to specify whether
292 " the owner/creator should be included in the list
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000293 if g:loaded_dbext >= 300
294 let saveSetting = DB_listOption('dict_show_owner')
295 exec 'DBSetOption dict_show_owner='.(g:omni_sql_include_owner==1?'1':'0')
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000296 endif
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000297
298 let compl_type_uc = substitute(compl_type, '\w\+', '\u&', '')
Bram Moolenaar5c736222010-01-06 20:54:52 +0100299 " Same call below, no need to do it twice
300 " if s:sql_file_{compl_type} == ""
301 " let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc)
302 " endif
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000303 let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000304 if s:sql_file_{compl_type} != ""
305 if filereadable(s:sql_file_{compl_type})
306 let compl_list = readfile(s:sql_file_{compl_type})
307 endif
308 endif
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000309
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000310 if g:loaded_dbext > 300
311 exec 'DBSetOption dict_show_owner='.saveSetting
312 endif
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000313 elseif compl_type =~? 'column'
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000314
315 " This type of completion relies upon the dbext.vim plugin
316 if s:SQLCCheck4dbext() == -1
317 return []
318 endif
319
320 if base == ""
321 " The last time we displayed a column list we stored
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100322 " the table name. If the user selects a column list
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000323 " without a table name of alias present, assume they want
324 " the previous column list displayed.
325 let base = s:save_prev_table
326 endif
327
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000328 let owner = ''
329 let column = ''
330
331 if base =~ '\.'
332 " Check if the owner/creator has been specified
333 let owner = matchstr( base, '^\zs.*\ze\..*\..*' )
334 let table = matchstr( base, '^\(.*\.\)\?\zs.*\ze\..*' )
335 let column = matchstr( base, '.*\.\zs.*' )
336
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100337 if g:omni_sql_include_owner == 1 && owner == '' && table != '' && column != ''
338 let owner = table
339 let table = column
340 let column = ''
341 endif
342
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000343 " It is pretty well impossible to determine if the user
344 " has entered:
345 " owner.table
346 " table.column_prefix
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100347 " So there are a couple of things we can do to mitigate
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000348 " this issue.
349 " 1. Check if the dbext plugin has the option turned
350 " on to even allow owners
351 " 2. Based on 1, if the user is showing a table list
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100352 " and the DrillIntoTable (using <Right>) then
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000353 " this will be owner.table. In this case, we can
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100354 " check to see the table.column exists in the
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000355 " cached table list. If it does, then we have
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100356 " determined the user has actually chosen
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000357 " owner.table, not table.column_prefix.
358 let found = -1
359 if g:omni_sql_include_owner == 1 && owner == ''
360 if filereadable(s:sql_file_table)
361 let tbl_list = readfile(s:sql_file_table)
362 let found = index( tbl_list, ((table != '')?(table.'.'):'').column)
363 endif
364 endif
365 " If the table.column was found in the table list, we can safely assume
366 " the owner was not provided and shift the items appropriately.
367 " OR
368 " If the user has indicated not to use table owners at all and
369 " the base ends in a '.' we know they are not providing a column
370 " name, so we can shift the items appropriately.
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100371 " if found != -1 || (g:omni_sql_include_owner == 0 && base !~ '\.$')
372 " let owner = table
373 " let table = column
374 " let column = ''
375 " endif
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000376 else
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100377 " If no "." was provided and the user asked for
378 " column level completion, first attempt the match
379 " on any previous column lists. If the user asked
380 " for a list of columns comma separated, continue as usual.
381 if compl_type == 'column' && s:save_prev_table != ''
382 " The last time we displayed a column list we stored
383 " the table name. If the user selects a column list
384 " without a table name of alias present, assume they want
385 " the previous column list displayed.
386 let table = s:save_prev_table
387 let list_type = ''
388
389 let compl_list = s:SQLCGetColumns(table, list_type)
390 if ! empty(compl_list)
391 " If no column prefix has been provided and the table
392 " name was provided, append it to each of the items
393 " returned.
394 let compl_list = filter(deepcopy(compl_list), 'v:val=~"^'.base.'"' )
395
396 " If not empty, we have a match on columns
397 " return the list
398 if ! empty(compl_list)
399 return compl_list
400 endif
401 endif
402 endif
403 " Since no columns were found to match the base supplied
404 " assume the user is trying to complete the column list
405 " for a table (and or an alias to a table).
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000406 let table = base
407 endif
408
409 " Get anything after the . and consider this the table name
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100410 " If an owner has been specified, then we must consider the
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000411 " base to be a partial column name
412 " let base = matchstr( base, '^\(.*\.\)\?\zs.*' )
413
414 if table != ""
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000415 let s:save_prev_table = base
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000416 let list_type = ''
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000417
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000418 if compl_type == 'column_csv'
419 " Return one array element, with a comma separated
420 " list of values instead of multiple array entries
421 " for each column in the table.
422 let list_type = 'csv'
423 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000424
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100425 " If we are including the OWNER for the objects, then for
426 " table completion, if we have it, it should be included
427 " as there can be the same table names in a database yet
428 " with different owner names.
429 if g:omni_sql_include_owner == 1 && owner != '' && table != ''
430 let compl_list = s:SQLCGetColumns(owner.'.'.table, list_type)
431 else
432 let compl_list = s:SQLCGetColumns(table, list_type)
433 endif
434
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000435 if column != ''
436 " If no column prefix has been provided and the table
437 " name was provided, append it to each of the items
438 " returned.
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100439 let compl_list = map(compl_list, 'table.".".v:val')
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000440 if owner != ''
441 " If an owner has been provided append it to each of the
442 " items returned.
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100443 let compl_list = map(compl_list, 'owner.".".v:val')
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000444 endif
445 else
446 let base = ''
447 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000448
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000449 if compl_type == 'column_csv'
450 " Join the column array into 1 single element array
451 " but make the columns column separated
452 let compl_list = [join(compl_list, ', ')]
453 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000454 endif
455 elseif compl_type == 'resetCache'
456 " Reset all cached items
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100457 let s:tbl_name = []
458 let s:tbl_alias = []
459 let s:tbl_cols = []
460 let s:syn_list = []
461 let s:syn_value = []
462 let s:sql_file_table = ""
463 let s:sql_file_procedure = ""
464 let s:sql_file_view = ""
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000465
466 let msg = "All SQL cached items have been removed."
467 call s:SQLCWarningMsg(msg)
468 " Leave time for the user to read the error message
469 :sleep 2
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000470 else
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000471 let compl_list = s:SQLCGetSyntaxList(compl_type)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000472 endif
473
474 if base != ''
Bram Moolenaar5c736222010-01-06 20:54:52 +0100475 " Filter the list based on the first few characters the user entered.
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100476 " Check if the text matches at the beginning
477 " \\(^.base.'\\)
478 " or
Bram Moolenaar5c736222010-01-06 20:54:52 +0100479 " Match to a owner.table or alias.column type match
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100480 " ^\\(\\w\\+\\.\\)\\?'.base.'\\)
Bram Moolenaar5c736222010-01-06 20:54:52 +0100481 " or
482 " Handle names with spaces "my table name"
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100483 " "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"'
484 "
Bram Moolenaar5c736222010-01-06 20:54:52 +0100485 let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"'
486 " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\)"'
487 " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\(\\.\\)\\?'.base.'\\)"'
488 " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\([^.]*\\)\\?'.base.'\\)"'
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000489 let compl_list = filter(deepcopy(compl_list), expr)
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100490
491 if empty(compl_list) && compl_type == 'table' && base =~ '\.$'
492 " It is possible we could be looking for column name completion
493 " and the user simply hit C-X C-O to lets try it as well
494 " since we had no hits with the tables.
495 " If the base ends with a . it is hard to know if we are
496 " completing table names or column names.
497 let list_type = ''
498
499 let compl_list = s:SQLCGetColumns(base, list_type)
500 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000501 endif
502
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000503 if exists('b:sql_compl_savefunc') && b:sql_compl_savefunc != ""
504 let &omnifunc = b:sql_compl_savefunc
505 endif
506
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100507 if empty(compl_list)
508 call s:SQLCWarningMsg( 'Could not find type['.compl_type.'] using prepend[.'.s:prepended.'] base['.a:base.']' )
509 endif
510
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000511 return compl_list
512endfunc
513
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000514function! sqlcomplete#PreCacheSyntax(...)
515 let syn_group_arr = []
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +0200516 let syn_items = []
517
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100518 if a:0 > 0
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +0200519 if type(a:1) != 3
520 call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']")
521 return ''
522 endif
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000523 let syn_group_arr = a:1
524 else
525 let syn_group_arr = g:omni_sql_precache_syntax_groups
526 endif
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000527 " For each group specified in the list, precache all
528 " the sytnax items.
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000529 if !empty(syn_group_arr)
530 for group_name in syn_group_arr
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +0200531 let syn_items = extend( syn_items, s:SQLCGetSyntaxList(group_name) )
532 endfor
533 endif
534
535 return syn_items
536endfunction
537
538function! sqlcomplete#ResetCacheSyntax(...)
539 let syn_group_arr = []
540
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100541 if a:0 > 0
Bram Moolenaarf9d5ca12010-08-01 16:13:51 +0200542 if type(a:1) != 3
543 call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']")
544 return ''
545 endif
546 let syn_group_arr = a:1
547 else
548 let syn_group_arr = g:omni_sql_precache_syntax_groups
549 endif
550 " For each group specified in the list, precache all
551 " the sytnax items.
552 if !empty(syn_group_arr)
553 for group_name in syn_group_arr
554 let list_idx = index(s:syn_list, group_name, 0, &ignorecase)
555 if list_idx > -1
556 " Remove from list of groups
557 call remove( s:syn_list, list_idx )
558 " Remove from list of keywords
559 call remove( s:syn_value, list_idx )
560 endif
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000561 endfor
562 endif
563endfunction
564
565function! sqlcomplete#Map(type)
566 " Tell the SQL plugin what you want to complete
567 let b:sql_compl_type=a:type
568 " Record previous omnifunc, if the SQL completion
569 " is being used in conjunction with other filetype
570 " completion plugins
571 if &omnifunc != "" && &omnifunc != 'sqlcomplete#Complete'
572 " Record the previous omnifunc, the plugin
573 " will automatically set this back so that it
574 " does not interfere with other ftplugins settings
575 let b:sql_compl_savefunc=&omnifunc
576 endif
577 " Set the OMNI func for the SQL completion plugin
578 let &omnifunc='sqlcomplete#Complete'
579endfunction
580
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000581function! sqlcomplete#DrillIntoTable()
582 " If the omni popup window is visible
583 if pumvisible()
584 call sqlcomplete#Map('column')
585 " C-Y, makes the currently highlighted entry active
586 " and trigger the omni popup to be redisplayed
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200587 call feedkeys("\<C-Y>\<C-X>\<C-O>", 'n')
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000588 else
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200589 " If the popup is not visible, simple perform the normal
590 " key behaviour.
591 " Must use exec since they key must be preceeded by "\"
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100592 " or feedkeys will simply push each character of the string
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200593 " rather than the "key press".
594 exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_right.'", "n")'
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000595 endif
596 return ""
597endfunction
598
599function! sqlcomplete#DrillOutOfColumns()
600 " If the omni popup window is visible
601 if pumvisible()
602 call sqlcomplete#Map('tableReset')
603 " Trigger the omni popup to be redisplayed
604 call feedkeys("\<C-X>\<C-O>")
605 else
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200606 " If the popup is not visible, simple perform the normal
607 " key behaviour.
608 " Must use exec since they key must be preceeded by "\"
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100609 " or feedkeys will simply push each character of the string
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200610 " rather than the "key press".
611 exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_left.'", "n")'
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000612 endif
613 return ""
614endfunction
615
616function! s:SQLCWarningMsg(msg)
617 echohl WarningMsg
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100618 echomsg 'SQLComplete:'.a:msg
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000619 echohl None
620endfunction
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100621
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000622function! s:SQLCErrorMsg(msg)
623 echohl ErrorMsg
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100624 echomsg 'SQLComplete:'.a:msg
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000625 echohl None
626endfunction
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100627
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000628function! s:SQLCGetSyntaxList(syn_group)
629 let syn_group = a:syn_group
630 let compl_list = []
631
632 " Check if we have already cached the syntax list
633 let list_idx = index(s:syn_list, syn_group, 0, &ignorecase)
634 if list_idx > -1
635 " Return previously cached value
636 let compl_list = s:syn_value[list_idx]
637 else
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200638 let s:save_inc = g:omni_syntax_group_include_sql
639 let s:save_exc = g:omni_syntax_group_exclude_sql
640 let g:omni_syntax_group_include_sql = ''
641 let g:omni_syntax_group_exclude_sql = ''
642
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100643 " Request the syntax list items from the
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000644 " syntax completion plugin
645 if syn_group == 'syntax'
646 " Handle this special case. This allows the user
647 " to indicate they want all the syntax items available,
648 " so do not specify a specific include list.
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200649 let syn_value = syntaxcomplete#OmniSyntaxList()
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000650 else
651 " The user has specified a specific syntax group
652 let g:omni_syntax_group_include_sql = syn_group
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200653 let syn_value = syntaxcomplete#OmniSyntaxList(syn_group)
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000654 endif
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000655 let g:omni_syntax_group_include_sql = s:save_inc
656 let g:omni_syntax_group_exclude_sql = s:save_exc
657 " Cache these values for later use
658 let s:syn_list = add( s:syn_list, syn_group )
659 let s:syn_value = add( s:syn_value, syn_value )
660 let compl_list = syn_value
661 endif
662
663 return compl_list
664endfunction
665
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000666function! s:SQLCCheck4dbext()
667 if !exists('g:loaded_dbext')
668 let msg = "The dbext plugin must be loaded for dynamic SQL completion"
669 call s:SQLCErrorMsg(msg)
670 " Leave time for the user to read the error message
671 :sleep 2
672 return -1
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000673 elseif g:loaded_dbext < 600
674 let msg = "The dbext plugin must be at least version 5.30 " .
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000675 \ " for dynamic SQL completion"
676 call s:SQLCErrorMsg(msg)
677 " Leave time for the user to read the error message
678 :sleep 2
679 return -1
680 endif
681 return 1
682endfunction
683
684function! s:SQLCAddAlias(table_name, table_alias, cols)
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000685 " Strip off the owner if included
686 let table_name = matchstr(a:table_name, '\%(.\{-}\.\)\?\zs\(.*\)' )
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000687 let table_alias = a:table_alias
688 let cols = a:cols
689
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100690 if g:omni_sql_use_tbl_alias != 'n'
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000691 if table_alias == ''
692 if 'da' =~? g:omni_sql_use_tbl_alias
693 if table_name =~ '_'
694 " Treat _ as separators since people often use these
695 " for word separators
696 let save_keyword = &iskeyword
697 setlocal iskeyword-=_
698
699 " Get the first letter of each word
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100700 " [[:alpha:]] is used instead of \w
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000701 " to catch extended accented characters
702 "
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100703 let table_alias = substitute(
704 \ table_name,
705 \ '\<[[:alpha:]]\+\>_\?',
706 \ '\=strpart(submatch(0), 0, 1)',
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000707 \ 'g'
708 \ )
709 " Restore original value
710 let &iskeyword = save_keyword
711 elseif table_name =~ '\u\U'
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000712 let table_alias = substitute(
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000713 \ table_name, '\(\u\)\U*', '\1', 'g')
714 else
715 let table_alias = strpart(table_name, 0, 1)
716 endif
717 endif
718 endif
719 if table_alias != ''
720 " Following a word character, make sure there is a . and no spaces
721 let table_alias = substitute(table_alias, '\w\zs\.\?\s*$', '.', '')
722 if 'a' =~? g:omni_sql_use_tbl_alias && a:table_alias == ''
723 let table_alias = inputdialog("Enter table alias:", table_alias)
724 endif
725 endif
726 if table_alias != ''
727 let cols = substitute(cols, '\<\w', table_alias.'&', 'g')
728 endif
729 endif
730
731 return cols
732endfunction
733
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100734function! s:SQLCGetObjectOwner(object)
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000735 " The owner regex matches a word at the start of the string which is
736 " followed by a dot, but doesn't include the dot in the result.
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000737 " ^ - from beginning of line
738 " \("\|\[\)\? - ignore any quotes
739 " \zs - start the match now
740 " .\{-} - get owner name
741 " \ze - end the match
742 " \("\|\[\)\? - ignore any quotes
743 " \. - must by followed by a .
744 " let owner = matchstr( a:object, '^\s*\zs.*\ze\.' )
745 let owner = matchstr( a:object, '^\("\|\[\)\?\zs\.\{-}\ze\("\|\]\)\?\.' )
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000746 return owner
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100747endfunction
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000748
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000749function! s:SQLCGetColumns(table_name, list_type)
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100750 if a:table_name =~ '\.'
751 " Check if the owner/creator has been specified
752 let owner = matchstr( a:table_name, '^\zs.*\ze\..*\..*' )
753 let table = matchstr( a:table_name, '^\(.*\.\)\?\zs.*\ze\..*' )
754 let column = matchstr( a:table_name, '.*\.\zs.*' )
755
756 if g:omni_sql_include_owner == 1 && owner == '' && table != '' && column != ''
757 let owner = table
758 let table = column
759 let column = ''
760 endif
761 else
762 let owner = ''
763 let table = matchstr(a:table_name, '^["\[\]a-zA-Z0-9_ ]\+\ze\.\?')
764 let column = ''
765 endif
766
Bram Moolenaar83e138c2007-05-05 18:27:07 +0000767 " Check if the table name was provided as part of the column name
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100768 " let table_name = matchstr(a:table_name, '^["\[\]a-zA-Z0-9_ ]\+\ze\.\?')
769 let table_name = table
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000770 let table_cols = []
771 let table_alias = ''
772 let move_to_top = 1
773
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000774 let table_name = substitute(table_name, '\s*\(.\{-}\)\s*$', '\1', 'g')
775
776 " If the table name was given as:
777 " where c.
778 let table_name = substitute(table_name, '^\c\(WHERE\|AND\|OR\)\s\+', '', '')
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000779 if g:loaded_dbext >= 300
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000780 let saveSettingAlias = DB_listOption('use_tbl_alias')
781 exec 'DBSetOption use_tbl_alias=n'
782 endif
783
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000784 let table_name_stripped = substitute(table_name, '["\[\]]*', '', 'g')
785
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000786 " Check if we have already cached the column list for this table
787 " by its name
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000788 let list_idx = index(s:tbl_name, table_name_stripped, 0, &ignorecase)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000789 if list_idx > -1
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000790 let table_cols = split(s:tbl_cols[list_idx], '\n')
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000791 else
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100792 " Check if we have already cached the column list for this table
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000793 " by its alias, assuming the table_name provided was actually
794 " the alias for the table instead
795 " select *
796 " from area a
797 " where a.
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000798 let list_idx = index(s:tbl_alias, table_name_stripped, 0, &ignorecase)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000799 if list_idx > -1
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000800 let table_alias = table_name_stripped
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000801 let table_name = s:tbl_name[list_idx]
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000802 let table_cols = split(s:tbl_cols[list_idx], '\n')
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000803 endif
804 endif
805
806 " If we have not found a cached copy of the table
807 " And the table ends in a "." or we are looking for a column list
808 " if list_idx == -1 && (a:table_name =~ '\.' || b:sql_compl_type =~ 'column')
809 " if list_idx == -1 && (a:table_name =~ '\.' || a:list_type =~ 'csv')
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100810 if list_idx == -1
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000811 let saveY = @y
812 let saveSearch = @/
813 let saveWScan = &wrapscan
814 let curline = line(".")
815 let curcol = col(".")
816
817 " Do not let searchs wrap
818 setlocal nowrapscan
819 " If . was entered, look at the word just before the .
820 " We are looking for something like this:
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100821 " select *
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000822 " from customer c
823 " where c.
824 " So when . is pressed, we need to find 'c'
825 "
826
827 " Search backwards to the beginning of the statement
828 " and do NOT wrap
829 " exec 'silent! normal! v?\<\(select\|update\|delete\|;\)\>'."\n".'"yy'
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200830 exec 'silent! normal! ?\<\c\(select\|update\|delete\|;\)\>'."\n"
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000831
832 " Start characterwise visual mode
833 " Advance right one character
834 " Search foward until one of the following:
835 " 1. Another select/update/delete statement
836 " 2. A ; at the end of a line (the delimiter)
837 " 3. The end of the file (incase no delimiter)
838 " Yank the visually selected text into the "y register.
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200839 exec 'silent! normal! vl/\c\(\<select\>\|\<update\>\|\<delete\>\|;\s*$\|\%$\)'."\n".'"yy'
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000840
841 let query = @y
842 let query = substitute(query, "\n", ' ', 'g')
843 let found = 0
844
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200845 " if query =~? '^\c\(select\)'
846 if query =~? '^\(select\|update\|delete\)'
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000847 let found = 1
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100848 " \(\(\<\w\+\>\)\.\)\? -
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200849 " '\c\(from\|join\|,\).\{-}' - Starting at the from clause (case insensitive)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000850 " '\zs\(\(\<\w\+\>\)\.\)\?' - Get the owner name (optional)
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100851 " '\<\w\+\>\ze' - Get the table name
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000852 " '\s\+\<'.table_name.'\>' - Followed by the alias
853 " '\s*\.\@!.*' - Cannot be followed by a .
854 " '\(\<where\>\|$\)' - Must be followed by a WHERE clause
855 " '.*' - Exclude the rest of the line in the match
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100856 " let table_name_new = matchstr(@y,
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200857 " \ '\c\(from\|join\|,\).\{-}'.
858 " \ '\zs\(\("\|\[\)\?.\{-}\("\|\]\)\.\)\?'.
859 " \ '\("\|\[\)\?.\{-}\("\|\]\)\?\ze'.
860 " \ '\s\+\%(as\s\+\)\?\<'.
861 " \ matchstr(table_name, '.\{-}\ze\.\?$').
862 " \ '\>'.
863 " \ '\s*\.\@!.*'.
864 " \ '\(\<where\>\|$\)'.
865 " \ '.*'
866 " \ )
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100867 "
868 "
869 " ''\c\(\<from\>\|\<join\>\|,\)\s*' - Starting at the from clause (case insensitive)
870 " '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?' - Get the owner name (optional)
871 " '\("\|\[\)\?\w\+\("\|\]\)\?\ze' - Get the table name
872 " '\s\+\%(as\s\+\)\?\<'.matchstr(table_name, '.\{-}\ze\.\?$').'\>' - Followed by the alias
873 " '\s*\.\@!.*' - Cannot be followed by a .
874 " '\(\<where\>\|$\)' - Must be followed by a WHERE clause
875 " '.*' - Exclude the rest of the line in the match
876 let table_name_new = matchstr(@y,
Bram Moolenaar00a927d2010-05-14 23:24:24 +0200877 \ '\c\(\<from\>\|\<join\>\|,\)\s*'.
878 \ '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?'.
879 \ '\("\|\[\)\?\w\+\("\|\]\)\?\ze'.
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000880 \ '\s\+\%(as\s\+\)\?\<'.
881 \ matchstr(table_name, '.\{-}\ze\.\?$').
882 \ '\>'.
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000883 \ '\s*\.\@!.*'.
884 \ '\(\<where\>\|$\)'.
885 \ '.*'
886 \ )
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000887
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000888 if table_name_new != ''
889 let table_alias = table_name
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100890 if g:omni_sql_include_owner == 1
891 let table_name = matchstr( table_name_new, '^\zs\(.\{-}\.\)\?\(.\{-}\.\)\?.*\ze' )
892 else
893 " let table_name = matchstr( table_name_new, '^\(.*\.\)\?\zs.*\ze' )
894 let table_name = matchstr( table_name_new, '^\(.\{-}\.\)\?\zs\(.\{-}\.\)\?.*\ze' )
895 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000896
897 let list_idx = index(s:tbl_name, table_name, 0, &ignorecase)
898 if list_idx > -1
899 let table_cols = split(s:tbl_cols[list_idx])
900 let s:tbl_name[list_idx] = table_name
901 let s:tbl_alias[list_idx] = table_alias
902 else
903 let list_idx = index(s:tbl_alias, table_name, 0, &ignorecase)
904 if list_idx > -1
905 let table_cols = split(s:tbl_cols[list_idx])
906 let s:tbl_name[list_idx] = table_name
907 let s:tbl_alias[list_idx] = table_alias
908 endif
909 endif
910
911 endif
912 else
913 " Simply assume it is a table name provided with a . on the end
914 let found = 1
915 endif
916
917 let @y = saveY
918 let @/ = saveSearch
919 let &wrapscan = saveWScan
920
921 " Return to previous location
922 call cursor(curline, curcol)
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100923
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000924 if found == 0
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000925 if g:loaded_dbext > 300
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000926 exec 'DBSetOption use_tbl_alias='.saveSettingAlias
927 endif
928
929 " Not a SQL statement, do not display a list
930 return []
931 endif
Bram Moolenaardb7207e2012-02-22 17:30:19 +0100932 endif
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000933
934 if empty(table_cols)
935 " Specify silent mode, no messages to the user (tbl, 1)
936 " Specify do not comma separate (tbl, 1, 1)
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100937 " let table_cols_str = DB_getListColumn(table_name, 1, 1)
938 let table_cols_str = DB_getListColumn((owner!=''?owner.'.':'').table_name, 1, 1)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000939
940 if table_cols_str != ""
941 let s:tbl_name = add( s:tbl_name, table_name )
942 let s:tbl_alias = add( s:tbl_alias, table_alias )
943 let s:tbl_cols = add( s:tbl_cols, table_cols_str )
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000944 let table_cols = split(table_cols_str, '\n')
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000945 endif
946
947 endif
948
Bram Moolenaareb3593b2006-04-22 22:33:57 +0000949 if g:loaded_dbext > 300
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000950 exec 'DBSetOption use_tbl_alias='.saveSettingAlias
951 endif
952
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000953 " If the user has asked for a comma separate list of column
954 " values, ask the user if they want to prepend each column
955 " with a tablename alias.
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000956 if a:list_type == 'csv' && !empty(table_cols)
Bram Moolenaarf193fff2006-04-27 00:02:13 +0000957 let cols = join(table_cols, ', ')
958 let cols = s:SQLCAddAlias(table_name, table_alias, cols)
Bram Moolenaare2f98b92006-03-29 21:18:24 +0000959 let table_cols = [cols]
960 endif
961
962 return table_cols
963endfunction
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100964" Restore:
965let &cpo= s:keepcpo
966unlet s:keepcpo
967" vim: ts=4 fdm=marker