1f193fffdSBram Moolenaar" Vim OMNI completion script for SQL 2e2f98b95SBram Moolenaar" Language: SQL 35c73622aSBram Moolenaar" Maintainer: David Fishburn <dfishburn dot vim at gmail dot com> 4*db7207e6SBram Moolenaar" Version: 12.0 5*db7207e6SBram Moolenaar" Last Change: 2012 Feb 08 6f193fffdSBram Moolenaar" Usage: For detailed help 7f193fffdSBram Moolenaar" ":help sql.txt" 8f193fffdSBram Moolenaar" or ":help ft-sql-omni" 9f193fffdSBram Moolenaar" or read $VIMRUNTIME/doc/sql.txt 10e2f98b95SBram Moolenaar 115c73622aSBram Moolenaar" History 12*db7207e6SBram Moolenaar" Version 12.0 13*db7207e6SBram Moolenaar" - Partial column name completion did not work when a table 14*db7207e6SBram Moolenaar" name or table alias was provided (Jonas Enberg). 15*db7207e6SBram Moolenaar" - Improved the handling of column completion. First we match any 16*db7207e6SBram Moolenaar" columns from a previous completion. If not matches are found, we 17*db7207e6SBram Moolenaar" consider the partial name to be a table or table alias for the 18*db7207e6SBram Moolenaar" query and attempt to match on it. 19*db7207e6SBram Moolenaar" 20*db7207e6SBram Moolenaar" Version 11.0 21*db7207e6SBram Moolenaar" Added g:omni_sql_default_compl_type variable 22*db7207e6SBram Moolenaar" - You can specify which type of completion to default to 23*db7207e6SBram Moolenaar" when pressing <C-X><C-O>. The entire list of available 24*db7207e6SBram Moolenaar" choices can be found in the calls to sqlcomplete#Map in: 25*db7207e6SBram Moolenaar" ftplugin/sql.vim 26*db7207e6SBram Moolenaar" 27f9d5ca1dSBram Moolenaar" Version 10.0 28f9d5ca1dSBram Moolenaar" Updated PreCacheSyntax() 29f9d5ca1dSBram Moolenaar" - Now returns a List of the syntax items it finds. 30f9d5ca1dSBram Moolenaar" This allows other plugins / scripts to use this list for their own 31f9d5ca1dSBram Moolenaar" purposes. In this case XPTemplate can use them for a Choose list. 32f9d5ca1dSBram Moolenaar" - Verifies the parameters are the correct type and displays a 33f9d5ca1dSBram Moolenaar" warning if not. 34f9d5ca1dSBram Moolenaar" - Verifies the parameters are the correct type and displays a 35f9d5ca1dSBram Moolenaar" warning if not. 36f9d5ca1dSBram Moolenaar" Updated SQLCWarningMsg() 37f9d5ca1dSBram Moolenaar" - Prepends warning message with SQLComplete so you know who issued 38f9d5ca1dSBram Moolenaar" the warning. 39f9d5ca1dSBram Moolenaar" Updated SQLCErrorMsg() 40f9d5ca1dSBram Moolenaar" - Prepends error message with SQLComplete so you know who issued 41f9d5ca1dSBram Moolenaar" the error. 42f9d5ca1dSBram Moolenaar" 4300a927d6SBram Moolenaar" Version 9.0 4400a927d6SBram Moolenaar" This change removes some of the support for tables with spaces in their 4500a927d6SBram Moolenaar" names in order to simplify the regexes used to pull out query table 4600a927d6SBram Moolenaar" aliases for more robust table name and column name code completion. 4700a927d6SBram Moolenaar" Full support for "table names with spaces" can be added in again 4800a927d6SBram Moolenaar" after 7.3. 49f9d5ca1dSBram Moolenaar" 5000a927d6SBram Moolenaar" Version 8.0 5100a927d6SBram Moolenaar" Incorrectly re-executed the g:ftplugin_sql_omni_key_right and g:ftplugin_sql_omni_key_left 5200a927d6SBram Moolenaar" when drilling in and out of a column list for a table. 53f9d5ca1dSBram Moolenaar" 545c73622aSBram Moolenaar" Version 7.0 555c73622aSBram Moolenaar" Better handling of object names 56f9d5ca1dSBram Moolenaar" 575c73622aSBram Moolenaar" Version 6.0 585c73622aSBram Moolenaar" Supports object names with spaces "my table name" 595c73622aSBram Moolenaar" 60e2f98b95SBram Moolenaar" Set completion with CTRL-X CTRL-O to autoloaded function. 61e2f98b95SBram Moolenaar" This check is in place in case this script is 62e2f98b95SBram Moolenaar" sourced directly instead of using the autoload feature. 63e2f98b95SBram Moolenaarif exists('&omnifunc') 64e2f98b95SBram Moolenaar " Do not set the option if already set since this 65e2f98b95SBram Moolenaar " results in an E117 warning. 66e2f98b95SBram Moolenaar if &omnifunc == "" 67e2f98b95SBram Moolenaar setlocal omnifunc=sqlcomplete#Complete 68e2f98b95SBram Moolenaar endif 69e2f98b95SBram Moolenaarendif 70e2f98b95SBram Moolenaar 71e2f98b95SBram Moolenaarif exists('g:loaded_sql_completion') 72e2f98b95SBram Moolenaar finish 73e2f98b95SBram Moolenaarendif 74*db7207e6SBram Moolenaarlet g:loaded_sql_completion = 120 75e2f98b95SBram Moolenaar 76e2f98b95SBram Moolenaar" Maintains filename of dictionary 77e2f98b95SBram Moolenaarlet s:sql_file_table = "" 78e2f98b95SBram Moolenaarlet s:sql_file_procedure = "" 79e2f98b95SBram Moolenaarlet s:sql_file_view = "" 80e2f98b95SBram Moolenaar 81e2f98b95SBram Moolenaar" Define various arrays to be used for caching 82e2f98b95SBram Moolenaarlet s:tbl_name = [] 83e2f98b95SBram Moolenaarlet s:tbl_alias = [] 84e2f98b95SBram Moolenaarlet s:tbl_cols = [] 85e2f98b95SBram Moolenaarlet s:syn_list = [] 86e2f98b95SBram Moolenaarlet s:syn_value = [] 87e2f98b95SBram Moolenaar 88e2f98b95SBram Moolenaar" Used in conjunction with the syntaxcomplete plugin 89e2f98b95SBram Moolenaarlet s:save_inc = "" 90e2f98b95SBram Moolenaarlet s:save_exc = "" 91e2f98b95SBram Moolenaarif exists('g:omni_syntax_group_include_sql') 92e2f98b95SBram Moolenaar let s:save_inc = g:omni_syntax_group_include_sql 93e2f98b95SBram Moolenaarendif 94e2f98b95SBram Moolenaarif exists('g:omni_syntax_group_exclude_sql') 95e2f98b95SBram Moolenaar let s:save_exc = g:omni_syntax_group_exclude_sql 96e2f98b95SBram Moolenaarendif 97e2f98b95SBram Moolenaar 98e2f98b95SBram Moolenaar" Used with the column list 99e2f98b95SBram Moolenaarlet s:save_prev_table = "" 100e2f98b95SBram Moolenaar 101e2f98b95SBram Moolenaar" Default the option to verify table alias 102e2f98b95SBram Moolenaarif !exists('g:omni_sql_use_tbl_alias') 103e2f98b95SBram Moolenaar let g:omni_sql_use_tbl_alias = 'a' 104e2f98b95SBram Moolenaarendif 105910f66f9SBram Moolenaar" Default syntax items to precache 106910f66f9SBram Moolenaarif !exists('g:omni_sql_precache_syntax_groups') 107910f66f9SBram Moolenaar let g:omni_sql_precache_syntax_groups = [ 108910f66f9SBram Moolenaar \ 'syntax', 109910f66f9SBram Moolenaar \ 'sqlKeyword', 110910f66f9SBram Moolenaar \ 'sqlFunction', 111910f66f9SBram Moolenaar \ 'sqlOption', 112910f66f9SBram Moolenaar \ 'sqlType', 113910f66f9SBram Moolenaar \ 'sqlStatement' 114910f66f9SBram Moolenaar \ ] 115910f66f9SBram Moolenaarendif 116eb3593b3SBram Moolenaar" Set ignorecase to the ftplugin standard 117eb3593b3SBram Moolenaarif !exists('g:omni_sql_ignorecase') 118eb3593b3SBram Moolenaar let g:omni_sql_ignorecase = &ignorecase 119eb3593b3SBram Moolenaarendif 120eb3593b3SBram Moolenaar" During table completion, should the table list also 121eb3593b3SBram Moolenaar" include the owner name 122eb3593b3SBram Moolenaarif !exists('g:omni_sql_include_owner') 123eb3593b3SBram Moolenaar let g:omni_sql_include_owner = 0 124eb3593b3SBram Moolenaar if exists('g:loaded_dbext') 125eb3593b3SBram Moolenaar if g:loaded_dbext >= 300 126eb3593b3SBram Moolenaar " New to dbext 3.00, by default the table lists include the owner 127eb3593b3SBram Moolenaar " name of the table. This is used when determining how much of 128eb3593b3SBram Moolenaar " whatever has been typed should be replaced as part of the 129eb3593b3SBram Moolenaar " code replacement. 130eb3593b3SBram Moolenaar let g:omni_sql_include_owner = 1 131eb3593b3SBram Moolenaar endif 132eb3593b3SBram Moolenaar endif 133eb3593b3SBram Moolenaarendif 134*db7207e6SBram Moolenaar" Default type of completion used when <C-X><C-O> is pressed 135*db7207e6SBram Moolenaarif !exists('g:omni_sql_default_compl_type') 136*db7207e6SBram Moolenaar let g:omni_sql_default_compl_type = 'table' 137*db7207e6SBram Moolenaarendif 138e2f98b95SBram Moolenaar 139e2f98b95SBram Moolenaar" This function is used for the 'omnifunc' option. 140e2f98b95SBram Moolenaarfunction! sqlcomplete#Complete(findstart, base) 141e2f98b95SBram Moolenaar 142e2f98b95SBram Moolenaar " Default to table name completion 143e2f98b95SBram Moolenaar let compl_type = 'table' 144e2f98b95SBram Moolenaar " Allow maps to specify what type of object completion they want 145e2f98b95SBram Moolenaar if exists('b:sql_compl_type') 146e2f98b95SBram Moolenaar let compl_type = b:sql_compl_type 147e2f98b95SBram Moolenaar endif 148e2f98b95SBram Moolenaar 149910f66f9SBram Moolenaar " First pass through this function determines how much of the line should 150910f66f9SBram Moolenaar " be replaced by whatever is chosen from the completion list 151e2f98b95SBram Moolenaar if a:findstart 152e2f98b95SBram Moolenaar " Locate the start of the item, including "." 153e2f98b95SBram Moolenaar let line = getline('.') 154e2f98b95SBram Moolenaar let start = col('.') - 1 155e2f98b95SBram Moolenaar let lastword = -1 156f193fffdSBram Moolenaar let begindot = 0 157f193fffdSBram Moolenaar " Check if the first character is a ".", for column completion 158f193fffdSBram Moolenaar if line[start - 1] == '.' 159f193fffdSBram Moolenaar let begindot = 1 160f193fffdSBram Moolenaar endif 161e2f98b95SBram Moolenaar while start > 0 1625c73622aSBram Moolenaar " Additional code was required to handle objects which 1635c73622aSBram Moolenaar " can contain spaces like "my table name". 1645c73622aSBram Moolenaar if line[start - 1] !~ '\(\w\|\.\)' 1655c73622aSBram Moolenaar " If the previous character is not a period or word character 1665c73622aSBram Moolenaar break 1675c73622aSBram Moolenaar " elseif line[start - 1] =~ '\(\w\|\s\+\)' 1685c73622aSBram Moolenaar " let start -= 1 1695c73622aSBram Moolenaar elseif line[start - 1] =~ '\w' 1705c73622aSBram Moolenaar " If the previous character is word character continue back 171e2f98b95SBram Moolenaar let start -= 1 172eb3593b3SBram Moolenaar elseif line[start - 1] =~ '\.' && 173eb3593b3SBram Moolenaar \ compl_type =~ 'column\|table\|view\|procedure' 1745c73622aSBram Moolenaar " If the previous character is a period and we are completing 1755c73622aSBram Moolenaar " an object which can be specified with a period like this: 1765c73622aSBram Moolenaar " table_name.column_name 1775c73622aSBram Moolenaar " owner_name.table_name 1785c73622aSBram Moolenaar 179eb3593b3SBram Moolenaar " If lastword has already been set for column completion 180eb3593b3SBram Moolenaar " break from the loop, since we do not also want to pickup 181eb3593b3SBram Moolenaar " a table name if it was also supplied. 182f193fffdSBram Moolenaar if lastword != -1 && compl_type == 'column' 183eb3593b3SBram Moolenaar break 184eb3593b3SBram Moolenaar endif 185f193fffdSBram Moolenaar " If column completion was specified stop at the "." if 186f193fffdSBram Moolenaar " a . was specified, otherwise, replace all the way up 187f193fffdSBram Moolenaar " to the owner name (if included). 188f193fffdSBram Moolenaar if lastword == -1 && compl_type == 'column' && begindot == 1 189e2f98b95SBram Moolenaar let lastword = start 190e2f98b95SBram Moolenaar endif 191eb3593b3SBram Moolenaar " If omni_sql_include_owner = 0, do not include the table 192eb3593b3SBram Moolenaar " name as part of the substitution, so break here 193eb3593b3SBram Moolenaar if lastword == -1 && 194f193fffdSBram Moolenaar \ compl_type =~ 'table\|view\|procedure\column_csv' && 195eb3593b3SBram Moolenaar \ g:omni_sql_include_owner == 0 196eb3593b3SBram Moolenaar let lastword = start 197eb3593b3SBram Moolenaar break 198eb3593b3SBram Moolenaar endif 199e2f98b95SBram Moolenaar let start -= 1 200e2f98b95SBram Moolenaar else 201e2f98b95SBram Moolenaar break 202e2f98b95SBram Moolenaar endif 203e2f98b95SBram Moolenaar endwhile 204e2f98b95SBram Moolenaar 205e2f98b95SBram Moolenaar " Return the column of the last word, which is going to be changed. 206e2f98b95SBram Moolenaar " Remember the text that comes before it in s:prepended. 207e2f98b95SBram Moolenaar if lastword == -1 208e2f98b95SBram Moolenaar let s:prepended = '' 209e2f98b95SBram Moolenaar return start 210e2f98b95SBram Moolenaar endif 211e2f98b95SBram Moolenaar let s:prepended = strpart(line, start, lastword - start) 212e2f98b95SBram Moolenaar return lastword 213e2f98b95SBram Moolenaar endif 214e2f98b95SBram Moolenaar 215910f66f9SBram Moolenaar " Second pass through this function will determine what data to put inside 216910f66f9SBram Moolenaar " of the completion list 217910f66f9SBram Moolenaar " s:prepended is set by the first pass 218e2f98b95SBram Moolenaar let base = s:prepended . a:base 219e2f98b95SBram Moolenaar 220910f66f9SBram Moolenaar " Default the completion list to an empty list 221e2f98b95SBram Moolenaar let compl_list = [] 222e2f98b95SBram Moolenaar 223e2f98b95SBram Moolenaar " Default to table name completion 224*db7207e6SBram Moolenaar let compl_type = g:omni_sql_default_compl_type 225e2f98b95SBram Moolenaar " Allow maps to specify what type of object completion they want 226e2f98b95SBram Moolenaar if exists('b:sql_compl_type') 227e2f98b95SBram Moolenaar let compl_type = b:sql_compl_type 228e2f98b95SBram Moolenaar unlet b:sql_compl_type 229e2f98b95SBram Moolenaar endif 230e2f98b95SBram Moolenaar 231e2f98b95SBram Moolenaar if compl_type == 'tableReset' 232e2f98b95SBram Moolenaar let compl_type = 'table' 233e2f98b95SBram Moolenaar let base = '' 234e2f98b95SBram Moolenaar endif 235e2f98b95SBram Moolenaar 236e2f98b95SBram Moolenaar if compl_type == 'table' || 237e2f98b95SBram Moolenaar \ compl_type == 'procedure' || 238e2f98b95SBram Moolenaar \ compl_type == 'view' 239e2f98b95SBram Moolenaar 240e2f98b95SBram Moolenaar " This type of completion relies upon the dbext.vim plugin 241e2f98b95SBram Moolenaar if s:SQLCCheck4dbext() == -1 242e2f98b95SBram Moolenaar return [] 243e2f98b95SBram Moolenaar endif 244e2f98b95SBram Moolenaar 24583e138c6SBram Moolenaar " Allow the user to override the dbext plugin to specify whether 24683e138c6SBram Moolenaar " the owner/creator should be included in the list 2478c8de839SBram Moolenaar if g:loaded_dbext >= 300 2488c8de839SBram Moolenaar let saveSetting = DB_listOption('dict_show_owner') 2498c8de839SBram Moolenaar exec 'DBSetOption dict_show_owner='.(g:omni_sql_include_owner==1?'1':'0') 250e2f98b95SBram Moolenaar endif 25183e138c6SBram Moolenaar 25283e138c6SBram Moolenaar let compl_type_uc = substitute(compl_type, '\w\+', '\u&', '') 2535c73622aSBram Moolenaar " Same call below, no need to do it twice 2545c73622aSBram Moolenaar " if s:sql_file_{compl_type} == "" 2555c73622aSBram Moolenaar " let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc) 2565c73622aSBram Moolenaar " endif 25783e138c6SBram Moolenaar let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc) 258e2f98b95SBram Moolenaar if s:sql_file_{compl_type} != "" 259e2f98b95SBram Moolenaar if filereadable(s:sql_file_{compl_type}) 260e2f98b95SBram Moolenaar let compl_list = readfile(s:sql_file_{compl_type}) 261e2f98b95SBram Moolenaar endif 262e2f98b95SBram Moolenaar endif 26383e138c6SBram Moolenaar 2648c8de839SBram Moolenaar if g:loaded_dbext > 300 2658c8de839SBram Moolenaar exec 'DBSetOption dict_show_owner='.saveSetting 2668c8de839SBram Moolenaar endif 26783e138c6SBram Moolenaar elseif compl_type =~? 'column' 268e2f98b95SBram Moolenaar 269e2f98b95SBram Moolenaar " This type of completion relies upon the dbext.vim plugin 270e2f98b95SBram Moolenaar if s:SQLCCheck4dbext() == -1 271e2f98b95SBram Moolenaar return [] 272e2f98b95SBram Moolenaar endif 273e2f98b95SBram Moolenaar 274e2f98b95SBram Moolenaar if base == "" 275e2f98b95SBram Moolenaar " The last time we displayed a column list we stored 276e2f98b95SBram Moolenaar " the table name. If the user selects a column list 277e2f98b95SBram Moolenaar " without a table name of alias present, assume they want 278e2f98b95SBram Moolenaar " the previous column list displayed. 279e2f98b95SBram Moolenaar let base = s:save_prev_table 280e2f98b95SBram Moolenaar endif 281e2f98b95SBram Moolenaar 28283e138c6SBram Moolenaar let owner = '' 28383e138c6SBram Moolenaar let column = '' 28483e138c6SBram Moolenaar 28583e138c6SBram Moolenaar if base =~ '\.' 28683e138c6SBram Moolenaar " Check if the owner/creator has been specified 28783e138c6SBram Moolenaar let owner = matchstr( base, '^\zs.*\ze\..*\..*' ) 28883e138c6SBram Moolenaar let table = matchstr( base, '^\(.*\.\)\?\zs.*\ze\..*' ) 28983e138c6SBram Moolenaar let column = matchstr( base, '.*\.\zs.*' ) 29083e138c6SBram Moolenaar 29183e138c6SBram Moolenaar " It is pretty well impossible to determine if the user 29283e138c6SBram Moolenaar " has entered: 29383e138c6SBram Moolenaar " owner.table 29483e138c6SBram Moolenaar " table.column_prefix 29583e138c6SBram Moolenaar " So there are a couple of things we can do to mitigate 29683e138c6SBram Moolenaar " this issue. 29783e138c6SBram Moolenaar " 1. Check if the dbext plugin has the option turned 29883e138c6SBram Moolenaar " on to even allow owners 29983e138c6SBram Moolenaar " 2. Based on 1, if the user is showing a table list 30000a927d6SBram Moolenaar " and the DrillIntoTable (using <Right>) then 30183e138c6SBram Moolenaar " this will be owner.table. In this case, we can 30283e138c6SBram Moolenaar " check to see the table.column exists in the 30383e138c6SBram Moolenaar " cached table list. If it does, then we have 30483e138c6SBram Moolenaar " determined the user has actually chosen 30583e138c6SBram Moolenaar " owner.table, not table.column_prefix. 30683e138c6SBram Moolenaar let found = -1 30783e138c6SBram Moolenaar if g:omni_sql_include_owner == 1 && owner == '' 30883e138c6SBram Moolenaar if filereadable(s:sql_file_table) 30983e138c6SBram Moolenaar let tbl_list = readfile(s:sql_file_table) 31083e138c6SBram Moolenaar let found = index( tbl_list, ((table != '')?(table.'.'):'').column) 31183e138c6SBram Moolenaar endif 31283e138c6SBram Moolenaar endif 31383e138c6SBram Moolenaar " If the table.column was found in the table list, we can safely assume 31483e138c6SBram Moolenaar " the owner was not provided and shift the items appropriately. 31583e138c6SBram Moolenaar " OR 31683e138c6SBram Moolenaar " If the user has indicated not to use table owners at all and 31783e138c6SBram Moolenaar " the base ends in a '.' we know they are not providing a column 31883e138c6SBram Moolenaar " name, so we can shift the items appropriately. 319*db7207e6SBram Moolenaar " if found != -1 || (g:omni_sql_include_owner == 0 && base !~ '\.$') 320*db7207e6SBram Moolenaar " let owner = table 321*db7207e6SBram Moolenaar " let table = column 322*db7207e6SBram Moolenaar " let column = '' 323*db7207e6SBram Moolenaar " endif 32483e138c6SBram Moolenaar else 325*db7207e6SBram Moolenaar " If no "." was provided and the user asked for 326*db7207e6SBram Moolenaar " column level completion, first attempt the match 327*db7207e6SBram Moolenaar " on any previous column lists. If the user asked 328*db7207e6SBram Moolenaar " for a list of columns comma separated, continue as usual. 329*db7207e6SBram Moolenaar if compl_type == 'column' && s:save_prev_table != '' 330*db7207e6SBram Moolenaar " The last time we displayed a column list we stored 331*db7207e6SBram Moolenaar " the table name. If the user selects a column list 332*db7207e6SBram Moolenaar " without a table name of alias present, assume they want 333*db7207e6SBram Moolenaar " the previous column list displayed. 334*db7207e6SBram Moolenaar let table = s:save_prev_table 335*db7207e6SBram Moolenaar let list_type = '' 336*db7207e6SBram Moolenaar 337*db7207e6SBram Moolenaar let compl_list = s:SQLCGetColumns(table, list_type) 338*db7207e6SBram Moolenaar if ! empty(compl_list) 339*db7207e6SBram Moolenaar " If no column prefix has been provided and the table 340*db7207e6SBram Moolenaar " name was provided, append it to each of the items 341*db7207e6SBram Moolenaar " returned. 342*db7207e6SBram Moolenaar let compl_list = filter(deepcopy(compl_list), 'v:val=~"^'.base.'"' ) 343*db7207e6SBram Moolenaar 344*db7207e6SBram Moolenaar " If not empty, we have a match on columns 345*db7207e6SBram Moolenaar " return the list 346*db7207e6SBram Moolenaar if ! empty(compl_list) 347*db7207e6SBram Moolenaar return compl_list 348*db7207e6SBram Moolenaar endif 349*db7207e6SBram Moolenaar endif 350*db7207e6SBram Moolenaar endif 351*db7207e6SBram Moolenaar " Since no columns were found to match the base supplied 352*db7207e6SBram Moolenaar " assume the user is trying to complete the column list 353*db7207e6SBram Moolenaar " for a table (and or an alias to a table). 35483e138c6SBram Moolenaar let table = base 35583e138c6SBram Moolenaar endif 35683e138c6SBram Moolenaar 35783e138c6SBram Moolenaar " Get anything after the . and consider this the table name 35883e138c6SBram Moolenaar " If an owner has been specified, then we must consider the 35983e138c6SBram Moolenaar " base to be a partial column name 36083e138c6SBram Moolenaar " let base = matchstr( base, '^\(.*\.\)\?\zs.*' ) 36183e138c6SBram Moolenaar 36283e138c6SBram Moolenaar if table != "" 363e2f98b95SBram Moolenaar let s:save_prev_table = base 36483e138c6SBram Moolenaar let list_type = '' 36583e138c6SBram Moolenaar 36683e138c6SBram Moolenaar if compl_type == 'column_csv' 36783e138c6SBram Moolenaar " Return one array element, with a comma separated 36883e138c6SBram Moolenaar " list of values instead of multiple array entries 36983e138c6SBram Moolenaar " for each column in the table. 37083e138c6SBram Moolenaar let list_type = 'csv' 37183e138c6SBram Moolenaar endif 37283e138c6SBram Moolenaar 37383e138c6SBram Moolenaar let compl_list = s:SQLCGetColumns(table, list_type) 37483e138c6SBram Moolenaar if column != '' 37583e138c6SBram Moolenaar " If no column prefix has been provided and the table 37683e138c6SBram Moolenaar " name was provided, append it to each of the items 37783e138c6SBram Moolenaar " returned. 378*db7207e6SBram Moolenaar let compl_list = map(compl_list, 'table.".".v:val') 37983e138c6SBram Moolenaar if owner != '' 38083e138c6SBram Moolenaar " If an owner has been provided append it to each of the 38183e138c6SBram Moolenaar " items returned. 382*db7207e6SBram Moolenaar let compl_list = map(compl_list, 'owner.".".v:val') 38383e138c6SBram Moolenaar endif 38483e138c6SBram Moolenaar else 385e2f98b95SBram Moolenaar let base = '' 386e2f98b95SBram Moolenaar endif 387e2f98b95SBram Moolenaar 38883e138c6SBram Moolenaar if compl_type == 'column_csv' 389e2f98b95SBram Moolenaar " Join the column array into 1 single element array 390e2f98b95SBram Moolenaar " but make the columns column separated 391e2f98b95SBram Moolenaar let compl_list = [join(compl_list, ', ')] 39283e138c6SBram Moolenaar endif 393e2f98b95SBram Moolenaar endif 394e2f98b95SBram Moolenaar elseif compl_type == 'resetCache' 395e2f98b95SBram Moolenaar " Reset all cached items 396e2f98b95SBram Moolenaar let s:tbl_name = [] 397e2f98b95SBram Moolenaar let s:tbl_alias = [] 398e2f98b95SBram Moolenaar let s:tbl_cols = [] 399e2f98b95SBram Moolenaar let s:syn_list = [] 400e2f98b95SBram Moolenaar let s:syn_value = [] 401f193fffdSBram Moolenaar 402f193fffdSBram Moolenaar let msg = "All SQL cached items have been removed." 403f193fffdSBram Moolenaar call s:SQLCWarningMsg(msg) 404f193fffdSBram Moolenaar " Leave time for the user to read the error message 405f193fffdSBram Moolenaar :sleep 2 406e2f98b95SBram Moolenaar else 407910f66f9SBram Moolenaar let compl_list = s:SQLCGetSyntaxList(compl_type) 408e2f98b95SBram Moolenaar endif 409e2f98b95SBram Moolenaar 410e2f98b95SBram Moolenaar if base != '' 4115c73622aSBram Moolenaar " Filter the list based on the first few characters the user entered. 4125c73622aSBram Moolenaar " Check if the text matches at the beginning 413*db7207e6SBram Moolenaar " \\(^.base.'\\) 4145c73622aSBram Moolenaar " or 4155c73622aSBram Moolenaar " Match to a owner.table or alias.column type match 416*db7207e6SBram Moolenaar " ^\\(\\w\\+\\.\\)\\?'.base.'\\) 4175c73622aSBram Moolenaar " or 4185c73622aSBram Moolenaar " Handle names with spaces "my table name" 419*db7207e6SBram Moolenaar " "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"' 420*db7207e6SBram Moolenaar " 4215c73622aSBram Moolenaar let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"' 4225c73622aSBram Moolenaar " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\)"' 4235c73622aSBram Moolenaar " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\(\\.\\)\\?'.base.'\\)"' 4245c73622aSBram Moolenaar " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\([^.]*\\)\\?'.base.'\\)"' 425eb3593b3SBram Moolenaar let compl_list = filter(deepcopy(compl_list), expr) 426e2f98b95SBram Moolenaar endif 427e2f98b95SBram Moolenaar 428910f66f9SBram Moolenaar if exists('b:sql_compl_savefunc') && b:sql_compl_savefunc != "" 429910f66f9SBram Moolenaar let &omnifunc = b:sql_compl_savefunc 430910f66f9SBram Moolenaar endif 431910f66f9SBram Moolenaar 432e2f98b95SBram Moolenaar return compl_list 433e2f98b95SBram Moolenaarendfunc 434e2f98b95SBram Moolenaar 435910f66f9SBram Moolenaarfunction! sqlcomplete#PreCacheSyntax(...) 436910f66f9SBram Moolenaar let syn_group_arr = [] 437f9d5ca1dSBram Moolenaar let syn_items = [] 438f9d5ca1dSBram Moolenaar 439910f66f9SBram Moolenaar if a:0 > 0 440f9d5ca1dSBram Moolenaar if type(a:1) != 3 441f9d5ca1dSBram Moolenaar call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']") 442f9d5ca1dSBram Moolenaar return '' 443f9d5ca1dSBram Moolenaar endif 444910f66f9SBram Moolenaar let syn_group_arr = a:1 445910f66f9SBram Moolenaar else 446910f66f9SBram Moolenaar let syn_group_arr = g:omni_sql_precache_syntax_groups 447910f66f9SBram Moolenaar endif 44883e138c6SBram Moolenaar " For each group specified in the list, precache all 44983e138c6SBram Moolenaar " the sytnax items. 450910f66f9SBram Moolenaar if !empty(syn_group_arr) 451910f66f9SBram Moolenaar for group_name in syn_group_arr 452f9d5ca1dSBram Moolenaar let syn_items = extend( syn_items, s:SQLCGetSyntaxList(group_name) ) 453f9d5ca1dSBram Moolenaar endfor 454f9d5ca1dSBram Moolenaar endif 455f9d5ca1dSBram Moolenaar 456f9d5ca1dSBram Moolenaar return syn_items 457f9d5ca1dSBram Moolenaarendfunction 458f9d5ca1dSBram Moolenaar 459f9d5ca1dSBram Moolenaarfunction! sqlcomplete#ResetCacheSyntax(...) 460f9d5ca1dSBram Moolenaar let syn_group_arr = [] 461f9d5ca1dSBram Moolenaar 462f9d5ca1dSBram Moolenaar if a:0 > 0 463f9d5ca1dSBram Moolenaar if type(a:1) != 3 464f9d5ca1dSBram Moolenaar call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']") 465f9d5ca1dSBram Moolenaar return '' 466f9d5ca1dSBram Moolenaar endif 467f9d5ca1dSBram Moolenaar let syn_group_arr = a:1 468f9d5ca1dSBram Moolenaar else 469f9d5ca1dSBram Moolenaar let syn_group_arr = g:omni_sql_precache_syntax_groups 470f9d5ca1dSBram Moolenaar endif 471f9d5ca1dSBram Moolenaar " For each group specified in the list, precache all 472f9d5ca1dSBram Moolenaar " the sytnax items. 473f9d5ca1dSBram Moolenaar if !empty(syn_group_arr) 474f9d5ca1dSBram Moolenaar for group_name in syn_group_arr 475f9d5ca1dSBram Moolenaar let list_idx = index(s:syn_list, group_name, 0, &ignorecase) 476f9d5ca1dSBram Moolenaar if list_idx > -1 477f9d5ca1dSBram Moolenaar " Remove from list of groups 478f9d5ca1dSBram Moolenaar call remove( s:syn_list, list_idx ) 479f9d5ca1dSBram Moolenaar " Remove from list of keywords 480f9d5ca1dSBram Moolenaar call remove( s:syn_value, list_idx ) 481f9d5ca1dSBram Moolenaar endif 482910f66f9SBram Moolenaar endfor 483910f66f9SBram Moolenaar endif 484910f66f9SBram Moolenaarendfunction 485910f66f9SBram Moolenaar 486910f66f9SBram Moolenaarfunction! sqlcomplete#Map(type) 487910f66f9SBram Moolenaar " Tell the SQL plugin what you want to complete 488910f66f9SBram Moolenaar let b:sql_compl_type=a:type 489910f66f9SBram Moolenaar " Record previous omnifunc, if the SQL completion 490910f66f9SBram Moolenaar " is being used in conjunction with other filetype 491910f66f9SBram Moolenaar " completion plugins 492910f66f9SBram Moolenaar if &omnifunc != "" && &omnifunc != 'sqlcomplete#Complete' 493910f66f9SBram Moolenaar " Record the previous omnifunc, the plugin 494910f66f9SBram Moolenaar " will automatically set this back so that it 495910f66f9SBram Moolenaar " does not interfere with other ftplugins settings 496910f66f9SBram Moolenaar let b:sql_compl_savefunc=&omnifunc 497910f66f9SBram Moolenaar endif 498910f66f9SBram Moolenaar " Set the OMNI func for the SQL completion plugin 499910f66f9SBram Moolenaar let &omnifunc='sqlcomplete#Complete' 500910f66f9SBram Moolenaarendfunction 501910f66f9SBram Moolenaar 502f193fffdSBram Moolenaarfunction! sqlcomplete#DrillIntoTable() 503f193fffdSBram Moolenaar " If the omni popup window is visible 504f193fffdSBram Moolenaar if pumvisible() 505f193fffdSBram Moolenaar call sqlcomplete#Map('column') 506f193fffdSBram Moolenaar " C-Y, makes the currently highlighted entry active 507f193fffdSBram Moolenaar " and trigger the omni popup to be redisplayed 50800a927d6SBram Moolenaar call feedkeys("\<C-Y>\<C-X>\<C-O>", 'n') 509f193fffdSBram Moolenaar else 510f193fffdSBram Moolenaar " If the popup is not visible, simple perform the normal 51100a927d6SBram Moolenaar " key behaviour. 51200a927d6SBram Moolenaar " Must use exec since they key must be preceeded by "\" 51300a927d6SBram Moolenaar " or feedkeys will simply push each character of the string 51400a927d6SBram Moolenaar " rather than the "key press". 51500a927d6SBram Moolenaar exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_right.'", "n")' 516f193fffdSBram Moolenaar endif 517f193fffdSBram Moolenaar return "" 518f193fffdSBram Moolenaarendfunction 519f193fffdSBram Moolenaar 520f193fffdSBram Moolenaarfunction! sqlcomplete#DrillOutOfColumns() 521f193fffdSBram Moolenaar " If the omni popup window is visible 522f193fffdSBram Moolenaar if pumvisible() 523f193fffdSBram Moolenaar call sqlcomplete#Map('tableReset') 524f193fffdSBram Moolenaar " Trigger the omni popup to be redisplayed 525f193fffdSBram Moolenaar call feedkeys("\<C-X>\<C-O>") 526f193fffdSBram Moolenaar else 527f193fffdSBram Moolenaar " If the popup is not visible, simple perform the normal 52800a927d6SBram Moolenaar " key behaviour. 52900a927d6SBram Moolenaar " Must use exec since they key must be preceeded by "\" 53000a927d6SBram Moolenaar " or feedkeys will simply push each character of the string 53100a927d6SBram Moolenaar " rather than the "key press". 53200a927d6SBram Moolenaar exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_left.'", "n")' 533f193fffdSBram Moolenaar endif 534f193fffdSBram Moolenaar return "" 535f193fffdSBram Moolenaarendfunction 536f193fffdSBram Moolenaar 537f193fffdSBram Moolenaarfunction! s:SQLCWarningMsg(msg) 538f193fffdSBram Moolenaar echohl WarningMsg 539f9d5ca1dSBram Moolenaar echomsg 'SQLComplete:'.a:msg 540f193fffdSBram Moolenaar echohl None 541f193fffdSBram Moolenaarendfunction 542f193fffdSBram Moolenaar 543f193fffdSBram Moolenaarfunction! s:SQLCErrorMsg(msg) 544f193fffdSBram Moolenaar echohl ErrorMsg 545f9d5ca1dSBram Moolenaar echomsg 'SQLComplete:'.a:msg 546f193fffdSBram Moolenaar echohl None 547f193fffdSBram Moolenaarendfunction 548f193fffdSBram Moolenaar 549910f66f9SBram Moolenaarfunction! s:SQLCGetSyntaxList(syn_group) 550910f66f9SBram Moolenaar let syn_group = a:syn_group 551910f66f9SBram Moolenaar let compl_list = [] 552910f66f9SBram Moolenaar 553910f66f9SBram Moolenaar " Check if we have already cached the syntax list 554910f66f9SBram Moolenaar let list_idx = index(s:syn_list, syn_group, 0, &ignorecase) 555910f66f9SBram Moolenaar if list_idx > -1 556910f66f9SBram Moolenaar " Return previously cached value 557910f66f9SBram Moolenaar let compl_list = s:syn_value[list_idx] 558910f66f9SBram Moolenaar else 559910f66f9SBram Moolenaar " Request the syntax list items from the 560910f66f9SBram Moolenaar " syntax completion plugin 561910f66f9SBram Moolenaar if syn_group == 'syntax' 562910f66f9SBram Moolenaar " Handle this special case. This allows the user 563910f66f9SBram Moolenaar " to indicate they want all the syntax items available, 564910f66f9SBram Moolenaar " so do not specify a specific include list. 565910f66f9SBram Moolenaar let g:omni_syntax_group_include_sql = '' 566910f66f9SBram Moolenaar else 567910f66f9SBram Moolenaar " The user has specified a specific syntax group 568910f66f9SBram Moolenaar let g:omni_syntax_group_include_sql = syn_group 569910f66f9SBram Moolenaar endif 570910f66f9SBram Moolenaar let g:omni_syntax_group_exclude_sql = '' 571f9d5ca1dSBram Moolenaar let syn_value = syntaxcomplete#OmniSyntaxList() 572910f66f9SBram Moolenaar let g:omni_syntax_group_include_sql = s:save_inc 573910f66f9SBram Moolenaar let g:omni_syntax_group_exclude_sql = s:save_exc 574910f66f9SBram Moolenaar " Cache these values for later use 575910f66f9SBram Moolenaar let s:syn_list = add( s:syn_list, syn_group ) 576910f66f9SBram Moolenaar let s:syn_value = add( s:syn_value, syn_value ) 577910f66f9SBram Moolenaar let compl_list = syn_value 578910f66f9SBram Moolenaar endif 579910f66f9SBram Moolenaar 580910f66f9SBram Moolenaar return compl_list 581910f66f9SBram Moolenaarendfunction 582910f66f9SBram Moolenaar 583e2f98b95SBram Moolenaarfunction! s:SQLCCheck4dbext() 584e2f98b95SBram Moolenaar if !exists('g:loaded_dbext') 585e2f98b95SBram Moolenaar let msg = "The dbext plugin must be loaded for dynamic SQL completion" 586e2f98b95SBram Moolenaar call s:SQLCErrorMsg(msg) 587e2f98b95SBram Moolenaar " Leave time for the user to read the error message 588e2f98b95SBram Moolenaar :sleep 2 589e2f98b95SBram Moolenaar return -1 5908c8de839SBram Moolenaar elseif g:loaded_dbext < 600 5918c8de839SBram Moolenaar let msg = "The dbext plugin must be at least version 5.30 " . 592e2f98b95SBram Moolenaar \ " for dynamic SQL completion" 593e2f98b95SBram Moolenaar call s:SQLCErrorMsg(msg) 594e2f98b95SBram Moolenaar " Leave time for the user to read the error message 595e2f98b95SBram Moolenaar :sleep 2 596e2f98b95SBram Moolenaar return -1 597e2f98b95SBram Moolenaar endif 598e2f98b95SBram Moolenaar return 1 599e2f98b95SBram Moolenaarendfunction 600e2f98b95SBram Moolenaar 601e2f98b95SBram Moolenaarfunction! s:SQLCAddAlias(table_name, table_alias, cols) 602f193fffdSBram Moolenaar " Strip off the owner if included 603f193fffdSBram Moolenaar let table_name = matchstr(a:table_name, '\%(.\{-}\.\)\?\zs\(.*\)' ) 604e2f98b95SBram Moolenaar let table_alias = a:table_alias 605e2f98b95SBram Moolenaar let cols = a:cols 606e2f98b95SBram Moolenaar 607e2f98b95SBram Moolenaar if g:omni_sql_use_tbl_alias != 'n' 608e2f98b95SBram Moolenaar if table_alias == '' 609e2f98b95SBram Moolenaar if 'da' =~? g:omni_sql_use_tbl_alias 610e2f98b95SBram Moolenaar if table_name =~ '_' 611e2f98b95SBram Moolenaar " Treat _ as separators since people often use these 612e2f98b95SBram Moolenaar " for word separators 613e2f98b95SBram Moolenaar let save_keyword = &iskeyword 614e2f98b95SBram Moolenaar setlocal iskeyword-=_ 615e2f98b95SBram Moolenaar 616e2f98b95SBram Moolenaar " Get the first letter of each word 617e2f98b95SBram Moolenaar " [[:alpha:]] is used instead of \w 618e2f98b95SBram Moolenaar " to catch extended accented characters 619e2f98b95SBram Moolenaar " 620e2f98b95SBram Moolenaar let table_alias = substitute( 621e2f98b95SBram Moolenaar \ table_name, 622e2f98b95SBram Moolenaar \ '\<[[:alpha:]]\+\>_\?', 623e2f98b95SBram Moolenaar \ '\=strpart(submatch(0), 0, 1)', 624e2f98b95SBram Moolenaar \ 'g' 625e2f98b95SBram Moolenaar \ ) 626e2f98b95SBram Moolenaar " Restore original value 627e2f98b95SBram Moolenaar let &iskeyword = save_keyword 628e2f98b95SBram Moolenaar elseif table_name =~ '\u\U' 629f193fffdSBram Moolenaar let table_alias = substitute( 630e2f98b95SBram Moolenaar \ table_name, '\(\u\)\U*', '\1', 'g') 631e2f98b95SBram Moolenaar else 632e2f98b95SBram Moolenaar let table_alias = strpart(table_name, 0, 1) 633e2f98b95SBram Moolenaar endif 634e2f98b95SBram Moolenaar endif 635e2f98b95SBram Moolenaar endif 636e2f98b95SBram Moolenaar if table_alias != '' 637e2f98b95SBram Moolenaar " Following a word character, make sure there is a . and no spaces 638e2f98b95SBram Moolenaar let table_alias = substitute(table_alias, '\w\zs\.\?\s*$', '.', '') 639e2f98b95SBram Moolenaar if 'a' =~? g:omni_sql_use_tbl_alias && a:table_alias == '' 640e2f98b95SBram Moolenaar let table_alias = inputdialog("Enter table alias:", table_alias) 641e2f98b95SBram Moolenaar endif 642e2f98b95SBram Moolenaar endif 643e2f98b95SBram Moolenaar if table_alias != '' 644e2f98b95SBram Moolenaar let cols = substitute(cols, '\<\w', table_alias.'&', 'g') 645e2f98b95SBram Moolenaar endif 646e2f98b95SBram Moolenaar endif 647e2f98b95SBram Moolenaar 648e2f98b95SBram Moolenaar return cols 649e2f98b95SBram Moolenaarendfunction 650e2f98b95SBram Moolenaar 65183e138c6SBram Moolenaarfunction! s:SQLCGetObjectOwner(object) 65283e138c6SBram Moolenaar " The owner regex matches a word at the start of the string which is 65383e138c6SBram Moolenaar " followed by a dot, but doesn't include the dot in the result. 65483e138c6SBram Moolenaar " ^ - from beginning of line 6558c8de839SBram Moolenaar " \("\|\[\)\? - ignore any quotes 65683e138c6SBram Moolenaar " \zs - start the match now 6578c8de839SBram Moolenaar " .\{-} - get owner name 65883e138c6SBram Moolenaar " \ze - end the match 6598c8de839SBram Moolenaar " \("\|\[\)\? - ignore any quotes 66083e138c6SBram Moolenaar " \. - must by followed by a . 6618c8de839SBram Moolenaar " let owner = matchstr( a:object, '^\s*\zs.*\ze\.' ) 6628c8de839SBram Moolenaar let owner = matchstr( a:object, '^\("\|\[\)\?\zs\.\{-}\ze\("\|\]\)\?\.' ) 66383e138c6SBram Moolenaar return owner 66483e138c6SBram Moolenaarendfunction 66583e138c6SBram Moolenaar 666e2f98b95SBram Moolenaarfunction! s:SQLCGetColumns(table_name, list_type) 66783e138c6SBram Moolenaar " Check if the table name was provided as part of the column name 6688c8de839SBram Moolenaar let table_name = matchstr(a:table_name, '^["\[\]a-zA-Z0-9_ ]\+\ze\.\?') 669e2f98b95SBram Moolenaar let table_cols = [] 670e2f98b95SBram Moolenaar let table_alias = '' 671e2f98b95SBram Moolenaar let move_to_top = 1 672e2f98b95SBram Moolenaar 6738c8de839SBram Moolenaar let table_name = substitute(table_name, '\s*\(.\{-}\)\s*$', '\1', 'g') 6748c8de839SBram Moolenaar 6758c8de839SBram Moolenaar " If the table name was given as: 6768c8de839SBram Moolenaar " where c. 6778c8de839SBram Moolenaar let table_name = substitute(table_name, '^\c\(WHERE\|AND\|OR\)\s\+', '', '') 678eb3593b3SBram Moolenaar if g:loaded_dbext >= 300 679e2f98b95SBram Moolenaar let saveSettingAlias = DB_listOption('use_tbl_alias') 680e2f98b95SBram Moolenaar exec 'DBSetOption use_tbl_alias=n' 681e2f98b95SBram Moolenaar endif 682e2f98b95SBram Moolenaar 6838c8de839SBram Moolenaar let table_name_stripped = substitute(table_name, '["\[\]]*', '', 'g') 6848c8de839SBram Moolenaar 685e2f98b95SBram Moolenaar " Check if we have already cached the column list for this table 686e2f98b95SBram Moolenaar " by its name 6878c8de839SBram Moolenaar let list_idx = index(s:tbl_name, table_name_stripped, 0, &ignorecase) 688e2f98b95SBram Moolenaar if list_idx > -1 6898c8de839SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx], '\n') 690e2f98b95SBram Moolenaar else 691e2f98b95SBram Moolenaar " Check if we have already cached the column list for this table 692e2f98b95SBram Moolenaar " by its alias, assuming the table_name provided was actually 693e2f98b95SBram Moolenaar " the alias for the table instead 694e2f98b95SBram Moolenaar " select * 695e2f98b95SBram Moolenaar " from area a 696e2f98b95SBram Moolenaar " where a. 6978c8de839SBram Moolenaar let list_idx = index(s:tbl_alias, table_name_stripped, 0, &ignorecase) 698e2f98b95SBram Moolenaar if list_idx > -1 6998c8de839SBram Moolenaar let table_alias = table_name_stripped 700e2f98b95SBram Moolenaar let table_name = s:tbl_name[list_idx] 7018c8de839SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx], '\n') 702e2f98b95SBram Moolenaar endif 703e2f98b95SBram Moolenaar endif 704e2f98b95SBram Moolenaar 705e2f98b95SBram Moolenaar " If we have not found a cached copy of the table 706e2f98b95SBram Moolenaar " And the table ends in a "." or we are looking for a column list 707e2f98b95SBram Moolenaar " if list_idx == -1 && (a:table_name =~ '\.' || b:sql_compl_type =~ 'column') 708e2f98b95SBram Moolenaar " if list_idx == -1 && (a:table_name =~ '\.' || a:list_type =~ 'csv') 709e2f98b95SBram Moolenaar if list_idx == -1 710e2f98b95SBram Moolenaar let saveY = @y 711e2f98b95SBram Moolenaar let saveSearch = @/ 712e2f98b95SBram Moolenaar let saveWScan = &wrapscan 713e2f98b95SBram Moolenaar let curline = line(".") 714e2f98b95SBram Moolenaar let curcol = col(".") 715e2f98b95SBram Moolenaar 716e2f98b95SBram Moolenaar " Do not let searchs wrap 717e2f98b95SBram Moolenaar setlocal nowrapscan 718e2f98b95SBram Moolenaar " If . was entered, look at the word just before the . 719e2f98b95SBram Moolenaar " We are looking for something like this: 720e2f98b95SBram Moolenaar " select * 721e2f98b95SBram Moolenaar " from customer c 722e2f98b95SBram Moolenaar " where c. 723e2f98b95SBram Moolenaar " So when . is pressed, we need to find 'c' 724e2f98b95SBram Moolenaar " 725e2f98b95SBram Moolenaar 726e2f98b95SBram Moolenaar " Search backwards to the beginning of the statement 727e2f98b95SBram Moolenaar " and do NOT wrap 728e2f98b95SBram Moolenaar " exec 'silent! normal! v?\<\(select\|update\|delete\|;\)\>'."\n".'"yy' 72900a927d6SBram Moolenaar exec 'silent! normal! ?\<\c\(select\|update\|delete\|;\)\>'."\n" 730e2f98b95SBram Moolenaar 731e2f98b95SBram Moolenaar " Start characterwise visual mode 732e2f98b95SBram Moolenaar " Advance right one character 733e2f98b95SBram Moolenaar " Search foward until one of the following: 734e2f98b95SBram Moolenaar " 1. Another select/update/delete statement 735e2f98b95SBram Moolenaar " 2. A ; at the end of a line (the delimiter) 736e2f98b95SBram Moolenaar " 3. The end of the file (incase no delimiter) 737e2f98b95SBram Moolenaar " Yank the visually selected text into the "y register. 73800a927d6SBram Moolenaar exec 'silent! normal! vl/\c\(\<select\>\|\<update\>\|\<delete\>\|;\s*$\|\%$\)'."\n".'"yy' 739e2f98b95SBram Moolenaar 740e2f98b95SBram Moolenaar let query = @y 741e2f98b95SBram Moolenaar let query = substitute(query, "\n", ' ', 'g') 742e2f98b95SBram Moolenaar let found = 0 743e2f98b95SBram Moolenaar 74400a927d6SBram Moolenaar " if query =~? '^\c\(select\)' 74500a927d6SBram Moolenaar if query =~? '^\(select\|update\|delete\)' 746e2f98b95SBram Moolenaar let found = 1 747e2f98b95SBram Moolenaar " \(\(\<\w\+\>\)\.\)\? - 74800a927d6SBram Moolenaar " '\c\(from\|join\|,\).\{-}' - Starting at the from clause (case insensitive) 749e2f98b95SBram Moolenaar " '\zs\(\(\<\w\+\>\)\.\)\?' - Get the owner name (optional) 750e2f98b95SBram Moolenaar " '\<\w\+\>\ze' - Get the table name 751e2f98b95SBram Moolenaar " '\s\+\<'.table_name.'\>' - Followed by the alias 752e2f98b95SBram Moolenaar " '\s*\.\@!.*' - Cannot be followed by a . 753e2f98b95SBram Moolenaar " '\(\<where\>\|$\)' - Must be followed by a WHERE clause 754e2f98b95SBram Moolenaar " '.*' - Exclude the rest of the line in the match 75500a927d6SBram Moolenaar " let table_name_new = matchstr(@y, 75600a927d6SBram Moolenaar " \ '\c\(from\|join\|,\).\{-}'. 75700a927d6SBram Moolenaar " \ '\zs\(\("\|\[\)\?.\{-}\("\|\]\)\.\)\?'. 75800a927d6SBram Moolenaar " \ '\("\|\[\)\?.\{-}\("\|\]\)\?\ze'. 75900a927d6SBram Moolenaar " \ '\s\+\%(as\s\+\)\?\<'. 76000a927d6SBram Moolenaar " \ matchstr(table_name, '.\{-}\ze\.\?$'). 76100a927d6SBram Moolenaar " \ '\>'. 76200a927d6SBram Moolenaar " \ '\s*\.\@!.*'. 76300a927d6SBram Moolenaar " \ '\(\<where\>\|$\)'. 76400a927d6SBram Moolenaar " \ '.*' 76500a927d6SBram Moolenaar " \ ) 766*db7207e6SBram Moolenaar " 767*db7207e6SBram Moolenaar " 768*db7207e6SBram Moolenaar " ''\c\(\<from\>\|\<join\>\|,\)\s*' - Starting at the from clause (case insensitive) 769*db7207e6SBram Moolenaar " '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?' - Get the owner name (optional) 770*db7207e6SBram Moolenaar " '\("\|\[\)\?\w\+\("\|\]\)\?\ze' - Get the table name 771*db7207e6SBram Moolenaar " '\s\+\%(as\s\+\)\?\<'.matchstr(table_name, '.\{-}\ze\.\?$').'\>' - Followed by the alias 772*db7207e6SBram Moolenaar " '\s*\.\@!.*' - Cannot be followed by a . 773*db7207e6SBram Moolenaar " '\(\<where\>\|$\)' - Must be followed by a WHERE clause 774*db7207e6SBram Moolenaar " '.*' - Exclude the rest of the line in the match 775e2f98b95SBram Moolenaar let table_name_new = matchstr(@y, 77600a927d6SBram Moolenaar \ '\c\(\<from\>\|\<join\>\|,\)\s*'. 77700a927d6SBram Moolenaar \ '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?'. 77800a927d6SBram Moolenaar \ '\("\|\[\)\?\w\+\("\|\]\)\?\ze'. 779f193fffdSBram Moolenaar \ '\s\+\%(as\s\+\)\?\<'. 780f193fffdSBram Moolenaar \ matchstr(table_name, '.\{-}\ze\.\?$'). 781f193fffdSBram Moolenaar \ '\>'. 782e2f98b95SBram Moolenaar \ '\s*\.\@!.*'. 783e2f98b95SBram Moolenaar \ '\(\<where\>\|$\)'. 784e2f98b95SBram Moolenaar \ '.*' 785e2f98b95SBram Moolenaar \ ) 7868c8de839SBram Moolenaar 787e2f98b95SBram Moolenaar if table_name_new != '' 788e2f98b95SBram Moolenaar let table_alias = table_name 78900a927d6SBram Moolenaar let table_name = matchstr( table_name_new, '^\(.*\.\)\?\zs.*\ze' ) 790e2f98b95SBram Moolenaar 791e2f98b95SBram Moolenaar let list_idx = index(s:tbl_name, table_name, 0, &ignorecase) 792e2f98b95SBram Moolenaar if list_idx > -1 793e2f98b95SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx]) 794e2f98b95SBram Moolenaar let s:tbl_name[list_idx] = table_name 795e2f98b95SBram Moolenaar let s:tbl_alias[list_idx] = table_alias 796e2f98b95SBram Moolenaar else 797e2f98b95SBram Moolenaar let list_idx = index(s:tbl_alias, table_name, 0, &ignorecase) 798e2f98b95SBram Moolenaar if list_idx > -1 799e2f98b95SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx]) 800e2f98b95SBram Moolenaar let s:tbl_name[list_idx] = table_name 801e2f98b95SBram Moolenaar let s:tbl_alias[list_idx] = table_alias 802e2f98b95SBram Moolenaar endif 803e2f98b95SBram Moolenaar endif 804e2f98b95SBram Moolenaar 805e2f98b95SBram Moolenaar endif 806e2f98b95SBram Moolenaar else 807e2f98b95SBram Moolenaar " Simply assume it is a table name provided with a . on the end 808e2f98b95SBram Moolenaar let found = 1 809e2f98b95SBram Moolenaar endif 810e2f98b95SBram Moolenaar 811e2f98b95SBram Moolenaar let @y = saveY 812e2f98b95SBram Moolenaar let @/ = saveSearch 813e2f98b95SBram Moolenaar let &wrapscan = saveWScan 814e2f98b95SBram Moolenaar 815e2f98b95SBram Moolenaar " Return to previous location 816e2f98b95SBram Moolenaar call cursor(curline, curcol) 817e2f98b95SBram Moolenaar 818e2f98b95SBram Moolenaar if found == 0 819eb3593b3SBram Moolenaar if g:loaded_dbext > 300 820e2f98b95SBram Moolenaar exec 'DBSetOption use_tbl_alias='.saveSettingAlias 821e2f98b95SBram Moolenaar endif 822e2f98b95SBram Moolenaar 823e2f98b95SBram Moolenaar " Not a SQL statement, do not display a list 824e2f98b95SBram Moolenaar return [] 825e2f98b95SBram Moolenaar endif 826e2f98b95SBram Moolenaar endif 827e2f98b95SBram Moolenaar 828e2f98b95SBram Moolenaar if empty(table_cols) 829e2f98b95SBram Moolenaar " Specify silent mode, no messages to the user (tbl, 1) 830e2f98b95SBram Moolenaar " Specify do not comma separate (tbl, 1, 1) 831e2f98b95SBram Moolenaar let table_cols_str = DB_getListColumn(table_name, 1, 1) 832e2f98b95SBram Moolenaar 833e2f98b95SBram Moolenaar if table_cols_str != "" 834e2f98b95SBram Moolenaar let s:tbl_name = add( s:tbl_name, table_name ) 835e2f98b95SBram Moolenaar let s:tbl_alias = add( s:tbl_alias, table_alias ) 836e2f98b95SBram Moolenaar let s:tbl_cols = add( s:tbl_cols, table_cols_str ) 8378c8de839SBram Moolenaar let table_cols = split(table_cols_str, '\n') 838e2f98b95SBram Moolenaar endif 839e2f98b95SBram Moolenaar 840e2f98b95SBram Moolenaar endif 841e2f98b95SBram Moolenaar 842eb3593b3SBram Moolenaar if g:loaded_dbext > 300 843e2f98b95SBram Moolenaar exec 'DBSetOption use_tbl_alias='.saveSettingAlias 844e2f98b95SBram Moolenaar endif 845e2f98b95SBram Moolenaar 846f193fffdSBram Moolenaar " If the user has asked for a comma separate list of column 847f193fffdSBram Moolenaar " values, ask the user if they want to prepend each column 848f193fffdSBram Moolenaar " with a tablename alias. 849e2f98b95SBram Moolenaar if a:list_type == 'csv' && !empty(table_cols) 850e2f98b95SBram Moolenaar let cols = join(table_cols, ', ') 851e2f98b95SBram Moolenaar let cols = s:SQLCAddAlias(table_name, table_alias, cols) 852e2f98b95SBram Moolenaar let table_cols = [cols] 853e2f98b95SBram Moolenaar endif 854e2f98b95SBram Moolenaar 855e2f98b95SBram Moolenaar return table_cols 856e2f98b95SBram Moolenaarendfunction 857