From 7792bf28e807ebfea7258f6aa1b8bbffc219f3d5 Mon Sep 17 00:00:00 2001 From: Tony123-tech Date: Sun, 27 Sep 2026 14:09:54 +0800 Subject: [PATCH 1/3] gh-158277: sqlite3 CLI completer: include views in column completion --- Lib/sqlite3/_completer.py | 2 +- Lib/test/test_sqlite3/test_cli.py | 21 +++++++++++++++++++ ...-09-27-14-00-00.gh-issue-158277.aBcDeF.rst | 3 +++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2026-09-27-14-00-00.gh-issue-158277.aBcDeF.rst diff --git a/Lib/sqlite3/_completer.py b/Lib/sqlite3/_completer.py index ba580f968bf92d..12cafc26602f8b 100644 --- a/Lib/sqlite3/_completer.py +++ b/Lib/sqlite3/_completer.py @@ -48,7 +48,7 @@ def _complete(con, text, state): f"""\ SELECT pti.name || ' ' FROM "{schema}".sqlite_master AS sm JOIN pragma_table_xinfo(sm.name,'{schema}') AS pti - WHERE sm.type='table' AND + WHERE sm.type IN ('table', 'view') AND pti.name LIKE REPLACE(:text, '_', '^_') || '%' ESCAPE '^'""" for schema in schemata ) diff --git a/Lib/test/test_sqlite3/test_cli.py b/Lib/test/test_sqlite3/test_cli.py index 0d235d90f1101b..39263acd2df91e 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -346,6 +346,27 @@ def test_complete_columns(self): @unittest.skipIf(sqlite3.sqlite_version_info < (3, 30, 0), "PRAGMA function_list is not available until " "SQLite 3.30.0") + def test_complete_view_columns(self): + input_ = textwrap.dedent("""\ + CREATE TABLE _table (_col_table); + CREATE VIEW _view AS SELECT _col_view AS _col_view_alias, + _col_table AS _col_table_alias + FROM _table; + + SELECT _col_\t\tta\tFROM _table; + .quit\n""").encode() + output = self.write_input(input_) + lines = output.decode().splitlines() + indices = [ + i for i, line in enumerate(lines) if line.startswith(self.PS1) + ] + start, end = indices[-3], indices[-2] + candidates = [l.strip() for l in lines[start+1:end]] + + self.assertIn("_col_view", candidates) + self.assertIn("_col_view_alias", candidates) + self.assertIn("_col_table_alias", candidates) + def test_complete_functions(self): input_ = b"SELECT AV\t1);\n.quit\n" output = self.write_input(input_) diff --git a/Misc/NEWS.d/next/Library/2026-09-27-14-00-00.gh-issue-158277.aBcDeF.rst b/Misc/NEWS.d/next/Library/2026-09-27-14-00-00.gh-issue-158277.aBcDeF.rst new file mode 100644 index 00000000000000..7f0434aeea6708 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-09-27-14-00-00.gh-issue-158277.aBcDeF.rst @@ -0,0 +1,3 @@ +Fix :mod:`sqlite3` CLI completer to include view columns in +column-name completion. + From 44592ac4dc502ab2b7209bcbebeba905de67a500 Mon Sep 17 00:00:00 2001 From: Tony123-tech Date: Sun, 27 Sep 2026 21:36:52 +0800 Subject: [PATCH 2/3] Fix test_complete_view_columns per review --- Lib/test/test_sqlite3/test_cli.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_sqlite3/test_cli.py b/Lib/test/test_sqlite3/test_cli.py index 39263acd2df91e..b821628054c318 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -342,13 +342,12 @@ def test_complete_columns(self): self.assertEqual( candidates, ["_col_attached", "_col_table", "_col_temp"] ) - - @unittest.skipIf(sqlite3.sqlite_version_info < (3, 30, 0), + @unittest.skipIf(sqlite3.sqlite_version_info < (3, 16, 0), "PRAGMA function_list is not available until " - "SQLite 3.30.0") + "SQLite 3.16.0") def test_complete_view_columns(self): input_ = textwrap.dedent("""\ - CREATE TABLE _table (_col_table); + CREATE TABLE _table (_col_table, _col_view); CREATE VIEW _view AS SELECT _col_view AS _col_view_alias, _col_table AS _col_table_alias FROM _table; From 0d647bb3ec7324fad24eee93358c0166bec43ea6 Mon Sep 17 00:00:00 2001 From: Tony123-tech Date: Mon, 28 Sep 2026 16:34:15 +0800 Subject: [PATCH 3/3] Address review: merge view column test into test_complete_columns --- Lib/test/test_sqlite3/test_cli.py | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/Lib/test/test_sqlite3/test_cli.py b/Lib/test/test_sqlite3/test_cli.py index b821628054c318..e049d16642ce0c 100644 --- a/Lib/test/test_sqlite3/test_cli.py +++ b/Lib/test/test_sqlite3/test_cli.py @@ -326,6 +326,8 @@ def test_complete_columns(self): input_ = textwrap.dedent("""\ CREATE TABLE _table (_col_table); CREATE TEMP TABLE _temp_table (_col_temp); + CREATE VIEW _view AS SELECT _col_table AS _col_table_alias + FROM _table; ATTACH ':memory:' AS attached; CREATE TABLE attached._attached_table (_col_attached); @@ -340,32 +342,12 @@ def test_complete_columns(self): candidates = [l.strip() for l in lines[start+1:end]] self.assertEqual( - candidates, ["_col_attached", "_col_table", "_col_temp"] + candidates, + ["_col_attached", "_col_table", "_col_table_alias", "_col_temp"], ) - @unittest.skipIf(sqlite3.sqlite_version_info < (3, 16, 0), + @unittest.skipIf(sqlite3.sqlite_version_info < (3, 30, 0), "PRAGMA function_list is not available until " - "SQLite 3.16.0") - def test_complete_view_columns(self): - input_ = textwrap.dedent("""\ - CREATE TABLE _table (_col_table, _col_view); - CREATE VIEW _view AS SELECT _col_view AS _col_view_alias, - _col_table AS _col_table_alias - FROM _table; - - SELECT _col_\t\tta\tFROM _table; - .quit\n""").encode() - output = self.write_input(input_) - lines = output.decode().splitlines() - indices = [ - i for i, line in enumerate(lines) if line.startswith(self.PS1) - ] - start, end = indices[-3], indices[-2] - candidates = [l.strip() for l in lines[start+1:end]] - - self.assertIn("_col_view", candidates) - self.assertIn("_col_view_alias", candidates) - self.assertIn("_col_table_alias", candidates) - + "SQLite 3.30.0") def test_complete_functions(self): input_ = b"SELECT AV\t1);\n.quit\n" output = self.write_input(input_)