1e2f98b95SBram Moolenaar" Vim completion script 2e2f98b95SBram Moolenaar" Language: SQL 3e2f98b95SBram Moolenaar" Maintainer: David Fishburn <[email protected]> 4*eb3593b3SBram Moolenaar" Version: 3.0 5*eb3593b3SBram Moolenaar" Last Change: Thu Apr 20 2006 8:47:12 PM 6e2f98b95SBram Moolenaar 7e2f98b95SBram Moolenaar" Set completion with CTRL-X CTRL-O to autoloaded function. 8e2f98b95SBram Moolenaar" This check is in place in case this script is 9e2f98b95SBram Moolenaar" sourced directly instead of using the autoload feature. 10e2f98b95SBram Moolenaarif exists('&omnifunc') 11e2f98b95SBram Moolenaar " Do not set the option if already set since this 12e2f98b95SBram Moolenaar " results in an E117 warning. 13e2f98b95SBram Moolenaar if &omnifunc == "" 14e2f98b95SBram Moolenaar setlocal omnifunc=sqlcomplete#Complete 15e2f98b95SBram Moolenaar endif 16e2f98b95SBram Moolenaarendif 17e2f98b95SBram Moolenaar 18e2f98b95SBram Moolenaarif exists('g:loaded_sql_completion') 19e2f98b95SBram Moolenaar finish 20e2f98b95SBram Moolenaarendif 21*eb3593b3SBram Moolenaarlet g:loaded_sql_completion = 30 22e2f98b95SBram Moolenaar 23e2f98b95SBram Moolenaar" Maintains filename of dictionary 24e2f98b95SBram Moolenaarlet s:sql_file_table = "" 25e2f98b95SBram Moolenaarlet s:sql_file_procedure = "" 26e2f98b95SBram Moolenaarlet s:sql_file_view = "" 27e2f98b95SBram Moolenaar 28e2f98b95SBram Moolenaar" Define various arrays to be used for caching 29e2f98b95SBram Moolenaarlet s:tbl_name = [] 30e2f98b95SBram Moolenaarlet s:tbl_alias = [] 31e2f98b95SBram Moolenaarlet s:tbl_cols = [] 32e2f98b95SBram Moolenaarlet s:syn_list = [] 33e2f98b95SBram Moolenaarlet s:syn_value = [] 34e2f98b95SBram Moolenaar 35e2f98b95SBram Moolenaar" Used in conjunction with the syntaxcomplete plugin 36e2f98b95SBram Moolenaarlet s:save_inc = "" 37e2f98b95SBram Moolenaarlet s:save_exc = "" 38e2f98b95SBram Moolenaarif exists('g:omni_syntax_group_include_sql') 39e2f98b95SBram Moolenaar let s:save_inc = g:omni_syntax_group_include_sql 40e2f98b95SBram Moolenaarendif 41e2f98b95SBram Moolenaarif exists('g:omni_syntax_group_exclude_sql') 42e2f98b95SBram Moolenaar let s:save_exc = g:omni_syntax_group_exclude_sql 43e2f98b95SBram Moolenaarendif 44e2f98b95SBram Moolenaar 45e2f98b95SBram Moolenaar" Used with the column list 46e2f98b95SBram Moolenaarlet s:save_prev_table = "" 47e2f98b95SBram Moolenaar 48e2f98b95SBram Moolenaar" Default the option to verify table alias 49e2f98b95SBram Moolenaarif !exists('g:omni_sql_use_tbl_alias') 50e2f98b95SBram Moolenaar let g:omni_sql_use_tbl_alias = 'a' 51e2f98b95SBram Moolenaarendif 52910f66f9SBram Moolenaar" Default syntax items to precache 53910f66f9SBram Moolenaarif !exists('g:omni_sql_precache_syntax_groups') 54910f66f9SBram Moolenaar let g:omni_sql_precache_syntax_groups = [ 55910f66f9SBram Moolenaar \ 'syntax', 56910f66f9SBram Moolenaar \ 'sqlKeyword', 57910f66f9SBram Moolenaar \ 'sqlFunction', 58910f66f9SBram Moolenaar \ 'sqlOption', 59910f66f9SBram Moolenaar \ 'sqlType', 60910f66f9SBram Moolenaar \ 'sqlStatement' 61910f66f9SBram Moolenaar \ ] 62910f66f9SBram Moolenaarendif 63*eb3593b3SBram Moolenaar" Set ignorecase to the ftplugin standard 64*eb3593b3SBram Moolenaarif !exists('g:omni_sql_ignorecase') 65*eb3593b3SBram Moolenaar let g:omni_sql_ignorecase = &ignorecase 66*eb3593b3SBram Moolenaarendif 67*eb3593b3SBram Moolenaar" During table completion, should the table list also 68*eb3593b3SBram Moolenaar" include the owner name 69*eb3593b3SBram Moolenaarif !exists('g:omni_sql_include_owner') 70*eb3593b3SBram Moolenaar let g:omni_sql_include_owner = 0 71*eb3593b3SBram Moolenaar if exists('g:loaded_dbext') 72*eb3593b3SBram Moolenaar if g:loaded_dbext >= 300 73*eb3593b3SBram Moolenaar " New to dbext 3.00, by default the table lists include the owner 74*eb3593b3SBram Moolenaar " name of the table. This is used when determining how much of 75*eb3593b3SBram Moolenaar " whatever has been typed should be replaced as part of the 76*eb3593b3SBram Moolenaar " code replacement. 77*eb3593b3SBram Moolenaar let g:omni_sql_include_owner = 1 78*eb3593b3SBram Moolenaar endif 79*eb3593b3SBram Moolenaar endif 80*eb3593b3SBram Moolenaarendif 81e2f98b95SBram Moolenaar 82e2f98b95SBram Moolenaar" This function is used for the 'omnifunc' option. 83e2f98b95SBram Moolenaarfunction! sqlcomplete#Complete(findstart, base) 84e2f98b95SBram Moolenaar 85e2f98b95SBram Moolenaar " Default to table name completion 86e2f98b95SBram Moolenaar let compl_type = 'table' 87e2f98b95SBram Moolenaar " Allow maps to specify what type of object completion they want 88e2f98b95SBram Moolenaar if exists('b:sql_compl_type') 89e2f98b95SBram Moolenaar let compl_type = b:sql_compl_type 90e2f98b95SBram Moolenaar endif 91e2f98b95SBram Moolenaar 92910f66f9SBram Moolenaar " First pass through this function determines how much of the line should 93910f66f9SBram Moolenaar " be replaced by whatever is chosen from the completion list 94e2f98b95SBram Moolenaar if a:findstart 95e2f98b95SBram Moolenaar " Locate the start of the item, including "." 96e2f98b95SBram Moolenaar let line = getline('.') 97e2f98b95SBram Moolenaar let start = col('.') - 1 98e2f98b95SBram Moolenaar let lastword = -1 99e2f98b95SBram Moolenaar while start > 0 100e2f98b95SBram Moolenaar if line[start - 1] =~ '\w' 101e2f98b95SBram Moolenaar let start -= 1 102*eb3593b3SBram Moolenaar elseif line[start - 1] =~ '\.' && 103*eb3593b3SBram Moolenaar \ compl_type =~ 'column\|table\|view\|procedure' 104*eb3593b3SBram Moolenaar " If lastword has already been set for column completion 105*eb3593b3SBram Moolenaar " break from the loop, since we do not also want to pickup 106*eb3593b3SBram Moolenaar " a table name if it was also supplied. 107*eb3593b3SBram Moolenaar if lastword != -1 && compl_type =~ 'column' 108*eb3593b3SBram Moolenaar break 109*eb3593b3SBram Moolenaar endif 110*eb3593b3SBram Moolenaar " Assume we are looking for column completion 111*eb3593b3SBram Moolenaar " column_type can be either 'column' or 'column_csv' 112*eb3593b3SBram Moolenaar if lastword == -1 && compl_type =~ 'column' 113e2f98b95SBram Moolenaar let lastword = start 114e2f98b95SBram Moolenaar endif 115*eb3593b3SBram Moolenaar " If omni_sql_include_owner = 0, do not include the table 116*eb3593b3SBram Moolenaar " name as part of the substitution, so break here 117*eb3593b3SBram Moolenaar if lastword == -1 && 118*eb3593b3SBram Moolenaar \ compl_type =~ 'table\|view\|procedure' && 119*eb3593b3SBram Moolenaar \ g:omni_sql_include_owner == 0 120*eb3593b3SBram Moolenaar let lastword = start 121*eb3593b3SBram Moolenaar break 122*eb3593b3SBram Moolenaar endif 123e2f98b95SBram Moolenaar let start -= 1 124e2f98b95SBram Moolenaar else 125e2f98b95SBram Moolenaar break 126e2f98b95SBram Moolenaar endif 127e2f98b95SBram Moolenaar endwhile 128e2f98b95SBram Moolenaar 129e2f98b95SBram Moolenaar " Return the column of the last word, which is going to be changed. 130e2f98b95SBram Moolenaar " Remember the text that comes before it in s:prepended. 131e2f98b95SBram Moolenaar if lastword == -1 132e2f98b95SBram Moolenaar let s:prepended = '' 133e2f98b95SBram Moolenaar return start 134e2f98b95SBram Moolenaar endif 135e2f98b95SBram Moolenaar let s:prepended = strpart(line, start, lastword - start) 136e2f98b95SBram Moolenaar return lastword 137e2f98b95SBram Moolenaar endif 138e2f98b95SBram Moolenaar 139910f66f9SBram Moolenaar " Second pass through this function will determine what data to put inside 140910f66f9SBram Moolenaar " of the completion list 141910f66f9SBram Moolenaar " s:prepended is set by the first pass 142e2f98b95SBram Moolenaar let base = s:prepended . a:base 143e2f98b95SBram Moolenaar 144910f66f9SBram Moolenaar " Default the completion list to an empty list 145e2f98b95SBram Moolenaar let compl_list = [] 146e2f98b95SBram Moolenaar 147e2f98b95SBram Moolenaar " Default to table name completion 148e2f98b95SBram Moolenaar let compl_type = 'table' 149e2f98b95SBram Moolenaar " Allow maps to specify what type of object completion they want 150e2f98b95SBram Moolenaar if exists('b:sql_compl_type') 151e2f98b95SBram Moolenaar let compl_type = b:sql_compl_type 152e2f98b95SBram Moolenaar unlet b:sql_compl_type 153e2f98b95SBram Moolenaar endif 154e2f98b95SBram Moolenaar 155e2f98b95SBram Moolenaar if compl_type == 'tableReset' 156e2f98b95SBram Moolenaar let compl_type = 'table' 157e2f98b95SBram Moolenaar let base = '' 158e2f98b95SBram Moolenaar endif 159e2f98b95SBram Moolenaar 160e2f98b95SBram Moolenaar if compl_type == 'table' || 161e2f98b95SBram Moolenaar \ compl_type == 'procedure' || 162e2f98b95SBram Moolenaar \ compl_type == 'view' 163e2f98b95SBram Moolenaar 164e2f98b95SBram Moolenaar " This type of completion relies upon the dbext.vim plugin 165e2f98b95SBram Moolenaar if s:SQLCCheck4dbext() == -1 166e2f98b95SBram Moolenaar return [] 167e2f98b95SBram Moolenaar endif 168e2f98b95SBram Moolenaar 169e2f98b95SBram Moolenaar if s:sql_file_{compl_type} == "" 170e2f98b95SBram Moolenaar let compl_type = substitute(compl_type, '\w\+', '\u&', '') 171e2f98b95SBram Moolenaar let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type) 172e2f98b95SBram Moolenaar endif 173e2f98b95SBram Moolenaar let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type) 174e2f98b95SBram Moolenaar if s:sql_file_{compl_type} != "" 175e2f98b95SBram Moolenaar if filereadable(s:sql_file_{compl_type}) 176e2f98b95SBram Moolenaar let compl_list = readfile(s:sql_file_{compl_type}) 177*eb3593b3SBram Moolenaar " let dic_list = readfile(s:sql_file_{compl_type}) 178*eb3593b3SBram Moolenaar " if !empty(dic_list) 179*eb3593b3SBram Moolenaar " for elem in dic_list 180*eb3593b3SBram Moolenaar " let kind = (compl_type=='table'?'m':(compl_type=='procedure'?'f':'v')) 181*eb3593b3SBram Moolenaar " let item = {'word':elem, 'menu':elem, 'kind':kind, 'info':compl_type} 182*eb3593b3SBram Moolenaar " let compl_list += [item] 183*eb3593b3SBram Moolenaar " endfor 184*eb3593b3SBram Moolenaar " endif 185e2f98b95SBram Moolenaar endif 186e2f98b95SBram Moolenaar endif 187e2f98b95SBram Moolenaar elseif compl_type == 'column' 188e2f98b95SBram Moolenaar 189e2f98b95SBram Moolenaar " This type of completion relies upon the dbext.vim plugin 190e2f98b95SBram Moolenaar if s:SQLCCheck4dbext() == -1 191e2f98b95SBram Moolenaar return [] 192e2f98b95SBram Moolenaar endif 193e2f98b95SBram Moolenaar 194e2f98b95SBram Moolenaar if base == "" 195e2f98b95SBram Moolenaar " The last time we displayed a column list we stored 196e2f98b95SBram Moolenaar " the table name. If the user selects a column list 197e2f98b95SBram Moolenaar " without a table name of alias present, assume they want 198e2f98b95SBram Moolenaar " the previous column list displayed. 199e2f98b95SBram Moolenaar let base = s:save_prev_table 200e2f98b95SBram Moolenaar endif 201e2f98b95SBram Moolenaar 202e2f98b95SBram Moolenaar if base != "" 203e2f98b95SBram Moolenaar let compl_list = s:SQLCGetColumns(base, '') 204e2f98b95SBram Moolenaar let s:save_prev_table = base 205e2f98b95SBram Moolenaar let base = '' 206e2f98b95SBram Moolenaar endif 207e2f98b95SBram Moolenaar elseif compl_type == 'column_csv' 208e2f98b95SBram Moolenaar 209e2f98b95SBram Moolenaar " This type of completion relies upon the dbext.vim plugin 210e2f98b95SBram Moolenaar if s:SQLCCheck4dbext() == -1 211e2f98b95SBram Moolenaar return [] 212e2f98b95SBram Moolenaar endif 213e2f98b95SBram Moolenaar 214e2f98b95SBram Moolenaar if base == "" 215e2f98b95SBram Moolenaar " The last time we displayed a column list we stored 216e2f98b95SBram Moolenaar " the table name. If the user selects a column list 217e2f98b95SBram Moolenaar " without a table name of alias present, assume they want 218e2f98b95SBram Moolenaar " the previous column list displayed. 219e2f98b95SBram Moolenaar let base = s:save_prev_table 220e2f98b95SBram Moolenaar endif 221e2f98b95SBram Moolenaar 222e2f98b95SBram Moolenaar if base != "" 223e2f98b95SBram Moolenaar let compl_list = s:SQLCGetColumns(base, 'csv') 224e2f98b95SBram Moolenaar let s:save_prev_table = base 225e2f98b95SBram Moolenaar " Join the column array into 1 single element array 226e2f98b95SBram Moolenaar " but make the columns column separated 227e2f98b95SBram Moolenaar let compl_list = [join(compl_list, ', ')] 228e2f98b95SBram Moolenaar let base = '' 229e2f98b95SBram Moolenaar endif 230e2f98b95SBram Moolenaar elseif compl_type == 'resetCache' 231e2f98b95SBram Moolenaar " Reset all cached items 232e2f98b95SBram Moolenaar let s:tbl_name = [] 233e2f98b95SBram Moolenaar let s:tbl_alias = [] 234e2f98b95SBram Moolenaar let s:tbl_cols = [] 235e2f98b95SBram Moolenaar let s:syn_list = [] 236e2f98b95SBram Moolenaar let s:syn_value = [] 237e2f98b95SBram Moolenaar else 238910f66f9SBram Moolenaar let compl_list = s:SQLCGetSyntaxList(compl_type) 239e2f98b95SBram Moolenaar endif 240e2f98b95SBram Moolenaar 241e2f98b95SBram Moolenaar if base != '' 242e2f98b95SBram Moolenaar " Filter the list based on the first few characters the user 243e2f98b95SBram Moolenaar " entered 244*eb3593b3SBram Moolenaar let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "^'.base.'"' 245*eb3593b3SBram Moolenaar let compl_list = filter(deepcopy(compl_list), expr) 246e2f98b95SBram Moolenaar endif 247e2f98b95SBram Moolenaar 248910f66f9SBram Moolenaar if exists('b:sql_compl_savefunc') && b:sql_compl_savefunc != "" 249910f66f9SBram Moolenaar let &omnifunc = b:sql_compl_savefunc 250910f66f9SBram Moolenaar endif 251910f66f9SBram Moolenaar 252e2f98b95SBram Moolenaar return compl_list 253e2f98b95SBram Moolenaarendfunc 254e2f98b95SBram Moolenaar 255e2f98b95SBram Moolenaarfunction! s:SQLCWarningMsg(msg) 256e2f98b95SBram Moolenaar echohl WarningMsg 257e2f98b95SBram Moolenaar echomsg a:msg 258e2f98b95SBram Moolenaar echohl None 259e2f98b95SBram Moolenaarendfunction 260e2f98b95SBram Moolenaar 261e2f98b95SBram Moolenaarfunction! s:SQLCErrorMsg(msg) 262e2f98b95SBram Moolenaar echohl ErrorMsg 263e2f98b95SBram Moolenaar echomsg a:msg 264e2f98b95SBram Moolenaar echohl None 265e2f98b95SBram Moolenaarendfunction 266e2f98b95SBram Moolenaar 267910f66f9SBram Moolenaarfunction! sqlcomplete#PreCacheSyntax(...) 268910f66f9SBram Moolenaar let syn_group_arr = [] 269910f66f9SBram Moolenaar if a:0 > 0 270910f66f9SBram Moolenaar let syn_group_arr = a:1 271910f66f9SBram Moolenaar else 272910f66f9SBram Moolenaar let syn_group_arr = g:omni_sql_precache_syntax_groups 273910f66f9SBram Moolenaar endif 274910f66f9SBram Moolenaar if !empty(syn_group_arr) 275910f66f9SBram Moolenaar for group_name in syn_group_arr 276910f66f9SBram Moolenaar call s:SQLCGetSyntaxList(group_name) 277910f66f9SBram Moolenaar endfor 278910f66f9SBram Moolenaar endif 279910f66f9SBram Moolenaarendfunction 280910f66f9SBram Moolenaar 281910f66f9SBram Moolenaarfunction! sqlcomplete#Map(type) 282910f66f9SBram Moolenaar " Tell the SQL plugin what you want to complete 283910f66f9SBram Moolenaar let b:sql_compl_type=a:type 284910f66f9SBram Moolenaar " Record previous omnifunc, if the SQL completion 285910f66f9SBram Moolenaar " is being used in conjunction with other filetype 286910f66f9SBram Moolenaar " completion plugins 287910f66f9SBram Moolenaar if &omnifunc != "" && &omnifunc != 'sqlcomplete#Complete' 288910f66f9SBram Moolenaar " Record the previous omnifunc, the plugin 289910f66f9SBram Moolenaar " will automatically set this back so that it 290910f66f9SBram Moolenaar " does not interfere with other ftplugins settings 291910f66f9SBram Moolenaar let b:sql_compl_savefunc=&omnifunc 292910f66f9SBram Moolenaar endif 293910f66f9SBram Moolenaar " Set the OMNI func for the SQL completion plugin 294910f66f9SBram Moolenaar let &omnifunc='sqlcomplete#Complete' 295910f66f9SBram Moolenaarendfunction 296910f66f9SBram Moolenaar 297910f66f9SBram Moolenaarfunction! s:SQLCGetSyntaxList(syn_group) 298910f66f9SBram Moolenaar let syn_group = a:syn_group 299910f66f9SBram Moolenaar let compl_list = [] 300910f66f9SBram Moolenaar 301910f66f9SBram Moolenaar " Check if we have already cached the syntax list 302910f66f9SBram Moolenaar let list_idx = index(s:syn_list, syn_group, 0, &ignorecase) 303910f66f9SBram Moolenaar if list_idx > -1 304910f66f9SBram Moolenaar " Return previously cached value 305910f66f9SBram Moolenaar let compl_list = s:syn_value[list_idx] 306910f66f9SBram Moolenaar else 307910f66f9SBram Moolenaar " Request the syntax list items from the 308910f66f9SBram Moolenaar " syntax completion plugin 309910f66f9SBram Moolenaar if syn_group == 'syntax' 310910f66f9SBram Moolenaar " Handle this special case. This allows the user 311910f66f9SBram Moolenaar " to indicate they want all the syntax items available, 312910f66f9SBram Moolenaar " so do not specify a specific include list. 313910f66f9SBram Moolenaar let g:omni_syntax_group_include_sql = '' 314910f66f9SBram Moolenaar else 315910f66f9SBram Moolenaar " The user has specified a specific syntax group 316910f66f9SBram Moolenaar let g:omni_syntax_group_include_sql = syn_group 317910f66f9SBram Moolenaar endif 318910f66f9SBram Moolenaar let g:omni_syntax_group_exclude_sql = '' 319910f66f9SBram Moolenaar let syn_value = OmniSyntaxList() 320910f66f9SBram Moolenaar let g:omni_syntax_group_include_sql = s:save_inc 321910f66f9SBram Moolenaar let g:omni_syntax_group_exclude_sql = s:save_exc 322910f66f9SBram Moolenaar " Cache these values for later use 323910f66f9SBram Moolenaar let s:syn_list = add( s:syn_list, syn_group ) 324910f66f9SBram Moolenaar let s:syn_value = add( s:syn_value, syn_value ) 325910f66f9SBram Moolenaar let compl_list = syn_value 326910f66f9SBram Moolenaar endif 327910f66f9SBram Moolenaar 328910f66f9SBram Moolenaar return compl_list 329910f66f9SBram Moolenaarendfunction 330910f66f9SBram Moolenaar 331e2f98b95SBram Moolenaarfunction! s:SQLCCheck4dbext() 332e2f98b95SBram Moolenaar if !exists('g:loaded_dbext') 333e2f98b95SBram Moolenaar let msg = "The dbext plugin must be loaded for dynamic SQL completion" 334e2f98b95SBram Moolenaar call s:SQLCErrorMsg(msg) 335e2f98b95SBram Moolenaar " Leave time for the user to read the error message 336e2f98b95SBram Moolenaar :sleep 2 337e2f98b95SBram Moolenaar return -1 338*eb3593b3SBram Moolenaar elseif g:loaded_dbext < 300 339*eb3593b3SBram Moolenaar let msg = "The dbext plugin must be at least version 3.00 " . 340e2f98b95SBram Moolenaar \ " for dynamic SQL completion" 341e2f98b95SBram Moolenaar call s:SQLCErrorMsg(msg) 342e2f98b95SBram Moolenaar " Leave time for the user to read the error message 343e2f98b95SBram Moolenaar :sleep 2 344e2f98b95SBram Moolenaar return -1 345e2f98b95SBram Moolenaar endif 346e2f98b95SBram Moolenaar return 1 347e2f98b95SBram Moolenaarendfunction 348e2f98b95SBram Moolenaar 349e2f98b95SBram Moolenaarfunction! s:SQLCAddAlias(table_name, table_alias, cols) 350e2f98b95SBram Moolenaar let table_name = a:table_name 351e2f98b95SBram Moolenaar let table_alias = a:table_alias 352e2f98b95SBram Moolenaar let cols = a:cols 353e2f98b95SBram Moolenaar 354e2f98b95SBram Moolenaar if g:omni_sql_use_tbl_alias != 'n' 355e2f98b95SBram Moolenaar if table_alias == '' 356e2f98b95SBram Moolenaar if 'da' =~? g:omni_sql_use_tbl_alias 357e2f98b95SBram Moolenaar if table_name =~ '_' 358e2f98b95SBram Moolenaar " Treat _ as separators since people often use these 359e2f98b95SBram Moolenaar " for word separators 360e2f98b95SBram Moolenaar let save_keyword = &iskeyword 361e2f98b95SBram Moolenaar setlocal iskeyword-=_ 362e2f98b95SBram Moolenaar 363e2f98b95SBram Moolenaar " Get the first letter of each word 364e2f98b95SBram Moolenaar " [[:alpha:]] is used instead of \w 365e2f98b95SBram Moolenaar " to catch extended accented characters 366e2f98b95SBram Moolenaar " 367e2f98b95SBram Moolenaar let table_alias = substitute( 368e2f98b95SBram Moolenaar \ table_name, 369e2f98b95SBram Moolenaar \ '\<[[:alpha:]]\+\>_\?', 370e2f98b95SBram Moolenaar \ '\=strpart(submatch(0), 0, 1)', 371e2f98b95SBram Moolenaar \ 'g' 372e2f98b95SBram Moolenaar \ ) 373e2f98b95SBram Moolenaar " Restore original value 374e2f98b95SBram Moolenaar let &iskeyword = save_keyword 375e2f98b95SBram Moolenaar elseif table_name =~ '\u\U' 376e2f98b95SBram Moolenaar let initials = substitute( 377e2f98b95SBram Moolenaar \ table_name, '\(\u\)\U*', '\1', 'g') 378e2f98b95SBram Moolenaar else 379e2f98b95SBram Moolenaar let table_alias = strpart(table_name, 0, 1) 380e2f98b95SBram Moolenaar endif 381e2f98b95SBram Moolenaar endif 382e2f98b95SBram Moolenaar endif 383e2f98b95SBram Moolenaar if table_alias != '' 384e2f98b95SBram Moolenaar " Following a word character, make sure there is a . and no spaces 385e2f98b95SBram Moolenaar let table_alias = substitute(table_alias, '\w\zs\.\?\s*$', '.', '') 386e2f98b95SBram Moolenaar if 'a' =~? g:omni_sql_use_tbl_alias && a:table_alias == '' 387e2f98b95SBram Moolenaar let table_alias = inputdialog("Enter table alias:", table_alias) 388e2f98b95SBram Moolenaar endif 389e2f98b95SBram Moolenaar endif 390e2f98b95SBram Moolenaar if table_alias != '' 391e2f98b95SBram Moolenaar let cols = substitute(cols, '\<\w', table_alias.'&', 'g') 392e2f98b95SBram Moolenaar endif 393e2f98b95SBram Moolenaar endif 394e2f98b95SBram Moolenaar 395e2f98b95SBram Moolenaar return cols 396e2f98b95SBram Moolenaarendfunction 397e2f98b95SBram Moolenaar 398e2f98b95SBram Moolenaarfunction! s:SQLCGetColumns(table_name, list_type) 399e2f98b95SBram Moolenaar let table_name = matchstr(a:table_name, '^\w\+') 400e2f98b95SBram Moolenaar let table_cols = [] 401e2f98b95SBram Moolenaar let table_alias = '' 402e2f98b95SBram Moolenaar let move_to_top = 1 403e2f98b95SBram Moolenaar 404*eb3593b3SBram Moolenaar if g:loaded_dbext >= 300 405e2f98b95SBram Moolenaar let saveSettingAlias = DB_listOption('use_tbl_alias') 406e2f98b95SBram Moolenaar exec 'DBSetOption use_tbl_alias=n' 407e2f98b95SBram Moolenaar endif 408e2f98b95SBram Moolenaar 409e2f98b95SBram Moolenaar " Check if we have already cached the column list for this table 410e2f98b95SBram Moolenaar " by its name 411e2f98b95SBram Moolenaar let list_idx = index(s:tbl_name, table_name, 0, &ignorecase) 412e2f98b95SBram Moolenaar if list_idx > -1 413e2f98b95SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx]) 414e2f98b95SBram Moolenaar else 415e2f98b95SBram Moolenaar " Check if we have already cached the column list for this table 416e2f98b95SBram Moolenaar " by its alias, assuming the table_name provided was actually 417e2f98b95SBram Moolenaar " the alias for the table instead 418e2f98b95SBram Moolenaar " select * 419e2f98b95SBram Moolenaar " from area a 420e2f98b95SBram Moolenaar " where a. 421e2f98b95SBram Moolenaar let list_idx = index(s:tbl_alias, table_name, 0, &ignorecase) 422e2f98b95SBram Moolenaar if list_idx > -1 423e2f98b95SBram Moolenaar let table_alias = table_name 424e2f98b95SBram Moolenaar let table_name = s:tbl_name[list_idx] 425e2f98b95SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx]) 426e2f98b95SBram Moolenaar endif 427e2f98b95SBram Moolenaar endif 428e2f98b95SBram Moolenaar 429e2f98b95SBram Moolenaar " If we have not found a cached copy of the table 430e2f98b95SBram Moolenaar " And the table ends in a "." or we are looking for a column list 431e2f98b95SBram Moolenaar " if list_idx == -1 && (a:table_name =~ '\.' || b:sql_compl_type =~ 'column') 432e2f98b95SBram Moolenaar " if list_idx == -1 && (a:table_name =~ '\.' || a:list_type =~ 'csv') 433e2f98b95SBram Moolenaar if list_idx == -1 434e2f98b95SBram Moolenaar let saveY = @y 435e2f98b95SBram Moolenaar let saveSearch = @/ 436e2f98b95SBram Moolenaar let saveWScan = &wrapscan 437e2f98b95SBram Moolenaar let curline = line(".") 438e2f98b95SBram Moolenaar let curcol = col(".") 439e2f98b95SBram Moolenaar 440e2f98b95SBram Moolenaar " Do not let searchs wrap 441e2f98b95SBram Moolenaar setlocal nowrapscan 442e2f98b95SBram Moolenaar " If . was entered, look at the word just before the . 443e2f98b95SBram Moolenaar " We are looking for something like this: 444e2f98b95SBram Moolenaar " select * 445e2f98b95SBram Moolenaar " from customer c 446e2f98b95SBram Moolenaar " where c. 447e2f98b95SBram Moolenaar " So when . is pressed, we need to find 'c' 448e2f98b95SBram Moolenaar " 449e2f98b95SBram Moolenaar 450e2f98b95SBram Moolenaar " Search backwards to the beginning of the statement 451e2f98b95SBram Moolenaar " and do NOT wrap 452e2f98b95SBram Moolenaar " exec 'silent! normal! v?\<\(select\|update\|delete\|;\)\>'."\n".'"yy' 453e2f98b95SBram Moolenaar exec 'silent! normal! ?\<\(select\|update\|delete\|;\)\>'."\n" 454e2f98b95SBram Moolenaar 455e2f98b95SBram Moolenaar " Start characterwise visual mode 456e2f98b95SBram Moolenaar " Advance right one character 457e2f98b95SBram Moolenaar " Search foward until one of the following: 458e2f98b95SBram Moolenaar " 1. Another select/update/delete statement 459e2f98b95SBram Moolenaar " 2. A ; at the end of a line (the delimiter) 460e2f98b95SBram Moolenaar " 3. The end of the file (incase no delimiter) 461e2f98b95SBram Moolenaar " Yank the visually selected text into the "y register. 462e2f98b95SBram Moolenaar exec 'silent! normal! vl/\(\<select\>\|\<update\>\|\<delete\>\|;\s*$\|\%$\)'."\n".'"yy' 463e2f98b95SBram Moolenaar 464e2f98b95SBram Moolenaar let query = @y 465e2f98b95SBram Moolenaar let query = substitute(query, "\n", ' ', 'g') 466e2f98b95SBram Moolenaar let found = 0 467e2f98b95SBram Moolenaar 468e2f98b95SBram Moolenaar " if query =~? '^\(select\|update\|delete\)' 469e2f98b95SBram Moolenaar if query =~? '^\(select\)' 470e2f98b95SBram Moolenaar let found = 1 471e2f98b95SBram Moolenaar " \(\(\<\w\+\>\)\.\)\? - 472e2f98b95SBram Moolenaar " 'from.\{-}' - Starting at the from clause 473e2f98b95SBram Moolenaar " '\zs\(\(\<\w\+\>\)\.\)\?' - Get the owner name (optional) 474e2f98b95SBram Moolenaar " '\<\w\+\>\ze' - Get the table name 475e2f98b95SBram Moolenaar " '\s\+\<'.table_name.'\>' - Followed by the alias 476e2f98b95SBram Moolenaar " '\s*\.\@!.*' - Cannot be followed by a . 477e2f98b95SBram Moolenaar " '\(\<where\>\|$\)' - Must be followed by a WHERE clause 478e2f98b95SBram Moolenaar " '.*' - Exclude the rest of the line in the match 479e2f98b95SBram Moolenaar let table_name_new = matchstr(@y, 480e2f98b95SBram Moolenaar \ 'from.\{-}'. 481e2f98b95SBram Moolenaar \ '\zs\(\(\<\w\+\>\)\.\)\?'. 482e2f98b95SBram Moolenaar \ '\<\w\+\>\ze'. 483e2f98b95SBram Moolenaar \ '\s\+\%(as\s\+\)\?\<'.table_name.'\>'. 484e2f98b95SBram Moolenaar \ '\s*\.\@!.*'. 485e2f98b95SBram Moolenaar \ '\(\<where\>\|$\)'. 486e2f98b95SBram Moolenaar \ '.*' 487e2f98b95SBram Moolenaar \ ) 488e2f98b95SBram Moolenaar if table_name_new != '' 489e2f98b95SBram Moolenaar let table_alias = table_name 490e2f98b95SBram Moolenaar let table_name = table_name_new 491e2f98b95SBram Moolenaar 492e2f98b95SBram Moolenaar let list_idx = index(s:tbl_name, table_name, 0, &ignorecase) 493e2f98b95SBram Moolenaar if list_idx > -1 494e2f98b95SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx]) 495e2f98b95SBram Moolenaar let s:tbl_name[list_idx] = table_name 496e2f98b95SBram Moolenaar let s:tbl_alias[list_idx] = table_alias 497e2f98b95SBram Moolenaar else 498e2f98b95SBram Moolenaar let list_idx = index(s:tbl_alias, table_name, 0, &ignorecase) 499e2f98b95SBram Moolenaar if list_idx > -1 500e2f98b95SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx]) 501e2f98b95SBram Moolenaar let s:tbl_name[list_idx] = table_name 502e2f98b95SBram Moolenaar let s:tbl_alias[list_idx] = table_alias 503e2f98b95SBram Moolenaar endif 504e2f98b95SBram Moolenaar endif 505e2f98b95SBram Moolenaar 506e2f98b95SBram Moolenaar endif 507e2f98b95SBram Moolenaar else 508e2f98b95SBram Moolenaar " Simply assume it is a table name provided with a . on the end 509e2f98b95SBram Moolenaar let found = 1 510e2f98b95SBram Moolenaar endif 511e2f98b95SBram Moolenaar 512e2f98b95SBram Moolenaar let @y = saveY 513e2f98b95SBram Moolenaar let @/ = saveSearch 514e2f98b95SBram Moolenaar let &wrapscan = saveWScan 515e2f98b95SBram Moolenaar 516e2f98b95SBram Moolenaar " Return to previous location 517e2f98b95SBram Moolenaar call cursor(curline, curcol) 518e2f98b95SBram Moolenaar 519e2f98b95SBram Moolenaar if found == 0 520*eb3593b3SBram Moolenaar if g:loaded_dbext > 300 521e2f98b95SBram Moolenaar exec 'DBSetOption use_tbl_alias='.saveSettingAlias 522e2f98b95SBram Moolenaar endif 523e2f98b95SBram Moolenaar 524e2f98b95SBram Moolenaar " Not a SQL statement, do not display a list 525e2f98b95SBram Moolenaar return [] 526e2f98b95SBram Moolenaar endif 527e2f98b95SBram Moolenaar endif 528e2f98b95SBram Moolenaar 529e2f98b95SBram Moolenaar if empty(table_cols) 530e2f98b95SBram Moolenaar " Specify silent mode, no messages to the user (tbl, 1) 531e2f98b95SBram Moolenaar " Specify do not comma separate (tbl, 1, 1) 532e2f98b95SBram Moolenaar let table_cols_str = DB_getListColumn(table_name, 1, 1) 533e2f98b95SBram Moolenaar 534e2f98b95SBram Moolenaar if table_cols_str != "" 535e2f98b95SBram Moolenaar let s:tbl_name = add( s:tbl_name, table_name ) 536e2f98b95SBram Moolenaar let s:tbl_alias = add( s:tbl_alias, table_alias ) 537e2f98b95SBram Moolenaar let s:tbl_cols = add( s:tbl_cols, table_cols_str ) 538e2f98b95SBram Moolenaar let table_cols = split(table_cols_str) 539e2f98b95SBram Moolenaar endif 540e2f98b95SBram Moolenaar 541e2f98b95SBram Moolenaar endif 542e2f98b95SBram Moolenaar 543*eb3593b3SBram Moolenaar if g:loaded_dbext > 300 544e2f98b95SBram Moolenaar exec 'DBSetOption use_tbl_alias='.saveSettingAlias 545e2f98b95SBram Moolenaar endif 546e2f98b95SBram Moolenaar 547e2f98b95SBram Moolenaar if a:list_type == 'csv' && !empty(table_cols) 548e2f98b95SBram Moolenaar let cols = join(table_cols, ', ') 549e2f98b95SBram Moolenaar let cols = s:SQLCAddAlias(table_name, table_alias, cols) 550e2f98b95SBram Moolenaar let table_cols = [cols] 551e2f98b95SBram Moolenaar endif 552e2f98b95SBram Moolenaar 553e2f98b95SBram Moolenaar return table_cols 554e2f98b95SBram Moolenaarendfunction 555e2f98b95SBram Moolenaar 556