diff --git a/cmd/sqlcmd/main.go b/cmd/sqlcmd/main.go index 9d2ce7be..ccfd5d96 100644 --- a/cmd/sqlcmd/main.go +++ b/cmd/sqlcmd/main.go @@ -49,6 +49,8 @@ type SQLCmdArguments struct { ErrorLevel int `short:"m" help:"Controls which error messages are sent to stdout. Messages that have severity level greater than or equal to this level are sent."` Format string `short:"F" help:"Specifies the formatting for results." default:"horiz" enum:"horiz,horizontal,vert,vertical"` ErrorsToStderr int `short:"r" help:"Redirects the error message output to the screen (stderr). A value of 0 means messages with severity >= 11 will b redirected. A value of 1 means all error message output including PRINT is redirected." enum:"-1,0,1" default:"-1"` + Help bool `short:"?" help:"Show syntax summary."` + Headers int `short:"h" help:"Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed."` } // Validate accounts for settings not described by Kong attributes @@ -56,7 +58,10 @@ func (a *SQLCmdArguments) Validate() error { if a.PacketSize != 0 && (a.PacketSize < 512 || a.PacketSize > 32767) { return fmt.Errorf(`'-a %d': Packet size has to be a number between 512 and 32767.`, a.PacketSize) } - + // Ignore 0 even though it's technically an invalid input + if a.Headers < -1 { + return fmt.Errorf(`'-h %d': header value must be either -1 or a value between 1 and 2147483647`, a.Headers) + } return nil } @@ -96,7 +101,11 @@ func (a SQLCmdArguments) authenticationMethod(hasPassword bool) string { } func main() { - kong.Parse(&args) + ctx := kong.Parse(&args, kong.NoDefaultHelp()) + if args.Help { + _ = ctx.PrintUsage(false) + os.Exit(0) + } vars := sqlcmd.InitializeVariables(!args.DisableCmdAndWarn) setVars(vars, &args) @@ -138,7 +147,7 @@ func setVars(vars *sqlcmd.Variables, args *SQLCmdArguments) { }, sqlcmd.SQLCMDUSER: func(a *SQLCmdArguments) string { return a.UserName }, sqlcmd.SQLCMDSTATTIMEOUT: func(a *SQLCmdArguments) string { return "" }, - sqlcmd.SQLCMDHEADERS: func(a *SQLCmdArguments) string { return "" }, + sqlcmd.SQLCMDHEADERS: func(a *SQLCmdArguments) string { return fmt.Sprint(a.Headers) }, sqlcmd.SQLCMDCOLSEP: func(a *SQLCmdArguments) string { return "" }, sqlcmd.SQLCMDCOLWIDTH: func(a *SQLCmdArguments) string { return "" }, sqlcmd.SQLCMDMAXVARTYPEWIDTH: func(a *SQLCmdArguments) string { return "" }, diff --git a/cmd/sqlcmd/main_test.go b/cmd/sqlcmd/main_test.go index 39cc0880..5d3c123e 100644 --- a/cmd/sqlcmd/main_test.go +++ b/cmd/sqlcmd/main_test.go @@ -19,6 +19,7 @@ func newKong(t *testing.T, cli interface{}, options ...kong.Option) *kong.Kong { t.Helper() options = append([]kong.Option{ kong.Name("test"), + kong.NoDefaultHelp(), kong.Exit(func(int) { t.Helper() t.Fatalf("unexpected exit()") @@ -76,6 +77,9 @@ func TestValidCommandLineToArgsConversion(t *testing.T) { {[]string{"-r", "1"}, func(args SQLCmdArguments) bool { return args.ErrorsToStderr == 1 }}, + {[]string{"-h", "2", "-?"}, func(args SQLCmdArguments) bool { + return args.Help && args.Headers == 2 + }}, } for _, test := range commands { @@ -104,6 +108,7 @@ func TestInvalidCommandLine(t *testing.T) { {[]string{"-a", "100"}, "test: '-a 100': Packet size has to be a number between 512 and 32767."}, {[]string{"-F", "what"}, "--format must be one of \"horiz\",\"horizontal\",\"vert\",\"vertical\" but got \"what\""}, {[]string{"-r", "5"}, `--errors-to-stderr must be one of "-1","0","1" but got '\x05'`}, + {[]string{"-h-4"}, "test: '-h -4': header value must be either -1 or a value between 1 and 2147483647"}, } for _, test := range commands { diff --git a/go.mod b/go.mod index 637ff2db..bb1ddbe7 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,12 @@ module github.com/microsoft/go-sqlcmd go 1.16 require ( - github.com/alecthomas/kong v0.2.18-0.20210621093454-54558f65e86f + github.com/alecthomas/kong v0.5.0 github.com/denisenkom/go-mssqldb v0.12.0 github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 github.com/google/uuid v1.3.0 github.com/peterh/liner v1.2.2 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.7.1 ) replace github.com/denisenkom/go-mssqldb => github.com/shueybubbles/go-mssqldb v0.10.1-0.20220317022252-fafb9d92e469 diff --git a/go.sum b/go.sum index 707fdc6a..d94cc5e1 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,9 @@ 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.2.18-0.20210621093454-54558f65e86f h1:VgRM6/wqZIB1D9W3XMllm/wplTmPgI5yvCHUXEsmKps= github.com/alecthomas/kong v0.2.18-0.20210621093454-54558f65e86f/go.mod h1:ka3VZ8GZNPXv9Ov+j4YNLkI8mTuhXyr/0ktSlqIydQQ= +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/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= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -29,9 +32,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/shueybubbles/go-mssqldb v0.10.1-0.20220317022252-fafb9d92e469 h1:BuUMqsxB86i1QEBf0q+dkQYfNLVpD1nH1fRJPKvXWSg= github.com/shueybubbles/go-mssqldb v0.10.1-0.20220317022252-fafb9d92e469/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=