Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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 @@ -3,9 +3,12 @@ Upcoming (TBD)

Features
--------

* Add enum value completions for WHERE/HAVING clauses. (#790)

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


1.43.1 (2026/01/03)
==============
Expand Down
31 changes: 28 additions & 3 deletions mycli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -817,14 +817,30 @@ def show_suggestion_tip() -> bool:
# mutating if any one of the component statements is mutating
mutating = False

def output_res(res: Generator[tuple], start: float) -> None:
def output_res(results: Generator[tuple], start: float) -> None:
nonlocal mutating
result_count = 0
for title, cur, headers, status in res:
for result in results:
# unpack the results, including the command info if present
try:
title, cur, headers, status, command = result
except ValueError:
title, cur, headers, status = result
command = None
except Exception as e:
self.echo("An unexpected error has occurred.", err=True, fg="red")
self.logger.error(f"Error unpacking results: {e}")
sys.exit(1)
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 @@ -1335,7 +1351,16 @@ def run_query(self, query: str, new_line: bool = True) -> None:
assert self.sqlexecute is not None
results = self.sqlexecute.run(query)
for result in results:
title, cur, headers, status = result
# discard the optional command portion of the results
# tuple since it is not used here currently
try:
title, cur, headers, status, _ = result
except ValueError:
title, cur, headers, status = result
except Exception as e:
self.echo("An unexpected error has occurred.", err=True, fg="red")
self.logger.error(f"Error unpacking results: {e}")
sys.exit(1)
self.main_formatter.query = query
self.redirect_formatter.query = query
output = self.format_output(
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 @@ -566,11 +566,15 @@ def watch_query(arg: str, **kwargs) -> Generator[tuple, 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 (title, cur, headers, None)
yield (title, cur, headers, None, command)
else:
yield (title, None, None, None)
yield (title, None, None, None, command)
sleep(seconds)
except KeyboardInterrupt:
# This prints the Ctrl-C character in its own line, which prevents
Expand Down