GitHub CopilotWrite better code with AI | MCP RegistryIntegrate external tools | ActionsAutomate any workflow | CodespacesInstant dev environments | IssuesPlan and track work | Code ReviewManage code changes | Code QualityEnforce quality at merge | Why GitHub | Marketplace | View all features | Enterprises | Small and medium teams | Startups | View all use cases | View all industries | View all solutions | AI | Software Development | DevOps | Security | View all topics | Customer stories | Events & webinars | Ebooks & reports | Business insights | Trust center | Partners | View all resources
@@ -216,10 +216,6 @@ class Completion(unittest.TestCase):
216216217217@classmethod
218218defsetUpClass(cls):
219-_sqlite3=import_module("_sqlite3")
220-ifnothasattr(_sqlite3, "SQLITE_KEYWORDS"):
221-raiseunittest.SkipTest("unable to determine SQLite keywords")
222-223219readline=import_module("readline")
224220ifreadline.backend=="editline":
225221raiseunittest.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
231227228+ # 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 """)
235239returnrun_pty(script, input_, env)
236240237241deftest_complete_sql_keywords(self):
242+_sqlite3=import_module("_sqlite3")
243+ifnothasattr(_sqlite3, "SQLITE_KEYWORDS"):
244+raiseunittest.SkipTest("unable to determine SQLite keywords")
245+238246# List candidates starting with 'S', there should be multiple matches.
239247input_=b"S\t\tEL\t 1;\n.quit\n"
240248output=self.write_input(input_)
@@ -254,6 +262,118 @@ def test_complete_sql_keywords(self):
254262output=self.write_input(input_)
255263self.assertIn(b".version", output)
256264265+deftest_complete_table_indexes_triggers_views(self):
266+input_=textwrap.dedent("""\
267+ CREATE TABLE _Table (id);
268+ CREATE INDEX _Index ON _table (id);
269+ CREATE TRIGGER _Trigger BEFORE INSERT
270+ ON _Table BEGIN SELECT 1; END;
271+ CREATE VIEW _View AS SELECT 1;
272+273+ CREATE TEMP TABLE _Temp_table (id);
274+ CREATE INDEX temp._Temp_index ON _Temp_table (id);
275+ CREATE TEMP TRIGGER _Temp_trigger BEFORE INSERT
276+ ON _Table BEGIN SELECT 1; END;
277+ CREATE TEMP VIEW _Temp_view AS SELECT 1;
278+279+ ATTACH ':memory:' AS attached;
280+ CREATE TABLE attached._Attached_table (id);
281+ CREATE INDEX attached._Attached_index ON _Attached_table (id);
282+ CREATE TRIGGER attached._Attached_trigger BEFORE INSERT
283+ ON _Attached_table BEGIN SELECT 1; END;
284+ CREATE VIEW attached._Attached_view AS SELECT 1;
285+286+ SELECT id FROM _\t\tta\t;
287+ .quit\n""").encode()
288+output=self.write_input(input_)
289+lines=output.decode().splitlines()
290+indices= [ifori, lineinenumerate(lines)
291+ifline.startswith(self.PS1)]
292+start, end=indices[-3], indices[-2]
293+candidates= [l.strip() forlinlines[start+1:end]]
294+self.assertEqual(candidates,
295+ [
296+"_Attached_index",
297+"_Attached_table",
298+"_Attached_trigger",
299+"_Attached_view",
300+"_Index",
301+"_Table",
302+"_Temp_index",
303+"_Temp_table",
304+"_Temp_trigger",
305+"_Temp_view",
306+"_Trigger",
307+"_View",
308+ ],
309+ )
310+start, end=indices[-2], indices[-1]
311+# direct match with '_Table' completed, no candidates displayed
312+candidates= [l.strip() forlinlines[start+1:end]]
313+self.assertEqual(len(candidates), 0)
[email protected](sqlite3.sqlite_version_info< (3, 16, 0),
316+"PRAGMA table-valued function is not available until "
317+"SQLite 3.16.0")
318+deftest_complete_columns(self):
319+input_=textwrap.dedent("""\
320+ CREATE TABLE _table (_col_table);
321+ CREATE TEMP TABLE _temp_table (_col_temp);
322+ ATTACH ':memory:' AS attached;
323+ CREATE TABLE attached._attached_table (_col_attached);
324+325+ SELECT _col_\t\tta\tFROM _table;
326+ .quit\n""").encode()
327+output=self.write_input(input_)
328+lines=output.decode().splitlines()
329+indices= [
330+ifori, lineinenumerate(lines) ifline.startswith(self.PS1)
331+ ]
332+start, end=indices[-3], indices[-2]
333+candidates= [l.strip() forlinlines[start+1:end]]
334+335+self.assertEqual(
336+candidates, ["_col_attached", "_col_table", "_col_temp"]
337+ )
[email protected](sqlite3.sqlite_version_info< (3, 30, 0),
340+"PRAGMA function_list is not available until "
341+"SQLite 3.30.0")
342+deftest_complete_functions(self):
343+input_=b"SELECT AV\t1);\n.quit\n"
344+output=self.write_input(input_)
345+self.assertIn(b"AVG(1);", output)
346+self.assertIn(b"(1.0,)", output)
347+348+# Functions are completed in upper case for even lower case user input.
349+input_=b"SELECT av\t1);\n.quit\n"
350+output=self.write_input(input_)
351+self.assertIn(b"AVG(1);", output)
352+self.assertIn(b"(1.0,)", output)
353+354+deftest_complete_schemata(self):
355+input_=textwrap.dedent("""\
356+ ATTACH ':memory:' AS MixedCase;
357+ -- Test '_' is escaped in Like pattern filtering
358+ ATTACH ':memory:' AS _underscore;
359+ -- Let database_list pragma have a 'temp' schema entry
360+ CREATE TEMP TABLE _table (id);
361+362+ SELECT * FROM \t\tmIX\t.sqlite_master;
363+ SELECT * FROM _und\t.sqlite_master;
364+ .quit\n""").encode()
365+output=self.write_input(input_)
366+lines=output.decode().splitlines()
367+indices= [
368+ifori, lineinenumerate(lines) ifline.startswith(self.PS1)
369+ ]
370+start, end=indices[-4], indices[-3]
371+candidates= [l.strip() forlinlines[start+1:end]]
372+self.assertIn("MixedCase", candidates)
373+self.assertIn("_underscore", candidates)
374+self.assertIn("main", candidates)
375+self.assertIn("temp", candidates)
[email protected](sys.platform.startswith("freebsd"),
258378"Two actual tabs are inserted when there are no matching"
259379" completions in the pseudo-terminal opened by run_pty()"
@@ -274,8 +394,6 @@ def test_complete_no_match(self):
274394self.assertEqual(line_num, len(lines))
275395276396deftest_complete_no_input(self):
277-from_sqlite3importSQLITE_KEYWORDS
278-279397script=textwrap.dedent("""
280398 import readline
281399 from sqlite3.__main__ import main
@@ -306,7 +424,7 @@ def test_complete_no_input(self):
306424self.assertEqual(len(indices), 2)
307425start, end=indices
308426candidates= [l.strip() forlinlines[start+1:end]]
309-self.assertEqual(candidates, sorted(SQLITE_KEYWORDS))
427+self.assertEqual(candidates, sorted(candidates))
310428except:
311429ifverbose:
312430print(' PTY output: '.center(30, '-'))