Skip to content
Merged
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
5 changes: 4 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Internal
--------
* Create new data class to handle SQL/command results to make further code improvements easier

Bug Fixes
--------
* Update watch query output to display the correct execution time on all iterations (#763).


1.44.1 (2026/01/10)
==============
Expand All @@ -19,7 +23,6 @@ Bug Fixes

Features
--------

* Add enum value completions for WHERE/HAVING clauses. (#790)
* Add `show_favorite_query` config option to control query printing when running favorite queries. (#1118)

Expand Down
18 changes: 12 additions & 6 deletions mycli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -819,11 +819,18 @@ def show_suggestion_tip() -> bool:
def output_res(res: Generator[SQLResult], start: float) -> None:
nonlocal mutating
result_count = 0
for title, cur, headers, status in res:
for title, cur, headers, status, command in res:
logger.debug("title: %r", title)
logger.debug("headers: %r", headers)
logger.debug("rows: %r", cur)
logger.debug("status: %r", status)
threshold = 1000
# If this is a watch query, offset the start time on the 2nd+ iteration
# to account for the sleep duration
if command is not None and command["name"] == "watch":
watch_seconds = float(command["seconds"])
if result_count > 0:
start += watch_seconds
if is_select(status) and cur and cur.rowcount > threshold:
self.echo(
f"The result set has more than {threshold} rows.",
Expand Down Expand Up @@ -873,7 +880,7 @@ def output_res(res: Generator[SQLResult], start: float) -> None:
# get and display warnings if enabled
if self.show_warnings and isinstance(cur, Cursor) and cur.warning_count > 0:
warnings = sqlexecute.run("SHOW WARNINGS")
for title, cur, headers, status in warnings:
for title, cur, headers, status, _command in warnings:
formatted = self.format_output(
title,
cur,
Expand Down Expand Up @@ -1332,9 +1339,8 @@ def get_prompt(self, string: str) -> str:
def run_query(self, query: str, new_line: bool = True) -> None:
"""Runs *query*."""
assert self.sqlexecute is not None
results = self.sqlexecute.run(query)
for result in results:
title, cur, headers, status = result
res = self.sqlexecute.run(query)
for title, cur, headers, _status, _command in res:
self.main_formatter.query = query
self.redirect_formatter.query = query
output = self.format_output(
Expand All @@ -1351,7 +1357,7 @@ def run_query(self, query: str, new_line: bool = True) -> None:
# get and display warnings if enabled
if self.show_warnings and isinstance(cur, Cursor) and cur.warning_count > 0:
warnings = self.sqlexecute.run("SHOW WARNINGS")
for title, cur, headers, _ in warnings:
for title, cur, headers, _status, _command in warnings:
output = self.format_output(
title,
cur,
Expand Down
8 changes: 6 additions & 2 deletions mycli/packages/special/iocommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,11 +580,15 @@ def watch_query(arg: str, **kwargs) -> Generator[SQLResult, None, None]:
set_pager_enabled(False)
for sql, title in sql_list:
cur.execute(sql)
command = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why a dict instead of two new properties?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't want to add a bunch of random properties (presuming other commands will need other args), so figured a general command property with the dict that could be added to as needed would be better. But if you prefer having standalone properties for it all I can do that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your implementation, your call.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I'll keep it as-is then. Don't want to make too many assumptions about future use since this is the first use case, and it can be adjusted later if we find another approach makes more sense given new use cases. Current imagined use case is other commands needing special args, and it fits that anyway.

"name": "watch",
"seconds": seconds,
}
if cur.description:
headers = [x[0] for x in cur.description]
yield SQLResult(title=title, results=cur, headers=headers)
yield SQLResult(title=title, results=cur, headers=headers, command=command)
else:
yield SQLResult(title=title)
yield SQLResult(title=title, command=command)
sleep(seconds)
except KeyboardInterrupt:
# This prints the Ctrl-C character in its own line, which prevents
Expand Down
5 changes: 3 additions & 2 deletions mycli/packages/sqlresult.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ class SQLResult:
results: Cursor | list[tuple] | None = None
headers: list[str] | str | None = None
status: str | None = None
command: dict[str, object] | None = None

def __iter__(self):
return iter((self.title, self.results, self.headers, self.status))
return iter((self.title, self.results, self.headers, self.status, self.command))

def __str__(self):
return f"{self.title}, {self.results}, {self.headers}, {self.status}"
return f"{self.title}, {self.results}, {self.headers}, {self.status}, {self.command}"
2 changes: 1 addition & 1 deletion mycli/sqlexecute.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ def reset_connection_id(self) -> None:
_logger.debug("Get current connection id")
try:
res = self.run("select connection_id()")
for _title, cur, _headers, _status in res:
for _title, cur, _headers, _status, _command in res:
self.connection_id = cur.fetchone()[0]
except Exception as e:
# See #1054
Expand Down
2 changes: 1 addition & 1 deletion test/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def run(executor, sql, rows_as_list=True):
"""Return string output for the sql to be run."""
result = []

for title, rows, headers, status in executor.run(sql):
for title, rows, headers, status, _command in executor.run(sql):
rows = list(rows) if (rows_as_list and rows) else rows
result.append({"title": title, "rows": rows, "headers": headers, "status": status})

Expand Down