diff --git a/README.md b/README.md index 4a4e436c..a73545eb 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,17 @@ switches are most important to you to have implemented next in the new sqlcmd. - `:Connect` now has an optional `-G` parameter to select one of the authentication methods for Azure SQL Database - `SqlAuthentication`, `ActiveDirectoryDefault`, `ActiveDirectoryIntegrated`, `ActiveDirectoryServicePrincipal`, `ActiveDirectoryManagedIdentity`, `ActiveDirectoryPassword`. If `-G` is not provided, either Integrated security or SQL Authentication will be used, dependent on the presence of a `-U` username parameter. - The new `--driver-logging-level` command line parameter allows you to see traces from the `go-mssqldb` client driver. Use `64` to see all traces. - Sqlcmd can now print results using a vertical format. Use the new `--vertical` command line option to set it. It's also controlled by the `SQLCMDFORMAT` scripting variable. +- `-p` prints performance statistics after each batch execution. Use `-p` for standard format or `-p1` for colon-separated format suitable for parsing. + +``` +1> select 1 +2> go + +Network packet size (bytes): 4096 +1 xact(s): +Clock Time (ms.): total 5 avg 5.00 (200.00 xacts per sec.) +``` + - Sqlcmd defaults to a horizontal output format (space separated, no borders). To use the new ASCII table format, use the new `--ascii` command line option or set `SQLCMDFORMAT` to `ascii` (`-v SQLCMDFORMAT=ascii`). Note that when using the ASCII table format, individual column widths are determined by the content, but the `SQLCMDCOLWIDTH` variable and the `-w` parameter are still used to control the maximum screen width, determining when columns wrap into separate table segments. The following variables are ignored: `SQLCMDMAXFIXEDTYPEWIDTH`, `SQLCMDMAXVARTYPEWIDTH`, and `SQLCMDHEADERS`. ``` diff --git a/cmd/sqlcmd/sqlcmd.go b/cmd/sqlcmd/sqlcmd.go index e0664955..742c0cdb 100644 --- a/cmd/sqlcmd/sqlcmd.go +++ b/cmd/sqlcmd/sqlcmd.go @@ -82,6 +82,7 @@ type SQLCmdArguments struct { ChangePassword string ChangePasswordAndExit string TraceFile string + PrintStatistics *int ServerNameOverride string RawErrors bool // Keep Help at the end of the list @@ -129,6 +130,7 @@ const ( disableCmdAndWarn = "disable-cmd-and-warn" listServers = "list-servers" removeControlCharacters = "remove-control-characters" + printStatistics = "print-statistics" ) func encryptConnectionAllowsTLS(value string) bool { @@ -363,6 +365,7 @@ func checkDefaultValue(args []string, i int) (val string) { 'k': "0", 'L': "|", // | is the sentinel for no value since users are unlikely to use it. It's "reserved" in most shells 'X': "0", + 'p': "0", } if isFlag(args[i]) && len(args[i]) == 2 && (len(args) == i+1 || args[i+1][0] == '-') { if v, ok := flags[rune(args[i][1])]; ok { @@ -426,6 +429,7 @@ func SetScreenWidthFlags(args *SQLCmdArguments, rootCmd *cobra.Command) { args.DisableCmd = getOptionalIntArgument(rootCmd, disableCmdAndWarn) args.ErrorsToStderr = getOptionalIntArgument(rootCmd, errorsToStderr) args.RemoveControlCharacters = getOptionalIntArgument(rootCmd, removeControlCharacters) + args.PrintStatistics = getOptionalIntArgument(rootCmd, printStatistics) } func setFlags(rootCmd *cobra.Command, args *SQLCmdArguments) { @@ -513,6 +517,7 @@ func setFlags(rootCmd *cobra.Command, args *SQLCmdArguments) { _ = rootCmd.Flags().BoolP("client-regional-setting", "R", false, localizer.Sprintf("Provided for backward compatibility. Client regional settings are not used")) _ = rootCmd.Flags().IntP(removeControlCharacters, "k", 0, localizer.Sprintf("%s Remove control characters from output. Pass 1 to substitute a space per character, 2 for a space per consecutive characters", "-k [1|2]")) rootCmd.Flags().BoolVarP(&args.EchoInput, "echo-input", "e", false, localizer.Sprintf("Echo input")) + _ = rootCmd.Flags().IntP(printStatistics, "p", 0, localizer.Sprintf("%s Print performance statistics after each batch. Pass 1 for colon-separated format", "-p[1]")) rootCmd.Flags().IntVarP(&args.QueryTimeout, "query-timeout", "t", 0, "Query timeout") rootCmd.Flags().BoolVarP(&args.EnableColumnEncryption, "enable-column-encryption", "g", false, localizer.Sprintf("Enable column encryption")) rootCmd.Flags().StringVarP(&args.ChangePassword, "change-password", "z", "", localizer.Sprintf("New password")) @@ -581,6 +586,14 @@ func normalizeFlags(cmd *cobra.Command) error { err = invalidParameterError("-k", v, "1", "2") return pflag.NormalizedName("") } + case printStatistics: + switch v { + case "0", "1": + return pflag.NormalizedName(name) + default: + err = invalidParameterError("-p", v, "0", "1") + return pflag.NormalizedName("") + } } return pflag.NormalizedName(name) @@ -858,6 +871,7 @@ func run(vars *sqlcmd.Variables, args *SQLCmdArguments) (int, error) { s.SetupCloseHandler() defer s.StopCloseHandler() s.UnicodeOutputFile = args.UnicodeOutputFile + s.PrintStatistics = args.PrintStatistics if args.DisableCmd != nil { s.Cmd.DisableSysCommands(args.errorOnBlockedCmd()) diff --git a/cmd/sqlcmd/sqlcmd_test.go b/cmd/sqlcmd/sqlcmd_test.go index 2880e331..7b9a929b 100644 --- a/cmd/sqlcmd/sqlcmd_test.go +++ b/cmd/sqlcmd/sqlcmd_test.go @@ -99,6 +99,15 @@ func TestValidCommandLineToArgsConversion(t *testing.T) { {[]string{"-k", "-X", "-r", "-z", "something"}, func(args SQLCmdArguments) bool { return args.warnOnBlockedCmd() && !args.useEnvVars() && args.getControlCharacterBehavior() == sqlcmd.ControlRemove && *args.ErrorsToStderr == 0 && args.ChangePassword == "something" }}, + {[]string{"-p"}, func(args SQLCmdArguments) bool { + return args.PrintStatistics != nil && *args.PrintStatistics == 0 + }}, + {[]string{"-p", "1"}, func(args SQLCmdArguments) bool { + return args.PrintStatistics != nil && *args.PrintStatistics == 1 + }}, + {[]string{"-p1"}, func(args SQLCmdArguments) bool { + return args.PrintStatistics != nil && *args.PrintStatistics == 1 + }}, {[]string{"-N"}, func(args SQLCmdArguments) bool { return args.EncryptConnection == "true" }}, diff --git a/internal/translations/catalog.go b/internal/translations/catalog.go index adcbf40e..5c475dae 100644 --- a/internal/translations/catalog.go +++ b/internal/translations/catalog.go @@ -55,6 +55,7 @@ var messageKeyToIndex = map[string]int{ "%s Disables commands that might compromise system security. Passing 1 tells sqlcmd to exit when disabled commands are run.": 240, "%s Error occurred while opening or operating on file %s (Reason: %s).": 293, "%s List servers. Pass %s to omit 'Servers:' output.": 264, + "%s Print performance statistics after each batch. Pass 1 for colon-separated format": 308, "%s Redirects error messages with severity >= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.": 252, "%s Remove control characters from output. Pass 1 to substitute a space per character, 2 for a space per consecutive characters": 268, "%s Specifies the instance of SQL Server to which to connect. It sets the sqlcmd scripting variable %s.": 239, @@ -152,6 +153,7 @@ var messageKeyToIndex = map[string]int{ "Display one or many users from the sqlconfig file": 142, "Display raw byte data": 159, "Display the current-context": 106, + "Do not strip the \"mssql: \" prefix from error messages": 307, "Don't download image. Use already downloaded image": 169, "Download (into container) and attach database (.bak) from URL": 176, "Downloading %s": 196, @@ -231,7 +233,8 @@ var messageKeyToIndex = map[string]int{ "Port (next available port from 1433 upwards used by default)": 175, "Press Ctrl+C to exit this process...": 216, "Print version information and exit": 231, - "Prints the output in vertical format. This option sets the sqlcmd scripting variable %s to '%s'. The default is false": 251, + "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable %s to '%s'. The default is false": 306, + "Prints the output in vertical format. This option sets the sqlcmd scripting variable %s to '%s'. The default is false": 251, "Provide a username with the %s flag": 95, "Provide a valid encryption method (%s) with the %s flag": 97, "Provide password in the %s (or %s) environment variable": 93, @@ -250,7 +253,7 @@ var messageKeyToIndex = map[string]int{ "Run a query using [%s] database": 13, "See all release tags for SQL Server, install previous version": 207, "See connection strings": 187, - "Server name override is not supported with the current authentication method": 306, + "Server name override is not supported with the current authentication method": 309, "Servers:": 222, "Set new default database": 14, "Set the current context": 149, @@ -357,7 +360,7 @@ var messageKeyToIndex = map[string]int{ "sqlcmd: Install/Create/Query SQL Server, Azure SQL, and Tools": 285, } -var de_DEIndex = []uint32{ // 308 elements +var de_DEIndex = []uint32{ // 311 elements // Entry 0 - 1F 0x00000000, 0x0000003c, 0x0000007e, 0x00000096, 0x000000d1, 0x000000e9, 0x000000fd, 0x00000148, @@ -445,7 +448,8 @@ var de_DEIndex = []uint32{ // 308 elements 0x00004cbf, 0x00004d1a, 0x00004d65, 0x00004d6f, 0x00004d83, 0x00004d9c, 0x00004dc2, 0x00004de2, 0x00004de2, 0x00004de2, 0x00004de2, 0x00004de2, -} // Size: 1256 bytes + 0x00004de2, 0x00004de2, 0x00004de2, +} // Size: 1268 bytes const de_DEData string = "" + // Size: 19938 bytes "\x02SQL Server installieren/erstellen, abfragen, deinstallieren\x02Konfi" + @@ -738,7 +742,7 @@ const de_DEData string = "" + // Size: 19938 bytes ":\x02(1 Zeile betroffen)\x02(%[1]d Zeilen betroffen)\x02Ungültiger Varia" + "blenbezeichner %[1]s\x02Ungültiger Variablenwert %[1]s" -var en_USIndex = []uint32{ // 308 elements +var en_USIndex = []uint32{ // 311 elements // Entry 0 - 1F 0x00000000, 0x0000002c, 0x00000062, 0x0000007a, 0x000000b3, 0x000000cb, 0x000000de, 0x00000113, @@ -825,10 +829,11 @@ var en_USIndex = []uint32{ // 308 elements 0x00003bf5, 0x00003c26, 0x00003c75, 0x00003c95, 0x00003ca5, 0x00003cfb, 0x00003d40, 0x00003d4a, 0x00003d5b, 0x00003d71, 0x00003d93, 0x00003db0, - 0x00003e0a, 0x00003eba, 0x00003fb5, 0x00004002, -} // Size: 1256 bytes + 0x00003e0a, 0x00003eba, 0x00003fb5, 0x00004034, + 0x0000406a, 0x000040c1, 0x0000410e, +} // Size: 1268 bytes -const en_USData string = "" + // Size: 16386 bytes +const en_USData string = "" + // Size: 16654 bytes "\x02Install/Create, Query, Uninstall SQL Server\x02View configuration in" + "formation and connection strings\x04\x02\x0a\x0a\x00\x12\x02Feedback:" + "\x0a %[1]s\x02help for backwards compatibility flags (-S, -U, -E etc.)" + @@ -1070,10 +1075,14 @@ const en_USData string = "" + // Size: 16386 bytes "r name sent to SQL Server.\x02Specifies the path to a server certificate" + " file (PEM, DER, or CER) to match against the server's TLS certificate. " + "Use when encryption is enabled (-N true, -N mandatory, or -N strict) for" + - " certificate pinning instead of standard certificate validation.\x02Serv" + - "er name override is not supported with the current authentication method" + " certificate pinning instead of standard certificate validation.\x02Prin" + + "ts the output in ASCII table format. This option sets the sqlcmd scripti" + + "ng variable %[1]s to '%[2]s'. The default is false\x02Do not strip the " + + "\x22mssql: \x22 prefix from error messages\x02%[1]s Print performance st" + + "atistics after each batch. Pass 1 for colon-separated format\x02Server n" + + "ame override is not supported with the current authentication method" -var es_ESIndex = []uint32{ // 308 elements +var es_ESIndex = []uint32{ // 311 elements // Entry 0 - 1F 0x00000000, 0x00000032, 0x00000081, 0x0000009c, 0x000000ec, 0x0000010d, 0x00000127, 0x0000017f, @@ -1161,7 +1170,8 @@ var es_ESIndex = []uint32{ // 308 elements 0x00004c6c, 0x00004ccf, 0x00004d1d, 0x00004d2a, 0x00004d3c, 0x00004d54, 0x00004d7f, 0x00004da2, 0x00004da2, 0x00004da2, 0x00004da2, 0x00004da2, -} // Size: 1256 bytes + 0x00004da2, 0x00004da2, 0x00004da2, +} // Size: 1268 bytes const es_ESData string = "" + // Size: 19874 bytes "\x02Instalar/Crear, Consultar, Desinstalar SQL Server\x02Visualización d" + @@ -1455,7 +1465,7 @@ const es_ESData string = "" + // Size: 19874 bytes " afectadas)\x02Identificador de variable %[1]s no válido\x02Valor de var" + "iable %[1]s no válido" -var fr_FRIndex = []uint32{ // 308 elements +var fr_FRIndex = []uint32{ // 311 elements // Entry 0 - 1F 0x00000000, 0x00000037, 0x0000007f, 0x0000009d, 0x000000e1, 0x000000fe, 0x00000117, 0x00000169, @@ -1543,7 +1553,8 @@ var fr_FRIndex = []uint32{ // 308 elements 0x00004fbe, 0x00005014, 0x00005059, 0x00005069, 0x0000507e, 0x00005098, 0x000050bf, 0x000050e1, 0x000050e1, 0x000050e1, 0x000050e1, 0x000050e1, -} // Size: 1256 bytes + 0x000050e1, 0x000050e1, 0x000050e1, +} // Size: 1268 bytes const fr_FRData string = "" + // Size: 20705 bytes "\x02Installer/créer, interroger, désinstaller SQL Server\x02Afficher les" + @@ -1847,7 +1858,7 @@ const fr_FRData string = "" + // Size: 20705 bytes "\x02Identifiant de variable invalide %[1]s\x02Valeur de variable invalid" + "e %[1]s" -var it_ITIndex = []uint32{ // 308 elements +var it_ITIndex = []uint32{ // 311 elements // Entry 0 - 1F 0x00000000, 0x0000003c, 0x00000088, 0x000000a0, 0x000000f7, 0x00000114, 0x0000012b, 0x0000016a, @@ -1935,7 +1946,8 @@ var it_ITIndex = []uint32{ // 308 elements 0x00004a16, 0x00004a74, 0x00004ac1, 0x00004acb, 0x00004ae0, 0x00004afa, 0x00004b2a, 0x00004b52, 0x00004b52, 0x00004b52, 0x00004b52, 0x00004b52, -} // Size: 1256 bytes + 0x00004b52, 0x00004b52, 0x00004b52, +} // Size: 1268 bytes const it_ITData string = "" + // Size: 19282 bytes "\x02Installare/creare, eseguire query, disinstallare SQL Server\x02Visua" + @@ -2221,7 +2233,7 @@ const it_ITData string = "" + // Size: 19282 bytes "riga interessata)\x02(%[1]d righe interessate)\x02Identificatore della v" + "ariabile %[1]s non valido\x02Valore della variabile %[1]s non valido" -var ja_JPIndex = []uint32{ // 308 elements +var ja_JPIndex = []uint32{ // 311 elements // Entry 0 - 1F 0x00000000, 0x0000004f, 0x00000077, 0x0000009d, 0x000000d8, 0x000000f8, 0x0000010b, 0x0000014c, @@ -2309,7 +2321,8 @@ var ja_JPIndex = []uint32{ // 308 elements 0x00005d02, 0x00005d7c, 0x00005ddb, 0x00005dec, 0x00005e0c, 0x00005e30, 0x00005e56, 0x00005e79, 0x00005e79, 0x00005e79, 0x00005e79, 0x00005e79, -} // Size: 1256 bytes + 0x00005e79, 0x00005e79, 0x00005e79, +} // Size: 1268 bytes const ja_JPData string = "" + // Size: 24185 bytes "\x02インストール/作成、クエリ、SQL Server のアンインストール\x02構成情報と接続文字列の表示\x04\x02\x0a\x0a" + @@ -2474,7 +2487,7 @@ const ja_JPData string = "" + // Size: 24185 bytes "\x02パスワード:\x02(1 行が影響を受けます)\x02(%[1]d 行が影響を受けます)\x02変数識別子 %[1]s が無効です" + "\x02変数値の %[1]s が無効です" -var ko_KRIndex = []uint32{ // 308 elements +var ko_KRIndex = []uint32{ // 311 elements // Entry 0 - 1F 0x00000000, 0x00000029, 0x00000053, 0x0000006c, 0x000000b8, 0x000000d0, 0x000000de, 0x00000121, @@ -2562,7 +2575,8 @@ var ko_KRIndex = []uint32{ // 308 elements 0x00004cc5, 0x00004d25, 0x00004d71, 0x00004d79, 0x00004d8e, 0x00004dae, 0x00004dcf, 0x00004dea, 0x00004dea, 0x00004dea, 0x00004dea, 0x00004dea, -} // Size: 1256 bytes + 0x00004dea, 0x00004dea, 0x00004dea, +} // Size: 1268 bytes const ko_KRData string = "" + // Size: 19946 bytes "\x02SQL Server 설치/생성, 쿼리, 제거\x02구성 정보 및 연결 문자열 보기\x04\x02\x0a\x0a\x00" + @@ -2719,7 +2733,7 @@ const ko_KRData string = "" + // Size: 19946 bytes "%[6]s\x02암호:\x02(1개 행 적용됨)\x02(영향을 받은 행 %[1]d개)\x02잘못된 변수 식별자 %[1]s\x02잘" + "못된 변수 값 %[1]s" -var pt_BRIndex = []uint32{ // 308 elements +var pt_BRIndex = []uint32{ // 311 elements // Entry 0 - 1F 0x00000000, 0x00000034, 0x00000071, 0x0000008d, 0x000000e3, 0x00000103, 0x0000011e, 0x0000016d, @@ -2807,7 +2821,8 @@ var pt_BRIndex = []uint32{ // 308 elements 0x00004920, 0x0000497e, 0x000049c8, 0x000049cf, 0x000049e1, 0x000049f9, 0x00004a24, 0x00004a47, 0x00004a47, 0x00004a47, 0x00004a47, 0x00004a47, -} // Size: 1256 bytes + 0x00004a47, 0x00004a47, 0x00004a47, +} // Size: 1268 bytes const pt_BRData string = "" + // Size: 19015 bytes "\x02Instalar/Criar, Consultar, Desinstalar o SQL Server\x02Exibir inform" + @@ -3087,7 +3102,7 @@ const pt_BRData string = "" + // Size: 19015 bytes "fetada)\x02(%[1]d linhas afetadas)\x02Identificador de variável %[1]s in" + "válido\x02Valor de variável inválido %[1]s" -var ru_RUIndex = []uint32{ // 308 elements +var ru_RUIndex = []uint32{ // 311 elements // Entry 0 - 1F 0x00000000, 0x00000056, 0x000000c1, 0x000000ec, 0x00000151, 0x00000172, 0x00000195, 0x0000023b, @@ -3175,7 +3190,8 @@ var ru_RUIndex = []uint32{ // 308 elements 0x00007e41, 0x00007ed3, 0x00007f4b, 0x00007f59, 0x00007f7d, 0x00007fa4, 0x00007ff3, 0x00008038, 0x00008038, 0x00008038, 0x00008038, 0x00008038, -} // Size: 1256 bytes + 0x00008038, 0x00008038, 0x00008038, +} // Size: 1268 bytes const ru_RUData string = "" + // Size: 32824 bytes "\x02Установка или создание, запрос, удаление SQL Server\x02Просмотреть с" + @@ -3464,7 +3480,7 @@ const ru_RUData string = "" + // Size: 32824 bytes "идентификатор переменной %[1]s\x02Недопустимое значение переменной %[1]" + "s" -var zh_CNIndex = []uint32{ // 308 elements +var zh_CNIndex = []uint32{ // 311 elements // Entry 0 - 1F 0x00000000, 0x0000002b, 0x00000050, 0x00000065, 0x00000096, 0x000000ab, 0x000000b8, 0x000000fc, @@ -3552,7 +3568,8 @@ var zh_CNIndex = []uint32{ // 308 elements 0x00003805, 0x00003861, 0x000038ae, 0x000038b6, 0x000038c7, 0x000038dc, 0x000038f9, 0x00003910, 0x00003910, 0x00003910, 0x00003910, 0x00003910, -} // Size: 1256 bytes + 0x00003910, 0x00003910, 0x00003910, +} // Size: 1268 bytes const zh_CNData string = "" + // Size: 14608 bytes "\x02安装/创建、查询、卸载 SQL Server\x02查看配置信息和连接字符串\x04\x02\x0a\x0a\x00\x0f\x02反馈" + @@ -3673,7 +3690,7 @@ const zh_CNData string = "" + // Size: 14608 bytes "[5]s,行 %#[6]v%[7]s\x02Msg %#[1]v,级别 %[2]d,状态 %[3]d,服务器 %[4]s,行 %#[5]v%[6" + "]s\x02密码:\x02(1 行受影响)\x02(%[1]d 行受影响)\x02变量标识符 %[1]s 无效\x02变量值 %[1]s 无效" -var zh_TWIndex = []uint32{ // 308 elements +var zh_TWIndex = []uint32{ // 311 elements // Entry 0 - 1F 0x00000000, 0x00000031, 0x00000053, 0x0000006e, 0x000000a1, 0x000000b8, 0x000000c2, 0x00000106, @@ -3761,7 +3778,8 @@ var zh_TWIndex = []uint32{ // 308 elements 0x00003853, 0x000038b2, 0x00003902, 0x0000390a, 0x00003924, 0x00003942, 0x00003961, 0x00003978, 0x00003978, 0x00003978, 0x00003978, 0x00003978, -} // Size: 1256 bytes + 0x00003978, 0x00003978, 0x00003978, +} // Size: 1268 bytes const zh_TWData string = "" + // Size: 14712 bytes "\x02安裝/建立、查詢、解除安裝 SQL Server\x02檢視組態資訊和連接字串\x04\x02\x0a\x0a\x00\x15\x02意" + @@ -3880,4 +3898,4 @@ const zh_TWData string = "" + // Size: 14712 bytes "#[5]v%[6]s\x02密碼:\x02(1 個資料列受影響)\x02(%[1]d 個資料列受影響)\x02無效的變數識別碼 %[1]s" + "\x02變數值 %[1]s 無效" - // Total table size 235291 bytes (229KiB); checksum: AA9B2EAD + // Total table size 235691 bytes (230KiB); checksum: 9E20967F diff --git a/internal/translations/locales/de-DE/out.gotext.json b/internal/translations/locales/de-DE/out.gotext.json index 5e74cf30..de08912a 100644 --- a/internal/translations/locales/de-DE/out.gotext.json +++ b/internal/translations/locales/de-DE/out.gotext.json @@ -2841,6 +2841,29 @@ ], "fuzzy": true }, + { + "id": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "message": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "translation": "", + "placeholders": [ + { + "id": "SQLCMDFORMAT", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "sqlcmd.SQLCMDFORMAT" + }, + { + "id": "Ascii", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "\"ascii\"" + } + ] + }, { "id": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", "message": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", @@ -2899,6 +2922,11 @@ ], "fuzzy": true }, + { + "id": "Do not strip the \"mssql: \" prefix from error messages", + "message": "Do not strip the \"mssql: \" prefix from error messages", + "translation": "" + }, { "id": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", "message": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", @@ -3045,6 +3073,21 @@ "translatorComment": "Copied from source.", "fuzzy": true }, + { + "id": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "message": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "translation": "", + "placeholders": [ + { + "id": "_p1", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "\"-p[1]\"" + } + ] + }, { "id": "Enable column encryption", "message": "Enable column encryption", diff --git a/internal/translations/locales/en-US/out.gotext.json b/internal/translations/locales/en-US/out.gotext.json index 21772c8d..a20e83ad 100644 --- a/internal/translations/locales/en-US/out.gotext.json +++ b/internal/translations/locales/en-US/out.gotext.json @@ -2847,6 +2847,31 @@ ], "fuzzy": true }, + { + "id": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "message": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "translation": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "translatorComment": "Copied from source.", + "placeholders": [ + { + "id": "SQLCMDFORMAT", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "sqlcmd.SQLCMDFORMAT" + }, + { + "id": "Ascii", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "\"ascii\"" + } + ], + "fuzzy": true + }, { "id": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", "message": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", @@ -2905,6 +2930,13 @@ ], "fuzzy": true }, + { + "id": "Do not strip the \"mssql: \" prefix from error messages", + "message": "Do not strip the \"mssql: \" prefix from error messages", + "translation": "Do not strip the \"mssql: \" prefix from error messages", + "translatorComment": "Copied from source.", + "fuzzy": true + }, { "id": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", "message": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", @@ -3051,6 +3083,23 @@ "translatorComment": "Copied from source.", "fuzzy": true }, + { + "id": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "message": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "translation": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "translatorComment": "Copied from source.", + "placeholders": [ + { + "id": "_p1", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "\"-p[1]\"" + } + ], + "fuzzy": true + }, { "id": "Enable column encryption", "message": "Enable column encryption", diff --git a/internal/translations/locales/es-ES/out.gotext.json b/internal/translations/locales/es-ES/out.gotext.json index 66b51962..a9eec808 100644 --- a/internal/translations/locales/es-ES/out.gotext.json +++ b/internal/translations/locales/es-ES/out.gotext.json @@ -2841,6 +2841,29 @@ ], "fuzzy": true }, + { + "id": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "message": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "translation": "", + "placeholders": [ + { + "id": "SQLCMDFORMAT", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "sqlcmd.SQLCMDFORMAT" + }, + { + "id": "Ascii", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "\"ascii\"" + } + ] + }, { "id": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", "message": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", @@ -2899,6 +2922,11 @@ ], "fuzzy": true }, + { + "id": "Do not strip the \"mssql: \" prefix from error messages", + "message": "Do not strip the \"mssql: \" prefix from error messages", + "translation": "" + }, { "id": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", "message": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", @@ -3045,6 +3073,21 @@ "translatorComment": "Copied from source.", "fuzzy": true }, + { + "id": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "message": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "translation": "", + "placeholders": [ + { + "id": "_p1", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "\"-p[1]\"" + } + ] + }, { "id": "Enable column encryption", "message": "Enable column encryption", diff --git a/internal/translations/locales/fr-FR/out.gotext.json b/internal/translations/locales/fr-FR/out.gotext.json index d09d0a6d..4d63e226 100644 --- a/internal/translations/locales/fr-FR/out.gotext.json +++ b/internal/translations/locales/fr-FR/out.gotext.json @@ -2841,6 +2841,29 @@ ], "fuzzy": true }, + { + "id": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "message": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "translation": "", + "placeholders": [ + { + "id": "SQLCMDFORMAT", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "sqlcmd.SQLCMDFORMAT" + }, + { + "id": "Ascii", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "\"ascii\"" + } + ] + }, { "id": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", "message": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", @@ -2899,6 +2922,11 @@ ], "fuzzy": true }, + { + "id": "Do not strip the \"mssql: \" prefix from error messages", + "message": "Do not strip the \"mssql: \" prefix from error messages", + "translation": "" + }, { "id": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", "message": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", @@ -3045,6 +3073,21 @@ "translatorComment": "Copied from source.", "fuzzy": true }, + { + "id": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "message": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "translation": "", + "placeholders": [ + { + "id": "_p1", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "\"-p[1]\"" + } + ] + }, { "id": "Enable column encryption", "message": "Enable column encryption", diff --git a/internal/translations/locales/it-IT/out.gotext.json b/internal/translations/locales/it-IT/out.gotext.json index b320dd5c..d9c9bc24 100644 --- a/internal/translations/locales/it-IT/out.gotext.json +++ b/internal/translations/locales/it-IT/out.gotext.json @@ -2841,6 +2841,29 @@ ], "fuzzy": true }, + { + "id": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "message": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "translation": "", + "placeholders": [ + { + "id": "SQLCMDFORMAT", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "sqlcmd.SQLCMDFORMAT" + }, + { + "id": "Ascii", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "\"ascii\"" + } + ] + }, { "id": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", "message": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", @@ -2899,6 +2922,11 @@ ], "fuzzy": true }, + { + "id": "Do not strip the \"mssql: \" prefix from error messages", + "message": "Do not strip the \"mssql: \" prefix from error messages", + "translation": "" + }, { "id": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", "message": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", @@ -3045,6 +3073,21 @@ "translatorComment": "Copied from source.", "fuzzy": true }, + { + "id": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "message": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "translation": "", + "placeholders": [ + { + "id": "_p1", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "\"-p[1]\"" + } + ] + }, { "id": "Enable column encryption", "message": "Enable column encryption", diff --git a/internal/translations/locales/ja-JP/out.gotext.json b/internal/translations/locales/ja-JP/out.gotext.json index 55cd0a6c..13095b03 100644 --- a/internal/translations/locales/ja-JP/out.gotext.json +++ b/internal/translations/locales/ja-JP/out.gotext.json @@ -2841,6 +2841,29 @@ ], "fuzzy": true }, + { + "id": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "message": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "translation": "", + "placeholders": [ + { + "id": "SQLCMDFORMAT", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "sqlcmd.SQLCMDFORMAT" + }, + { + "id": "Ascii", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "\"ascii\"" + } + ] + }, { "id": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", "message": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", @@ -2899,6 +2922,11 @@ ], "fuzzy": true }, + { + "id": "Do not strip the \"mssql: \" prefix from error messages", + "message": "Do not strip the \"mssql: \" prefix from error messages", + "translation": "" + }, { "id": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", "message": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", @@ -3045,6 +3073,21 @@ "translatorComment": "Copied from source.", "fuzzy": true }, + { + "id": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "message": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "translation": "", + "placeholders": [ + { + "id": "_p1", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "\"-p[1]\"" + } + ] + }, { "id": "Enable column encryption", "message": "Enable column encryption", diff --git a/internal/translations/locales/ko-KR/out.gotext.json b/internal/translations/locales/ko-KR/out.gotext.json index c7bfe94a..9e4c981b 100644 --- a/internal/translations/locales/ko-KR/out.gotext.json +++ b/internal/translations/locales/ko-KR/out.gotext.json @@ -2841,6 +2841,29 @@ ], "fuzzy": true }, + { + "id": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "message": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "translation": "", + "placeholders": [ + { + "id": "SQLCMDFORMAT", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "sqlcmd.SQLCMDFORMAT" + }, + { + "id": "Ascii", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "\"ascii\"" + } + ] + }, { "id": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", "message": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", @@ -2899,6 +2922,11 @@ ], "fuzzy": true }, + { + "id": "Do not strip the \"mssql: \" prefix from error messages", + "message": "Do not strip the \"mssql: \" prefix from error messages", + "translation": "" + }, { "id": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", "message": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", @@ -3045,6 +3073,21 @@ "translatorComment": "Copied from source.", "fuzzy": true }, + { + "id": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "message": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "translation": "", + "placeholders": [ + { + "id": "_p1", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "\"-p[1]\"" + } + ] + }, { "id": "Enable column encryption", "message": "Enable column encryption", diff --git a/internal/translations/locales/pt-BR/out.gotext.json b/internal/translations/locales/pt-BR/out.gotext.json index 6ca60db9..92977acc 100644 --- a/internal/translations/locales/pt-BR/out.gotext.json +++ b/internal/translations/locales/pt-BR/out.gotext.json @@ -2841,6 +2841,29 @@ ], "fuzzy": true }, + { + "id": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "message": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "translation": "", + "placeholders": [ + { + "id": "SQLCMDFORMAT", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "sqlcmd.SQLCMDFORMAT" + }, + { + "id": "Ascii", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "\"ascii\"" + } + ] + }, { "id": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", "message": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", @@ -2899,6 +2922,11 @@ ], "fuzzy": true }, + { + "id": "Do not strip the \"mssql: \" prefix from error messages", + "message": "Do not strip the \"mssql: \" prefix from error messages", + "translation": "" + }, { "id": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", "message": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", @@ -3045,6 +3073,21 @@ "translatorComment": "Copied from source.", "fuzzy": true }, + { + "id": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "message": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "translation": "", + "placeholders": [ + { + "id": "_p1", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "\"-p[1]\"" + } + ] + }, { "id": "Enable column encryption", "message": "Enable column encryption", diff --git a/internal/translations/locales/ru-RU/out.gotext.json b/internal/translations/locales/ru-RU/out.gotext.json index e57c1ca7..704b5a83 100644 --- a/internal/translations/locales/ru-RU/out.gotext.json +++ b/internal/translations/locales/ru-RU/out.gotext.json @@ -2841,6 +2841,29 @@ ], "fuzzy": true }, + { + "id": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "message": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "translation": "", + "placeholders": [ + { + "id": "SQLCMDFORMAT", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "sqlcmd.SQLCMDFORMAT" + }, + { + "id": "Ascii", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "\"ascii\"" + } + ] + }, { "id": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", "message": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", @@ -2899,6 +2922,11 @@ ], "fuzzy": true }, + { + "id": "Do not strip the \"mssql: \" prefix from error messages", + "message": "Do not strip the \"mssql: \" prefix from error messages", + "translation": "" + }, { "id": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", "message": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", @@ -3045,6 +3073,21 @@ "translatorComment": "Copied from source.", "fuzzy": true }, + { + "id": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "message": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "translation": "", + "placeholders": [ + { + "id": "_p1", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "\"-p[1]\"" + } + ] + }, { "id": "Enable column encryption", "message": "Enable column encryption", diff --git a/internal/translations/locales/zh-CN/out.gotext.json b/internal/translations/locales/zh-CN/out.gotext.json index 145eb3ac..6682f74a 100644 --- a/internal/translations/locales/zh-CN/out.gotext.json +++ b/internal/translations/locales/zh-CN/out.gotext.json @@ -2841,6 +2841,29 @@ ], "fuzzy": true }, + { + "id": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "message": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "translation": "", + "placeholders": [ + { + "id": "SQLCMDFORMAT", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "sqlcmd.SQLCMDFORMAT" + }, + { + "id": "Ascii", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "\"ascii\"" + } + ] + }, { "id": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", "message": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", @@ -2899,6 +2922,11 @@ ], "fuzzy": true }, + { + "id": "Do not strip the \"mssql: \" prefix from error messages", + "message": "Do not strip the \"mssql: \" prefix from error messages", + "translation": "" + }, { "id": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", "message": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", @@ -3045,6 +3073,21 @@ "translatorComment": "Copied from source.", "fuzzy": true }, + { + "id": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "message": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "translation": "", + "placeholders": [ + { + "id": "_p1", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "\"-p[1]\"" + } + ] + }, { "id": "Enable column encryption", "message": "Enable column encryption", diff --git a/internal/translations/locales/zh-TW/out.gotext.json b/internal/translations/locales/zh-TW/out.gotext.json index ee4e808c..fd286e64 100644 --- a/internal/translations/locales/zh-TW/out.gotext.json +++ b/internal/translations/locales/zh-TW/out.gotext.json @@ -2841,6 +2841,29 @@ ], "fuzzy": true }, + { + "id": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "message": "Prints the output in ASCII table format. This option sets the sqlcmd scripting variable {SQLCMDFORMAT} to '{Ascii}'. The default is false", + "translation": "", + "placeholders": [ + { + "id": "SQLCMDFORMAT", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "sqlcmd.SQLCMDFORMAT" + }, + { + "id": "Ascii", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "\"ascii\"" + } + ] + }, { "id": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", "message": "{_r0__1} Redirects error messages with severity \u003e= 11 output to stderr. Pass 1 to to redirect all errors including PRINT.", @@ -2899,6 +2922,11 @@ ], "fuzzy": true }, + { + "id": "Do not strip the \"mssql: \" prefix from error messages", + "message": "Do not strip the \"mssql: \" prefix from error messages", + "translation": "" + }, { "id": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", "message": "Specifies the number of rows to print between the column headings. Use -h-1 to specify that headers not be printed", @@ -3045,6 +3073,21 @@ "translatorComment": "Copied from source.", "fuzzy": true }, + { + "id": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "message": "{_p1} Print performance statistics after each batch. Pass 1 for colon-separated format", + "translation": "", + "placeholders": [ + { + "id": "_p1", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "\"-p[1]\"" + } + ] + }, { "id": "Enable column encryption", "message": "Enable column encryption", diff --git a/pkg/sqlcmd/commands.go b/pkg/sqlcmd/commands.go index 66dd1dba..5bd5bfd9 100644 --- a/pkg/sqlcmd/commands.go +++ b/pkg/sqlcmd/commands.go @@ -249,7 +249,9 @@ func exitCommand(s *Sqlcmd, args []string, line uint) error { if len(query1) > 0 || len(query2) > 0 { query := query1 + SqlcmdEol + query2 - s.Exitcode, _ = s.runQuery(query) + var elapsedMs int64 + s.Exitcode, elapsedMs, _ = s.runQuery(query) + s.printStatistics(elapsedMs, 1, s.GetOutput()) } return ErrExitRequested } @@ -290,12 +292,16 @@ func goCommand(s *Sqlcmd, args []string, line uint) error { return nil } query = s.getRunnableQuery(query) + var totalElapsedMs int64 for i := 0; i < n; i++ { - if retcode, err := s.runQuery(query); err != nil { + retcode, elapsedMs, err := s.runQuery(query) + totalElapsedMs += elapsedMs + if err != nil { s.Exitcode = retcode return err } } + s.printStatistics(totalElapsedMs, n, s.GetOutput()) s.batch.Reset(nil) return nil } diff --git a/pkg/sqlcmd/sqlcmd.go b/pkg/sqlcmd/sqlcmd.go index 93637a02..3ef85814 100644 --- a/pkg/sqlcmd/sqlcmd.go +++ b/pkg/sqlcmd/sqlcmd.go @@ -86,8 +86,11 @@ type Sqlcmd struct { UnicodeOutputFile bool // EchoInput tells the GO command to print the batch text before running the query EchoInput bool - colorizer color.Colorizer - termchan chan os.Signal + // PrintStatistics controls printing of performance statistics after each batch + // nil means disabled, 0 means standard format, 1 means colon-separated format + PrintStatistics *int + colorizer color.Colorizer + termchan chan os.Signal } // New creates a new Sqlcmd instance. @@ -446,13 +449,14 @@ func (s *Sqlcmd) getRunnableQuery(q string) string { return b.String() } -// runQuery runs the query and prints the results -// The return value is based on the first cell of the last column of the last result set. +// runQuery runs the query and prints the results. +// Returns (exitcode, elapsedMs, error). +// The exitcode is based on the first cell of the last column of the last result set. // If it's numeric, it will be converted to int // -100 : Error encountered prior to selecting return value // -101: No rows found // -102: Conversion error occurred when selecting return value -func (s *Sqlcmd) runQuery(query string) (int, error) { +func (s *Sqlcmd) runQuery(query string) (int, int64, error) { retcode := -101 s.Format.BeginBatch(query, s.vars, s.GetOutput(), s.GetError()) ctx := context.Background() @@ -463,6 +467,7 @@ func (s *Sqlcmd) runQuery(query string) (int, error) { ctx = ct } retmsg := &sqlexp.ReturnMessage{} + startTime := time.Now() rows, qe := s.db.QueryContext(ctx, query, retmsg) if qe != nil { s.Format.AddError(qe) @@ -540,8 +545,9 @@ func (s *Sqlcmd) runQuery(query string) (int, error) { s.Format.EndResultSet() } } + elapsedMs := time.Since(startTime).Milliseconds() s.Format.EndBatch() - return retcode, qe + return retcode, elapsedMs, qe } // returns ErrExitRequested if the error is a SQL error and satisfies the connection's error handling configuration @@ -613,3 +619,41 @@ func (s *Sqlcmd) SetupCloseHandler() { func (s *Sqlcmd) StopCloseHandler() { signal.Stop(s.termchan) } + +// printStatistics writes batch performance statistics when enabled. +func (s *Sqlcmd) printStatistics(elapsedMs int64, numBatches int, out io.Writer) { + if s.PrintStatistics == nil || numBatches <= 0 { + return + } + + // Get packet size from connect settings or use default + packetSize := s.Connect.PacketSize + if packetSize <= 0 { + packetSize = 4096 // default packet size + } + + // Ensure minimum 1ms for rate calculations, but display actual 0 as "< 1" + displayElapsedMs := elapsedMs + calcElapsedMs := elapsedMs + if calcElapsedMs < 1 { + calcElapsedMs = 1 + } + + avgTime := float64(displayElapsedMs) / float64(numBatches) + batchesPerSec := float64(numBatches) / (float64(calcElapsedMs) / 1000.0) + + if *s.PrintStatistics == 1 { + // Colon-separated format: n:x:t1:t2:t3 + // packetSize:numBatches:totalTime:avgTime:batchesPerSec + _, _ = fmt.Fprintf(out, "%s%d:%d:%d:%.2f:%.2f%s", SqlcmdEol, packetSize, numBatches, displayElapsedMs, avgTime, batchesPerSec, SqlcmdEol) + } else { + // Standard format + _, _ = fmt.Fprintf(out, "%sNetwork packet size (bytes): %d%s", SqlcmdEol, packetSize, SqlcmdEol) + _, _ = fmt.Fprintf(out, "%d xact(s):%s", numBatches, SqlcmdEol) + if displayElapsedMs < 1 { + _, _ = fmt.Fprintf(out, "Clock Time (ms.): total < 1 avg %.2f (%.2f xacts per sec.)%s", avgTime, batchesPerSec, SqlcmdEol) + } else { + _, _ = fmt.Fprintf(out, "Clock Time (ms.): total %7d avg %.2f (%.2f xacts per sec.)%s", displayElapsedMs, avgTime, batchesPerSec, SqlcmdEol) + } + } +} diff --git a/pkg/sqlcmd/sqlcmd_test.go b/pkg/sqlcmd/sqlcmd_test.go index 2c325fed..a3ee7e33 100644 --- a/pkg/sqlcmd/sqlcmd_test.go +++ b/pkg/sqlcmd/sqlcmd_test.go @@ -305,27 +305,27 @@ func TestExitInitialQuery(t *testing.T) { func TestExitCodeSetOnError(t *testing.T) { s, _ := setupSqlCmdWithMemoryOutput(t) s.Connect.ErrorSeverityLevel = 12 - retcode, err := s.runQuery("RAISERROR (N'Testing!' , 11, 1)") + retcode, _, err := s.runQuery("RAISERROR (N'Testing!' , 11, 1)") assert.NoError(t, err, "!ExitOnError 11") assert.Equal(t, -101, retcode, "Raiserror below ErrorSeverityLevel") - retcode, err = s.runQuery("RAISERROR (N'Testing!' , 14, 1)") + retcode, _, err = s.runQuery("RAISERROR (N'Testing!' , 14, 1)") assert.NoError(t, err, "!ExitOnError 14") assert.Equal(t, 14, retcode, "Raiserror above ErrorSeverityLevel") s.Connect.ExitOnError = true - retcode, err = s.runQuery("RAISERROR (N'Testing!' , 11, 1)") + retcode, _, err = s.runQuery("RAISERROR (N'Testing!' , 11, 1)") assert.NoError(t, err, "ExitOnError and Raiserror below ErrorSeverityLevel") assert.Equal(t, -101, retcode, "Raiserror below ErrorSeverityLevel") - retcode, err = s.runQuery("RAISERROR (N'Testing!' , 14, 1)") + retcode, _, err = s.runQuery("RAISERROR (N'Testing!' , 14, 1)") assert.ErrorIs(t, err, ErrExitRequested, "ExitOnError and Raiserror above ErrorSeverityLevel") assert.Equal(t, 14, retcode, "ExitOnError and Raiserror above ErrorSeverityLevel") s.Connect.ErrorSeverityLevel = 0 - retcode, err = s.runQuery("RAISERROR (N'Testing!' , 11, 1)") + retcode, _, err = s.runQuery("RAISERROR (N'Testing!' , 11, 1)") assert.ErrorIs(t, err, ErrExitRequested, "ExitOnError and ErrorSeverityLevel = 0, Raiserror above 10") assert.Equal(t, 1, retcode, "ExitOnError and ErrorSeverityLevel = 0, Raiserror above 10") - retcode, err = s.runQuery("RAISERROR (N'Testing!' , 5, 1)") + 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 (15002, 10, 127, 'param')") + retcode, _, err = s.runQuery("RAISERROR (15002, 10, 127, 'param')") assert.ErrorIs(t, err, ErrExitRequested, "RAISERROR with state 127") assert.Equal(t, 15002, retcode, "RAISERROR (15002, 10, 127, 'param')") } @@ -457,7 +457,7 @@ func TestVerticalLayoutNoColumns(t *testing.T) { s, buf := setupSqlCmdWithMemoryOutput(t) defer buf.Close() s.vars.Set(SQLCMDFORMAT, "vert") - _, err := s.runQuery("SELECT 100 as 'column1', 2000 as 'col2', 300") + _, _, err := s.runQuery("SELECT 100 as 'column1', 2000 as 'col2', 300") assert.NoError(t, err, "runQuery failed") assert.Equal(t, "100"+SqlcmdEol+"2000"+SqlcmdEol+"300"+SqlcmdEol+SqlcmdEol+SqlcmdEol+oneRowAffected+SqlcmdEol, @@ -467,7 +467,7 @@ func TestVerticalLayoutNoColumns(t *testing.T) { func TestSelectGuidColumn(t *testing.T) { s, buf := setupSqlCmdWithMemoryOutput(t) defer buf.Close() - _, err := s.runQuery("select convert(uniqueidentifier, N'3ddba21e-ff0f-4d24-90b4-f355864d7865')") + _, _, err := s.runQuery("select convert(uniqueidentifier, N'3ddba21e-ff0f-4d24-90b4-f355864d7865')") assert.NoError(t, err, "runQuery failed") assert.Equal(t, "3ddba21e-ff0f-4d24-90b4-f355864d7865"+SqlcmdEol+SqlcmdEol+oneRowAffected+SqlcmdEol, buf.buf.String(), "select a uniqueidentifier should work") } @@ -475,7 +475,7 @@ func TestSelectGuidColumn(t *testing.T) { func TestSelectNullGuidColumn(t *testing.T) { s, buf := setupSqlCmdWithMemoryOutput(t) defer buf.Close() - _, err := s.runQuery("select convert(uniqueidentifier,null)") + _, _, err := s.runQuery("select convert(uniqueidentifier,null)") assert.NoError(t, err, "runQuery failed") assert.Equal(t, "NULL"+SqlcmdEol+SqlcmdEol+oneRowAffected+SqlcmdEol, buf.buf.String(), "select a null uniqueidentifier should work") } @@ -485,7 +485,7 @@ func TestVerticalLayoutWithColumns(t *testing.T) { defer buf.Close() s.vars.Set(SQLCMDFORMAT, "vert") s.vars.Set(SQLCMDMAXVARTYPEWIDTH, "256") - _, err := s.runQuery("SELECT 100 as 'column1', 2000 as 'col2', 300") + _, _, err := s.runQuery("SELECT 100 as 'column1', 2000 as 'col2', 300") assert.NoError(t, err, "runQuery failed") assert.Equal(t, "column1 100"+SqlcmdEol+"col2 2000"+SqlcmdEol+" 300"+SqlcmdEol+SqlcmdEol+SqlcmdEol+oneRowAffected+SqlcmdEol, @@ -607,7 +607,7 @@ func TestQueryTimeout(t *testing.T) { s, buf := setupSqlCmdWithMemoryOutput(t) defer buf.Close() s.vars.Set(SQLCMDSTATTIMEOUT, "1") - i, err := s.runQuery("waitfor delay '00:00:10'") + i, _, err := s.runQuery("waitfor delay '00:00:10'") if assert.NoError(t, err, "runQuery returned an error") { assert.Equal(t, -100, i, "return from runQuery") assert.Equal(t, "Timeout expired"+SqlcmdEol, buf.buf.String(), "Query should have timed out") @@ -721,3 +721,121 @@ func TestSqlcmdPrefersSharedMemoryProtocol(t *testing.T) { assert.EqualValuesf(t, "np", msdsn.ProtocolParsers[3].Protocol(), "np should be fourth protocol") } + +func TestPrintStatisticsStandardFormat(t *testing.T) { + s, buf := setupSqlCmdWithMemoryOutput(t) + defer func() { _ = buf.Close() }() + standardFormat := 0 + s.PrintStatistics = &standardFormat + s.Connect.PacketSize = 4096 + _, elapsedMs, err := s.runQuery("SELECT 1") + assert.NoError(t, err, "runQuery failed") + s.printStatistics(elapsedMs, 1, s.GetOutput()) + output := buf.buf.String() + // Standard format should contain specific phrases + assert.Contains(t, output, "Network packet size (bytes): 4096", "Should contain packet size") + assert.Contains(t, output, "xact(s):", "Should contain xacts label") + assert.Contains(t, output, "Clock Time (ms.):", "Should contain clock time label") + assert.Contains(t, output, "xacts per sec.", "Should contain xacts per sec") +} + +func TestPrintStatisticsColonFormat(t *testing.T) { + s, buf := setupSqlCmdWithMemoryOutput(t) + defer func() { _ = buf.Close() }() + colonFormat := 1 + s.PrintStatistics = &colonFormat + s.Connect.PacketSize = 8192 + _, elapsedMs, err := s.runQuery("SELECT 1") + assert.NoError(t, err, "runQuery failed") + s.printStatistics(elapsedMs, 1, s.GetOutput()) + output := buf.buf.String() + // Colon format: packetSize:numBatches:totalTime:avgTime:batchesPerSec + // Should start with 8192:1: + assert.Contains(t, output, "8192:1:", "Should contain packet size and batch count in colon format") +} + +func TestPrintStatisticsDisabled(t *testing.T) { + s, buf := setupSqlCmdWithMemoryOutput(t) + defer func() { _ = buf.Close() }() + // PrintStatistics is nil by default (disabled) + _, _, err := s.runQuery("SELECT 1") + assert.NoError(t, err, "runQuery failed") + output := buf.buf.String() + // Should not contain statistics output + assert.NotContains(t, output, "Network packet size", "Should not contain packet size when disabled") + assert.NotContains(t, output, "xact(s):", "Should not contain xacts label when disabled") +} + +func TestPrintStatisticsUnit(t *testing.T) { + newSqlcmd := func(format int, packetSize int) *Sqlcmd { + s := &Sqlcmd{Connect: &ConnectSettings{}} + s.PrintStatistics = &format + s.Connect.PacketSize = packetSize + return s + } + + t.Run("standard format", func(t *testing.T) { + s := newSqlcmd(0, 4096) + var buf bytes.Buffer + s.printStatistics(150, 3, &buf) + out := buf.String() + assert.Contains(t, out, "Network packet size (bytes): 4096") + assert.Contains(t, out, "3 xact(s):") + assert.Contains(t, out, "Clock Time (ms.): total 150") + assert.Contains(t, out, "xacts per sec.") + }) + + t.Run("colon format", func(t *testing.T) { + s := newSqlcmd(1, 8192) + var buf bytes.Buffer + s.printStatistics(200, 2, &buf) + out := buf.String() + assert.Contains(t, out, "8192:2:200:") + }) + + t.Run("sub-millisecond standard", func(t *testing.T) { + s := newSqlcmd(0, 4096) + var buf bytes.Buffer + s.printStatistics(0, 1, &buf) + out := buf.String() + assert.Equal(t, SqlcmdEol+ + "Network packet size (bytes): 4096"+SqlcmdEol+ + "1 xact(s):"+SqlcmdEol+ + "Clock Time (ms.): total < 1 avg 0.00 (1000.00 xacts per sec.)"+SqlcmdEol, + out) + }) + + t.Run("sub-millisecond colon", func(t *testing.T) { + s := newSqlcmd(1, 4096) + var buf bytes.Buffer + s.printStatistics(0, 1, &buf) + out := buf.String() + assert.Equal(t, SqlcmdEol+"4096:1:0:0.00:1000.00"+SqlcmdEol, out) + }) + + t.Run("disabled", func(t *testing.T) { + s := &Sqlcmd{Connect: &ConnectSettings{}} + var buf bytes.Buffer + s.printStatistics(100, 1, &buf) + assert.Empty(t, buf.String(), "should produce no output when disabled") + }) + + t.Run("default packet size", func(t *testing.T) { + s := newSqlcmd(0, 0) + var buf bytes.Buffer + s.printStatistics(50, 1, &buf) + out := buf.String() + assert.Contains(t, out, "Network packet size (bytes): 4096", "should default to 4096") + }) + + t.Run("multiple batches", func(t *testing.T) { + s := newSqlcmd(0, 4096) + var buf bytes.Buffer + s.printStatistics(1000, 10, &buf) + out := buf.String() + assert.Contains(t, out, "10 xact(s):") + assert.Contains(t, out, "total 1000") + assert.Contains(t, out, "avg 100.00") + assert.Contains(t, out, "10.00 xacts per sec.") + }) +}