From cff628c2abc2100b53198a912eb1565c2a008329 Mon Sep 17 00:00:00 2001 From: David Shiflet Date: Fri, 20 May 2022 12:53:44 -0400 Subject: [PATCH 1/3] exit on state 127 --- go.mod | 4 ++-- go.sum | 5 ++++- pkg/sqlcmd/sqlcmd.go | 17 +++++++++++++++-- pkg/sqlcmd/sqlcmd_test.go | 3 +++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index fef3e0ba..a7d615f8 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,9 @@ go 1.16 require ( github.com/alecthomas/kong v0.5.0 - github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 + github.com/golang-sql/sqlexp v0.1.0 github.com/google/uuid v1.3.0 - github.com/microsoft/go-mssqldb v0.13.2 + github.com/microsoft/go-mssqldb v0.14.0 github.com/peterh/liner v1.2.2 github.com/stretchr/testify v1.7.1 golang.org/x/text v0.3.6 diff --git a/go.sum b/go.sum index 4958b731..2e78c120 100644 --- a/go.sum +++ b/go.sum @@ -14,14 +14,17 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= -github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4= github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= +github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/microsoft/go-mssqldb v0.13.2 h1:PeUn6Fu7okbaPpcv5QOk+9h7PcetOuB5ff6tVwz5V24= github.com/microsoft/go-mssqldb v0.13.2/go.mod h1:JWsC4ToRBruAAoknz9wV9Iiqb/K85J4zabR6PnBNbro= +github.com/microsoft/go-mssqldb v0.14.0 h1:eo0rUzFOIImkrJi50KGpXKJe6WbrqzDqmG/yY1+yCHk= +github.com/microsoft/go-mssqldb v0.14.0/go.mod h1:ti85dZ/KY16b1MsdsSm+P+04lz83uPDNdc7mBvKgwU8= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/peterh/liner v1.2.2 h1:aJ4AOodmL+JxOZZEL2u9iJf8omNRpqHc/EbrK+3mAXw= github.com/peterh/liner v1.2.2/go.mod h1:xFwJyiKIXJZUKItq5dGHZSTBRAuG/CpeNpWLyiNRNwI= diff --git a/pkg/sqlcmd/sqlcmd.go b/pkg/sqlcmd/sqlcmd.go index 73cc652b..0e64db80 100644 --- a/pkg/sqlcmd/sqlcmd.go +++ b/pkg/sqlcmd/sqlcmd.go @@ -389,8 +389,12 @@ func (s *Sqlcmd) runQuery(query string) (int, error) { msg := retmsg.Message(ctx) switch m := msg.(type) { case sqlexp.MsgNotice: - if !s.PrintError(m.Message, 10) { - s.Format.AddMessage(m.Message) + if !s.PrintError(m.Message.String(), 10) { + s.Format.AddMessage(m.Message.String()) + switch e := m.Message.(type) { + case mssql.Error: + qe = s.handleError(&retcode, e) + } } case sqlexp.MsgError: switch e := m.Error.(type) { @@ -465,11 +469,20 @@ func (s *Sqlcmd) handleError(retcode *int, err error) error { minSeverityToExit = s.Connect.ErrorSeverityLevel } var errSeverity uint8 + var errState uint8 + var errNumber int32 switch sqlError := err.(type) { case mssql.Error: errSeverity = sqlError.Class + errState = sqlError.State + errNumber = sqlError.Number } + // 127 is the magic exit code + if errState == 127 { + *retcode = int(errNumber) + return ErrExitRequested + } if s.Connect.ErrorSeverityLevel > 0 { if errSeverity >= minSeverityToExit { *retcode = int(errSeverity) diff --git a/pkg/sqlcmd/sqlcmd_test.go b/pkg/sqlcmd/sqlcmd_test.go index 6c38d755..2676e89a 100644 --- a/pkg/sqlcmd/sqlcmd_test.go +++ b/pkg/sqlcmd/sqlcmd_test.go @@ -237,6 +237,9 @@ func TestExitCodeSetOnError(t *testing.T) { retcode, err = s.runQuery("RAISERROR (N'Testing!' , 5, 1)") assert.NoError(t, err, "ExitOnError and ErrorSeverityLevel = 0, Raiserror below 10") assert.Equal(t, -101, retcode, "ExitOnError and ErrorSeverityLevel = 0, Raiserror below 10") + retcode, err = s.runQuery("RAISERROR (15001, 10, 127)") + assert.ErrorIs(t, err, ErrExitRequested, "RAISERROR with state 127") + assert.Equal(t, 15001, retcode, "RAISERROR (15001, 10, 127)") } func TestSqlCmdExitOnError(t *testing.T) { From 0440596d76262bd2627dc568861118859cb95c7a Mon Sep 17 00:00:00 2001 From: David Shiflet Date: Fri, 20 May 2022 13:28:57 -0400 Subject: [PATCH 2/3] call Close on liner on exit --- cmd/sqlcmd/main.go | 1 + pkg/sqlcmd/sqlcmd.go | 2 ++ 2 files changed, 3 insertions(+) diff --git a/cmd/sqlcmd/main.go b/cmd/sqlcmd/main.go index c1cfc55d..f9a893be 100644 --- a/cmd/sqlcmd/main.go +++ b/cmd/sqlcmd/main.go @@ -211,6 +211,7 @@ func run(vars *sqlcmd.Variables, args *SQLCmdArguments) (int, error) { var line sqlcmd.Console = nil if iactive { line = console.NewConsole("") + defer line.Close() } s := sqlcmd.New(line, wd, vars) diff --git a/pkg/sqlcmd/sqlcmd.go b/pkg/sqlcmd/sqlcmd.go index 0e64db80..4446274d 100644 --- a/pkg/sqlcmd/sqlcmd.go +++ b/pkg/sqlcmd/sqlcmd.go @@ -44,6 +44,8 @@ type Console interface { ReadPassword(prompt string) ([]byte, error) // SetPrompt sets the prompt text shown to input the next line SetPrompt(s string) + // Close clears any buffers and closes open file handles + Close() } // Sqlcmd is the core processor for text lines. From b5f15e33962cdf90cb4197e386a853bb122a012d Mon Sep 17 00:00:00 2001 From: David Shiflet Date: Fri, 20 May 2022 13:37:35 -0400 Subject: [PATCH 3/3] update kong for windows file paths --- cmd/sqlcmd/testdata/select,100.sql | 1 + go.mod | 3 ++- go.sum | 2 ++ pkg/sqlcmd/sqlcmd_test.go | 4 ++++ 4 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 cmd/sqlcmd/testdata/select,100.sql diff --git a/cmd/sqlcmd/testdata/select,100.sql b/cmd/sqlcmd/testdata/select,100.sql new file mode 100644 index 00000000..718c071f --- /dev/null +++ b/cmd/sqlcmd/testdata/select,100.sql @@ -0,0 +1 @@ +select 100 diff --git a/go.mod b/go.mod index a7d615f8..8049c53e 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,12 @@ module github.com/microsoft/go-sqlcmd go 1.16 require ( - github.com/alecthomas/kong v0.5.0 + github.com/alecthomas/kong v0.5.1-0.20220516223738-0aaa4c11997b github.com/golang-sql/sqlexp v0.1.0 github.com/google/uuid v1.3.0 github.com/microsoft/go-mssqldb v0.14.0 github.com/peterh/liner v1.2.2 + github.com/pkg/errors v0.9.1 // indirect github.com/stretchr/testify v1.7.1 golang.org/x/text v0.3.6 ) diff --git a/go.sum b/go.sum index 2e78c120..16a96fc9 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0 h1:v9p9TfTbf7AwNb5NYQt7hI4 github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= github.com/alecthomas/kong v0.5.0 h1:u8Kdw+eeml93qtMZ04iei0CFYve/WPcA5IFh+9wSskE= github.com/alecthomas/kong v0.5.0/go.mod h1:uzxf/HUh0tj43x1AyJROl3JT7SgsZ5m+icOv1csRhc0= +github.com/alecthomas/kong v0.5.1-0.20220516223738-0aaa4c11997b h1:QF7Hdi3ReQRAST66vU7bqkHODmcVJIUZyTGo9gLHluk= +github.com/alecthomas/kong v0.5.1-0.20220516223738-0aaa4c11997b/go.mod h1:GaAkr/DV/nSKftP7snQLewFh9pZqrm+OEn3HqkvWU7c= github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142 h1:8Uy0oSf5co/NZXje7U1z8Mpep++QJOldL2hs/sBQf48= github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/pkg/sqlcmd/sqlcmd_test.go b/pkg/sqlcmd/sqlcmd_test.go index 2676e89a..7a681f22 100644 --- a/pkg/sqlcmd/sqlcmd_test.go +++ b/pkg/sqlcmd/sqlcmd_test.go @@ -293,6 +293,10 @@ func (tc *testConsole) SetPrompt(s string) { tc.PromptText = s } +func (tc *testConsole) Close() { + +} + func TestPromptForPasswordNegative(t *testing.T) { prompted := false console := &testConsole{