Skip to content

feat: implement :perftrace and :help commands - #632

Open
David Levy (dlevy-msft-sql) wants to merge 14 commits into
microsoft:mainfrom
dlevy-msft-sql:perftrace
Open

feat: implement :perftrace and :help commands#632
David Levy (dlevy-msft-sql) wants to merge 14 commits into
microsoft:mainfrom
dlevy-msft-sql:perftrace

Conversation

@dlevy-msft-sql

@dlevy-msft-sql David Levy (dlevy-msft-sql) commented Jan 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds two new interactive commands: :help and :perftrace.

:help displays a reference of all available sqlcmd commands with short descriptions. It can also show help for a single command: :help connect.

:perftrace redirects performance statistics output (from the -p flag, PR #631) to a file, stderr, or stdout -- the same way :out and :error redirect query and error output.

New commands

Command Description
:help Lists all available commands with descriptions
:help <command> Shows help for a single command (case-insensitive)
:perftrace <file> Redirects timing output to a file, stderr, or stdout

Usage

1> :help
:!! [<command>]
  - Executes a command in the operating system shell.
:connect server[\instance] [-l timeout] [-U user [-P password]]
  - Connects to a SQL Server instance.
...

1> :help connect
:connect server[\instance] [-l timeout] [-U user [-P password]]
  - Connects to a SQL Server instance.

1> :perftrace c:/logs/perf.txt
1> select 1
2> go

Implementation

  • Added a help field to the Command struct. Every registered command carries its own help text, so :help output is always in sync with the command registry. A TestAllCommandsHaveHelp test guards against drift.
  • :help <command> does a case-insensitive lookup into the command map. Unknown names fall through to the full listing.
  • Extracted redirectWriter() to share file/stderr/stdout resolution logic across :out, :error, and :perftrace (was duplicated between outCommand and errorCommand).
  • Added stat (io.WriteCloser) field to Sqlcmd with GetStat()/SetStat() accessors. GetStat() falls back to GetOutput() when no :perftrace redirection is active, so existing -p output is unaffected.
  • SetStat(nil) called during cleanup in cmd/sqlcmd/sqlcmd.go to close any open perf trace file.

Testing

  • TestHelpCommand: full listing, per-command filtering, case-insensitive lookup, unknown command fallback
  • TestAllCommandsHaveHelp: drift guard ensuring every command has help text
  • TestPerftraceCommand: empty arg error, stdout, stderr, file redirect, variable resolution
  • TestCommandParsing: parsing for :help, :help CONNECT, :perftrace stderr, etc.
  • All tests run without a database connection

Merge notes

Fixes #622.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR implements the :perftrace command to redirect performance statistics output to a file, stderr, or stdout, working in conjunction with the -p flag from PR #631.

Changes:

  • Added stat writer infrastructure with GetStat/SetStat methods following the established pattern for output/error writers
  • Implemented PERFTRACE command supporting file paths, "stdout", and "stderr" with variable substitution
  • Added comprehensive test coverage for the command functionality

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
pkg/sqlcmd/sqlcmd.go Added stat field and GetStat()/SetStat() methods for managing performance statistics output writer
pkg/sqlcmd/commands.go Registered PERFTRACE command and implemented perftraceCommand() function with file/stdout/stderr support
pkg/sqlcmd/commands_test.go Added TestPerftraceCommand() with comprehensive test scenarios and added PERFTRACE parsing tests
README.md Documented the :perftrace command with usage example

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

Comment thread pkg/sqlcmd/commands_test.go
Comment thread pkg/sqlcmd/commands_test.go Outdated
Comment thread pkg/sqlcmd/commands.go Outdated
Comment thread README.md Outdated
Comment thread pkg/sqlcmd/commands.go Outdated
Comment thread pkg/sqlcmd/commands_test.go

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread README.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread pkg/sqlcmd/sqlcmd.go

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

@dlevy-msft-sql David Levy (dlevy-msft-sql) added sqlcmd switch switch in existing sqlcmd Size: S Small issue (less than one week effort) labels Jan 25, 2026
@dlevy-msft-sql David Levy (dlevy-msft-sql) changed the title Implement :perftrace command Implement :perftrace and :help commands Feb 5, 2026
@dlevy-msft-sql
David Levy (dlevy-msft-sql) force-pushed the perftrace branch 2 times, most recently from e7abfe7 to 4d25bf2 Compare February 5, 2026 19:58
@dlevy-msft-sql David Levy (dlevy-msft-sql) changed the title Implement :perftrace and :help commands feat: implement :perftrace and :help commands Feb 5, 2026
:perftrace redirects timing/statistics output to a file, stderr, or stdout.
:help displays the list of available sqlcmd commands with usage.

Both commands validate arguments and return appropriate errors.
- helpCommand writes to os.Stdout instead of s.GetOutput() so :HELP
  output is not redirected when :OUT is active (matches ODBC sqlcmd)
- Remove dead alias fallback loop (ED/R resolved by regex, not :HELP)
- Fix TestHelpCommand: NOSUCHCMD now correctly asserts error
- Add TestPerftraceCloseChain: verifies file1 closed when switching
- Restore BOM context comment on outCommand
- redirectWriter checks stdout before stderr (matches upstream order)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 6, 2026 05:48

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The implemented :help <command> behavior conflicts with the PR description and a new test intended to validate perftrace file-handle closure does not actually assert closure.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 3
  • Review effort level: Lite

Comment thread pkg/sqlcmd/commands.go Outdated
Comment thread pkg/sqlcmd/commands_test.go Outdated
Comment thread pkg/sqlcmd/commands.go Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 6, 2026 05:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The :help feature is implemented but its own help/README documentation doesn’t mention the supported :help <command> form, making a covered capability undiscoverable.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread README.md Outdated
Comment thread pkg/sqlcmd/commands.go
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 6, 2026 05:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

:help <command> can’t show help for some commands using the spelling shown in the help output (e.g., :r, :ed, :!!), which is a functional usability bug in the new command.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread pkg/sqlcmd/commands.go
Comment thread pkg/sqlcmd/commands.go Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 6, 2026 06:03

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The -u (UnicodeOutputFile) :out path wraps files in a transform writer that does not close the underlying file, which can leak file descriptors when redirecting output.

Review details

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

pkg/sqlcmd/commands.go:374

  • When -u (UnicodeOutputFile) is enabled, :out wraps the destination file in transform.NewWriter and stores only the transform.Writer in Sqlcmd. Closing that wrapper does not close the underlying *os.File, so repeated :out redirections (or cleanup via SetOutput(nil)) can leak file descriptors.
    pkg/sqlcmd/commands.go:73
  • The :error help text uses the placeholder "", while :out and :perftrace document the exact accepted values ("|stderr|stdout"). Aligning this keeps :help output precise and consistent with the redirectWriter behavior.
    pkg/sqlcmd/commands.go:78
  • Grammar in :r help text: "Append" should be "Appends" to match the other present-tense descriptions in :help output.
  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 6, 2026 06:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Needs a closer look

redirectWriter() doesn’t trim whitespace, so inputs like :out stdout can be misinterpreted as a filename and redirect incorrectly.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

pkg/sqlcmd/commands.go:343

  • redirectWriter() treats arguments like "stdout " (with trailing whitespace) as a filename rather than the stdout/stderr sentinel, because it never trims spaces before comparing. Since the command regex captures the rest of the line verbatim, users can easily end up creating a file named "stdout " instead of redirecting to stdout/stderr.
  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 6, 2026 06:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The new TestHelpCommand helper mutates global os.Stdout without defers for guaranteed restoration/FD cleanup, which can leak handles and destabilize subsequent tests if a failure/panic occurs.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

pkg/sqlcmd/commands_test.go:494

  • captureHelp mutates the global os.Stdout but doesn’t use defers to guarantee restoration/FD cleanup if fn panics or a require/FailNow happens later. This can leak pipe handles and make subsequent tests fail in hard-to-diagnose ways.
  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 6, 2026 06:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The implementation matches the PR description, centralizes redirection safely (including proper file closing), and includes targeted unit tests for the new behaviors.

Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Size: S Small issue (less than one week effort) sqlcmd switch switch in existing sqlcmd

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: :TIMING ON/OFF command for interactive sessions

2 participants