Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## 0.11.2dev

* [Fix] Handle empty SQL statements gracefully (#1066)

## 0.11.1 (2025-03-25)

* [Fix] No longer showing the Slack link in error messages
Expand Down
28 changes: 20 additions & 8 deletions src/sql/run/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,30 @@ def run_statements(conn, sql, config, parameters=None):
.. literalinclude:: ../../examples/run_statements.py

"""
if not sql.strip():
# First, try to extract the usable SQL statements without comments
statements = list(
filter(
None,
map(
lambda stmt: sqlparse.format(stmt, strip_comments=True),
sqlparse.split(sql),
),
)
)

# Handle the empty SQL case
if not sql.strip() or not statements:
return "Connected: %s" % conn.name

for statement in sqlparse.split(sql):
# strip all comments from sql
statement = sqlparse.format(statement, strip_comments=True)
# trailing comment after semicolon can be confused as its own statement,
# so we ignore it here.
if not statement:
# Ensure we have some return value. This maintains type checkers happy
result = None
statement = None

for statement in statements:
if not statement.strip():
continue

first_word = sql.strip().split()[0].lower()
first_word = statement.strip().split()[0].lower()

if first_word == "begin":
raise exceptions.RuntimeError("JupySQL does not support transactions")
Expand Down
4 changes: 2 additions & 2 deletions src/tests/test_magic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1221,7 +1221,7 @@ def test_error_on_invalid_connection_string_with_possible_typo(ip_empty, clean_c
""" # noqa

invalid_connection_string_duckdb_bottom = f"""
Perhaps you meant to use the 'duckdb' db
Perhaps you meant to use the 'duckdb' db
To find more information regarding connection: https://jupysql.ploomber.io/en/latest/integrations/duckdb.html

To fix it:
Expand Down Expand Up @@ -1783,7 +1783,7 @@ def test_error_when_using_section_argument_but_values_are_invalid(ip_empty, tmp_
with pytest.raises(UsageError) as excinfo:
ip_empty.run_cell("%sql --section section")

message = "Could not parse SQLAlchemy URL from string 'not-a-driver://'"
message = "Could not parse SQLAlchemy URL from given URL string"
assert message in str(excinfo.value)


Expand Down
7 changes: 7 additions & 0 deletions src/tests/test_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ def test_sql_is_empty(mock_conns):
assert run_statements(mock_conns, " ", Config) == "Connected: %s" % mock_conns.name


def test_sql_comment_only(mock_conns):
assert (
run_statements(mock_conns, "-- this is a comment", Config)
== "Connected: %s" % mock_conns.name
)


@pytest.mark.parametrize(
"connection",
[
Expand Down
Loading