1f193fffdSBram Moolenaar" Vim OMNI completion script for SQL 2e2f98b95SBram Moolenaar" Language: SQL 35c73622aSBram Moolenaar" Maintainer: David Fishburn <dfishburn dot vim at gmail dot com> 45e9b2fa9SBram Moolenaar" Version: 16.0 501164a65SBram Moolenaar" Last Change: 2017 Oct 15 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" 14ad3b366cSBram Moolenaar" TODO 15ad3b366cSBram Moolenaar" - Jonas Enberg - if no table is found when using column completion 16ad3b366cSBram Moolenaar" look backwards to a FROM clause and find the first table 17ad3b366cSBram Moolenaar" and complete it. 18ad3b366cSBram Moolenaar" 195e9b2fa9SBram Moolenaar" Version 16.0 (Dec 2015) 20*6c391a74SBram Moolenaar" - NF: If resetting the cache and table, procedure or view completion 215e9b2fa9SBram Moolenaar" had been used via dbext, have dbext delete or recreate the 225e9b2fa9SBram Moolenaar" dictionary so that new objects are picked up for the 235e9b2fa9SBram Moolenaar" next completion. 245e9b2fa9SBram Moolenaar" 25ad3b366cSBram Moolenaar" Version 15.0 (May 2013) 26ad3b366cSBram Moolenaar" - NF: Changed the SQL precached syntax items, omni_sql_precache_syntax_groups, 27ad3b366cSBram Moolenaar" to use regular expressions to pick up extended syntax group names. 28ad3b366cSBram Moolenaar" This requires an updated SyntaxComplete plugin version 13.0. 29ad3b366cSBram Moolenaar" If the required versions have not been installed, previous 30ad3b366cSBram Moolenaar" behaviour will not be impacted. 31ad3b366cSBram Moolenaar" 3234feacbcSBram Moolenaar" Version 14.0 (Dec 2012) 3334feacbcSBram Moolenaar" - BF: Added check for cpo 3434feacbcSBram Moolenaar" 3534feacbcSBram Moolenaar" Version 13.0 (Dec 2012) 3634feacbcSBram Moolenaar" - NF: When completing column lists or drilling into a table 3734feacbcSBram Moolenaar" and g:omni_sql_include_owner is enabled, the 3834feacbcSBram Moolenaar" only the table name would be replaced with the column 3934feacbcSBram Moolenaar" list instead of the table name and owner (if specified). 4034feacbcSBram Moolenaar" - NF: When completing column lists using table aliases 4134feacbcSBram Moolenaar" and g:omni_sql_include_owner is enabled, account 4234feacbcSBram Moolenaar" for the owner name when looking up the table 4334feacbcSBram Moolenaar" list instead of the table name and owner (if specified). 4434feacbcSBram Moolenaar" - BF: When completing column lists or drilling into a table 4534feacbcSBram Moolenaar" and g:omni_sql_include_owner is enabled, the 4634feacbcSBram Moolenaar" column list could often not be found for the table. 4734feacbcSBram Moolenaar" - BF: When OMNI popped up, possibly the wrong word 4834feacbcSBram Moolenaar" would be replaced for column and column list options. 4934feacbcSBram Moolenaar" 5034feacbcSBram Moolenaar" Version 12.0 (Feb 2012) 51db7207e6SBram Moolenaar" - Partial column name completion did not work when a table 52db7207e6SBram Moolenaar" name or table alias was provided (Jonas Enberg). 53db7207e6SBram Moolenaar" - Improved the handling of column completion. First we match any 54db7207e6SBram Moolenaar" columns from a previous completion. If not matches are found, we 55db7207e6SBram Moolenaar" consider the partial name to be a table or table alias for the 56db7207e6SBram Moolenaar" query and attempt to match on it. 57db7207e6SBram Moolenaar" 5834feacbcSBram Moolenaar" Version 11.0 (Jan 2012) 59db7207e6SBram Moolenaar" Added g:omni_sql_default_compl_type variable 60db7207e6SBram Moolenaar" - You can specify which type of completion to default to 61db7207e6SBram Moolenaar" when pressing <C-X><C-O>. The entire list of available 62db7207e6SBram Moolenaar" choices can be found in the calls to sqlcomplete#Map in: 63db7207e6SBram Moolenaar" ftplugin/sql.vim 64db7207e6SBram Moolenaar" 65f9d5ca1dSBram Moolenaar" Version 10.0 66f9d5ca1dSBram Moolenaar" Updated PreCacheSyntax() 67f9d5ca1dSBram Moolenaar" - Now returns a List of the syntax items it finds. 68f9d5ca1dSBram Moolenaar" This allows other plugins / scripts to use this list for their own 69f9d5ca1dSBram Moolenaar" purposes. In this case XPTemplate can use them for a Choose list. 70f9d5ca1dSBram Moolenaar" - Verifies the parameters are the correct type and displays a 71f9d5ca1dSBram Moolenaar" warning if not. 72f9d5ca1dSBram Moolenaar" - Verifies the parameters are the correct type and displays a 73f9d5ca1dSBram Moolenaar" warning if not. 74f9d5ca1dSBram Moolenaar" Updated SQLCWarningMsg() 75f9d5ca1dSBram Moolenaar" - Prepends warning message with SQLComplete so you know who issued 76f9d5ca1dSBram Moolenaar" the warning. 77f9d5ca1dSBram Moolenaar" Updated SQLCErrorMsg() 78f9d5ca1dSBram Moolenaar" - Prepends error message with SQLComplete so you know who issued 79f9d5ca1dSBram Moolenaar" the error. 80f9d5ca1dSBram Moolenaar" 8134feacbcSBram Moolenaar" Version 9.0 (May 2010) 8200a927d6SBram Moolenaar" This change removes some of the support for tables with spaces in their 8300a927d6SBram Moolenaar" names in order to simplify the regexes used to pull out query table 8400a927d6SBram Moolenaar" aliases for more robust table name and column name code completion. 8500a927d6SBram Moolenaar" Full support for "table names with spaces" can be added in again 8600a927d6SBram Moolenaar" after 7.3. 87f9d5ca1dSBram Moolenaar" 8800a927d6SBram Moolenaar" Version 8.0 8900a927d6SBram Moolenaar" Incorrectly re-executed the g:ftplugin_sql_omni_key_right and g:ftplugin_sql_omni_key_left 9000a927d6SBram Moolenaar" when drilling in and out of a column list for a table. 91f9d5ca1dSBram Moolenaar" 9234feacbcSBram Moolenaar" Version 7.0 (Jan 2010) 935c73622aSBram Moolenaar" Better handling of object names 94f9d5ca1dSBram Moolenaar" 9534feacbcSBram Moolenaar" Version 6.0 (Apr 2008) 965c73622aSBram Moolenaar" Supports object names with spaces "my table name" 975c73622aSBram Moolenaar" 98e2f98b95SBram Moolenaar" Set completion with CTRL-X CTRL-O to autoloaded function. 99e2f98b95SBram Moolenaar" This check is in place in case this script is 100e2f98b95SBram Moolenaar" sourced directly instead of using the autoload feature. 101e2f98b95SBram Moolenaarif exists('&omnifunc') 102e2f98b95SBram Moolenaar " Do not set the option if already set since this 103e2f98b95SBram Moolenaar " results in an E117 warning. 104e2f98b95SBram Moolenaar if &omnifunc == "" 105e2f98b95SBram Moolenaar setlocal omnifunc=sqlcomplete#Complete 106e2f98b95SBram Moolenaar endif 107e2f98b95SBram Moolenaarendif 108e2f98b95SBram Moolenaar 109e2f98b95SBram Moolenaarif exists('g:loaded_sql_completion') 110e2f98b95SBram Moolenaar finish 111e2f98b95SBram Moolenaarendif 1125e9b2fa9SBram Moolenaarlet g:loaded_sql_completion = 160 11334feacbcSBram Moolenaarlet s:keepcpo= &cpo 11434feacbcSBram Moolenaarset cpo&vim 115e2f98b95SBram Moolenaar 116e2f98b95SBram Moolenaar" Maintains filename of dictionary 117e2f98b95SBram Moolenaarlet s:sql_file_table = "" 118e2f98b95SBram Moolenaarlet s:sql_file_procedure = "" 119e2f98b95SBram Moolenaarlet s:sql_file_view = "" 120e2f98b95SBram Moolenaar 121e2f98b95SBram Moolenaar" Define various arrays to be used for caching 122e2f98b95SBram Moolenaarlet s:tbl_name = [] 123e2f98b95SBram Moolenaarlet s:tbl_alias = [] 124e2f98b95SBram Moolenaarlet s:tbl_cols = [] 125e2f98b95SBram Moolenaarlet s:syn_list = [] 126e2f98b95SBram Moolenaarlet s:syn_value = [] 127e2f98b95SBram Moolenaar 128e2f98b95SBram Moolenaar" Used in conjunction with the syntaxcomplete plugin 129e2f98b95SBram Moolenaarlet s:save_inc = "" 130e2f98b95SBram Moolenaarlet s:save_exc = "" 131ad3b366cSBram Moolenaarif !exists('g:omni_syntax_group_include_sql') 132ad3b366cSBram Moolenaar let g:omni_syntax_group_include_sql = '' 133ad3b366cSBram Moolenaarendif 134ad3b366cSBram Moolenaarif !exists('g:omni_syntax_group_exclude_sql') 135ad3b366cSBram Moolenaar let g:omni_syntax_group_exclude_sql = '' 136ad3b366cSBram Moolenaarendif 137e2f98b95SBram Moolenaarlet s:save_inc = g:omni_syntax_group_include_sql 138e2f98b95SBram Moolenaarlet s:save_exc = g:omni_syntax_group_exclude_sql 139e2f98b95SBram Moolenaar 140e2f98b95SBram Moolenaar" Used with the column list 141e2f98b95SBram Moolenaarlet s:save_prev_table = "" 142e2f98b95SBram Moolenaar 143e2f98b95SBram Moolenaar" Default the option to verify table alias 144e2f98b95SBram Moolenaarif !exists('g:omni_sql_use_tbl_alias') 145e2f98b95SBram Moolenaar let g:omni_sql_use_tbl_alias = 'a' 146e2f98b95SBram Moolenaarendif 147910f66f9SBram Moolenaar" Default syntax items to precache 148910f66f9SBram Moolenaarif !exists('g:omni_sql_precache_syntax_groups') 149910f66f9SBram Moolenaar let g:omni_sql_precache_syntax_groups = [ 150ad3b366cSBram Moolenaar \ 'syntax\w*', 151ad3b366cSBram Moolenaar \ 'sqlKeyword\w*', 152ad3b366cSBram Moolenaar \ 'sqlFunction\w*', 153ad3b366cSBram Moolenaar \ 'sqlOption\w*', 154ad3b366cSBram Moolenaar \ 'sqlType\w*', 155ad3b366cSBram Moolenaar \ 'sqlStatement\w*' 156910f66f9SBram Moolenaar \ ] 157910f66f9SBram Moolenaarendif 158eb3593b3SBram Moolenaar" Set ignorecase to the ftplugin standard 159eb3593b3SBram Moolenaarif !exists('g:omni_sql_ignorecase') 160eb3593b3SBram Moolenaar let g:omni_sql_ignorecase = &ignorecase 161eb3593b3SBram Moolenaarendif 162eb3593b3SBram Moolenaar" During table completion, should the table list also 163eb3593b3SBram Moolenaar" include the owner name 164eb3593b3SBram Moolenaarif !exists('g:omni_sql_include_owner') 165eb3593b3SBram Moolenaar let g:omni_sql_include_owner = 0 166eb3593b3SBram Moolenaar if exists('g:loaded_dbext') 167eb3593b3SBram Moolenaar if g:loaded_dbext >= 300 168eb3593b3SBram Moolenaar " New to dbext 3.00, by default the table lists include the owner 169eb3593b3SBram Moolenaar " name of the table. This is used when determining how much of 170eb3593b3SBram Moolenaar " whatever has been typed should be replaced as part of the 171eb3593b3SBram Moolenaar " code replacement. 172eb3593b3SBram Moolenaar let g:omni_sql_include_owner = 1 173eb3593b3SBram Moolenaar endif 174eb3593b3SBram Moolenaar endif 175eb3593b3SBram Moolenaarendif 176db7207e6SBram Moolenaar" Default type of completion used when <C-X><C-O> is pressed 177db7207e6SBram Moolenaarif !exists('g:omni_sql_default_compl_type') 178db7207e6SBram Moolenaar let g:omni_sql_default_compl_type = 'table' 179db7207e6SBram Moolenaarendif 180e2f98b95SBram Moolenaar 181e2f98b95SBram Moolenaar" This function is used for the 'omnifunc' option. 18234feacbcSBram Moolenaar" It is called twice by omni and it is responsible 18334feacbcSBram Moolenaar" for returning the completion list of items. 18434feacbcSBram Moolenaar" But it must also determine context of what to complete 18534feacbcSBram Moolenaar" and what to "replace" with the completion. 18634feacbcSBram Moolenaar" The a:base, is replaced directly with what the user 18734feacbcSBram Moolenaar" chooses from the choices. 18834feacbcSBram Moolenaar" The s:prepend provides context for the completion. 189e2f98b95SBram Moolenaarfunction! sqlcomplete#Complete(findstart, base) 190e2f98b95SBram Moolenaar 191e2f98b95SBram Moolenaar " Default to table name completion 192e2f98b95SBram Moolenaar let compl_type = 'table' 193e2f98b95SBram Moolenaar " Allow maps to specify what type of object completion they want 194e2f98b95SBram Moolenaar if exists('b:sql_compl_type') 195e2f98b95SBram Moolenaar let compl_type = b:sql_compl_type 196e2f98b95SBram Moolenaar endif 19734feacbcSBram Moolenaar let begindot = 0 198e2f98b95SBram Moolenaar 199910f66f9SBram Moolenaar " First pass through this function determines how much of the line should 200910f66f9SBram Moolenaar " be replaced by whatever is chosen from the completion list 201e2f98b95SBram Moolenaar if a:findstart 202e2f98b95SBram Moolenaar " Locate the start of the item, including "." 203e2f98b95SBram Moolenaar let line = getline('.') 204e2f98b95SBram Moolenaar let start = col('.') - 1 205e2f98b95SBram Moolenaar let lastword = -1 206f193fffdSBram Moolenaar " Check if the first character is a ".", for column completion 207f193fffdSBram Moolenaar if line[start - 1] == '.' 208f193fffdSBram Moolenaar let begindot = 1 209f193fffdSBram Moolenaar endif 210e2f98b95SBram Moolenaar while start > 0 2115c73622aSBram Moolenaar " Additional code was required to handle objects which 2125c73622aSBram Moolenaar " can contain spaces like "my table name". 2135c73622aSBram Moolenaar if line[start - 1] !~ '\(\w\|\.\)' 2145c73622aSBram Moolenaar " If the previous character is not a period or word character 2155c73622aSBram Moolenaar break 2165c73622aSBram Moolenaar " elseif line[start - 1] =~ '\(\w\|\s\+\)' 2175c73622aSBram Moolenaar " let start -= 1 2185c73622aSBram Moolenaar elseif line[start - 1] =~ '\w' 2195c73622aSBram Moolenaar " If the previous character is word character continue back 220e2f98b95SBram Moolenaar let start -= 1 221eb3593b3SBram Moolenaar elseif line[start - 1] =~ '\.' && 222eb3593b3SBram Moolenaar \ compl_type =~ 'column\|table\|view\|procedure' 2235c73622aSBram Moolenaar " If the previous character is a period and we are completing 2245c73622aSBram Moolenaar " an object which can be specified with a period like this: 2255c73622aSBram Moolenaar " table_name.column_name 2265c73622aSBram Moolenaar " owner_name.table_name 2275c73622aSBram Moolenaar 228eb3593b3SBram Moolenaar " If lastword has already been set for column completion 229eb3593b3SBram Moolenaar " break from the loop, since we do not also want to pickup 230eb3593b3SBram Moolenaar " a table name if it was also supplied. 23134feacbcSBram Moolenaar " Unless g:omni_sql_include_owner == 1, then we can 23234feacbcSBram Moolenaar " include the ownername. 233f193fffdSBram Moolenaar if lastword != -1 && compl_type == 'column' 23434feacbcSBram Moolenaar \ && g:omni_sql_include_owner == 0 235eb3593b3SBram Moolenaar break 236eb3593b3SBram Moolenaar endif 237f193fffdSBram Moolenaar " If column completion was specified stop at the "." if 238f193fffdSBram Moolenaar " a . was specified, otherwise, replace all the way up 239f193fffdSBram Moolenaar " to the owner name (if included). 240f193fffdSBram Moolenaar if lastword == -1 && compl_type == 'column' && begindot == 1 241e2f98b95SBram Moolenaar let lastword = start 242e2f98b95SBram Moolenaar endif 243eb3593b3SBram Moolenaar " If omni_sql_include_owner = 0, do not include the table 244eb3593b3SBram Moolenaar " name as part of the substitution, so break here 245eb3593b3SBram Moolenaar if lastword == -1 && 24634feacbcSBram Moolenaar \ compl_type =~ '\<\(table\|view\|procedure\|column\|column_csv\)\>' && 247eb3593b3SBram Moolenaar \ g:omni_sql_include_owner == 0 248eb3593b3SBram Moolenaar let lastword = start 249eb3593b3SBram Moolenaar break 250eb3593b3SBram Moolenaar endif 251e2f98b95SBram Moolenaar let start -= 1 252e2f98b95SBram Moolenaar else 253e2f98b95SBram Moolenaar break 254e2f98b95SBram Moolenaar endif 255e2f98b95SBram Moolenaar endwhile 256e2f98b95SBram Moolenaar 257e2f98b95SBram Moolenaar " Return the column of the last word, which is going to be changed. 258e2f98b95SBram Moolenaar " Remember the text that comes before it in s:prepended. 259e2f98b95SBram Moolenaar if lastword == -1 260e2f98b95SBram Moolenaar let s:prepended = '' 261e2f98b95SBram Moolenaar return start 262e2f98b95SBram Moolenaar endif 263e2f98b95SBram Moolenaar let s:prepended = strpart(line, start, lastword - start) 264e2f98b95SBram Moolenaar return lastword 265e2f98b95SBram Moolenaar endif 266e2f98b95SBram Moolenaar 267910f66f9SBram Moolenaar " Second pass through this function will determine what data to put inside 268910f66f9SBram Moolenaar " of the completion list 269910f66f9SBram Moolenaar " s:prepended is set by the first pass 270e2f98b95SBram Moolenaar let base = s:prepended . a:base 271e2f98b95SBram Moolenaar 272910f66f9SBram Moolenaar " Default the completion list to an empty list 273e2f98b95SBram Moolenaar let compl_list = [] 274e2f98b95SBram Moolenaar 275e2f98b95SBram Moolenaar " Default to table name completion 276db7207e6SBram Moolenaar let compl_type = g:omni_sql_default_compl_type 277e2f98b95SBram Moolenaar " Allow maps to specify what type of object completion they want 278e2f98b95SBram Moolenaar if exists('b:sql_compl_type') 279e2f98b95SBram Moolenaar let compl_type = b:sql_compl_type 280e2f98b95SBram Moolenaar unlet b:sql_compl_type 281e2f98b95SBram Moolenaar endif 282e2f98b95SBram Moolenaar 283e2f98b95SBram Moolenaar if compl_type == 'tableReset' 284e2f98b95SBram Moolenaar let compl_type = 'table' 285e2f98b95SBram Moolenaar let base = '' 286e2f98b95SBram Moolenaar endif 287e2f98b95SBram Moolenaar 288e2f98b95SBram Moolenaar if compl_type == 'table' || 289e2f98b95SBram Moolenaar \ compl_type == 'procedure' || 290e2f98b95SBram Moolenaar \ compl_type == 'view' 291e2f98b95SBram Moolenaar 292e2f98b95SBram Moolenaar " This type of completion relies upon the dbext.vim plugin 293e2f98b95SBram Moolenaar if s:SQLCCheck4dbext() == -1 294e2f98b95SBram Moolenaar return [] 295e2f98b95SBram Moolenaar endif 296e2f98b95SBram Moolenaar 29783e138c6SBram Moolenaar " Allow the user to override the dbext plugin to specify whether 29883e138c6SBram Moolenaar " the owner/creator should be included in the list 2998c8de839SBram Moolenaar if g:loaded_dbext >= 300 3008c8de839SBram Moolenaar let saveSetting = DB_listOption('dict_show_owner') 3018c8de839SBram Moolenaar exec 'DBSetOption dict_show_owner='.(g:omni_sql_include_owner==1?'1':'0') 302e2f98b95SBram Moolenaar endif 30383e138c6SBram Moolenaar 30483e138c6SBram Moolenaar let compl_type_uc = substitute(compl_type, '\w\+', '\u&', '') 3055c73622aSBram Moolenaar " Same call below, no need to do it twice 3065c73622aSBram Moolenaar " if s:sql_file_{compl_type} == "" 3075c73622aSBram Moolenaar " let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc) 3085c73622aSBram Moolenaar " endif 30983e138c6SBram Moolenaar let s:sql_file_{compl_type} = DB_getDictionaryName(compl_type_uc) 310e2f98b95SBram Moolenaar if s:sql_file_{compl_type} != "" 311e2f98b95SBram Moolenaar if filereadable(s:sql_file_{compl_type}) 312e2f98b95SBram Moolenaar let compl_list = readfile(s:sql_file_{compl_type}) 313e2f98b95SBram Moolenaar endif 314e2f98b95SBram Moolenaar endif 31583e138c6SBram Moolenaar 3168c8de839SBram Moolenaar if g:loaded_dbext > 300 3178c8de839SBram Moolenaar exec 'DBSetOption dict_show_owner='.saveSetting 3188c8de839SBram Moolenaar endif 31983e138c6SBram Moolenaar elseif compl_type =~? 'column' 320e2f98b95SBram Moolenaar 321e2f98b95SBram Moolenaar " This type of completion relies upon the dbext.vim plugin 322e2f98b95SBram Moolenaar if s:SQLCCheck4dbext() == -1 323e2f98b95SBram Moolenaar return [] 324e2f98b95SBram Moolenaar endif 325e2f98b95SBram Moolenaar 326e2f98b95SBram Moolenaar if base == "" 327e2f98b95SBram Moolenaar " The last time we displayed a column list we stored 328e2f98b95SBram Moolenaar " the table name. If the user selects a column list 329e2f98b95SBram Moolenaar " without a table name of alias present, assume they want 330e2f98b95SBram Moolenaar " the previous column list displayed. 331e2f98b95SBram Moolenaar let base = s:save_prev_table 332e2f98b95SBram Moolenaar endif 333e2f98b95SBram Moolenaar 33483e138c6SBram Moolenaar let owner = '' 33583e138c6SBram Moolenaar let column = '' 33683e138c6SBram Moolenaar 33783e138c6SBram Moolenaar if base =~ '\.' 33883e138c6SBram Moolenaar " Check if the owner/creator has been specified 33983e138c6SBram Moolenaar let owner = matchstr( base, '^\zs.*\ze\..*\..*' ) 34083e138c6SBram Moolenaar let table = matchstr( base, '^\(.*\.\)\?\zs.*\ze\..*' ) 34183e138c6SBram Moolenaar let column = matchstr( base, '.*\.\zs.*' ) 34283e138c6SBram Moolenaar 34334feacbcSBram Moolenaar if g:omni_sql_include_owner == 1 && owner == '' && table != '' && column != '' 34434feacbcSBram Moolenaar let owner = table 34534feacbcSBram Moolenaar let table = column 34634feacbcSBram Moolenaar let column = '' 34734feacbcSBram Moolenaar endif 34834feacbcSBram Moolenaar 34983e138c6SBram Moolenaar " It is pretty well impossible to determine if the user 35083e138c6SBram Moolenaar " has entered: 35183e138c6SBram Moolenaar " owner.table 35283e138c6SBram Moolenaar " table.column_prefix 35383e138c6SBram Moolenaar " So there are a couple of things we can do to mitigate 35483e138c6SBram Moolenaar " this issue. 35583e138c6SBram Moolenaar " 1. Check if the dbext plugin has the option turned 35683e138c6SBram Moolenaar " on to even allow owners 35783e138c6SBram Moolenaar " 2. Based on 1, if the user is showing a table list 35800a927d6SBram Moolenaar " and the DrillIntoTable (using <Right>) then 35983e138c6SBram Moolenaar " this will be owner.table. In this case, we can 36083e138c6SBram Moolenaar " check to see the table.column exists in the 36183e138c6SBram Moolenaar " cached table list. If it does, then we have 36283e138c6SBram Moolenaar " determined the user has actually chosen 36383e138c6SBram Moolenaar " owner.table, not table.column_prefix. 36483e138c6SBram Moolenaar let found = -1 36583e138c6SBram Moolenaar if g:omni_sql_include_owner == 1 && owner == '' 36683e138c6SBram Moolenaar if filereadable(s:sql_file_table) 36783e138c6SBram Moolenaar let tbl_list = readfile(s:sql_file_table) 36883e138c6SBram Moolenaar let found = index( tbl_list, ((table != '')?(table.'.'):'').column) 36983e138c6SBram Moolenaar endif 37083e138c6SBram Moolenaar endif 37183e138c6SBram Moolenaar " If the table.column was found in the table list, we can safely assume 37283e138c6SBram Moolenaar " the owner was not provided and shift the items appropriately. 37383e138c6SBram Moolenaar " OR 37483e138c6SBram Moolenaar " If the user has indicated not to use table owners at all and 37583e138c6SBram Moolenaar " the base ends in a '.' we know they are not providing a column 37683e138c6SBram Moolenaar " name, so we can shift the items appropriately. 377db7207e6SBram Moolenaar " if found != -1 || (g:omni_sql_include_owner == 0 && base !~ '\.$') 378db7207e6SBram Moolenaar " let owner = table 379db7207e6SBram Moolenaar " let table = column 380db7207e6SBram Moolenaar " let column = '' 381db7207e6SBram Moolenaar " endif 38283e138c6SBram Moolenaar else 383db7207e6SBram Moolenaar " If no "." was provided and the user asked for 384db7207e6SBram Moolenaar " column level completion, first attempt the match 385db7207e6SBram Moolenaar " on any previous column lists. If the user asked 386db7207e6SBram Moolenaar " for a list of columns comma separated, continue as usual. 387db7207e6SBram Moolenaar if compl_type == 'column' && s:save_prev_table != '' 388db7207e6SBram Moolenaar " The last time we displayed a column list we stored 389db7207e6SBram Moolenaar " the table name. If the user selects a column list 390db7207e6SBram Moolenaar " without a table name of alias present, assume they want 391db7207e6SBram Moolenaar " the previous column list displayed. 392db7207e6SBram Moolenaar let table = s:save_prev_table 393db7207e6SBram Moolenaar let list_type = '' 394db7207e6SBram Moolenaar 395db7207e6SBram Moolenaar let compl_list = s:SQLCGetColumns(table, list_type) 396db7207e6SBram Moolenaar if ! empty(compl_list) 397db7207e6SBram Moolenaar " If no column prefix has been provided and the table 398db7207e6SBram Moolenaar " name was provided, append it to each of the items 399db7207e6SBram Moolenaar " returned. 400db7207e6SBram Moolenaar let compl_list = filter(deepcopy(compl_list), 'v:val=~"^'.base.'"' ) 401db7207e6SBram Moolenaar 402db7207e6SBram Moolenaar " If not empty, we have a match on columns 403db7207e6SBram Moolenaar " return the list 404db7207e6SBram Moolenaar if ! empty(compl_list) 405db7207e6SBram Moolenaar return compl_list 406db7207e6SBram Moolenaar endif 407db7207e6SBram Moolenaar endif 408db7207e6SBram Moolenaar endif 409db7207e6SBram Moolenaar " Since no columns were found to match the base supplied 410db7207e6SBram Moolenaar " assume the user is trying to complete the column list 411db7207e6SBram Moolenaar " for a table (and or an alias to a table). 41283e138c6SBram Moolenaar let table = base 41383e138c6SBram Moolenaar endif 41483e138c6SBram Moolenaar 41583e138c6SBram Moolenaar " Get anything after the . and consider this the table name 41683e138c6SBram Moolenaar " If an owner has been specified, then we must consider the 41783e138c6SBram Moolenaar " base to be a partial column name 41883e138c6SBram Moolenaar " let base = matchstr( base, '^\(.*\.\)\?\zs.*' ) 41983e138c6SBram Moolenaar 42083e138c6SBram Moolenaar if table != "" 421e2f98b95SBram Moolenaar let s:save_prev_table = base 42283e138c6SBram Moolenaar let list_type = '' 42383e138c6SBram Moolenaar 42483e138c6SBram Moolenaar if compl_type == 'column_csv' 42583e138c6SBram Moolenaar " Return one array element, with a comma separated 42683e138c6SBram Moolenaar " list of values instead of multiple array entries 42783e138c6SBram Moolenaar " for each column in the table. 42883e138c6SBram Moolenaar let list_type = 'csv' 42983e138c6SBram Moolenaar endif 43083e138c6SBram Moolenaar 43134feacbcSBram Moolenaar " If we are including the OWNER for the objects, then for 43234feacbcSBram Moolenaar " table completion, if we have it, it should be included 43334feacbcSBram Moolenaar " as there can be the same table names in a database yet 43434feacbcSBram Moolenaar " with different owner names. 43534feacbcSBram Moolenaar if g:omni_sql_include_owner == 1 && owner != '' && table != '' 43634feacbcSBram Moolenaar let compl_list = s:SQLCGetColumns(owner.'.'.table, list_type) 43734feacbcSBram Moolenaar else 43883e138c6SBram Moolenaar let compl_list = s:SQLCGetColumns(table, list_type) 43934feacbcSBram Moolenaar endif 44034feacbcSBram Moolenaar 44183e138c6SBram Moolenaar if column != '' 44283e138c6SBram Moolenaar " If no column prefix has been provided and the table 44383e138c6SBram Moolenaar " name was provided, append it to each of the items 44483e138c6SBram Moolenaar " returned. 445db7207e6SBram Moolenaar let compl_list = map(compl_list, 'table.".".v:val') 44683e138c6SBram Moolenaar if owner != '' 44783e138c6SBram Moolenaar " If an owner has been provided append it to each of the 44883e138c6SBram Moolenaar " items returned. 449db7207e6SBram Moolenaar let compl_list = map(compl_list, 'owner.".".v:val') 45083e138c6SBram Moolenaar endif 45183e138c6SBram Moolenaar else 452e2f98b95SBram Moolenaar let base = '' 453e2f98b95SBram Moolenaar endif 454e2f98b95SBram Moolenaar 45583e138c6SBram Moolenaar if compl_type == 'column_csv' 456e2f98b95SBram Moolenaar " Join the column array into 1 single element array 457e2f98b95SBram Moolenaar " but make the columns column separated 458e2f98b95SBram Moolenaar let compl_list = [join(compl_list, ', ')] 45983e138c6SBram Moolenaar endif 460e2f98b95SBram Moolenaar endif 461e2f98b95SBram Moolenaar elseif compl_type == 'resetCache' 462e2f98b95SBram Moolenaar " Reset all cached items 463e2f98b95SBram Moolenaar let s:tbl_name = [] 464e2f98b95SBram Moolenaar let s:tbl_alias = [] 465e2f98b95SBram Moolenaar let s:tbl_cols = [] 466e2f98b95SBram Moolenaar let s:syn_list = [] 467e2f98b95SBram Moolenaar let s:syn_value = [] 4685e9b2fa9SBram Moolenaar 4695e9b2fa9SBram Moolenaar if s:sql_file_table != "" 4705e9b2fa9SBram Moolenaar if g:loaded_dbext >= 2300 4715e9b2fa9SBram Moolenaar call DB_DictionaryDelete("table") 4725e9b2fa9SBram Moolenaar else 4735e9b2fa9SBram Moolenaar DBCompleteTables! 4745e9b2fa9SBram Moolenaar endif 4755e9b2fa9SBram Moolenaar endif 4765e9b2fa9SBram Moolenaar if s:sql_file_procedure != "" 4775e9b2fa9SBram Moolenaar if g:loaded_dbext >= 2300 4785e9b2fa9SBram Moolenaar call DB_DictionaryDelete("procedure") 4795e9b2fa9SBram Moolenaar else 4805e9b2fa9SBram Moolenaar DBCompleteProcedures! 4815e9b2fa9SBram Moolenaar endif 4825e9b2fa9SBram Moolenaar endif 4835e9b2fa9SBram Moolenaar if s:sql_file_view != "" 4845e9b2fa9SBram Moolenaar if g:loaded_dbext >= 2300 4855e9b2fa9SBram Moolenaar call DB_DictionaryDelete("view") 4865e9b2fa9SBram Moolenaar else 4875e9b2fa9SBram Moolenaar DBCompleteViews! 4885e9b2fa9SBram Moolenaar endif 4895e9b2fa9SBram Moolenaar endif 4905e9b2fa9SBram Moolenaar 49134feacbcSBram Moolenaar let s:sql_file_table = "" 49234feacbcSBram Moolenaar let s:sql_file_procedure = "" 49334feacbcSBram Moolenaar let s:sql_file_view = "" 494f193fffdSBram Moolenaar 495f193fffdSBram Moolenaar let msg = "All SQL cached items have been removed." 496f193fffdSBram Moolenaar call s:SQLCWarningMsg(msg) 497f193fffdSBram Moolenaar " Leave time for the user to read the error message 498f193fffdSBram Moolenaar :sleep 2 499e2f98b95SBram Moolenaar else 500910f66f9SBram Moolenaar let compl_list = s:SQLCGetSyntaxList(compl_type) 501e2f98b95SBram Moolenaar endif 502e2f98b95SBram Moolenaar 503e2f98b95SBram Moolenaar if base != '' 5045c73622aSBram Moolenaar " Filter the list based on the first few characters the user entered. 5055c73622aSBram Moolenaar " Check if the text matches at the beginning 506db7207e6SBram Moolenaar " \\(^.base.'\\) 5075c73622aSBram Moolenaar " or 5085c73622aSBram Moolenaar " Match to a owner.table or alias.column type match 509db7207e6SBram Moolenaar " ^\\(\\w\\+\\.\\)\\?'.base.'\\) 5105c73622aSBram Moolenaar " or 5115c73622aSBram Moolenaar " Handle names with spaces "my table name" 512db7207e6SBram Moolenaar " "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"' 513db7207e6SBram Moolenaar " 5145c73622aSBram Moolenaar let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|^\\(\\w\\+\\.\\)\\?'.base.'\\)"' 5155c73622aSBram Moolenaar " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\)"' 5165c73622aSBram Moolenaar " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\(\\.\\)\\?'.base.'\\)"' 5175c73622aSBram Moolenaar " let expr = 'v:val '.(g:omni_sql_ignorecase==1?'=~?':'=~#').' "\\(^'.base.'\\|\\([^.]*\\)\\?'.base.'\\)"' 518eb3593b3SBram Moolenaar let compl_list = filter(deepcopy(compl_list), expr) 51934feacbcSBram Moolenaar 52034feacbcSBram Moolenaar if empty(compl_list) && compl_type == 'table' && base =~ '\.$' 52134feacbcSBram Moolenaar " It is possible we could be looking for column name completion 52234feacbcSBram Moolenaar " and the user simply hit C-X C-O to lets try it as well 52334feacbcSBram Moolenaar " since we had no hits with the tables. 52434feacbcSBram Moolenaar " If the base ends with a . it is hard to know if we are 52534feacbcSBram Moolenaar " completing table names or column names. 52634feacbcSBram Moolenaar let list_type = '' 52734feacbcSBram Moolenaar 52834feacbcSBram Moolenaar let compl_list = s:SQLCGetColumns(base, list_type) 52934feacbcSBram Moolenaar endif 530e2f98b95SBram Moolenaar endif 531e2f98b95SBram Moolenaar 532910f66f9SBram Moolenaar if exists('b:sql_compl_savefunc') && b:sql_compl_savefunc != "" 533910f66f9SBram Moolenaar let &omnifunc = b:sql_compl_savefunc 534910f66f9SBram Moolenaar endif 535910f66f9SBram Moolenaar 53634feacbcSBram Moolenaar if empty(compl_list) 53734feacbcSBram Moolenaar call s:SQLCWarningMsg( 'Could not find type['.compl_type.'] using prepend[.'.s:prepended.'] base['.a:base.']' ) 53834feacbcSBram Moolenaar endif 53934feacbcSBram Moolenaar 540e2f98b95SBram Moolenaar return compl_list 541e2f98b95SBram Moolenaarendfunc 542e2f98b95SBram Moolenaar 543910f66f9SBram Moolenaarfunction! sqlcomplete#PreCacheSyntax(...) 544910f66f9SBram Moolenaar let syn_group_arr = [] 545f9d5ca1dSBram Moolenaar let syn_items = [] 546f9d5ca1dSBram Moolenaar 547910f66f9SBram Moolenaar if a:0 > 0 548f9d5ca1dSBram Moolenaar if type(a:1) != 3 549f9d5ca1dSBram Moolenaar call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']") 550f9d5ca1dSBram Moolenaar return '' 551f9d5ca1dSBram Moolenaar endif 552910f66f9SBram Moolenaar let syn_group_arr = a:1 553910f66f9SBram Moolenaar else 554910f66f9SBram Moolenaar let syn_group_arr = g:omni_sql_precache_syntax_groups 555910f66f9SBram Moolenaar endif 55683e138c6SBram Moolenaar " For each group specified in the list, precache all 557*6c391a74SBram Moolenaar " the syntax items. 558910f66f9SBram Moolenaar if !empty(syn_group_arr) 559910f66f9SBram Moolenaar for group_name in syn_group_arr 560f9d5ca1dSBram Moolenaar let syn_items = extend( syn_items, s:SQLCGetSyntaxList(group_name) ) 561f9d5ca1dSBram Moolenaar endfor 562f9d5ca1dSBram Moolenaar endif 563f9d5ca1dSBram Moolenaar 564f9d5ca1dSBram Moolenaar return syn_items 565f9d5ca1dSBram Moolenaarendfunction 566f9d5ca1dSBram Moolenaar 567f9d5ca1dSBram Moolenaarfunction! sqlcomplete#ResetCacheSyntax(...) 568f9d5ca1dSBram Moolenaar let syn_group_arr = [] 569f9d5ca1dSBram Moolenaar 570f9d5ca1dSBram Moolenaar if a:0 > 0 571f9d5ca1dSBram Moolenaar if type(a:1) != 3 572f9d5ca1dSBram Moolenaar call s:SQLCWarningMsg("Parameter is not a list. Example:['syntaxGroup1', 'syntaxGroup2']") 573f9d5ca1dSBram Moolenaar return '' 574f9d5ca1dSBram Moolenaar endif 575f9d5ca1dSBram Moolenaar let syn_group_arr = a:1 576f9d5ca1dSBram Moolenaar else 577f9d5ca1dSBram Moolenaar let syn_group_arr = g:omni_sql_precache_syntax_groups 578f9d5ca1dSBram Moolenaar endif 579f9d5ca1dSBram Moolenaar " For each group specified in the list, precache all 580*6c391a74SBram Moolenaar " the syntax items. 581f9d5ca1dSBram Moolenaar if !empty(syn_group_arr) 582f9d5ca1dSBram Moolenaar for group_name in syn_group_arr 583f9d5ca1dSBram Moolenaar let list_idx = index(s:syn_list, group_name, 0, &ignorecase) 584f9d5ca1dSBram Moolenaar if list_idx > -1 585f9d5ca1dSBram Moolenaar " Remove from list of groups 586f9d5ca1dSBram Moolenaar call remove( s:syn_list, list_idx ) 587f9d5ca1dSBram Moolenaar " Remove from list of keywords 588f9d5ca1dSBram Moolenaar call remove( s:syn_value, list_idx ) 589f9d5ca1dSBram Moolenaar endif 590910f66f9SBram Moolenaar endfor 591910f66f9SBram Moolenaar endif 592910f66f9SBram Moolenaarendfunction 593910f66f9SBram Moolenaar 594910f66f9SBram Moolenaarfunction! sqlcomplete#Map(type) 595910f66f9SBram Moolenaar " Tell the SQL plugin what you want to complete 596910f66f9SBram Moolenaar let b:sql_compl_type=a:type 597910f66f9SBram Moolenaar " Record previous omnifunc, if the SQL completion 598910f66f9SBram Moolenaar " is being used in conjunction with other filetype 599910f66f9SBram Moolenaar " completion plugins 600910f66f9SBram Moolenaar if &omnifunc != "" && &omnifunc != 'sqlcomplete#Complete' 601910f66f9SBram Moolenaar " Record the previous omnifunc, the plugin 602910f66f9SBram Moolenaar " will automatically set this back so that it 603910f66f9SBram Moolenaar " does not interfere with other ftplugins settings 604910f66f9SBram Moolenaar let b:sql_compl_savefunc=&omnifunc 605910f66f9SBram Moolenaar endif 606910f66f9SBram Moolenaar " Set the OMNI func for the SQL completion plugin 607910f66f9SBram Moolenaar let &omnifunc='sqlcomplete#Complete' 608910f66f9SBram Moolenaarendfunction 609910f66f9SBram Moolenaar 610f193fffdSBram Moolenaarfunction! sqlcomplete#DrillIntoTable() 611f193fffdSBram Moolenaar " If the omni popup window is visible 612f193fffdSBram Moolenaar if pumvisible() 613f193fffdSBram Moolenaar call sqlcomplete#Map('column') 614f193fffdSBram Moolenaar " C-Y, makes the currently highlighted entry active 615f193fffdSBram Moolenaar " and trigger the omni popup to be redisplayed 61600a927d6SBram Moolenaar call feedkeys("\<C-Y>\<C-X>\<C-O>", 'n') 617f193fffdSBram Moolenaar else 618f193fffdSBram Moolenaar " If the popup is not visible, simple perform the normal 61900a927d6SBram Moolenaar " key behaviour. 620*6c391a74SBram Moolenaar " Must use exec since the key must be preceded by "\" 62100a927d6SBram Moolenaar " or feedkeys will simply push each character of the string 62200a927d6SBram Moolenaar " rather than the "key press". 62300a927d6SBram Moolenaar exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_right.'", "n")' 624f193fffdSBram Moolenaar endif 625f193fffdSBram Moolenaar return "" 626f193fffdSBram Moolenaarendfunction 627f193fffdSBram Moolenaar 628f193fffdSBram Moolenaarfunction! sqlcomplete#DrillOutOfColumns() 629f193fffdSBram Moolenaar " If the omni popup window is visible 630f193fffdSBram Moolenaar if pumvisible() 631f193fffdSBram Moolenaar call sqlcomplete#Map('tableReset') 632f193fffdSBram Moolenaar " Trigger the omni popup to be redisplayed 633f193fffdSBram Moolenaar call feedkeys("\<C-X>\<C-O>") 634f193fffdSBram Moolenaar else 635f193fffdSBram Moolenaar " If the popup is not visible, simple perform the normal 63600a927d6SBram Moolenaar " key behaviour. 637*6c391a74SBram Moolenaar " Must use exec since the key must be preceded by "\" 63800a927d6SBram Moolenaar " or feedkeys will simply push each character of the string 63900a927d6SBram Moolenaar " rather than the "key press". 64000a927d6SBram Moolenaar exec 'call feedkeys("\'.g:ftplugin_sql_omni_key_left.'", "n")' 641f193fffdSBram Moolenaar endif 642f193fffdSBram Moolenaar return "" 643f193fffdSBram Moolenaarendfunction 644f193fffdSBram Moolenaar 645f193fffdSBram Moolenaarfunction! s:SQLCWarningMsg(msg) 646f193fffdSBram Moolenaar echohl WarningMsg 647f9d5ca1dSBram Moolenaar echomsg 'SQLComplete:'.a:msg 648f193fffdSBram Moolenaar echohl None 649f193fffdSBram Moolenaarendfunction 650f193fffdSBram Moolenaar 651f193fffdSBram Moolenaarfunction! s:SQLCErrorMsg(msg) 652f193fffdSBram Moolenaar echohl ErrorMsg 653f9d5ca1dSBram Moolenaar echomsg 'SQLComplete:'.a:msg 654f193fffdSBram Moolenaar echohl None 655f193fffdSBram Moolenaarendfunction 656f193fffdSBram Moolenaar 657910f66f9SBram Moolenaarfunction! s:SQLCGetSyntaxList(syn_group) 658910f66f9SBram Moolenaar let syn_group = a:syn_group 659910f66f9SBram Moolenaar let compl_list = [] 660910f66f9SBram Moolenaar 661910f66f9SBram Moolenaar " Check if we have already cached the syntax list 662910f66f9SBram Moolenaar let list_idx = index(s:syn_list, syn_group, 0, &ignorecase) 663910f66f9SBram Moolenaar if list_idx > -1 664910f66f9SBram Moolenaar " Return previously cached value 665910f66f9SBram Moolenaar let compl_list = s:syn_value[list_idx] 666910f66f9SBram Moolenaar else 667ad3b366cSBram Moolenaar let s:save_inc = g:omni_syntax_group_include_sql 668ad3b366cSBram Moolenaar let s:save_exc = g:omni_syntax_group_exclude_sql 669ad3b366cSBram Moolenaar let g:omni_syntax_group_include_sql = '' 670ad3b366cSBram Moolenaar let g:omni_syntax_group_exclude_sql = '' 671ad3b366cSBram Moolenaar 672910f66f9SBram Moolenaar " Request the syntax list items from the 673910f66f9SBram Moolenaar " syntax completion plugin 674910f66f9SBram Moolenaar if syn_group == 'syntax' 675910f66f9SBram Moolenaar " Handle this special case. This allows the user 676910f66f9SBram Moolenaar " to indicate they want all the syntax items available, 677910f66f9SBram Moolenaar " so do not specify a specific include list. 678ad3b366cSBram Moolenaar let syn_value = syntaxcomplete#OmniSyntaxList() 679910f66f9SBram Moolenaar else 680910f66f9SBram Moolenaar " The user has specified a specific syntax group 681910f66f9SBram Moolenaar let g:omni_syntax_group_include_sql = syn_group 682ad3b366cSBram Moolenaar let syn_value = syntaxcomplete#OmniSyntaxList(syn_group) 683910f66f9SBram Moolenaar endif 684910f66f9SBram Moolenaar let g:omni_syntax_group_include_sql = s:save_inc 685910f66f9SBram Moolenaar let g:omni_syntax_group_exclude_sql = s:save_exc 686910f66f9SBram Moolenaar " Cache these values for later use 687910f66f9SBram Moolenaar let s:syn_list = add( s:syn_list, syn_group ) 688910f66f9SBram Moolenaar let s:syn_value = add( s:syn_value, syn_value ) 689910f66f9SBram Moolenaar let compl_list = syn_value 690910f66f9SBram Moolenaar endif 691910f66f9SBram Moolenaar 692910f66f9SBram Moolenaar return compl_list 693910f66f9SBram Moolenaarendfunction 694910f66f9SBram Moolenaar 695e2f98b95SBram Moolenaarfunction! s:SQLCCheck4dbext() 696e2f98b95SBram Moolenaar if !exists('g:loaded_dbext') 697e2f98b95SBram Moolenaar let msg = "The dbext plugin must be loaded for dynamic SQL completion" 698e2f98b95SBram Moolenaar call s:SQLCErrorMsg(msg) 699e2f98b95SBram Moolenaar " Leave time for the user to read the error message 700e2f98b95SBram Moolenaar :sleep 2 701e2f98b95SBram Moolenaar return -1 7028c8de839SBram Moolenaar elseif g:loaded_dbext < 600 7038c8de839SBram Moolenaar let msg = "The dbext plugin must be at least version 5.30 " . 704e2f98b95SBram Moolenaar \ " for dynamic SQL completion" 705e2f98b95SBram Moolenaar call s:SQLCErrorMsg(msg) 706e2f98b95SBram Moolenaar " Leave time for the user to read the error message 707e2f98b95SBram Moolenaar :sleep 2 708e2f98b95SBram Moolenaar return -1 709e2f98b95SBram Moolenaar endif 710e2f98b95SBram Moolenaar return 1 711e2f98b95SBram Moolenaarendfunction 712e2f98b95SBram Moolenaar 713e2f98b95SBram Moolenaarfunction! s:SQLCAddAlias(table_name, table_alias, cols) 714f193fffdSBram Moolenaar " Strip off the owner if included 715f193fffdSBram Moolenaar let table_name = matchstr(a:table_name, '\%(.\{-}\.\)\?\zs\(.*\)' ) 716e2f98b95SBram Moolenaar let table_alias = a:table_alias 717e2f98b95SBram Moolenaar let cols = a:cols 718e2f98b95SBram Moolenaar 719e2f98b95SBram Moolenaar if g:omni_sql_use_tbl_alias != 'n' 720e2f98b95SBram Moolenaar if table_alias == '' 721e2f98b95SBram Moolenaar if 'da' =~? g:omni_sql_use_tbl_alias 722e2f98b95SBram Moolenaar if table_name =~ '_' 723e2f98b95SBram Moolenaar " Treat _ as separators since people often use these 724e2f98b95SBram Moolenaar " for word separators 725e2f98b95SBram Moolenaar let save_keyword = &iskeyword 726e2f98b95SBram Moolenaar setlocal iskeyword-=_ 727e2f98b95SBram Moolenaar 728e2f98b95SBram Moolenaar " Get the first letter of each word 729e2f98b95SBram Moolenaar " [[:alpha:]] is used instead of \w 730e2f98b95SBram Moolenaar " to catch extended accented characters 731e2f98b95SBram Moolenaar " 732e2f98b95SBram Moolenaar let table_alias = substitute( 733e2f98b95SBram Moolenaar \ table_name, 734e2f98b95SBram Moolenaar \ '\<[[:alpha:]]\+\>_\?', 735e2f98b95SBram Moolenaar \ '\=strpart(submatch(0), 0, 1)', 736e2f98b95SBram Moolenaar \ 'g' 737e2f98b95SBram Moolenaar \ ) 738e2f98b95SBram Moolenaar " Restore original value 739e2f98b95SBram Moolenaar let &iskeyword = save_keyword 740e2f98b95SBram Moolenaar elseif table_name =~ '\u\U' 741f193fffdSBram Moolenaar let table_alias = substitute( 742e2f98b95SBram Moolenaar \ table_name, '\(\u\)\U*', '\1', 'g') 743e2f98b95SBram Moolenaar else 744e2f98b95SBram Moolenaar let table_alias = strpart(table_name, 0, 1) 745e2f98b95SBram Moolenaar endif 746e2f98b95SBram Moolenaar endif 747e2f98b95SBram Moolenaar endif 748e2f98b95SBram Moolenaar if table_alias != '' 749e2f98b95SBram Moolenaar " Following a word character, make sure there is a . and no spaces 750e2f98b95SBram Moolenaar let table_alias = substitute(table_alias, '\w\zs\.\?\s*$', '.', '') 751e2f98b95SBram Moolenaar if 'a' =~? g:omni_sql_use_tbl_alias && a:table_alias == '' 752e2f98b95SBram Moolenaar let table_alias = inputdialog("Enter table alias:", table_alias) 753e2f98b95SBram Moolenaar endif 754e2f98b95SBram Moolenaar endif 755e2f98b95SBram Moolenaar if table_alias != '' 756e2f98b95SBram Moolenaar let cols = substitute(cols, '\<\w', table_alias.'&', 'g') 757e2f98b95SBram Moolenaar endif 758e2f98b95SBram Moolenaar endif 759e2f98b95SBram Moolenaar 760e2f98b95SBram Moolenaar return cols 761e2f98b95SBram Moolenaarendfunction 762e2f98b95SBram Moolenaar 76383e138c6SBram Moolenaarfunction! s:SQLCGetObjectOwner(object) 76483e138c6SBram Moolenaar " The owner regex matches a word at the start of the string which is 76583e138c6SBram Moolenaar " followed by a dot, but doesn't include the dot in the result. 76683e138c6SBram Moolenaar " ^ - from beginning of line 7678c8de839SBram Moolenaar " \("\|\[\)\? - ignore any quotes 76883e138c6SBram Moolenaar " \zs - start the match now 7698c8de839SBram Moolenaar " .\{-} - get owner name 77083e138c6SBram Moolenaar " \ze - end the match 7718c8de839SBram Moolenaar " \("\|\[\)\? - ignore any quotes 77283e138c6SBram Moolenaar " \. - must by followed by a . 7738c8de839SBram Moolenaar " let owner = matchstr( a:object, '^\s*\zs.*\ze\.' ) 7748c8de839SBram Moolenaar let owner = matchstr( a:object, '^\("\|\[\)\?\zs\.\{-}\ze\("\|\]\)\?\.' ) 77583e138c6SBram Moolenaar return owner 77683e138c6SBram Moolenaarendfunction 77783e138c6SBram Moolenaar 778e2f98b95SBram Moolenaarfunction! s:SQLCGetColumns(table_name, list_type) 77934feacbcSBram Moolenaar if a:table_name =~ '\.' 78034feacbcSBram Moolenaar " Check if the owner/creator has been specified 78134feacbcSBram Moolenaar let owner = matchstr( a:table_name, '^\zs.*\ze\..*\..*' ) 78234feacbcSBram Moolenaar let table = matchstr( a:table_name, '^\(.*\.\)\?\zs.*\ze\..*' ) 78334feacbcSBram Moolenaar let column = matchstr( a:table_name, '.*\.\zs.*' ) 78434feacbcSBram Moolenaar 78534feacbcSBram Moolenaar if g:omni_sql_include_owner == 1 && owner == '' && table != '' && column != '' 78634feacbcSBram Moolenaar let owner = table 78734feacbcSBram Moolenaar let table = column 78834feacbcSBram Moolenaar let column = '' 78934feacbcSBram Moolenaar endif 79034feacbcSBram Moolenaar else 79134feacbcSBram Moolenaar let owner = '' 79234feacbcSBram Moolenaar let table = matchstr(a:table_name, '^["\[\]a-zA-Z0-9_ ]\+\ze\.\?') 79334feacbcSBram Moolenaar let column = '' 79434feacbcSBram Moolenaar endif 79534feacbcSBram Moolenaar 79683e138c6SBram Moolenaar " Check if the table name was provided as part of the column name 79734feacbcSBram Moolenaar " let table_name = matchstr(a:table_name, '^["\[\]a-zA-Z0-9_ ]\+\ze\.\?') 79834feacbcSBram Moolenaar let table_name = table 799e2f98b95SBram Moolenaar let table_cols = [] 800e2f98b95SBram Moolenaar let table_alias = '' 801e2f98b95SBram Moolenaar let move_to_top = 1 802e2f98b95SBram Moolenaar 8038c8de839SBram Moolenaar let table_name = substitute(table_name, '\s*\(.\{-}\)\s*$', '\1', 'g') 8048c8de839SBram Moolenaar 8058c8de839SBram Moolenaar " If the table name was given as: 8068c8de839SBram Moolenaar " where c. 8078c8de839SBram Moolenaar let table_name = substitute(table_name, '^\c\(WHERE\|AND\|OR\)\s\+', '', '') 808eb3593b3SBram Moolenaar if g:loaded_dbext >= 300 809e2f98b95SBram Moolenaar let saveSettingAlias = DB_listOption('use_tbl_alias') 810e2f98b95SBram Moolenaar exec 'DBSetOption use_tbl_alias=n' 811e2f98b95SBram Moolenaar endif 812e2f98b95SBram Moolenaar 8138c8de839SBram Moolenaar let table_name_stripped = substitute(table_name, '["\[\]]*', '', 'g') 8148c8de839SBram Moolenaar 815e2f98b95SBram Moolenaar " Check if we have already cached the column list for this table 816e2f98b95SBram Moolenaar " by its name 8178c8de839SBram Moolenaar let list_idx = index(s:tbl_name, table_name_stripped, 0, &ignorecase) 818e2f98b95SBram Moolenaar if list_idx > -1 8198c8de839SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx], '\n') 820e2f98b95SBram Moolenaar else 821e2f98b95SBram Moolenaar " Check if we have already cached the column list for this table 822e2f98b95SBram Moolenaar " by its alias, assuming the table_name provided was actually 823e2f98b95SBram Moolenaar " the alias for the table instead 824e2f98b95SBram Moolenaar " select * 825e2f98b95SBram Moolenaar " from area a 826e2f98b95SBram Moolenaar " where a. 8278c8de839SBram Moolenaar let list_idx = index(s:tbl_alias, table_name_stripped, 0, &ignorecase) 828e2f98b95SBram Moolenaar if list_idx > -1 8298c8de839SBram Moolenaar let table_alias = table_name_stripped 830e2f98b95SBram Moolenaar let table_name = s:tbl_name[list_idx] 8318c8de839SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx], '\n') 832e2f98b95SBram Moolenaar endif 833e2f98b95SBram Moolenaar endif 834e2f98b95SBram Moolenaar 835e2f98b95SBram Moolenaar " If we have not found a cached copy of the table 836e2f98b95SBram Moolenaar " And the table ends in a "." or we are looking for a column list 837e2f98b95SBram Moolenaar " if list_idx == -1 && (a:table_name =~ '\.' || b:sql_compl_type =~ 'column') 838e2f98b95SBram Moolenaar " if list_idx == -1 && (a:table_name =~ '\.' || a:list_type =~ 'csv') 839e2f98b95SBram Moolenaar if list_idx == -1 840e2f98b95SBram Moolenaar let saveY = @y 841e2f98b95SBram Moolenaar let saveSearch = @/ 842e2f98b95SBram Moolenaar let saveWScan = &wrapscan 843e2f98b95SBram Moolenaar let curline = line(".") 844e2f98b95SBram Moolenaar let curcol = col(".") 845e2f98b95SBram Moolenaar 846*6c391a74SBram Moolenaar " Do not let searches wrap 847e2f98b95SBram Moolenaar setlocal nowrapscan 848e2f98b95SBram Moolenaar " If . was entered, look at the word just before the . 849e2f98b95SBram Moolenaar " We are looking for something like this: 850e2f98b95SBram Moolenaar " select * 851e2f98b95SBram Moolenaar " from customer c 852e2f98b95SBram Moolenaar " where c. 853e2f98b95SBram Moolenaar " So when . is pressed, we need to find 'c' 854e2f98b95SBram Moolenaar " 855e2f98b95SBram Moolenaar 856e2f98b95SBram Moolenaar " Search backwards to the beginning of the statement 857e2f98b95SBram Moolenaar " and do NOT wrap 858e2f98b95SBram Moolenaar " exec 'silent! normal! v?\<\(select\|update\|delete\|;\)\>'."\n".'"yy' 85900a927d6SBram Moolenaar exec 'silent! normal! ?\<\c\(select\|update\|delete\|;\)\>'."\n" 860e2f98b95SBram Moolenaar 861e2f98b95SBram Moolenaar " Start characterwise visual mode 862e2f98b95SBram Moolenaar " Advance right one character 86301164a65SBram Moolenaar " Search forward until one of the following: 864e2f98b95SBram Moolenaar " 1. Another select/update/delete statement 865e2f98b95SBram Moolenaar " 2. A ; at the end of a line (the delimiter) 866e2f98b95SBram Moolenaar " 3. The end of the file (in case no delimiter) 867e2f98b95SBram Moolenaar " Yank the visually selected text into the "y register. 86800a927d6SBram Moolenaar exec 'silent! normal! vl/\c\(\<select\>\|\<update\>\|\<delete\>\|;\s*$\|\%$\)'."\n".'"yy' 869e2f98b95SBram Moolenaar 870e2f98b95SBram Moolenaar let query = @y 871e2f98b95SBram Moolenaar let query = substitute(query, "\n", ' ', 'g') 872e2f98b95SBram Moolenaar let found = 0 873e2f98b95SBram Moolenaar 87400a927d6SBram Moolenaar " if query =~? '^\c\(select\)' 87500a927d6SBram Moolenaar if query =~? '^\(select\|update\|delete\)' 876e2f98b95SBram Moolenaar let found = 1 877e2f98b95SBram Moolenaar " \(\(\<\w\+\>\)\.\)\? - 87800a927d6SBram Moolenaar " '\c\(from\|join\|,\).\{-}' - Starting at the from clause (case insensitive) 879e2f98b95SBram Moolenaar " '\zs\(\(\<\w\+\>\)\.\)\?' - Get the owner name (optional) 880e2f98b95SBram Moolenaar " '\<\w\+\>\ze' - Get the table name 881e2f98b95SBram Moolenaar " '\s\+\<'.table_name.'\>' - Followed by the alias 882e2f98b95SBram Moolenaar " '\s*\.\@!.*' - Cannot be followed by a . 883e2f98b95SBram Moolenaar " '\(\<where\>\|$\)' - Must be followed by a WHERE clause 884e2f98b95SBram Moolenaar " '.*' - Exclude the rest of the line in the match 88500a927d6SBram Moolenaar " let table_name_new = matchstr(@y, 88600a927d6SBram Moolenaar " \ '\c\(from\|join\|,\).\{-}'. 88700a927d6SBram Moolenaar " \ '\zs\(\("\|\[\)\?.\{-}\("\|\]\)\.\)\?'. 88800a927d6SBram Moolenaar " \ '\("\|\[\)\?.\{-}\("\|\]\)\?\ze'. 88900a927d6SBram Moolenaar " \ '\s\+\%(as\s\+\)\?\<'. 89000a927d6SBram Moolenaar " \ matchstr(table_name, '.\{-}\ze\.\?$'). 89100a927d6SBram Moolenaar " \ '\>'. 89200a927d6SBram Moolenaar " \ '\s*\.\@!.*'. 89300a927d6SBram Moolenaar " \ '\(\<where\>\|$\)'. 89400a927d6SBram Moolenaar " \ '.*' 89500a927d6SBram Moolenaar " \ ) 896db7207e6SBram Moolenaar " 897db7207e6SBram Moolenaar " 898db7207e6SBram Moolenaar " ''\c\(\<from\>\|\<join\>\|,\)\s*' - Starting at the from clause (case insensitive) 899db7207e6SBram Moolenaar " '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?' - Get the owner name (optional) 900db7207e6SBram Moolenaar " '\("\|\[\)\?\w\+\("\|\]\)\?\ze' - Get the table name 901db7207e6SBram Moolenaar " '\s\+\%(as\s\+\)\?\<'.matchstr(table_name, '.\{-}\ze\.\?$').'\>' - Followed by the alias 902db7207e6SBram Moolenaar " '\s*\.\@!.*' - Cannot be followed by a . 903db7207e6SBram Moolenaar " '\(\<where\>\|$\)' - Must be followed by a WHERE clause 904db7207e6SBram Moolenaar " '.*' - Exclude the rest of the line in the match 905e2f98b95SBram Moolenaar let table_name_new = matchstr(@y, 90600a927d6SBram Moolenaar \ '\c\(\<from\>\|\<join\>\|,\)\s*'. 90700a927d6SBram Moolenaar \ '\zs\(\("\|\[\)\?\w\+\("\|\]\)\?\.\)\?'. 90800a927d6SBram Moolenaar \ '\("\|\[\)\?\w\+\("\|\]\)\?\ze'. 909f193fffdSBram Moolenaar \ '\s\+\%(as\s\+\)\?\<'. 910f193fffdSBram Moolenaar \ matchstr(table_name, '.\{-}\ze\.\?$'). 911f193fffdSBram Moolenaar \ '\>'. 912e2f98b95SBram Moolenaar \ '\s*\.\@!.*'. 913e2f98b95SBram Moolenaar \ '\(\<where\>\|$\)'. 914e2f98b95SBram Moolenaar \ '.*' 915e2f98b95SBram Moolenaar \ ) 9168c8de839SBram Moolenaar 917e2f98b95SBram Moolenaar if table_name_new != '' 918e2f98b95SBram Moolenaar let table_alias = table_name 91934feacbcSBram Moolenaar if g:omni_sql_include_owner == 1 92034feacbcSBram Moolenaar let table_name = matchstr( table_name_new, '^\zs\(.\{-}\.\)\?\(.\{-}\.\)\?.*\ze' ) 92134feacbcSBram Moolenaar else 92234feacbcSBram Moolenaar " let table_name = matchstr( table_name_new, '^\(.*\.\)\?\zs.*\ze' ) 92334feacbcSBram Moolenaar let table_name = matchstr( table_name_new, '^\(.\{-}\.\)\?\zs\(.\{-}\.\)\?.*\ze' ) 92434feacbcSBram Moolenaar endif 925e2f98b95SBram Moolenaar 926e2f98b95SBram Moolenaar let list_idx = index(s:tbl_name, table_name, 0, &ignorecase) 927e2f98b95SBram Moolenaar if list_idx > -1 928e2f98b95SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx]) 929e2f98b95SBram Moolenaar let s:tbl_name[list_idx] = table_name 930e2f98b95SBram Moolenaar let s:tbl_alias[list_idx] = table_alias 931e2f98b95SBram Moolenaar else 932e2f98b95SBram Moolenaar let list_idx = index(s:tbl_alias, table_name, 0, &ignorecase) 933e2f98b95SBram Moolenaar if list_idx > -1 934e2f98b95SBram Moolenaar let table_cols = split(s:tbl_cols[list_idx]) 935e2f98b95SBram Moolenaar let s:tbl_name[list_idx] = table_name 936e2f98b95SBram Moolenaar let s:tbl_alias[list_idx] = table_alias 937e2f98b95SBram Moolenaar endif 938e2f98b95SBram Moolenaar endif 939e2f98b95SBram Moolenaar 940e2f98b95SBram Moolenaar endif 941e2f98b95SBram Moolenaar else 942e2f98b95SBram Moolenaar " Simply assume it is a table name provided with a . on the end 943e2f98b95SBram Moolenaar let found = 1 944e2f98b95SBram Moolenaar endif 945e2f98b95SBram Moolenaar 946e2f98b95SBram Moolenaar let @y = saveY 947e2f98b95SBram Moolenaar let @/ = saveSearch 948e2f98b95SBram Moolenaar let &wrapscan = saveWScan 949e2f98b95SBram Moolenaar 950e2f98b95SBram Moolenaar " Return to previous location 951e2f98b95SBram Moolenaar call cursor(curline, curcol) 952e2f98b95SBram Moolenaar 953e2f98b95SBram Moolenaar if found == 0 954eb3593b3SBram Moolenaar if g:loaded_dbext > 300 955e2f98b95SBram Moolenaar exec 'DBSetOption use_tbl_alias='.saveSettingAlias 956e2f98b95SBram Moolenaar endif 957e2f98b95SBram Moolenaar 958e2f98b95SBram Moolenaar " Not a SQL statement, do not display a list 959e2f98b95SBram Moolenaar return [] 960e2f98b95SBram Moolenaar endif 961e2f98b95SBram Moolenaar endif 962e2f98b95SBram Moolenaar 963e2f98b95SBram Moolenaar if empty(table_cols) 964e2f98b95SBram Moolenaar " Specify silent mode, no messages to the user (tbl, 1) 965e2f98b95SBram Moolenaar " Specify do not comma separate (tbl, 1, 1) 96634feacbcSBram Moolenaar " let table_cols_str = DB_getListColumn(table_name, 1, 1) 96734feacbcSBram Moolenaar let table_cols_str = DB_getListColumn((owner!=''?owner.'.':'').table_name, 1, 1) 968e2f98b95SBram Moolenaar 969e2f98b95SBram Moolenaar if table_cols_str != "" 970e2f98b95SBram Moolenaar let s:tbl_name = add( s:tbl_name, table_name ) 971e2f98b95SBram Moolenaar let s:tbl_alias = add( s:tbl_alias, table_alias ) 972e2f98b95SBram Moolenaar let s:tbl_cols = add( s:tbl_cols, table_cols_str ) 9738c8de839SBram Moolenaar let table_cols = split(table_cols_str, '\n') 974e2f98b95SBram Moolenaar endif 975e2f98b95SBram Moolenaar 976e2f98b95SBram Moolenaar endif 977e2f98b95SBram Moolenaar 978eb3593b3SBram Moolenaar if g:loaded_dbext > 300 979e2f98b95SBram Moolenaar exec 'DBSetOption use_tbl_alias='.saveSettingAlias 980e2f98b95SBram Moolenaar endif 981e2f98b95SBram Moolenaar 982f193fffdSBram Moolenaar " If the user has asked for a comma separate list of column 983f193fffdSBram Moolenaar " values, ask the user if they want to prepend each column 984f193fffdSBram Moolenaar " with a tablename alias. 985e2f98b95SBram Moolenaar if a:list_type == 'csv' && !empty(table_cols) 986e2f98b95SBram Moolenaar let cols = join(table_cols, ', ') 987e2f98b95SBram Moolenaar let cols = s:SQLCAddAlias(table_name, table_alias, cols) 988e2f98b95SBram Moolenaar let table_cols = [cols] 989e2f98b95SBram Moolenaar endif 990e2f98b95SBram Moolenaar 991e2f98b95SBram Moolenaar return table_cols 992e2f98b95SBram Moolenaarendfunction 99334feacbcSBram Moolenaar" Restore: 99434feacbcSBram Moolenaarlet &cpo= s:keepcpo 99534feacbcSBram Moolenaarunlet s:keepcpo 99634feacbcSBram Moolenaar" vim: ts=4 fdm=marker 997