Skip to content

Commit 22cf289

Browse files
authored
[3.13] gh-133439: Fix dot commands with trailing spaces are mistaken for multi-line sqlite statements in the sqlite3 command-line interface (GH-133440) (GH-133765)
(cherry picked from commit ebd4881)
1 parent 4455cba commit 22cf289

File tree

3 files changed

+55
-12
lines changed

3 files changed

+55
-12
lines changed

Lib/sqlite3/__main__.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,25 @@ def runsource(self, source, filename="<input>", symbol="single"):
4848
Return True if more input is needed; buffering is done automatically.
4949
Return False is input is a complete statement ready for execution.
5050
"""
51-
match source:
52-
case ".version":
53-
print(f"{sqlite3.sqlite_version}")
54-
case ".help":
55-
print("Enter SQL code and press enter.")
56-
case ".quit":
57-
sys.exit(0)
58-
case _:
59-
if not sqlite3.complete_statement(source):
60-
return True
61-
execute(self._cur, source)
51+
if not source or source.isspace():
52+
return False
53+
if source[0] == ".":
54+
match source[1:].strip():
55+
case "version":
56+
print(f"{sqlite3.sqlite_version}")
57+
case "help":
58+
print("Enter SQL code and press enter.")
59+
case "quit":
60+
sys.exit(0)
61+
case "":
62+
pass
63+
case _ as unknown:
64+
self.write("Error: unknown command or invalid arguments:"
65+
f' "{unknown}".\n')
66+
else:
67+
if not sqlite3.complete_statement(source):
68+
return True
69+
execute(self._cur, source)
6270
return False
6371

6472

Lib/test/test_sqlite3/test_cli.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from sqlite3.__main__ import main as cli
66
from test.support.os_helper import TESTFN, unlink
7+
from test.support.testcase import ExtraAssertions
78
from test.support import captured_stdout, captured_stderr, captured_stdin
89

910

@@ -61,7 +62,7 @@ def test_cli_on_disk_db(self):
6162
self.assertIn("(0,)", out)
6263

6364

64-
class InteractiveSession(unittest.TestCase):
65+
class InteractiveSession(unittest.TestCase, ExtraAssertions):
6566
MEMORY_DB_MSG = "Connected to a transient in-memory database"
6667
PS1 = "sqlite> "
6768
PS2 = "... "
@@ -108,6 +109,38 @@ def test_interact_version(self):
108109
self.assertEqual(out.count(self.PS2), 0)
109110
self.assertIn(sqlite3.sqlite_version, out)
110111

112+
def test_interact_empty_source(self):
113+
out, err = self.run_cli(commands=("", " "))
114+
self.assertIn(self.MEMORY_DB_MSG, err)
115+
self.assertEndsWith(out, self.PS1)
116+
self.assertEqual(out.count(self.PS1), 3)
117+
self.assertEqual(out.count(self.PS2), 0)
118+
119+
def test_interact_dot_commands_unknown(self):
120+
out, err = self.run_cli(commands=(".unknown_command", ))
121+
self.assertIn(self.MEMORY_DB_MSG, err)
122+
self.assertEndsWith(out, self.PS1)
123+
self.assertEqual(out.count(self.PS1), 2)
124+
self.assertEqual(out.count(self.PS2), 0)
125+
self.assertIn("Error", err)
126+
# test "unknown_command" is pointed out in the error message
127+
self.assertIn("unknown_command", err)
128+
129+
def test_interact_dot_commands_empty(self):
130+
out, err = self.run_cli(commands=("."))
131+
self.assertIn(self.MEMORY_DB_MSG, err)
132+
self.assertEndsWith(out, self.PS1)
133+
self.assertEqual(out.count(self.PS1), 2)
134+
self.assertEqual(out.count(self.PS2), 0)
135+
136+
def test_interact_dot_commands_with_whitespaces(self):
137+
out, err = self.run_cli(commands=(".version ", ". version"))
138+
self.assertIn(self.MEMORY_DB_MSG, err)
139+
self.assertEqual(out.count(sqlite3.sqlite_version + "\n"), 2)
140+
self.assertEndsWith(out, self.PS1)
141+
self.assertEqual(out.count(self.PS1), 3)
142+
self.assertEqual(out.count(self.PS2), 0)
143+
111144
def test_interact_valid_sql(self):
112145
out, err = self.run_cli(commands=("SELECT 1;",))
113146
self.assertIn(self.MEMORY_DB_MSG, err)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix dot commands with trailing spaces are mistaken for multi-line SQL
2+
statements in the sqlite3 command-line interface.

0 commit comments

Comments
 (0)