Skip to content

Distinguish non-error output from error output #122

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed

Conversation

apoorvdeshmukh
Copy link
Contributor

In certain cases such as non-interactive mode it was observed
that error messages meant for error stream were captured under
output stream. This is not desirable if the user only wants to
retrieve the error messages. This commit aligns the go-sqlcmd
behaviour with ODBC sqlcmd where error messages are captured
in the appropriate error stream.
Resolves #105

Validation:

go-sqlcmd>type test.sql
:r missing.sql
go
C:\Users\apdeshmukh\git\go-sqlcmd>type test.sql
:r missing.sql
go
select @@version
go
go-sqlcmd>.\sqlcmd.exe -i test.sql >stdout.txt 2>stderr.txt

go-sqlcmd>type stdout.txt


------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Microsoft SQL Server 2019 (RTM-GDR) (KB5014356) - 15.0.2095.3 (X64)
        Apr 29 2022 18:00:13
        Copyright (C) 2019 Microsoft Corporation
        Developer Edition (64-bit) on Windows 10 Enterprise 10.0 <X64> (Build 22000: ) (Hypervisor)


(1 row affected)

go-sqlcmd>type stderr.txt
Sqlcmd: Error:  Error occurred while opening or operating on file missing.sql (Reason: open missing.sql: The system cannot find the file specified.).

In certain cases such as non-interactive mode it was observed
that error messages meant for error stream were captured under
output stream. This is not desirable if the user only wants to
retrieve the error messages. This commit aligns the go-sqlcmd
behaviour with ODBC sqlcmd where error messages are captured
in the appropriate error stream.
if iactive {
_, _ = s.GetOutput().Write([]byte(err.Error() + SqlcmdEol))
} else {
_, _ = s.GetError().Write([]byte(err.Error() + SqlcmdEol))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't you need to distinguish the case of iactive being true because of the user name parameter being passed in, which is part of your other PR?

Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe Sqlcmd should have a property like "WriteErrorsToErrorStream bool" that would be set by main before it calls Run.

There are some other settings that control command output destination that this could be like.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added flag in sqlcmd struct to indicate an interactive session.
The interactive session will be determined when the first input is scanned.

Copy link
Collaborator

Choose a reason for hiding this comment

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

would it make sense to fix s.GetError to do the right thing based on context and just change this code to use GetError() only?
I'm not 100% certain that every kind of error in sqlcmd goes to the same stream, though.

@@ -109,6 +109,28 @@ func TestSqlCmdQueryAndExit(t *testing.T) {
}
}

func TestSqlCmdOutputAndError(t *testing.T) {
s, outfile, errfile := setupSqlcmdWithFileErrorOutput(t)
Copy link
Collaborator

Choose a reason for hiding this comment

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

don't you need to test the s.IncludeFile path too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added test for s.IncludeFile

return s
}

func (s *Sqlcmd) scanNext() (string, error) {
s.IsInteractiveSession = true
Copy link
Collaborator

Choose a reason for hiding this comment

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

add a comment on why this is being set

@@ -86,10 +87,13 @@ func New(l Console, workingDirectory string, vars *Variables) *Sqlcmd {
s.PrintError = func(msg string, severity uint8) bool {
return false
}
s.SetOutput(os.Stdout)
s.SetError(os.Stderr)
Copy link
Collaborator

Choose a reason for hiding this comment

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

s.SetError(os.Stderr)

this is a change in behavior for any other places that call GetError(), now it's going to return stderr by default instead of stdout. Please verify that's the right behavior in those other places.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This functionality change is leading to undesired side effects such as redirecting server errors to stderr as well. (I will close this PR and create new one)
I have reworked the changes to keep existing functionality as is in PR #143 and redirecting only the sqlcmd errors which is what the ODBC is also doing.

Copy link
Collaborator

@shueybubbles shueybubbles left a comment

Choose a reason for hiding this comment

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

:shipit:

Copy link
Collaborator

@stuartpa stuartpa left a comment

Choose a reason for hiding this comment

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

:shipit:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Errors for :R are thrown on stdout instead of stderr
3 participants