Skip to content

feat:Add -P -y -Y flags #369

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

Merged
merged 8 commits into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"request": "launch",
"mode" : "auto",
"program": "${workspaceFolder}/cmd/modern",
"args" : ["-Q", "EXIT(select net_transport from sys.dm_exec_connections)"],
"args" : ["-Q", "EXIT(select net_transport from sys.dm_exec_connections)"],
},
{
"name" : "Run file query",
Expand Down
9 changes: 2 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,10 @@ The `sqlcmd` project aims to be a complete port of the original ODBC sqlcmd to t
### Changes in behavior from the ODBC based sqlcmd

The following switches have different behavior in this version of `sqlcmd` compared to the original ODBC based `sqlcmd`.

- `-P` switch will be removed. Passwords for SQL authentication can only be provided through these mechanisms:

- The `SQLCMDPASSWORD` environment variable
- The `:CONNECT` command
- When prompted, the user can type the password to complete a connection
- `-r` requires a 0 or 1 argument
- `-R` switch will be removed. The go runtime does not provide access to user locale information, and it's not readily available through syscall on all supported platforms.
- `-I` switch will be removed. To disable quoted identifier behavior, add `SET QUOTED IDENTIFIER OFF` in your scripts.
- `-N` now takes a string value that can be one of `true`, `false`, or `disable` to specify the encryption choice. (`default` is the same as omitting the parameter)
- `-N` now takes a string value that can be one of `true`, `false`, or `disable` to specify the encryption choice.
- If `-N` and `-C` are not provided, sqlcmd will negotiate authentication with the server without validating the server certificate.
- If `-N` is provided but `-C` is not, sqlcmd will require validation of the server certificate. Note that a `false` value for encryption could still lead to encryption of the login packet.
- If both `-N` and `-C` are provided, sqlcmd will use their values for encryption negotiation.
Expand All @@ -133,6 +127,7 @@ The following switches have different behavior in this version of `sqlcmd` compa
- Some behaviors that were kept to maintain compatibility with `OSQL` may be changed, such as alignment of column headers for some data types.
- All commands must fit on one line, even `EXIT`. Interactive mode will not check for open parentheses or quotes for commands and prompt for successive lines. The ODBC sqlcmd allows the query run by `EXIT(query)` to span multiple lines.
- `-i` now requires multiple arguments for the switch to be separated by `,`.
- `-v` requires multiple variable setters to be comma-separated. eg: `-v var1=v1,var2=v2 -v "var3=v 3"`

### Switches not available in the new sqlcmd (go-sqlcmd) yet

Expand Down
27 changes: 24 additions & 3 deletions build/build.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1)
set "DEL=%%a"
set "ESC=%%b"
)

REM Get Version Tag
for /f %%i in ('"git describe --tags --abbrev=0"') do set sqlcmdVersion=%%i

setlocal
SET RED=%ESC%[1;31m
echo %RED%
Expand All @@ -13,10 +17,26 @@ REM using for/do instead of running it directly so the status code isn't checked
REM Once we are prepared to block the build with the linter we will move this step into a pipeline
for /F "usebackq" %%l in (`go run cmd\sqlcmd-linter\main.go -test %~dp0../...`) DO echo %%l
echo %ESC%[0m

if not exist %gopath%\bin\go-winres.exe (
go install github.com/tc-hib/go-winres@latest
)
if not exist %gopath%\bin\gotext.exe (
go install golang.org/x/text/cmd/gotext@latest
)

REM go-winres likes to append instead of overwrite so delete existing resource file
del %~dp0..\cmd\modern\*.syso

REM generates translations file and resources
go generate %~dp0../... 2> %~dp0generate.txt
echo Fix any conflicting localizable strings:
echo %RED%
findstr conflicting "%~dp0generate.txt"
echo %ESC%[0m
endlocal
REM Get Version Tag
for /f %%i in ('"git describe --tags --abbrev=0"') do set sqlcmdVersion=%%i

if not %errorlevel% == 0 goto :end
REM Generates sqlcmd.exe in the root dir of the repo
go build -o %~dp0..\sqlcmd.exe -ldflags="-X main.version=%sqlcmdVersion%" %~dp0..\cmd\modern

Expand All @@ -34,4 +54,5 @@ setlocal
for /F "tokens=1-3 delims=," %%i in (%~dp0arch.txt) do set GOOS=%%i&set GOARCH=%%j&go build -o %~dp0..\%%i-%%j\%%k -ldflags="-X main.version=%sqlcmdVersion%" %~dp0..\cmd\modern
endlocal


:end
del %~dp0generate.txt
228 changes: 164 additions & 64 deletions cmd/sqlcmd/sqlcmd.go

Large diffs are not rendered by default.

57 changes: 42 additions & 15 deletions cmd/sqlcmd/sqlcmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestValidCommandLineToArgsConversion(t *testing.T) {
// The long flag names are up for debate.
commands := []cmdLineTest{
{[]string{}, func(args SQLCmdArguments) bool {
return args.Server == "" && !args.UseTrustedConnection && args.UserName == ""
return args.Server == "" && !args.UseTrustedConnection && args.UserName == "" && args.ScreenWidth == nil && args.ErrorsToStderr == -1 && args.EncryptConnection == "default"
}},
{[]string{"-c", "MYGO", "-C", "-E", "-i", "file1", "-o", "outfile", "-i", "file2"}, func(args SQLCmdArguments) bool {
return args.BatchTerminator == "MYGO" && args.TrustServerCertificate && len(args.InputFile) == 2 && strings.HasSuffix(args.OutputFile, "outfile")
Expand Down Expand Up @@ -75,15 +75,15 @@ func TestValidCommandLineToArgsConversion(t *testing.T) {
{[]string{"--version"}, func(args SQLCmdArguments) bool {
return args.Version
}},
{[]string{}, func(args SQLCmdArguments) bool {
return args.ScreenWidth == nil
}},
{[]string{"-w", "10"}, func(args SQLCmdArguments) bool {
return args.ScreenWidth != nil && *args.ScreenWidth == 10
return args.ScreenWidth != nil && *args.ScreenWidth == 10 && args.FixedTypeWidth == nil && args.VariableTypeWidth == nil
}},
{[]string{"-s", "|", "-w", "10", "-W"}, func(args SQLCmdArguments) bool {
return args.TrimSpaces && args.ColumnSeparator == "|" && *args.ScreenWidth == 10
}},
{[]string{"-y", "100", "-Y", "200", "-P", "placeholder"}, func(args SQLCmdArguments) bool {
return *args.FixedTypeWidth == 200 && *args.VariableTypeWidth == 100 && args.Password == "placeholder"
}},
}

for _, test := range commands {
Expand All @@ -93,8 +93,8 @@ func TestValidCommandLineToArgsConversion(t *testing.T) {
Short: "A brief description of my command",
Long: "A long description of my command",
PreRunE: func(cmd *cobra.Command, argss []string) error {
SetScreenWidthFlag(arguments, cmd)
return arguments.Validate()
SetScreenWidthFlags(arguments, cmd)
return arguments.Validate(cmd)
},
Run: func(cmd *cobra.Command, argss []string) {
// Command logic goes here
Expand All @@ -103,6 +103,7 @@ func TestValidCommandLineToArgsConversion(t *testing.T) {
SilenceUsage: true,
}
cmd.SetOut(new(bytes.Buffer))
cmd.SetErr(new(bytes.Buffer))
setFlags(cmd, arguments)
cmd.SetArgs(test.commandLine)
err := cmd.Execute()
Expand All @@ -125,8 +126,13 @@ func TestInvalidCommandLine(t *testing.T) {
commands := []cmdLineTest{
// Issue:341 https://github.com/microsoft/go-sqlcmd/issues/341
//{[]string{"-E", "-U", "someuser"}, "--use-trusted-connection and --user-name can't be used together"},
{[]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 "5"`},
{[]string{"-F", "what"}, "'-F what': Unexpected argument. Argument value has to be one of [horiz horizontal vert vertical]."},
{[]string{"-r", "5"}, `'-r 5': Unexpected argument. Argument value has to be one of [0 1].`},
{[]string{"-w", "x"}, "'-w x': value must be greater than 8 and less than 65536."},
{[]string{"-y", "111111"}, "'-y 111111': value must be greater than or equal to 0 and less than or equal to 8000."},
{[]string{"-Y", "-2"}, "'-Y -2': value must be greater than or equal to 0 and less than or equal to 8000."},
{[]string{"-P"}, "'-P': Missing argument. Enter '-?' for help."},
{[]string{"-;"}, "';': Unknown Option. Enter '-?' for help."},
}

for _, test := range commands {
Expand All @@ -136,17 +142,25 @@ func TestInvalidCommandLine(t *testing.T) {
Short: "A brief description of my command",
Long: "A long description of my command",
PreRunE: func(cmd *cobra.Command, argss []string) error {
SetScreenWidthFlags(arguments, cmd)
if err := arguments.Validate(cmd); err != nil {
cmd.SilenceUsage = true
return err
}
return normalizeFlags(cmd)
},
Run: func(cmd *cobra.Command, argss []string) {
},
SilenceErrors: true,
SilenceUsage: true,
SilenceUsage: true,
}
buf := &memoryBuffer{buf: new(bytes.Buffer)}
cmd.SetErr(buf)
setFlags(cmd, arguments)
cmd.SetArgs(test.commandLine)
err := cmd.Execute()
assert.EqualError(t, err, test.errorMessage, "Command line:%v", test.commandLine)
assert.EqualError(t, err, test.errorMessage, "Command line:", test.commandLine)
errBytes := buf.buf.String()
assert.Equalf(t, sqlcmdErrorPrefix, string(errBytes)[:len(sqlcmdErrorPrefix)], "Output error should start with '%s' - %s", sqlcmdErrorPrefix, test.commandLine)
}
}

Expand All @@ -170,15 +184,15 @@ func TestValidateFlags(t *testing.T) {
Short: "A brief description of my command",
Long: "A long description of my command",
PreRunE: func(cmd *cobra.Command, argss []string) error {
SetScreenWidthFlag(arguments, cmd)
return arguments.Validate()
SetScreenWidthFlags(arguments, cmd)
return arguments.Validate(cmd)
},
Run: func(cmd *cobra.Command, argss []string) {
},
SilenceErrors: true,
SilenceUsage: true,
}

cmd.SetErr(new(bytes.Buffer))
setFlags(cmd, arguments)
cmd.SetArgs(test.commandLine)
err := cmd.Execute()
Expand Down Expand Up @@ -469,3 +483,16 @@ func canTestAzureAuth() bool {
userName := os.Getenv(sqlcmd.SQLCMDUSER)
return strings.Contains(server, ".database.windows.net") && userName == ""
}

// memoryBuffer has both Write and Close methods for use as io.WriteCloser
type memoryBuffer struct {
buf *bytes.Buffer
}

func (b *memoryBuffer) Write(p []byte) (n int, err error) {
return b.buf.Write(p)
}

func (b *memoryBuffer) Close() error {
return nil
}
3 changes: 1 addition & 2 deletions internal/localizer/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ const (
StdoutName = "stdout"
ColSeparatorVar = "SQLCMDCOLSEP"
ErrorLevel = "ERRORLEVEL"
AppIntentValues = "\"default\",\"readonly\""
EncryptConnValues = "\"default\",\"false\",\"true\",\"disable\""
AppIntentValues = `"readonly"`
FormatValues = "\"horiz\",\"horizontal\",\"vert\",\"vertical\""
ErrToStderrValues = "\"-1\",\"0\",\"1\""
)
Loading