changeset 132:2baecb3d5356

improving tab completion
author catherine@Elli.myhome.westell.com
date Wed, 27 Aug 2008 21:49:26 -0400
parents 2b7ce838120d
children 25cbb45b190d
files sqlpyPlus.py
diffstat 1 files changed, 41 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/sqlpyPlus.py	Wed Aug 27 19:35:28 2008 -0400
+++ b/sqlpyPlus.py	Wed Aug 27 21:49:26 2008 -0400
@@ -185,7 +185,7 @@
 """
 }
 
-import sys, os, re, sqlpython, cx_Oracle, pyparsing
+import sys, os, re, sqlpython, cx_Oracle, pyparsing, re, completion
 from cmd2 import Cmd, make_option, options, Statekeeper
 
 if float(sys.version[:3]) < 2.3:
@@ -506,13 +506,47 @@
 
     legalOracle = re.compile('[a-zA-Z_$#]')
 
-    def complete_select(self, text, line, begidx, endidx):
+    def select_list(self, sql):
+        self.curs.execute(sql)
+        return [r[0] for r in self.curs.fetchall()]
+    
+    tableNameRegex = re.compile(
+        r'(from|update)\s+(([a-zA-Z0-9_#$]+)\.)?([a-zA-Z0-9_#$]+)\s+',
+        re.IGNORECASE | re.DOTALL | re.MULTILINE)
+    columnNameRegex = re.compile(
+        r'select\s+(.*)from',
+        re.IGNORECASE | re.DOTALL | re.MULTILINE)        
+    def completedefault(self, text, line, begidx, endidx):
+        segment = completion.whichSegment(line)
+        text = text.upper()
         completions = []
-        for statement in """SELECT column_name FROM all_tab_columns WHERE column_name LIKE '%s%%'
-        SELECT table_name FROM all_tables WHERE table_name LIKE '%s%%'
-        SELECT DISTINCT owner FROM all_tables WHERE owner LIKE '%%%s'""".splitlines():
-            self.curs.execute(statement % text.upper())
-            completions.extend([r[0] for r in self.curs.fetchall()])
+        if segment == 'select':
+            stmt = "SELECT column_name FROM user_tab_columns WHERE column_name LIKE '%s%%'"
+            completions = self.select_list(stmt % (text))
+            if not completions:
+                stmt = "SELECT column_name FROM all_tab_columns WHERE column_name LIKE '%s%%'"            
+                completions = self.select_list(stmt % (text))
+        elif segment in ('from', 'update'):
+            stmt = "SELECT table_name FROM user_tables WHERE table_name LIKE '%s%%'"
+            completions = self.select_list(stmt % (text))
+            if not completions:
+                stmt = """SELECT table_name FROM user_tables WHERE table_name LIKE '%s%%'
+                      UNION
+                      SELECT DISTINCT owner FROM all_tables WHERE owner LIKE '%%%s'"""
+                completions = self.select_list(stmt % (text, text))
+        elif segment in ('where', 'group by', 'order by'):
+            try:
+                owner, tableName = self.tableNameRegex.search(line).groups()[2:4]
+            except AttributeError:
+                return []
+            if owner:
+                stmt = "SELECT column_name FROM all_tab_columns WHERE owner = '%s' AND table_name = '%s'" \
+                     % (owner.upper(), tableName.upper())
+            else:
+                stmt = "SELECT column_name FROM all_tab_columns WHERE table_name = '%s'" \
+                     % (tableName.upper())
+            completions = self.select_list(stmt)
+            
         return completions
     
     rowlimitPattern = pyparsing.Word(pyparsing.nums)('rowlimit')
@@ -977,55 +1011,6 @@
         object_type, owner, object_name = self.resolve(arg)
         if object_type == 'TABLE':
             self.do_select(queries['refs'],bindVarsIn={'object_name':object_name, 'owner':owner})
-
-sqlStyleComment = pyparsing.Literal("--") + pyparsing.ZeroOrMore(pyparsing.CharsNotIn("\n"))
-keywords = {'order by': pyparsing.Keyword('order', caseless=True) +
-                        pyparsing.Keyword('by', caseless=True),
-            'select': pyparsing.Keyword('select', caseless=True),
-            'from': pyparsing.Keyword('from', caseless=True),
-            'having': pyparsing.Keyword('having', caseless=True),            
-            'update': pyparsing.Keyword('update', caseless=True),
-            'set': pyparsing.Keyword('set', caseless=True),            
-            'delete': pyparsing.Keyword('delete', caseless=True),            
-            'insert into': pyparsing.Keyword('insert', caseless=True) +
-                           pyparsing.Keyword('into', caseless=True),
-            'values': pyparsing.Keyword('values', caseless=True),
-            'group by': pyparsing.Keyword('group', caseless=True) +
-                        pyparsing.Keyword('by', caseless=True),
-            'where': pyparsing.Keyword('where', caseless=True)}
-for (name, parser) in keywords.items():
-    parser.ignore(pyparsing.sglQuotedString)
-    parser.ignore(pyparsing.dblQuotedString)
-    parser.ignore(pyparsing.cStyleComment)
-    parser.ignore(sqlStyleComment)
-    parser.name = name
-    
-def orderedParseResults(parsers, statement):
-    results = []
-    for parser in parsers:
-        results.extend(parser.scanString(statement))
-    results.sort(cmp=lambda x,y:cmp(x[1],y[1]))
-    return results
-        
-def whichSqlPhrase(statement):
-    results = orderedParseResults(keywords.values(), statement)
-    if results:
-        return ' '.join(results[-1][0])
-    else:
-        return None
-    
-oracleIdentifierCharacters = pyparsing.alphanums + '_#$'
-def wordInProgress(statement):
-    result = []
-    letters = list(statement)
-    letters.reverse()
-    for letter in letters:
-        if letter not in oracleIdentifierCharacters:
-            result.reverse()
-            return ''.join(result)
-        result.append(letter)
-    result.reverse()
-    return ''.join(result)
     
 def _test():
     import doctest