@@ -216,10 +216,6 @@ class Completion(unittest.TestCase):
216216
217217    @classmethod  
218218    def  setUpClass (cls ):
219-         _sqlite3  =  import_module ("_sqlite3" )
220-         if  not  hasattr (_sqlite3 , "SQLITE_KEYWORDS" ):
221-             raise  unittest .SkipTest ("unable to determine SQLite keywords" )
222- 
223219        readline  =  import_module ("readline" )
224220        if  readline .backend  ==  "editline" :
225221            raise  unittest .SkipTest ("libedit readline is not supported" )
@@ -229,12 +225,24 @@ def write_input(self, input_, env=None):
229225            import readline 
230226            from sqlite3.__main__ import main 
231227
228+             # Configure readline to ...: 
229+             # - hide control sequences surrounding each candidate 
230+             # - hide "Display all xxx possibilities? (y or n)" 
231+             # - show candidates one per line 
232232            readline.parse_and_bind("set colored-completion-prefix off") 
233+             readline.parse_and_bind("set completion-query-items 0") 
234+             readline.parse_and_bind("set page-completions off") 
235+             readline.parse_and_bind("set completion-display-width 0") 
236+ 
233237            main() 
234238        """ )
235239        return  run_pty (script , input_ , env )
236240
237241    def  test_complete_sql_keywords (self ):
242+         _sqlite3  =  import_module ("_sqlite3" )
243+         if  not  hasattr (_sqlite3 , "SQLITE_KEYWORDS" ):
244+             raise  unittest .SkipTest ("unable to determine SQLite keywords" )
245+ 
238246        # List candidates starting with 'S', there should be multiple matches. 
239247        input_  =  b"S\t \t EL\t  1;\n .quit\n " 
240248        output  =  self .write_input (input_ )
@@ -249,6 +257,103 @@ def test_complete_sql_keywords(self):
249257        self .assertIn (b"SELECT" , output )
250258        self .assertIn (b"(1,)" , output )
251259
260+     def  test_complete_table_indexes_triggers_views (self ):
261+         input_  =  textwrap .dedent ("""\  
262+              CREATE TABLE _table (id);
263+             CREATE INDEX _index ON _table (id); 
264+             CREATE TRIGGER _trigger BEFORE INSERT 
265+                    ON _table BEGIN SELECT 1; END; 
266+             CREATE VIEW _view AS SELECT 1; 
267+ 
268+             CREATE TEMP TABLE _temp_table (id); 
269+             CREATE INDEX temp._temp_index ON _temp_table (id); 
270+             CREATE TEMP TRIGGER _temp_trigger BEFORE INSERT 
271+                    ON _table BEGIN SELECT 1; END; 
272+             CREATE TEMP VIEW _temp_view AS SELECT 1; 
273+ 
274+             ATTACH ':memory:' AS attached; 
275+             CREATE TABLE attached._attached_table (id); 
276+             CREATE INDEX attached._attached_index ON _attached_table (id); 
277+             CREATE TRIGGER attached._attached_trigger BEFORE INSERT 
278+                    ON _attached_table BEGIN SELECT 1; END; 
279+             CREATE VIEW attached._attached_view AS SELECT 1; 
280+ 
281+             SELECT id FROM _\t \t ta\t ; 
282+             .quit\n """ ).encode ()
283+         output  =  self .write_input (input_ )
284+         lines  =  output .decode ().splitlines ()
285+         indices  =  [i  for  i , line  in  enumerate (lines )
286+                   if  line .startswith (self .PS1 )]
287+         start , end  =  indices [- 3 ], indices [- 2 ]
288+         candidates  =  [l .strip () for  l  in  lines [start + 1 :end ]]
289+         self .assertEqual (candidates ,
290+             [
291+                 "_attached_index" ,
292+                 "_attached_table" ,
293+                 "_attached_trigger" ,
294+                 "_attached_view" ,
295+                 "_index" ,
296+                 "_table" ,
297+                 "_temp_index" ,
298+                 "_temp_table" ,
299+                 "_temp_trigger" ,
300+                 "_temp_view" ,
301+                 "_trigger" ,
302+                 "_view" ,
303+             ],
304+         )
305+ 
306+     def  test_complete_columns (self ):
307+         input_  =  textwrap .dedent ("""\  
308+              CREATE TABLE _table (_col_table);
309+             CREATE TEMP TABLE _temp_table (_col_temp); 
310+             ATTACH ':memory:' AS attached; 
311+             CREATE TABLE attached._attached_table (_col_attached); 
312+ 
313+             SELECT _col_\t \t ta\t FROM _table; 
314+             .quit\n """ ).encode ()
315+         output  =  self .write_input (input_ )
316+         lines  =  output .decode ().splitlines ()
317+         indices  =  [
318+             i  for  i , line  in  enumerate (lines ) if  line .startswith (self .PS1 )
319+         ]
320+         start , end  =  indices [- 3 ], indices [- 2 ]
321+         candidates  =  [l .strip () for  l  in  lines [start + 1 :end ]]
322+ 
323+         self .assertEqual (
324+             candidates , ["_col_attached" , "_col_table" , "_col_temp" ]
325+         )
326+ 
327+     def  test_complete_functions (self ):
328+         input_  =  b"SELECT AV\t 1);\n .quit\n " 
329+         output  =  self .write_input (input_ )
330+         self .assertIn (b"AVG(1);" , output )
331+         self .assertIn (b"(1.0,)" , output )
332+ 
333+         # Functions are completed in upper case for even lower case user input. 
334+         input_  =  b"SELECT av\t 1);\n .quit\n " 
335+         output  =  self .write_input (input_ )
336+         self .assertIn (b"AVG(1);" , output )
337+         self .assertIn (b"(1.0,)" , output )
338+ 
339+     def  test_complete_schemata (self ):
340+         input_  =  textwrap .dedent ("""\  
341+              ATTACH ':memory:' AS _attached;
342+             CREATE TEMP TABLE _table (id); 
343+ 
344+             SELECT * FROM \t \t _att\t .sqlite_master; 
345+             .quit\n """ ).encode ()
346+         output  =  self .write_input (input_ )
347+         lines  =  output .decode ().splitlines ()
348+         indices  =  [
349+             i  for  i , line  in  enumerate (lines ) if  line .startswith (self .PS1 )
350+         ]
351+         start , end  =  indices [- 3 ], indices [- 2 ]
352+         candidates  =  [l .strip () for  l  in  lines [start + 1 :end ]]
353+         self .assertIn ("_attached" , candidates )
354+         self .assertIn ("main" , candidates )
355+         self .assertIn ("temp" , candidates )
356+ 
252357    @unittest .skipIf (sys .platform .startswith ("freebsd" ), 
253358                    "Two actual tabs are inserted when there are no matching"  
254359                    " completions in the pseudo-terminal opened by run_pty()"  
@@ -269,8 +374,6 @@ def test_complete_no_match(self):
269374        self .assertEqual (line_num , len (lines ))
270375
271376    def  test_complete_no_input (self ):
272-         from  _sqlite3  import  SQLITE_KEYWORDS 
273- 
274377        script  =  textwrap .dedent (""" 
275378            import readline 
276379            from sqlite3.__main__ import main 
@@ -301,7 +404,7 @@ def test_complete_no_input(self):
301404            self .assertEqual (len (indices ), 2 )
302405            start , end  =  indices 
303406            candidates  =  [l .strip () for  l  in  lines [start + 1 :end ]]
304-             self .assertEqual (candidates , sorted (SQLITE_KEYWORDS ))
407+             self .assertEqual (candidates , sorted (candidates ))
305408        except :
306409            if  verbose :
307410                print (' PTY output: ' .center (30 , '-' ))
0 commit comments