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*ad3b366cSBram Moolenaar" Version: 15.0 5*ad3b366cSBram Moolenaar" Last Change: 2013 May 13 634feacbcSBram Moolenaar" Homepage: http://www.vim.org/scripts/script.php?script_id=1572 7f193fffdSBram Moolenaar" Usage: For detailed help 8f193fffdSBram Moolenaar" ":help sql.txt" 9f193fffdSBram Moolenaar" or ":help ft-sql-omni" 10f193fffdSBram Moolenaar" or read $VIMRUNTIME/doc/sql.txt 11e2f98b95SBram Moolenaar 125c73622aSBram Moolenaar" History 1334feacbcSBram Moolenaar" 14*ad3b366cSBram Moolenaar" TODO 15*ad3b366cSBram Moolenaar" - Jonas Enberg - if no table is found when using column completion 16*ad3b366cSBram Moolenaar" look backwards to a FROM clause and find the first table 17*ad3b366cSBram Moolenaar" and complete it. 18*ad3b366cSBram Moolenaar" 19*ad3b366cSBram Moolenaar" Version 15.0 (May 2013) 20*ad3b366cSBram Moolenaar" - NF: Changed the SQL precached syntax items, omni_sql_precache_syntax_groups, 21*ad3b366cSBram Moolenaar" to use regular expressions to pick up extended syntax group names. 22*ad3b366cSBram Moolenaar" This requires an updated SyntaxComplete plugin version 13.0. 23*ad3b366cSBram Moolenaar" If the required versions have not been installed, previous 24*ad3b366cSBram Moolenaar" behaviour will not be impacted. 25*ad3b366cSBram Moolenaar" 2634feacbcSBram Moolenaar" Version 14.0 (Dec 2012) 2734feacbcSBram Moolenaar" - BF: Added check for cpo 2834feacbcSBram Moolenaar" 2934feacbcSBram Moolenaar" Version 13.0 (Dec 2012) 3034feacbcSBram Moolenaar" - NF: When completing column lists or drilling into a table 3134feacbcSBram Moolenaar" and g:omni_sql_include_owner is enabled, the 3234feacbcSBram Moolenaar" only the table name would be replaced with the column 3334feacbcSBram Moolenaar" list instead of the table name and owner (if specified). 3434feacbcSBram Moolenaar" - NF: When completing column lists using table aliases 3534feacbcSBram Moolenaar" and g:omni_sql_include_owner is enabled, account 3634feacbcSBram Moolenaar" for the owner name when looking up the table 3734feacbcSBram Moolenaar" list instead of the table name and owner (if specified). 3834feacbcSBram Moolenaar" - BF: When completing column lists or drilling into a table 3934feacbcSBram Moolenaar" and g:omni_sql_include_owner is enabled, the 4034feacbcSBram Moolenaar" column list could often not be found for the table. 4134feacbcSBram Moolenaar" - BF: When OMNI popped up, possibly the wrong word 4234feacbcSBram Moolenaar" would be replaced for column and column list options. 4334feacbcSBram Moolenaar" 4434feacbcSBram Moolenaar" Version 12.0 (Feb 2012) 45db7207e6SBram Moolenaar" - Partial column name completion did not work when a table 46db7207e6SBram Moolenaar" name or table alias was provided (Jonas Enberg). 47db7207e6SBram Moolenaar" - Improved the handling of column completion. First we match any 48db7207e6SBram Moolenaar" columns from a previous completion. If not matches are found, we 49db7207e6SBram Moolenaar" consider the partial name to be a table or table alias for the 50db7207e6SBram Moolenaar" query and attempt to match on it. 51db7207e6SBram Moolenaar" 5234feacbcSBram Moolenaar" Version 11.0 (Jan 2012) 53db7207e6SBram Moolenaar" Added g:omni_sql_default_compl_type variable 54db7207e6SBram Moolenaar" - You can specify which type of completion to default to 55db7207e6SBram Moolenaar" when pressing <C-X><C-O>. The entire list of available 56db7207e6SBram Moolenaar" choices can be found in the calls to sqlcomplete#Map in: 57db7207e6SBram Moolenaar" ftplugin/sql.vim 58db7207e6SBram Moolenaar" 59f9d5ca1dSBram Moolenaar" Version 10.0 60f9d5ca1dSBram Moolenaar" Updated PreCacheSyntax() 61f9d5ca1dSBram Moolenaar" - Now returns a List of the syntax items it finds. 62f9d5ca1dSBram Moolenaar" This allows other plugins / scripts to use this list for their own 63f9d5ca1dSBram Moolenaar" purposes. In this case XPTemplate can use them for a Choose list. 64f9d5ca1dSBram Moolenaar" - Verifies the parameters are the correct type and displays a 65f9d5ca1dSBram Moolenaar" warning if not. 66f9d5ca1dSBram Moolenaar" - Verifies the parameters are the correct type and displays a 67f9d5ca1dSBram Moolenaar" warning if not. 68f9d5ca1dSBram Moolenaar" Updated SQLCWarningMsg() 69f9d5ca1dSBram Moolenaar" - Prepends warning message with SQLComplete so you know who issued 70f9d5ca1dSBram Moolenaar" the warning. 71f9d5ca1dSBram Moolenaar" Updated SQLCErrorMsg() 72f9d5ca1dSBram Moolenaar" - Prepends error message with SQLComplete so you know who issued 73f9d5ca1dSBram Moolenaar" the error. 74f9d5ca1dSBram Moolenaar" 7534feacbcSBram Moolenaar" Version 9.0 (May 2010) 7600a927d6SBram Moolenaar" This change removes some of the support for tables with spaces in their 7700a927d6SBram Moolenaar" names in order to simplify the regexes used to pull out query table 7800a927d6SBram Moolenaar" aliases for more robust table name and column name code completion. 7900a927d6SBram Moolenaar" Full support for "table names with spaces" can be added in again 8000a927d6SBram Moolenaar" after 7.3. 81f9d5ca1dSBram Moolenaar" 8200a927d6SBram Moolenaar" Version 8.0 8300a927d6SBram Moolenaar" Incorrectly re-executed the g:ftplugin_sql_omni_key_right and g:ftplugin_sql_omni_key_left 8400a927d6SBram Moolenaar" when drilling in and out of a column list for a table. 85f9d5ca1dSBram Moolenaar" 8634feacbcSBram Moolenaar" Version 7.0 (Jan 2010) 875c73622aSBram Moolenaar" Better handling of object names 88f9d5ca1dSBram Moolenaar" 8934feacbcSBram Moolenaar" Version 6.0 (Apr 2008) 905c73622aSBram Moolenaar" Supports object names with spaces "my table name" 915c73622aSBram Moolenaar" 92e2f98b95SBram Moolenaar" Set completion with CTRL-X CTRL-O to autoloaded function. 93e2f98b95SBram Moolenaar" This check is in place in case this script is 94e2f98b95SBram Moolenaar" sourced directly instead of using the autoload feature. 95e2f98b95SBram Moolenaarif exists('&omnifunc') 96e2f98b95SBram Moolenaar " Do not set the option if already set since this 97e2f98b95SBram Moolenaar " results in an E117 warning. 98e2f98b95SBram Moolenaar if &omnifunc == "" 99e2f98b95SBram Moolenaar setlocal omnifunc=sqlcomplete#Complete 100e2f98b95SBram Moolenaar endif 101e2f98b95SBram Moolenaarendif 102e2f98b95SBram Moolenaar 103e2f98b95SBram Moolenaarif exists('g:loaded_sql_completion') 104e2f98b95SBram Moolenaar finish 105e2f98b95SBram Moolenaarendif 106*ad3b366cSBram Moolenaarlet g:loaded_sql_completion = 150 10734feacbcSBram Moolenaarlet s:keepcpo= &cpo 10834feacbcSBram Moolenaarset cpo&vim 109e2f98b95SBram Moolenaar 110e2f98b95SBram Moolenaar" Maintains filename of dictionary 111e2f98b95SBram Moolenaarlet s:sql_file_table = "" 112e2f98b95SBram Moolenaarlet s:sql_file_procedure = "" 113e2f98b95SBram Moolenaarlet s:sql_file_view = "" 114e2f98b95SBram Moolenaar 115e2f98b95SBram Moolenaar" Define various arrays to be used for caching 116e2f98b95SBram Moolenaarlet s:tbl_name = [] 117e2f98b95SBram Moolenaarlet s:tbl_alias = [] 118e2f98b95SBram Moolenaarlet s:tbl_cols = [] 119e2f98b95SBram Moolenaarlet s:syn_list = [] 120e2f98b95SBram Moolenaarlet s:syn_value = [] 121e2f98b95SBram Moolenaar 122e2f98b95SBram Moolenaar" Used in conjunction with the syntaxcomplete plugin 123e2f98b95SBram Moolenaarlet s:save_inc = "" 124e2f98b95SBram Moolenaarlet s:save_exc = "" 125*ad3b366cSBram Moolenaarif !exists('g:omni_syntax_group_include_sql') 126*ad3b366cSBram Moolenaar let g:omni_syntax_group_include_sql = '' 127*ad3b366cSBram Moolenaarendif 128*ad3b366cSBram Moolenaarif !exists('g:omni_syntax_group_exclude_sql') 129*ad3b366cSBram Moolenaar let g:omni_syntax_group_exclude_sql = '' 130*ad3b366cSBram Moolenaarendif 131e2f98b95SBram Moolenaarlet s:save_inc = g:omni_syntax_group_include_sql 132e2f98b95SBram Moolenaarlet s:save_exc = g:omni_syntax_group_exclude_sql 133e2f98b95SBram Moolenaar 134e2f98b95SBram Moolenaar" Used with the column list 135e2f98b95SBram Moolenaarlet s:save_prev_table = "" 136e2f98b95SBram Moolenaar 137e2f98b95SBram Moolenaar" Default the option to verify table alias 138e2f98b95SBram Moolenaarif !exists('g:omni_sql_use_tbl_alias') 139e2f98b95SBram Moolenaar let g:omni_sql_use_tbl_alias = 'a' 140e2f98b95SBram Moolenaarendif 141910f66f9SBram Moolenaar" Default syntax items to precache 142910f66f9SBram Moolenaarif !exists('g:omni_sql_precache_syntax_groups') 143910f66f9SBram Moolenaar let g:omni_sql_precache_syntax_groups = [ 144*ad3b366cSBram Moolenaar \ 'syntax\w*', 145*ad3b366cSBram Moolenaar \ 'sqlKeyword\w*', 146*ad3b366cSBram Moolenaar \ 'sqlFunction\w*', 147*ad3b366cSBram Moolenaar \ 'sqlOption\w*', 148*ad3b366cSBram Moolenaar \ 'sqlType\w*', 149*ad3b366cSBram Moolenaar \ 'sqlStatement\w*' 150910f66f9SBram Moolenaar \ ] 151910f66f9SBram Moolenaarendif 152eb3593b3SBram Moolenaar" Set ignorecase to the ftplugin standard 153eb3593b3SBram Moolenaarif !exists('g:omni_sql_ignorecase') 154eb3593b3SBram Moolenaar let g:omni_sql_ignorecase = &ignorecase 155eb3593b3SBram Moolenaarendif 156eb3593b3SBram Moolenaar" During table completion, should the table list also 157eb3593b3SBram Moolenaar" include the owner name 158eb3593b3SBram Moolenaarif !exists('g:omni_sql_include_owner') 159eb3593b3SBram Moolenaar let g:omni_sql_include_owner = 0 160eb3593b3SBram Moolenaar if exists('g:loaded_dbext') 161eb3593b3SBram Moolenaar if g:loaded_dbext >= 300 162eb3593b3SBram Moolenaar " New to dbext 3.00, by default the table lists include the owner 163eb3593b3SBram Moolenaar " name of the table. This is used when determining how much of 164eb3593b3SBram Moolenaar " whatever has been typed should be replaced as part of the 165eb3593b3SBram Moolenaar " code replacement. 166eb3593b3SBram Moolenaar let g:omni_sql_include_owner = 1 167eb3593b3SBram Moolenaar endif 168eb3593b3SBram Moolenaar endif 169eb3593b3SBram Moolenaarendif 170db7207e6SBram Moolenaar" Default type of completion used when <C-X><C-O> is pressed 171db7207e6SBram Moolenaarif !exists('g:omni_sql_default_compl_type') 172db7207e6SBram Moolenaar let g:omni_sql_default_compl_type = 'table' 173db7207e6SBram Moolenaarendif 174e2f98b95SBram Moolenaar 175e2f98b95SBram Moolenaar" This function is used for the 'omnifunc' option. 17634feacbcSBram Moolenaar" It is called twice by omni and it is responsible 17734feacbcSBram Moolenaar" for returning the completion list of items. 17834feacbcSBram Moolenaar" But it must also determine context of what to complete 17934feacbcSBram Moolenaar" and what to "replace" with the completion. 18034feacbcSBram Moolenaar" The a:base, is replaced directly with what the user 18134feacbcSBram Moolenaar" chooses from the choices. 18234feacbcSBram Moolenaar" The s:prepend provides context for the completion. 183e2f98b95SBram Moolenaarfunction! sqlcomplete#Complete(findstart, base) 184e2f98b95SBram Moolenaar 185e2f98b95SBram Moolenaar " Default to table name completion 186e2f98b95SBram Moolenaar let compl_type = 'table' 187e2f98b95SBram Moolenaar " Allow maps to specify what type of object completion they want 188e2f98b95SBram Moolenaar if exists('b:sql_compl_type') 189e2f98b95SBram Moolenaar let compl_type = b:sql_compl_type 190e2f98b95SBram Moolenaar endif 19134feacbcSBram Moolenaar let begindot = 0 192e2f98b95SBram Moolenaar 193910f66f9SBram Moolenaar " First pass through this function determines how much of the line should 194910f66f9SBram Moolenaar " be replaced by whatever is chosen from the completion list 195e2f98b95SBram Moolenaar if a:findstart 196e2f98b95SBram Moolenaar " Locate the start of the item, including "." 197e2f98b95SBram Moolenaar let line = getline('.') 198e2f98b95SBram Moolenaar let start = col('.') - 1 199e2f98b95SBram Moolenaar let lastword = -1 200f193fffdSBram Moolenaar " Check if the first character is a ".", for column completion 201f193fffdSBram Moolenaar if line[start - 1] == '.' 202f193fffdSBram Moolenaar let begindot = 1 203f193fffdSBram Moolenaar endif 204e2f98b95SBram Moolenaar while start > 0 2055c73622aSBram Moolenaar " Additional code was required to handle objects which 2065c73622aSBram Moolenaar " can contain spaces like "my table name". 2075c73622aSBram Moolenaar if line[start - 1] !~ '\(\w\|\.\)' 2085c73622aSBram Moolenaar " If the previous character is not a period or word character 2095c73622aSBram Moolenaar break 2105c73622aSBram Moolenaar " elseif line[start - 1] =~ '\(\w\|\s\+\)' 2115c73622aSBram Moolenaar " let start -= 1 2125c73622aSBram Moolenaar elseif line[start - 1] =~ '\w' 2135c73622aSBram Moolenaar " If the previous character is word character continue back 214e2f98b95SBram Moolenaar let start -= 1 215eb3593b3SBram Moolenaar elseif line[start - 1] =~ '\.' && 216eb3593b3SBram Moolenaar \ compl_type =~ 'column\|table\|view\|procedure' 2175c73622aSBram Moolenaar " If the previous character is a period and we are completing 2185c73622aSBram Moolenaar " an object which can be specified with a period like this: 2195c73622aSBram Moolenaar " table_name.column_name 2205c73622aSBram Moolenaar " owner_name.table_name 2215c73622aSBram Moolenaar 222eb3593b3SBram Moolenaar " If lastword has already been set for column completion 223eb3593b3SBram Moolenaar " break from the loop, since we do not also want to pickup 224eb3593b3SBram Moolenaar " a table name if it was also supplied. 22534feacbcSBram Moolenaar " Unless g:omni_sql_include_owner == 1, then we can 22634feacbcSBram Moolenaar " include the ownername. 227f193fffdSBram Moolenaar if lastword != -1 && compl_type == 'column' 22834feacbcSBram Moolenaar \ && g:omni_sql_include_owner == 0 229eb3593b3SBram Moolenaar break 230eb3593b3SBram Moolenaar endif 231f193fffdSBram Moolenaar " If column completion was specified stop at the "." if 232f193fffdSBram Moolenaar " a . was specified, otherwise, replace all the way up 233f193fffdSBram Moolenaar " to the owner name (if included). 234f193fffdSBram Moolenaar if lastword == -1 && compl_type == 'column' && begindot == 1 235e2f98b95SBram Moolenaar let lastword = start 236e2f98b95SBram Moolenaar endif 237eb3593b3SBram Moolenaar " If omni_sql_include_owner = 0, do not include the table 238eb3593b3SBram Moolenaar " name as part of the substitution, so break here 239eb3593b3SBram Moolenaar if lastword == -1 && 24034feacbcSBram Moolenaar \ compl_type =~ '\<\(table\|view\|procedure\|column\|column_csv\)\>' && 241eb3593b3SBram Moolenaar \ g:omni_sql_include_owner == 0 242eb3593b3SBram Moolenaar let lastword = start 243eb3593b3SBram Moolenaar break 244eb3593b3SBram Moolenaar endif 245e2f98b95SBram Moolenaar let start -= 1 246e2f98b95SBram Moolenaar else 247e2f98b95SBram Moolenaar break 248e2f98b95SBram Moolenaar endif 249e2f98b95SBram Moolenaar endwhile 250e2f98b95SBram Moolenaar 251e2f98b95SBram Moolenaar " Return the column of the last word, which is going to be changed. 252e2f98b95SBram Moolenaar " Remember the text that comes before it in s:prepended. 253e2f98b95SBram Moolenaar if lastword == -1 254e2f98b95SBram Moolenaar let s:prepended = '' 255e2f98b95SBram Moolenaar return start 256e2f98b95SBram Moolenaar endif 257e2f98b95SBram Moolenaar let s:prepended = strpart(line, start, lastword - start) 258e2f98b95SBram Moolenaar return lastword 259e2f98b95SBram Moolenaar endif 260e2f98b95SBram Moolenaar 261910f66f9SBram Moolenaar " Second pass through this function will determine what data to put inside 262910f66f9SBram Moolenaar " of the completion list 263910f66f9SBram Moolenaar " s:prepended is set by the first pass 264e2f98b95SBram Moolenaar let base = s:prepended . a:base 265e2f98b95SBram Moolenaar 266910f66f9SBram Moolenaar " Default the completion list to an empty list 267e2f98b95SBram Moolenaar let compl_list = [] 268e2f98b95SBram Moolenaar 269e2f98b95SBram Moolenaar " Default to table name completion 270db7207e6SBram Moolenaar let compl_type = g:omni_sql_default_compl_type 271e2f98b95SBram Moolenaar " Allow maps to specify what type of object completion they want 272e2f98b95SBram Moolenaar if exists('b:sql_compl_type') 273e2f98b95SBram Moolenaar let compl_type = b:sql_compl_type 274e2f98b95SBram Moolenaar unlet b:sql_compl_type 275e2f98b95SBram Moolenaar endif 276e2f98b95SBram Moolenaar 277e2f98b95SBram Moolenaar if compl_type == 'tableReset' 278e2f98b95SBram Moolenaar let compl_type = 'table' 279e2f98b95SBram Moolenaar let base = '' 280e2f98b95SBram Moolenaar endif 281e2f98b95SBram Moolenaar 282e2f98b95SBram Moolenaar if compl_type == 'table' || 283e2f98b95SBram Moolenaar \ compl_type == 'procedure' || 284e2f98b95SBram Moolenaar \ compl_type == 'view' 285e2f98b95SBram Moolenaar 286e2f98b95SBram Moolenaar " This type of completion relies upon the dbext.vim plugin 287e2f98b95SBram Moolenaar if s:SQLCCheck4dbext() == -1 288e2f98b95SBram Moolenaar return [] 289e2f98b95SBram Moolenaar endif 290e2f98b95SBram Moolenaar 29183e138c6SBram Moolenaar " Allow the user to override the dbext plugin to specify whether 29283e138c6SBram Moolenaar " the owner/creator should be included in the list 2938c8de839SBram Moolenaar if g:loaded_dbext >= 300 2948c8de839SBram Moolenaar let saveSetting = DB_listOption('dict_show_owner') 2958c8de839SBram Moolenaar exec 'DBSetOption dict_show_owner='.(g:omni_sql_include_owner==1?'1':'0') 296e2f98b95SBram Moolenaar endif 29783e138c6SBram Moolenaar 29883e138c6SBram Moolenaar let compl_type_uc = substitute(compl_type, '\w\+', '\u&', '') 2995c73622aSBram Moolenaar " Same call below, no need to do it twice 3005c73622aSBram Moolenaar " if s:sql_file_{compl_type} == "" 3015c73622aSBram Moolenaar " let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc) 3025c73622aSBram Moolenaar " endif 30383e138c6SBram Moolenaar let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc) 304e2f98b95SBram Moolenaar if s:sql_file_{compl_type} != "" 305e2f98b95SBram Moolenaar if filereadable(s:sql_file_{compl_type}) 306e2f98b95SBram Moolenaar let compl_list = readfile(s:sql_file_{compl_type}) 307e2f98b95SBram Moolenaar endif 308e2f98b95SBram Moolenaar endif 30983e138c6SBram Moolenaar 3108c8de839SBram Moolenaar if g:loaded_dbext > 300 3118c8de839SBram Moolenaar exec 'DBSetOption dict_show_owner='.saveSetting 3128c8de839SBram Moolenaar endif 31383e138c6SBram Moolenaar elseif compl_type =~? 'column' 314e2f98b95SBram Moolenaar 315e2f98b95SBram Moolenaar " This type of completion relies upon the dbext.vim plugin 316e2f98b95SBram Moolenaar if s:SQLCCheck4dbext() == -1 317e2f98b95SBram Moolenaar return [] 318e2f98b95SBram Moolenaar endif 319e2f98b95SBram Moolenaar 320e2f98b95SBram Moolenaar if base == "" 321e2f98b95SBram Moolenaar " The last time we displayed a column list we stored 322e2f98b95SBram Moolenaar " the table name. If the user selects a column list 323e2f98b95SBram Moolenaar " without a table name of alias present, assume they want 324e2f98b95SBram Moolenaar " the previous column list displayed. 325e2f98b95SBram Moolenaar let base = s:save_prev_table 326e2f98b95SBram Moolenaar endif 327e2f98b95SBram Moolenaar 32883e138c6SBram Moolenaar let owner = '' 32983e138c6SBram Moolenaar let column = '' 33083e138c6SBram Moolenaar 33183e138c6SBram Moolenaar if base =~ '\.' 33283e138c6SBram Moolenaar " Check if the owner/creator has been specified 33383e138c6SBram Moolenaar let owner = matchstr( base, '^\zs.*\ze\..*\..*' ) 33483e138c6SBram Moolenaar let table = matchstr( base, '^\(.*\.\)\?\zs.*\ze\..*' ) 33583e138c6SBram Moolenaar let column = matchstr( base, '.*\.\zs.*' ) 33683e138c6SBram Moolenaar 33734feacbcSBram Moolenaar if g:omni_sql_include_owner == 1 && owner == '' && table != '' && column != '' 33834feacbcSBram Moolenaar let owner = table 33934feacbcSBram Moolenaar let table = column 34034feacbcSBram Moolenaar let column = '' 34134feacbcSBram Moolenaar endif 34234feacbcSBram Moolenaar 34383e138c6SBram Moolenaar " It is pretty well impossible to determine if the user 34483e138c6SBram Moolenaar " has entered: 34583e138c6SBram Moolenaar " owner.table 34683e138c6SBram Moolenaar " table.column_prefix 34783e138c6SBram Moolenaar " So there are a couple of things we can do to mitigate 34883e138c6SBram Moolenaar " this issue. 34983e138c6SBram Moolenaar " 1. Check if the dbext plugin has the option turned 35083e138c6SBram Moolenaar " on to even allow owners 35183e138c6SBram Moolenaar " 2. Based on 1, if the user is showing a table list 35200a927d6SBram Moolenaar " and the DrillIntoTable (using <Right>) then 35383e138c6SBram Moolenaar " this will be owner.table. In this case, we can 35483e138c6SBram Moolenaar " check to see the table.column exists in the 35583e138c6SBram Moolenaar " cached table list. If it does, then we have 35683e138c6SBram Moolenaar " determined the user has actually chosen 35783e138c6SBram Moolenaar " owner.table, not table.column_prefix. 35883e138c6SBram Moolenaar let found = -1 35983e138c6SBram Moolenaar if g:omni_sql_include_owner == 1 && owner == '' 36083e138c6SBram Moolenaar if filereadable(s:sql_file_table) 36183e138c6SBram Moolenaar let tbl_list = readfile(s:sql_file_table) 36283e138c6SBram Moolenaar let found = index( tbl_list, ((table != '')?(table.'.'):'').column) 36383e138c6SBram Moolenaar endif 36483e138c6SBram Moolenaar endif 36583e138c6SBram Moolenaar " If the table.column was found in the table list, we can safely assume 36683e138c6SBram Moolenaar " the owner was not provided and shift the items appropriately. 36783e138c6SBram Moolenaar " OR 36883e138c6SBram Moolenaar " If the user has indicated not to use table owners at all and 36983e138c6SBram Moolenaar " the base ends in a '.' we know they are not providing a column 37083e138c6SBram Moolenaar " name, so we can shift the items appropriately. 371db7207e6SBram Moolenaar " if found != -1 || (g:omni_sql_include_owner == 0 && base !~ '\.$') 372db7207e6SBram Moolenaar " let owner = table 373db7207e6SBram Moolenaar " let table = column 374db7207e6SBram Moolenaar " let column = '' 375db7207e6SBram Moolenaar " endif 37683e138c6SBram Moolenaar else 377db7207e6SBram Moolenaar " If no "." was provided and the user asked for 378db7207e6SBram Moolenaar " column level completion, first attempt the match 379db7207e6SBram Moolenaar " on any previous column lists. If the user asked 380db7207e6SBram Moolenaar " for a list of columns comma separated, continue as usual. 381db7207e6SBram Moolenaar if compl_type == 'column' && s:save_prev_table != '' 382db7207e6SBram Moolenaar " The last time we displayed a column list we stored 383db7207e6SBram Moolenaar " the table name. If the user selects a column list 384db7207e6SBram Moolenaar " without a table name of alias present, assume they want 385db7207e6SBram Moolenaar " the previous column list displayed. 386db7207e6SBram Moolenaar let table = s:save_prev_table 387db7207e6SBram Moolenaar let list_type = '' 388db7207e6SBram Moolenaar 389db7207e6SBram Moolenaar let compl_list = s:SQLCGetColumns(table, list_type) 390db7207e6SBram Moolenaar if ! empty(compl_list) 391db7207e6SBram Moolenaar " If no column prefix has been provided and the table 392db7207e6SBram Moolenaar " name was provided, append it to each of the items 393db7207e6SBram Moolenaar " returned. 394db7207e6SBram Moolenaar let compl_list = filter(deepcopy(compl_list), 'v:val=~"^'.base.'"' ) 395db7207e6SBram Moolenaar 396db7207e6SBram Moolenaar " If not empty, we have a match on columns 397db7207e6SBram Moolenaar " return the list 398db7207e6SBram Moolenaar if ! empty(compl_list) 399db7207e6SBram Moolenaar return compl_list 400db7207e6SBram Moolenaar endif 401db7207e6SBram Moolenaar endif 402db7207e6SBram Moolenaar endif 403db7207e6SBram Moolenaar " Since no columns were found to match the base supplied 404db7207e6SBram Moolenaar " assume the user is trying to complete the column list 405db7207e6SBram Moolenaar " for a table (and or an alias to a table). 40683e138c6SBram Moolenaar let table = base 40783e138c6SBram Moolenaar endif 40883e138c6SBram Moolenaar 40983e138c6SBram Moolenaar " Get anything after the . and consider this the table name 41083e138c6SBram Moolenaar " If an owner has been specified, then we must consider the 41183e138c6SBram Moolenaar " base to be a partial column name 41283e138c6SBram Moolenaar " let base = matchstr( base, '^\(.*\.\)\?\zs.*' ) 41383e138c6SBram Moolenaar 41483e138c6SBram Moolenaar if table != "" 415e2f98b95SBram Moolenaar let s:save_prev_table = base 41683e138c6SBram Moolenaar let list_type = '' 41783e138c6SBram Moolenaar 41883e138c6SBram Moolenaar if compl_type == 'column_csv' 41983e138c6SBram Moolenaar " Return one array element, with a comma separated 42083e138c6SBram Moolenaar " list of values instead of multiple array entries 42183e138c6SBram Moolenaar " for each column in the table. 42283e138c6SBram Moolenaar let list_type = 'csv' 42383e138c6SBram Moolenaar endif 42483e138c6SBram Moolenaar 42534feacbcSBram Moolenaar " If we are including the OWNER for the objects, then for 42634feacbcSBram Moolenaar " table completion, if we have it, it should be included 42734feacbcSBram Moolenaar " as there can be the same table names in a database yet 42834feacbcSBram Moolenaar " with different owner names. 42934feacbcSBram Moolenaar if g:omni_sql_include_owner == 1 && owner != '' && table != '' 43034feacbcSBram Moolenaar let compl_list = s:SQLCGetColumns(owner.'.'.table, list_type) 43134feacbcSBram Moolenaar else 43283e138c6SBram Moolenaar let compl_list = s:SQLCGetColumns(table, list_type) 43334feacbcSBram Moolenaar endif 43434feacbcSBram Moolenaar 43583e138c6SBram Moolenaar if column != '' 43683e138c6SBram Moolenaar " If no column prefix has been provided and the table 43783e138c6SBram Moolenaar " name was provided, append it to each of the items 43883e138c6SBram Moolenaar " returned. 439db7207e6SBram Moolenaar let compl_list = map(compl_list, 'table.".".v:val') 44083e138c6SBram Moolenaar if owner != '' 44183e138c6SBram Moolenaar " If an owner has been provided append it to each of the 44283e138c6SBram Moolenaar " items returned. 443db7207e6SBram Moolenaar let compl_list = map(compl_list, 'owner.".".v:val') 44483e138c6SBram Moolenaar endif 44583e138c6SBram Moolenaar else 446e2f98b95SBram Moolenaar let base = '' 447e2f98b95SBram Moolenaar endif 448e2f98b95SBram Moolenaar 44983e138c6SBram Moolenaar if compl_type == 'column_csv' 450e2f98b95SBram Moolenaar " Join the column array into 1 single element array 451e2f98b95SBram Moolenaar " but make the columns column separated 452e2f98b95SBram Moolenaar let compl_list = [join(compl_list, ', ')] 45383e138c6SBram Moolenaar endif 454e2f98b95SBram Moolenaar endif 455e2f98b95SBram Moolenaar elseif compl_type == 'resetCache' 456e2f98b95SBram Moolenaar " Reset all cached items 457e2f98b95SBram Moolenaar let s:tbl_name = [] 458e2f98b95SBram Moolenaar let s:tbl_alias = [] 459e2f98b95SBram Moolenaar let s:tbl_cols = [] 460e2f98b95SBram Moolenaar let s:syn_list = [] 461e2f98b95SBram Moolenaar let s:syn_value = [] 46234feacbcSBram Moolenaar let s:sql_file_table = "" 46334feacbcSBram Moolenaar let s:sql_file_procedure = "" 46434feacbcSBram Moolenaar let s:sql_file_view = "" 465f193fffdSBram Moolenaar 466f193fffdSBram Moolenaar let msg = "All SQL cached items have been removed." 467f193fffdSBram Moolenaar call s:SQLCWarningMsg(msg) 468f193fffdSBram Moolenaar " Leave time for the user to read the error message 469f193fffdSBram Moolenaar :sleep 2 470e2f98b95SBram Moolenaar else 471910f66f9SBram Moolenaar let compl_list = s:SQLCGetSyntaxList(compl_type) 472e2f98b95SBram Moolenaar endif 473e2f98b95SBram Moolenaar 474e2f98b95SBram Moolenaar if base != '' 4755c73622aSBram Moolenaar " Filter the list based on the first few characters the user entered. 4765c73622aSBram Moolenaar " Check if the text matches at the beginning 477db7207e6SBram Moolenaar " \\(^.base.'\\) 4785c73622aSBram Moolenaar " or 4795c73622aSBram Moolenaar " Match to a owner.table or alias.column type match 480db7207e6SBram Moolenaar " ^\\(\\w\\+\\.\\)\\?'.base.'\\) 4815c73622aSBram Moolenaar " or 4825c73622aSBram Moolenaar " Handle names with spaces "my table name" 483db7207e6SBram Moolenaar " "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"' 484db7207e6SBram Moolenaar " 4855c73622aSBram Moolenaar let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"' 4865c73622aSBram Moolenaar " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\)"' 4875c73622aSBram Moolenaar " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\(\\.\\)\\?'.base.'\\)"' 4885c73622aSBram Moolenaar " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\([^.]*\\)\\?'.base.'\\)"' 489eb3593b3SBram Moolenaar let compl_list = filter(deepcopy(compl_list), expr) 49034feacbcSBram Moolenaar 49134feacbcSBram Moolenaar if empty(compl_list) && compl_type == 'table' && base =~ '\.$' 49234feacbcSBram Moolenaar " It is possible we could be looking for column name completion 49334feacbcSBram Moolenaar " and the user simply hit C-X C-O to lets try it as well 49434feacbcSBram Moolenaar " since we had no hits with the tables. 49534feacbcSBram Moolenaar " If the base ends with a . it is hard to know if we are 49634feacbcSBram Moolenaar " completing table names or column names. 49734feacbcSBram Moolenaar let list_type = '' 49834feacbcSBram Moolenaar 49934feacbcSBram Moolenaar let compl_list = s:SQLCGetColumns(base, list_type) 50034feacbcSBram Moolenaar endif 501e2f98b95SBram Moolenaar endif 502e2f98b95SBram Moolenaar 503910f66f9SBram Moolenaar if exists('b:sql_compl_savefunc') && b:sql_compl_savefunc != "" 504910f66f9SBram Moolenaar let &omnifunc = b:sql_compl_savefunc 505910f66f9SBram Moolenaar endif 506910f66f9SBram Moolenaar 50734feacbcSBram Moolenaar if empty(compl_list) 50834feacbcSBram Moolenaar call s:SQLCWarningMsg( 'Could not find type['.compl_type.'] using prepend[.'.s:prepended.'] base['.a:base.']' ) 50934feacbcSBram Moolenaar endif 51034feacbcSBram Moolenaar 511e2f98b95SBram Moolenaar return compl_list 512e2f98b95SBram Moolenaarendfunc 513e2f98b95SBram Moolenaar 514910f66f9SBram Moolenaarfunction! sqlcomplete#PreCacheSyntax(...) 515910f66f9SBram Moolenaar let syn_group_arr = [] 516f9d5ca1dSBram Moolenaar let syn_items = [] 517f9d5ca1dSBram Moolenaar 518910f66f9SBram Moolenaar if a:0 > 0 519f9d5ca1dSBram Moolenaar if type(a:1) != 3 520f9d5ca1dSBram Moolenaar call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']") 521f9d5ca1dSBram Moolenaar return '' 522f9d5ca1dSBram Moolenaar endif 523910f66f9SBram Moolenaar let syn_group_arr = a:1 524910f66f9SBram Moolenaar else 525910f66f9SBram Moolenaar let syn_group_arr = g:omni_sql_precache_syntax_groups 526910f66f9SBram Moolenaar endif 52783e138c6SBram Moolenaar " For each group specified in the list, precache all 52883e138c6SBram Moolenaar " the sytnax items. 529910f66f9SBram Moolenaar if !empty(syn_group_arr) 530910f66f9SBram Moolenaar for group_name in syn_group_arr 531f9d5ca1dSBram Moolenaar let syn_items = extend( syn_items, s:SQLCGetSyntaxList(group_name) ) 532f9d5ca1dSBram Moolenaar endfor 533f9d5ca1dSBram Moolenaar endif 534f9d5ca1dSBram Moolenaar 535f9d5ca1dSBram Moolenaar return syn_items 536f9d5ca1dSBram Moolenaarendfunction 537f9d5ca1dSBram Moolenaar 538f9d5ca1dSBram Moolenaarfunction! sqlcomplete#ResetCacheSyntax(...) 539f9d5ca1dSBram Moolenaar let syn_group_arr = [] 540f9d5ca1dSBram Moolenaar 541f9d5ca1dSBram Moolenaar if a:0 > 0 542f9d5ca1dSBram Moolenaar if type(a:1) != 3 543f9d5ca1dSBram Moolenaar call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']") 544f9d5ca1dSBram Moolenaar return '' 545f9d5ca1dSBram Moolenaar endif 546f9d5ca1dSBram Moolenaar let syn_group_arr = a:1 547f9d5ca1dSBram Moolenaar else 548f9d5ca1dSBram Moolenaar let syn_group_arr = g:omni_sql_precache_syntax_groups 549f9d5ca1dSBram Moolenaar endif 550f9d5ca1dSBram Moolenaar " For each group specified in the list, precache all 551f9d5ca1dSBram Moolenaar " the sytnax items. 552f9d5ca1dSBram Moolenaar if !empty(syn_group_arr) 553f9d5ca1dSBram Moolenaar for group_name in syn_group_arr 554f9d5ca1dSBram Moolenaar let list_idx = index(s:syn_list, group_name, 0, &ignorecase) 555f9d5ca1dSBram Moolenaar if list_idx > -1 556f9d5ca1dSBram Moolenaar " Remove from list of groups 557f9d5ca1dSBram Moolenaar call remove( s:syn_list, list_idx ) 558f9d5ca1dSBram Moolenaar " Remove from list of keywords 559f9d5ca1dSBram Moolenaar call remove( s:syn_value, list_idx ) 560f9d5ca1dSBram Moolenaar endif 561910f66f9SBram Moolenaar endfor 562910f66f9SBram Moolenaar endif 563910f66f9SBram Moolenaarendfunction 564910f66f9SBram Moolenaar 565910f66f9SBram Moolenaarfunction! sqlcomplete#Map(type) 566910f66f9SBram Moolenaar " Tell the SQL plugin what you want to complete 567910f66f9SBram Moolenaar let b:sql_compl_type=a:type 568910f66f9SBram Moolenaar " Record previous omnifunc, if the SQL completion 569910f66f9SBram Moolenaar " is being used in conjunction with other filetype 570910f66f9SBram Moolenaar " completion plugins 571910f66f9SBram Moolenaar if &omnifunc != "" && &omnifunc != 'sqlcomplete#Complete' 572910f66f9SBram Moolenaar " Record the previous omnifunc, the plugin 573910f66f9SBram Moolenaar " will automatically set this back so that it 574910f66f9SBram Moolenaar " does not interfere with other ftplugins settings 575910f66f9SBram Moolenaar let b:sql_compl_savefunc=&omnifunc 576910f66f9SBram Moolenaar endif 577910f66f9SBram Moolenaar " Set the OMNI func for the SQL completion plugin 578910f66f9SBram Moolenaar let &omnifunc='sqlcomplete#Complete' 579910f66f9SBram Moolenaarendfunction 580910f66f9SBram Moolenaar 581f193fffdSBram Moolenaarfunction! sqlcomplete#DrillIntoTable() 582f193fffdSBram Moolenaar " If the omni popup window is visible 583f193fffdSBram Moolenaar if pumvisible() 584f193fffdSBram Moolenaar call sqlcomplete#Map('column') 585f193fffdSBram Moolenaar " C-Y, makes the currently highlighted entry active 586f193fffdSBram Moolenaar " and trigger the omni popup to be redisplayed 58700a927d6SBram Moolenaar call feedkeys("\<C-Y>\<C-X>\<C-O>", 'n') 588f193fffdSBram Moolenaar else 589f193fffdSBram Moolenaar " If the popup is not visible, simple perform the normal 59000a927d6SBram Moolenaar " key behaviour. 59100a927d6SBram Moolenaar " Must use exec since they key must be preceeded by "\" 59200a927d6SBram Moolenaar " or feedkeys will simply push each character of the string 59300a927d6SBram Moolenaar " rather than the "key press". 59400a927d6SBram Moolenaar exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_right.'", "n")' 595f193fffdSBram Moolenaar endif 596f193fffdSBram Moolenaar return "" 597f193fffdSBram Moolenaarendfunction 598f193fffdSBram Moolenaar 599f193fffdSBram Moolenaarfunction! sqlcomplete#DrillOutOfColumns() 600f193fffdSBram Moolenaar " If the omni popup window is visible 601f193fffdSBram Moolenaar if pumvisible() 602f193fffdSBram Moolenaar call sqlcomplete#Map('tableReset') 603f193fffdSBram Moolenaar " Trigger the omni popup to be redisplayed 604f193fffdSBram Moolenaar call feedkeys("\<C-X>\<C-O>") 605f193fffdSBram Moolenaar else 606f193fffdSBram Moolenaar " If the popup is not visible, simple perform the normal 60700a927d6SBram Moolenaar " key behaviour. 60800a927d6SBram Moolenaar " Must use exec since they key must be preceeded by "\" 60900a927d6SBram Moolenaar " or feedkeys will simply push each character of the string 61000a927d6SBram Moolenaar " rather than the "key press". 61100a927d6SBram Moolenaar exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_left.'", "n")' 612f193fffdSBram Moolenaar endif 613f193fffdSBram Moolenaar return "" 614f193fffdSBram Moolenaarendfunction 615f193fffdSBram Moolenaar 616f193fffdSBram Moolenaarfunction! s:SQLCWarningMsg(msg) 617f193fffdSBram Moolenaar echohl WarningMsg 618f9d5ca1dSBram Moolenaar echomsg 'SQLComplete:'.a:msg 619f193fffdSBram Moolenaar echohl None 620f193fffdSBram Moolenaarendfunction 621f193fffdSBram Moolenaar 622f193fffdSBram Moolenaarfunction! s:SQLCErrorMsg(msg) 623f193fffdSBram Moolenaar echohl ErrorMsg 624f9d5ca1dSBram Moolenaar echomsg 'SQLComplete:'.a:msg 625f193fffdSBram Moolenaar echohl None 626f193fffdSBram Moolenaarendfunction 627f193fffdSBram Moolenaar 628910f66f9SBram Moolenaarfunction! s:SQLCGetSyntaxList(syn_group) 629910f66f9SBram Moolenaar let syn_group = a:syn_group 630910f66f9SBram Moolenaar let compl_list = [] 631910f66f9SBram Moolenaar 632910f66f9SBram Moolenaar " Check if we have already cached the syntax list 633910f66f9SBram Moolenaar let list_idx = index(s:syn_list, syn_group, 0, &ignorecase) 634910f66f9SBram Moolenaar if list_idx > -1 635910f66f9SBram Moolenaar " Return previously cached value 636910f66f9SBram Moolenaar let compl_list = s:syn_value[list_idx] 637910f66f9SBram Moolenaar else 638*ad3b366cSBram Moolenaar let s:save_inc = g:omni_syntax_group_include_sql 639*ad3b366cSBram Moolenaar let s:save_exc = g:omni_syntax_group_exclude_sql 640*ad3b366cSBram Moolenaar let g:omni_syntax_group_include_sql = '' 641*ad3b366cSBram Moolenaar let g:omni_syntax_group_exclude_sql = '' 642*ad3b366cSBram Moolenaar 643910f66f9SBram Moolenaar " Request the syntax list items from the 644910f66f9SBram Moolenaar " syntax completion plugin 645910f66f9SBram Moolenaar if syn_group == 'syntax' 646910f66f9SBram Moolenaar " Handle this special case. This allows the user 647910f66f9SBram Moolenaar " to indicate they want all the syntax items available, 648910f66f9SBram Moolenaar " so do not specify a specific include list. 649*ad3b366cSBram Moolenaar let syn_value = syntaxcomplete#OmniSyntaxList() 650910f66f9SBram Moolenaar else 651910f66f9SBram Moolenaar " The user has specified a specific syntax group 652910f66f9SBram Moolenaar let g:omni_syntax_group_include_sql = syn_group 653*ad3b366cSBram Moolenaar let syn_value = syntaxcomplete#OmniSyntaxList(syn_group) 654910f66f9SBram Moolenaar endif 655910f66f9SBram Moolenaar let g:omni_syntax_group_include_sql = s:save_inc 656910f66f9SBram Moolenaar let g:omni_syntax_group_exclude_sql = s:save_exc 657910f66f9SBram Moolenaar " Cache these values for later use 658910f66f9SBram Moolenaar let s:syn_list = add( s:syn_list, syn_group ) 659910f66f9SBram Moolenaar let s:syn_value = add( s:syn_value, syn_value ) 660910f66f9SBram Moolenaar let compl_list = syn_value 661910f66f9SBram Moolenaar endif 662910f66f9SBram Moolenaar 663910f66f9SBram Moolenaar return compl_list 664910f66f9SBram Moolenaarendfunction 665910f66f9SBram Moolenaar 666e2f98b95SBram Moolenaarfunction! s:SQLCCheck4dbext() 667e2f98b95SBram Moolenaar if !exists('g:loaded_dbext') 668e2f98b95SBram Moolenaar let msg = "The dbext plugin must be loaded for dynamic SQL completion" 669e2f98b95SBram Moolenaar call s:SQLCErrorMsg(msg) 670e2f98b95SBram Moolenaar " Leave time for the user to read the error message 671e2f98b95SBram Moolenaar :sleep 2 672e2f98b95SBram Moolenaar return -1 6738c8de839SBram Moolenaar elseif g:loaded_dbext < 600 6748c8de839SBram Moolenaar let msg = "The dbext plugin must be at least version 5.30 " . 675e2f98b95SBram Moolenaar \ " for dynamic SQL completion" 676e2f98b95SBram Moolenaar call s:SQLCErrorMsg(msg) 677e2f98b95SBram Moolenaar " Leave time for the user to read the error message 678e2f98b95SBram Moolenaar :sleep 2 679e2f98b95SBram Moolenaar return -1 680e2f98b95SBram Moolenaar endif 681e2f98b95SBram Moolenaar return 1 682e2f98b95SBram Moolenaarendfunction 683e2f98b95SBram Moolenaar 684e2f98b95SBram Moolenaarfunction! s:SQLCAddAlias(table_name, table_alias, cols) 685f193fffdSBram Moolenaar " Strip off the owner if included 686f193fffdSBram Moolenaar let table_name = matchstr(a:table_name, '\%(.\{-}\.\)\?\zs\(.*\)' ) 687e2f98b95SBram Moolenaar let table_alias = a:table_alias 688e2f98b95SBram Moolenaar let cols = a:cols 689e2f98b95SBram Moolenaar 690e2f98b95SBram Moolenaar if g:omni_sql_use_tbl_alias != 'n' 691e2f98b95SBram Moolenaar if table_alias == '' 692e2f98b95SBram Moolenaar if 'da' =~? g:omni_sql_use_tbl_alias 693e2f98b95SBram Moolenaar if table_name =~ '_' 694e2f98b95SBram Moolenaar " Treat _ as separators since people often use these 695e2f98b95SBram Moolenaar " for word separators 696e2f98b95SBram Moolenaar let save_keyword = &iskeyword 697e2f98b95SBram Moolenaar setlocal iskeyword-=_ 698e2f98b95SBram Moolenaar 699e2f98b95SBram Moolenaar " Get the first letter of each word 700e2f98b95SBram Moolenaar " [[:alpha:]] is used instead of \w 701e2f98b95SBram Moolenaar " to catch extended accented characters 702e2f98b95SBram Moolenaar " 703e2f98b95SBram Moolenaar let table_alias = substitute( 704e2f98b95SBram Moolenaar \ table_name, 705e2f98b95SBram Moolenaar \ '\<[[:alpha:]]\+\>_\?', 706e2f98b95SBram Moolenaar \ '\=strpart(submatch(0), 0, 1)', 707e2f98b95SBram Moolenaar \ 'g' 708e2f98b95SBram Moolenaar \ ) 709e2f98b95SBram Moolenaar " Restore original value 710e2f98b95SBram Moolenaar let &iskeyword = save_keyword 711e2f98b95SBram Moolenaar elseif table_name =~ '\u\U' 712f193fffdSBram Moolenaar let table_alias = substitute( 713e2f98b95SBram Moolenaar \ table_name, '\(\u\)\U*', '\1', 'g') 714e2f98b95SBram Moolenaar else 715e2f98b95SBram Moolenaar let table_alias = strpart(table_name, 0, 1) 716e2f98b95SBram Moolenaar endif 717e2f98b95SBram Moolenaar endif 718e2f98b95SBram Moolenaar endif 719e2f98b95SBram Moolenaar if table_alias != '' 720e2f98b95SBram Moolenaar " Following a word character, make sure there is a . and no spaces 721e2f98b95SBram Moolenaar let table_alias = substitute(table_alias, '\w\zs\.\?\s*$', '.', '') 722e2f98b95SBram Moolenaar if 'a' =~? g:omni_sql_use_tbl_alias && a:table_alias == '' 723e2f98b95SBram Moolenaar let table_alias = inputdialog("Enter table alias:", table_alias) 724e2f98b95SBram Moolenaar endif 725e2f98b95SBram Moolenaar endif 726e2f98b95SBram Moolenaar if table_alias != '' 727e2f98b95SBram Moolenaar let cols = substitute(cols, '\<\w', table_alias.'&', 'g') 728e2f98b95SBram Moolenaar endif 729e2f98b95SBram Moolenaar endif 730e2f98b95SBram Moolenaar 731e2f98b95SBram Moolenaar return cols 732e2f98b95SBram Moolenaarendfunction 733e2f98b95SBram Moolenaar 73483e138c6SBram Moolenaarfunction! s:SQLCGetObjectOwner(object) 73583e138c6SBram Moolenaar " The owner regex matches a word at the start of the string which is 73683e138c6SBram Moolenaar " followed by a dot, but doesn't include the dot in the result. 73783e138c6SBram Moolenaar " ^ - from beginning of line 7388c8de839SBram Moolenaar " \("\|\[\)\? - ignore any quotes 73983e138c6SBram Moolenaar " \zs - start the match now 7408c8de839SBram Moolenaar " .\{-} - get owner name 74183e138c6SBram Moolenaar " \ze - end the match 7428c8de839SBram Moolenaar " \("\|\[\)\? - ignore any quotes 74383e138c6SBram Moolenaar " \. - must by followed by a . 7448c8de839SBram Moolenaar " let owner = matchstr( a:object, '^\s*\zs.*\ze\.' ) 7458c8de839SBram Moolenaar let owner = matchstr( a:object, '^\("\|\[\)\?\zs\.\{-}\ze\("\|\]\)\?\.' ) 74683e138c6SBram Moolenaar return owner 74783e138c6SBram Moolenaarendfunction 74883e138c6SBram Moolenaar 749e2f98b95SBram Moolenaarfunction! s:SQLCGetColumns(table_name, list_type) 75034feacbcSBram Moolenaar if a:table_name =~ '\.' 75134feacbcSBram Moolenaar " Check if the owner/creator has been specified 75234feacbcSBram Moolenaar let owner = matchstr( a:table_name, '^\zs.*\ze\..*\..*' ) 75334feacbcSBram Moolenaar let table = matchstr( a:table_name, '^\(.*\.\)\?\zs.*\ze\..*' ) 75434feacbcSBram Moolenaar let column = matchstr( a:table_name, '.*\.\zs.*' ) 75534feacbcSBram Moolenaar 75634feacbcSBram Moolenaar if g:omni_sql_include_owner == 1 && owner == '' && table != '' && column != '' 75734feacbcSBram Moolenaar let owner = table 75834feacbcSBram Moolenaar let table = column 75934feacbcSBram Moolenaar let column = '' 76034feacbcSBram Moolenaar endif 76134feacbcSBram Moolenaar else 76234feacbcSBram Moolenaar let owner = '' 76334feacbcSBram Moolenaar let table = matchstr(a:table_name, '^["\[\]a-zA-Z0-9_ ]\+\ze\.\?') 76434feacbcSBram Moolenaar let column = '' 76534feacbcSBram Moolenaar endif 76634feacbcSBram Moolenaar 76783e138c6SBram Moolenaar " Check if the table name was provided as part of the column name 76834feacbcSBram Moolenaar " let table_name = matchstr(a:table_name, '^["\[\]a-zA-Z0-9_ ]\+\ze\.\?') 76934feacbcSBram Moolenaar let table_name = table 770e2f98b95SBram Moolenaar let table_cols = [] 771e2f98b95SBram Moolenaar let table_alias = '' 772e2f98b95SBram Moolenaar let move_to_top = 1 773e2f98b95SBram Moolenaar 7748c8de839SBram Moolenaar let table_name = substitute(table_name, '\s*\(.\{-}\)\s*$', '\1', 'g') 7758c8de839SBram Moolenaar 7768c8de839SBram Moolenaar " If the table name was given as: 7778c8de839SBram Moolenaar " where c. 7788c8de839SBram Moolenaar let table_name = substitute(table_name, '^\c\(WHERE\|AND\|OR\)\s\+', '', '') 779eb3593b3SBram Moolenaar if g:loaded_dbext >= 300 780e2f98b95SBram Moolenaar let saveSettingAlias = DB_listOption('use_tbl_alias') 781e2f98b95SBram Moolenaar exec 'DBSetOption use_tbl_alias=n' 782e2f98b95SBram Moolenaar endif 783e2f98b95SBram Moolenaar 7848c8de839SBram Moolenaar let table_name_stripped = substitute(table_name, '["\[\]]*', '', 'g') 7858c8de839SBram Moolenaar 786e2f98b95SBram Moolenaar " Check if we have already cached the column list for this table 787e2f98b95SBram Moolenaar " by its name 7888c8de839SBram Moolenaar let list_idx = index(s:tbl_name, table_name_stripped, 0, &ignorecase) 789e2f98b95SBram Moolenaar if list_idx > -1 7908c8de839SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx], '\n') 791e2f98b95SBram Moolenaar else 792e2f98b95SBram Moolenaar " Check if we have already cached the column list for this table 793e2f98b95SBram Moolenaar " by its alias, assuming the table_name provided was actually 794e2f98b95SBram Moolenaar " the alias for the table instead 795e2f98b95SBram Moolenaar " select * 796e2f98b95SBram Moolenaar " from area a 797e2f98b95SBram Moolenaar " where a. 7988c8de839SBram Moolenaar let list_idx = index(s:tbl_alias, table_name_stripped, 0, &ignorecase) 799e2f98b95SBram Moolenaar if list_idx > -1 8008c8de839SBram Moolenaar let table_alias = table_name_stripped 801e2f98b95SBram Moolenaar let table_name = s:tbl_name[list_idx] 8028c8de839SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx], '\n') 803e2f98b95SBram Moolenaar endif 804e2f98b95SBram Moolenaar endif 805e2f98b95SBram Moolenaar 806e2f98b95SBram Moolenaar " If we have not found a cached copy of the table 807e2f98b95SBram Moolenaar " And the table ends in a "." or we are looking for a column list 808e2f98b95SBram Moolenaar " if list_idx == -1 && (a:table_name =~ '\.' || b:sql_compl_type =~ 'column') 809e2f98b95SBram Moolenaar " if list_idx == -1 && (a:table_name =~ '\.' || a:list_type =~ 'csv') 810e2f98b95SBram Moolenaar if list_idx == -1 811e2f98b95SBram Moolenaar let saveY = @y 812e2f98b95SBram Moolenaar let saveSearch = @/ 813e2f98b95SBram Moolenaar let saveWScan = &wrapscan 814e2f98b95SBram Moolenaar let curline = line(".") 815e2f98b95SBram Moolenaar let curcol = col(".") 816e2f98b95SBram Moolenaar 817e2f98b95SBram Moolenaar " Do not let searchs wrap 818e2f98b95SBram Moolenaar setlocal nowrapscan 819e2f98b95SBram Moolenaar " If . was entered, look at the word just before the . 820e2f98b95SBram Moolenaar " We are looking for something like this: 821e2f98b95SBram Moolenaar " select * 822e2f98b95SBram Moolenaar " from customer c 823e2f98b95SBram Moolenaar " where c. 824e2f98b95SBram Moolenaar " So when . is pressed, we need to find 'c' 825e2f98b95SBram Moolenaar " 826e2f98b95SBram Moolenaar 827e2f98b95SBram Moolenaar " Search backwards to the beginning of the statement 828e2f98b95SBram Moolenaar " and do NOT wrap 829e2f98b95SBram Moolenaar " exec 'silent! normal! v?\<\(select\|update\|delete\|;\)\>'."\n".'"yy' 83000a927d6SBram Moolenaar exec 'silent! normal! ?\<\c\(select\|update\|delete\|;\)\>'."\n" 831e2f98b95SBram Moolenaar 832e2f98b95SBram Moolenaar " Start characterwise visual mode 833e2f98b95SBram Moolenaar " Advance right one character 834e2f98b95SBram Moolenaar " Search foward until one of the following: 835e2f98b95SBram Moolenaar " 1. Another select/update/delete statement 836e2f98b95SBram Moolenaar " 2. A ; at the end of a line (the delimiter) 837e2f98b95SBram Moolenaar " 3. The end of the file (incase no delimiter) 838e2f98b95SBram Moolenaar " Yank the visually selected text into the "y register. 83900a927d6SBram Moolenaar exec 'silent! normal! vl/\c\(\<select\>\|\<update\>\|\<delete\>\|;\s*$\|\%$\)'."\n".'"yy' 840e2f98b95SBram Moolenaar 841e2f98b95SBram Moolenaar let query = @y 842e2f98b95SBram Moolenaar let query = substitute(query, "\n", ' ', 'g') 843e2f98b95SBram Moolenaar let found = 0 844e2f98b95SBram Moolenaar 84500a927d6SBram Moolenaar " if query =~? '^\c\(select\)' 84600a927d6SBram Moolenaar if query =~? '^\(select\|update\|delete\)' 847e2f98b95SBram Moolenaar let found = 1 848e2f98b95SBram Moolenaar " \(\(\<\w\+\>\)\.\)\? - 84900a927d6SBram Moolenaar " '\c\(from\|join\|,\).\{-}' - Starting at the from clause (case insensitive) 850e2f98b95SBram Moolenaar " '\zs\(\(\<\w\+\>\)\.\)\?' - Get the owner name (optional) 851e2f98b95SBram Moolenaar " '\<\w\+\>\ze' - Get the table name 852e2f98b95SBram Moolenaar " '\s\+\<'.table_name.'\>' - Followed by the alias 853e2f98b95SBram Moolenaar " '\s*\.\@!.*' - Cannot be followed by a . 854e2f98b95SBram Moolenaar " '\(\<where\>\|$\)' - Must be followed by a WHERE clause 855e2f98b95SBram Moolenaar " '.*' - Exclude the rest of the line in the match 85600a927d6SBram Moolenaar " let table_name_new = matchstr(@y, 85700a927d6SBram Moolenaar " \ '\c\(from\|join\|,\).\{-}'. 85800a927d6SBram Moolenaar " \ '\zs\(\("\|\[\)\?.\{-}\("\|\]\)\.\)\?'. 85900a927d6SBram Moolenaar " \ '\("\|\[\)\?.\{-}\("\|\]\)\?\ze'. 86000a927d6SBram Moolenaar " \ '\s\+\%(as\s\+\)\?\<'. 86100a927d6SBram Moolenaar " \ matchstr(table_name, '.\{-}\ze\.\?$'). 86200a927d6SBram Moolenaar " \ '\>'. 86300a927d6SBram Moolenaar " \ '\s*\.\@!.*'. 86400a927d6SBram Moolenaar " \ '\(\<where\>\|$\)'. 86500a927d6SBram Moolenaar " \ '.*' 86600a927d6SBram Moolenaar " \ ) 867db7207e6SBram Moolenaar " 868db7207e6SBram Moolenaar " 869db7207e6SBram Moolenaar " ''\c\(\<from\>\|\<join\>\|,\)\s*' - Starting at the from clause (case insensitive) 870db7207e6SBram Moolenaar " '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?' - Get the owner name (optional) 871db7207e6SBram Moolenaar " '\("\|\[\)\?\w\+\("\|\]\)\?\ze' - Get the table name 872db7207e6SBram Moolenaar " '\s\+\%(as\s\+\)\?\<'.matchstr(table_name, '.\{-}\ze\.\?$').'\>' - Followed by the alias 873db7207e6SBram Moolenaar " '\s*\.\@!.*' - Cannot be followed by a . 874db7207e6SBram Moolenaar " '\(\<where\>\|$\)' - Must be followed by a WHERE clause 875db7207e6SBram Moolenaar " '.*' - Exclude the rest of the line in the match 876e2f98b95SBram Moolenaar let table_name_new = matchstr(@y, 87700a927d6SBram Moolenaar \ '\c\(\<from\>\|\<join\>\|,\)\s*'. 87800a927d6SBram Moolenaar \ '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?'. 87900a927d6SBram Moolenaar \ '\("\|\[\)\?\w\+\("\|\]\)\?\ze'. 880f193fffdSBram Moolenaar \ '\s\+\%(as\s\+\)\?\<'. 881f193fffdSBram Moolenaar \ matchstr(table_name, '.\{-}\ze\.\?$'). 882f193fffdSBram Moolenaar \ '\>'. 883e2f98b95SBram Moolenaar \ '\s*\.\@!.*'. 884e2f98b95SBram Moolenaar \ '\(\<where\>\|$\)'. 885e2f98b95SBram Moolenaar \ '.*' 886e2f98b95SBram Moolenaar \ ) 8878c8de839SBram Moolenaar 888e2f98b95SBram Moolenaar if table_name_new != '' 889e2f98b95SBram Moolenaar let table_alias = table_name 89034feacbcSBram Moolenaar if g:omni_sql_include_owner == 1 89134feacbcSBram Moolenaar let table_name = matchstr( table_name_new, '^\zs\(.\{-}\.\)\?\(.\{-}\.\)\?.*\ze' ) 89234feacbcSBram Moolenaar else 89334feacbcSBram Moolenaar " let table_name = matchstr( table_name_new, '^\(.*\.\)\?\zs.*\ze' ) 89434feacbcSBram Moolenaar let table_name = matchstr( table_name_new, '^\(.\{-}\.\)\?\zs\(.\{-}\.\)\?.*\ze' ) 89534feacbcSBram Moolenaar endif 896e2f98b95SBram Moolenaar 897e2f98b95SBram Moolenaar let list_idx = index(s:tbl_name, table_name, 0, &ignorecase) 898e2f98b95SBram Moolenaar if list_idx > -1 899e2f98b95SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx]) 900e2f98b95SBram Moolenaar let s:tbl_name[list_idx] = table_name 901e2f98b95SBram Moolenaar let s:tbl_alias[list_idx] = table_alias 902e2f98b95SBram Moolenaar else 903e2f98b95SBram Moolenaar let list_idx = index(s:tbl_alias, table_name, 0, &ignorecase) 904e2f98b95SBram Moolenaar if list_idx > -1 905e2f98b95SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx]) 906e2f98b95SBram Moolenaar let s:tbl_name[list_idx] = table_name 907e2f98b95SBram Moolenaar let s:tbl_alias[list_idx] = table_alias 908e2f98b95SBram Moolenaar endif 909e2f98b95SBram Moolenaar endif 910e2f98b95SBram Moolenaar 911e2f98b95SBram Moolenaar endif 912e2f98b95SBram Moolenaar else 913e2f98b95SBram Moolenaar " Simply assume it is a table name provided with a . on the end 914e2f98b95SBram Moolenaar let found = 1 915e2f98b95SBram Moolenaar endif 916e2f98b95SBram Moolenaar 917e2f98b95SBram Moolenaar let @y = saveY 918e2f98b95SBram Moolenaar let @/ = saveSearch 919e2f98b95SBram Moolenaar let &wrapscan = saveWScan 920e2f98b95SBram Moolenaar 921e2f98b95SBram Moolenaar " Return to previous location 922e2f98b95SBram Moolenaar call cursor(curline, curcol) 923e2f98b95SBram Moolenaar 924e2f98b95SBram Moolenaar if found == 0 925eb3593b3SBram Moolenaar if g:loaded_dbext > 300 926e2f98b95SBram Moolenaar exec 'DBSetOption use_tbl_alias='.saveSettingAlias 927e2f98b95SBram Moolenaar endif 928e2f98b95SBram Moolenaar 929e2f98b95SBram Moolenaar " Not a SQL statement, do not display a list 930e2f98b95SBram Moolenaar return [] 931e2f98b95SBram Moolenaar endif 932e2f98b95SBram Moolenaar endif 933e2f98b95SBram Moolenaar 934e2f98b95SBram Moolenaar if empty(table_cols) 935e2f98b95SBram Moolenaar " Specify silent mode, no messages to the user (tbl, 1) 936e2f98b95SBram Moolenaar " Specify do not comma separate (tbl, 1, 1) 93734feacbcSBram Moolenaar " let table_cols_str = DB_getListColumn(table_name, 1, 1) 93834feacbcSBram Moolenaar let table_cols_str = DB_getListColumn((owner!=''?owner.'.':'').table_name, 1, 1) 939e2f98b95SBram Moolenaar 940e2f98b95SBram Moolenaar if table_cols_str != "" 941e2f98b95SBram Moolenaar let s:tbl_name = add( s:tbl_name, table_name ) 942e2f98b95SBram Moolenaar let s:tbl_alias = add( s:tbl_alias, table_alias ) 943e2f98b95SBram Moolenaar let s:tbl_cols = add( s:tbl_cols, table_cols_str ) 9448c8de839SBram Moolenaar let table_cols = split(table_cols_str, '\n') 945e2f98b95SBram Moolenaar endif 946e2f98b95SBram Moolenaar 947e2f98b95SBram Moolenaar endif 948e2f98b95SBram Moolenaar 949eb3593b3SBram Moolenaar if g:loaded_dbext > 300 950e2f98b95SBram Moolenaar exec 'DBSetOption use_tbl_alias='.saveSettingAlias 951e2f98b95SBram Moolenaar endif 952e2f98b95SBram Moolenaar 953f193fffdSBram Moolenaar " If the user has asked for a comma separate list of column 954f193fffdSBram Moolenaar " values, ask the user if they want to prepend each column 955f193fffdSBram Moolenaar " with a tablename alias. 956e2f98b95SBram Moolenaar if a:list_type == 'csv' && !empty(table_cols) 957e2f98b95SBram Moolenaar let cols = join(table_cols, ', ') 958e2f98b95SBram Moolenaar let cols = s:SQLCAddAlias(table_name, table_alias, cols) 959e2f98b95SBram Moolenaar let table_cols = [cols] 960e2f98b95SBram Moolenaar endif 961e2f98b95SBram Moolenaar 962e2f98b95SBram Moolenaar return table_cols 963e2f98b95SBram Moolenaarendfunction 96434feacbcSBram Moolenaar" Restore: 96534feacbcSBram Moolenaarlet &cpo= s:keepcpo 96634feacbcSBram Moolenaarunlet s:keepcpo 96734feacbcSBram Moolenaar" vim: ts=4 fdm=marker 968