From faf2f3974120752dc6db99c5cafc29a4f8e20f73 Mon Sep 17 00:00:00 2001 From: Arthur Stankevich Date: Wed, 14 Oct 2026 11:09:44 +0200 Subject: [PATCH 1/2] feat: support (localdb)\instance server names on Windows Resolve (localdb)\ to the instance's named pipe through the LocalDB instance API (SqlUserInstance.dll), starting the instance and creating the automatic MSSQLLocalDB instance when needed. (localdb) without an instance uses MSSQLLocalDB. Other platforms report that LocalDB is only supported on Windows. Fixes #470 --- README.md | 1 + internal/translations/catalog.go | 90 ++++++++---- .../locales/de-DE/out.gotext.json | 79 +++++++++++ .../locales/en-US/out.gotext.json | 89 ++++++++++++ .../locales/es-ES/out.gotext.json | 79 +++++++++++ .../locales/fr-FR/out.gotext.json | 79 +++++++++++ .../locales/it-IT/out.gotext.json | 79 +++++++++++ .../locales/ja-JP/out.gotext.json | 79 +++++++++++ .../locales/ko-KR/out.gotext.json | 79 +++++++++++ .../locales/pt-BR/out.gotext.json | 79 +++++++++++ .../locales/ru-RU/out.gotext.json | 79 +++++++++++ .../locales/zh-CN/out.gotext.json | 79 +++++++++++ .../locales/zh-TW/out.gotext.json | 79 +++++++++++ pkg/sqlcmd/connect.go | 15 +- pkg/sqlcmd/localdb.go | 30 ++++ pkg/sqlcmd/localdb_other.go | 12 ++ pkg/sqlcmd/localdb_test.go | 63 +++++++++ pkg/sqlcmd/localdb_windows.go | 130 ++++++++++++++++++ pkg/sqlcmd/localdb_windows_test.go | 30 ++++ pkg/sqlcmd/util.go | 4 + 20 files changed, 1224 insertions(+), 30 deletions(-) create mode 100644 pkg/sqlcmd/localdb.go create mode 100644 pkg/sqlcmd/localdb_other.go create mode 100644 pkg/sqlcmd/localdb_test.go create mode 100644 pkg/sqlcmd/localdb_windows.go create mode 100644 pkg/sqlcmd/localdb_windows_test.go diff --git a/README.md b/README.md index 4a4e436c..702fb620 100644 --- a/README.md +++ b/README.md @@ -204,6 +204,7 @@ program_name sqlcmd 2> go net_transport Named pipe ``` +- On Windows, `sqlcmd` can connect to SQL Server Express LocalDB instances: `sqlcmd -S (localdb)\MSSQLLocalDB`. The instance is started (and created, for the automatic `MSSQLLocalDB` instance) if needed, and the connection uses the instance's named pipe. ### Azure Active Directory Authentication diff --git a/internal/translations/catalog.go b/internal/translations/catalog.go index adcbf40e..3f7ab703 100644 --- a/internal/translations/catalog.go +++ b/internal/translations/catalog.go @@ -152,6 +152,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 +232,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, @@ -248,9 +250,10 @@ var messageKeyToIndex = map[string]int{ "Run a query": 12, "Run a query against the current context": 11, "Run a query using [%s] database": 13, + "SQL Server Express LocalDB is not installed": 310, "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": 311, "Servers:": 222, "Set new default database": 14, "Set the current context": 149, @@ -317,6 +320,8 @@ var messageKeyToIndex = map[string]int{ "Unable to continue, a user (non-system) database (%s) is present": 49, "Unable to download file": 205, "Unable to download image %s": 203, + "Unable to load the LocalDB instance API %s: %v": 308, + "Unable to start LocalDB instance %s: %s": 309, "Uninstall/Delete the current context": 28, "Uninstall/Delete the current context, no user prompt": 29, "Uninstall/Delete the current context, no user prompt and override safety check for user databases": 30, @@ -357,7 +362,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{ // 313 elements // Entry 0 - 1F 0x00000000, 0x0000003c, 0x0000007e, 0x00000096, 0x000000d1, 0x000000e9, 0x000000fd, 0x00000148, @@ -445,7 +450,9 @@ var de_DEIndex = []uint32{ // 308 elements 0x00004cbf, 0x00004d1a, 0x00004d65, 0x00004d6f, 0x00004d83, 0x00004d9c, 0x00004dc2, 0x00004de2, 0x00004de2, 0x00004de2, 0x00004de2, 0x00004de2, -} // Size: 1256 bytes + 0x00004de2, 0x00004de2, 0x00004de2, 0x00004de2, + 0x00004de2, +} // Size: 1276 bytes const de_DEData string = "" + // Size: 19938 bytes "\x02SQL Server installieren/erstellen, abfragen, deinstallieren\x02Konfi" + @@ -738,7 +745,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{ // 313 elements // Entry 0 - 1F 0x00000000, 0x0000002c, 0x00000062, 0x0000007a, 0x000000b3, 0x000000cb, 0x000000de, 0x00000113, @@ -825,10 +832,12 @@ 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, 0x0000409f, 0x000040cd, 0x000040f9, + 0x00004146, +} // Size: 1276 bytes -const en_USData string = "" + // Size: 16386 bytes +const en_USData string = "" + // Size: 16710 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 +1079,15 @@ 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\x02Unable to load the LocalDB" + + " instance API %[1]s: %[2]v\x02Unable to start LocalDB instance %[1]s: %[" + + "2]s\x02SQL Server Express LocalDB is not installed\x02Server name overri" + + "de is not supported with the current authentication method" -var es_ESIndex = []uint32{ // 308 elements +var es_ESIndex = []uint32{ // 313 elements // Entry 0 - 1F 0x00000000, 0x00000032, 0x00000081, 0x0000009c, 0x000000ec, 0x0000010d, 0x00000127, 0x0000017f, @@ -1161,7 +1175,9 @@ var es_ESIndex = []uint32{ // 308 elements 0x00004c6c, 0x00004ccf, 0x00004d1d, 0x00004d2a, 0x00004d3c, 0x00004d54, 0x00004d7f, 0x00004da2, 0x00004da2, 0x00004da2, 0x00004da2, 0x00004da2, -} // Size: 1256 bytes + 0x00004da2, 0x00004da2, 0x00004da2, 0x00004da2, + 0x00004da2, +} // Size: 1276 bytes const es_ESData string = "" + // Size: 19874 bytes "\x02Instalar/Crear, Consultar, Desinstalar SQL Server\x02Visualización d" + @@ -1455,7 +1471,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{ // 313 elements // Entry 0 - 1F 0x00000000, 0x00000037, 0x0000007f, 0x0000009d, 0x000000e1, 0x000000fe, 0x00000117, 0x00000169, @@ -1543,7 +1559,9 @@ var fr_FRIndex = []uint32{ // 308 elements 0x00004fbe, 0x00005014, 0x00005059, 0x00005069, 0x0000507e, 0x00005098, 0x000050bf, 0x000050e1, 0x000050e1, 0x000050e1, 0x000050e1, 0x000050e1, -} // Size: 1256 bytes + 0x000050e1, 0x000050e1, 0x000050e1, 0x000050e1, + 0x000050e1, +} // Size: 1276 bytes const fr_FRData string = "" + // Size: 20705 bytes "\x02Installer/créer, interroger, désinstaller SQL Server\x02Afficher les" + @@ -1847,7 +1865,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{ // 313 elements // Entry 0 - 1F 0x00000000, 0x0000003c, 0x00000088, 0x000000a0, 0x000000f7, 0x00000114, 0x0000012b, 0x0000016a, @@ -1935,7 +1953,9 @@ var it_ITIndex = []uint32{ // 308 elements 0x00004a16, 0x00004a74, 0x00004ac1, 0x00004acb, 0x00004ae0, 0x00004afa, 0x00004b2a, 0x00004b52, 0x00004b52, 0x00004b52, 0x00004b52, 0x00004b52, -} // Size: 1256 bytes + 0x00004b52, 0x00004b52, 0x00004b52, 0x00004b52, + 0x00004b52, +} // Size: 1276 bytes const it_ITData string = "" + // Size: 19282 bytes "\x02Installare/creare, eseguire query, disinstallare SQL Server\x02Visua" + @@ -2221,7 +2241,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{ // 313 elements // Entry 0 - 1F 0x00000000, 0x0000004f, 0x00000077, 0x0000009d, 0x000000d8, 0x000000f8, 0x0000010b, 0x0000014c, @@ -2309,7 +2329,9 @@ var ja_JPIndex = []uint32{ // 308 elements 0x00005d02, 0x00005d7c, 0x00005ddb, 0x00005dec, 0x00005e0c, 0x00005e30, 0x00005e56, 0x00005e79, 0x00005e79, 0x00005e79, 0x00005e79, 0x00005e79, -} // Size: 1256 bytes + 0x00005e79, 0x00005e79, 0x00005e79, 0x00005e79, + 0x00005e79, +} // Size: 1276 bytes const ja_JPData string = "" + // Size: 24185 bytes "\x02インストール/作成、クエリ、SQL Server のアンインストール\x02構成情報と接続文字列の表示\x04\x02\x0a\x0a" + @@ -2474,7 +2496,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{ // 313 elements // Entry 0 - 1F 0x00000000, 0x00000029, 0x00000053, 0x0000006c, 0x000000b8, 0x000000d0, 0x000000de, 0x00000121, @@ -2562,7 +2584,9 @@ var ko_KRIndex = []uint32{ // 308 elements 0x00004cc5, 0x00004d25, 0x00004d71, 0x00004d79, 0x00004d8e, 0x00004dae, 0x00004dcf, 0x00004dea, 0x00004dea, 0x00004dea, 0x00004dea, 0x00004dea, -} // Size: 1256 bytes + 0x00004dea, 0x00004dea, 0x00004dea, 0x00004dea, + 0x00004dea, +} // Size: 1276 bytes const ko_KRData string = "" + // Size: 19946 bytes "\x02SQL Server 설치/생성, 쿼리, 제거\x02구성 정보 및 연결 문자열 보기\x04\x02\x0a\x0a\x00" + @@ -2719,7 +2743,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{ // 313 elements // Entry 0 - 1F 0x00000000, 0x00000034, 0x00000071, 0x0000008d, 0x000000e3, 0x00000103, 0x0000011e, 0x0000016d, @@ -2807,7 +2831,9 @@ var pt_BRIndex = []uint32{ // 308 elements 0x00004920, 0x0000497e, 0x000049c8, 0x000049cf, 0x000049e1, 0x000049f9, 0x00004a24, 0x00004a47, 0x00004a47, 0x00004a47, 0x00004a47, 0x00004a47, -} // Size: 1256 bytes + 0x00004a47, 0x00004a47, 0x00004a47, 0x00004a47, + 0x00004a47, +} // Size: 1276 bytes const pt_BRData string = "" + // Size: 19015 bytes "\x02Instalar/Criar, Consultar, Desinstalar o SQL Server\x02Exibir inform" + @@ -3087,7 +3113,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{ // 313 elements // Entry 0 - 1F 0x00000000, 0x00000056, 0x000000c1, 0x000000ec, 0x00000151, 0x00000172, 0x00000195, 0x0000023b, @@ -3175,7 +3201,9 @@ var ru_RUIndex = []uint32{ // 308 elements 0x00007e41, 0x00007ed3, 0x00007f4b, 0x00007f59, 0x00007f7d, 0x00007fa4, 0x00007ff3, 0x00008038, 0x00008038, 0x00008038, 0x00008038, 0x00008038, -} // Size: 1256 bytes + 0x00008038, 0x00008038, 0x00008038, 0x00008038, + 0x00008038, +} // Size: 1276 bytes const ru_RUData string = "" + // Size: 32824 bytes "\x02Установка или создание, запрос, удаление SQL Server\x02Просмотреть с" + @@ -3464,7 +3492,7 @@ const ru_RUData string = "" + // Size: 32824 bytes "идентификатор переменной %[1]s\x02Недопустимое значение переменной %[1]" + "s" -var zh_CNIndex = []uint32{ // 308 elements +var zh_CNIndex = []uint32{ // 313 elements // Entry 0 - 1F 0x00000000, 0x0000002b, 0x00000050, 0x00000065, 0x00000096, 0x000000ab, 0x000000b8, 0x000000fc, @@ -3552,7 +3580,9 @@ var zh_CNIndex = []uint32{ // 308 elements 0x00003805, 0x00003861, 0x000038ae, 0x000038b6, 0x000038c7, 0x000038dc, 0x000038f9, 0x00003910, 0x00003910, 0x00003910, 0x00003910, 0x00003910, -} // Size: 1256 bytes + 0x00003910, 0x00003910, 0x00003910, 0x00003910, + 0x00003910, +} // Size: 1276 bytes const zh_CNData string = "" + // Size: 14608 bytes "\x02安装/创建、查询、卸载 SQL Server\x02查看配置信息和连接字符串\x04\x02\x0a\x0a\x00\x0f\x02反馈" + @@ -3673,7 +3703,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{ // 313 elements // Entry 0 - 1F 0x00000000, 0x00000031, 0x00000053, 0x0000006e, 0x000000a1, 0x000000b8, 0x000000c2, 0x00000106, @@ -3761,7 +3791,9 @@ var zh_TWIndex = []uint32{ // 308 elements 0x00003853, 0x000038b2, 0x00003902, 0x0000390a, 0x00003924, 0x00003942, 0x00003961, 0x00003978, 0x00003978, 0x00003978, 0x00003978, 0x00003978, -} // Size: 1256 bytes + 0x00003978, 0x00003978, 0x00003978, 0x00003978, + 0x00003978, +} // Size: 1276 bytes const zh_TWData string = "" + // Size: 14712 bytes "\x02安裝/建立、查詢、解除安裝 SQL Server\x02檢視組態資訊和連接字串\x04\x02\x0a\x0a\x00\x15\x02意" + @@ -3880,4 +3912,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 235835 bytes (230KiB); checksum: 144F38D1 diff --git a/internal/translations/locales/de-DE/out.gotext.json b/internal/translations/locales/de-DE/out.gotext.json index 5e74cf30..d22e7f56 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", @@ -3655,6 +3683,57 @@ ], "fuzzy": true }, + { + "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "translation": "", + "placeholders": [ + { + "id": "ApiPath", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "apiPath" + }, + { + "id": "Err", + "string": "%[2]v", + "type": "error", + "underlyingType": "interface{Error() string}", + "argNum": 2, + "expr": "err" + } + ] + }, + { + "id": "Unable to start LocalDB instance {Instance}: {Message}", + "message": "Unable to start LocalDB instance {Instance}: {Message}", + "translation": "", + "placeholders": [ + { + "id": "Instance", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "instance" + }, + { + "id": "Message", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "message" + } + ] + }, + { + "id": "SQL Server Express LocalDB is not installed", + "message": "SQL Server Express LocalDB is not installed", + "translation": "" + }, { "id": "Server name override is not supported with the current authentication method", "message": "Server name override is not supported with the current authentication method", diff --git a/internal/translations/locales/en-US/out.gotext.json b/internal/translations/locales/en-US/out.gotext.json index 21772c8d..c3096d22 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", @@ -3661,6 +3693,63 @@ ], "fuzzy": true }, + { + "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "translation": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "translatorComment": "Copied from source.", + "placeholders": [ + { + "id": "ApiPath", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "apiPath" + }, + { + "id": "Err", + "string": "%[2]v", + "type": "error", + "underlyingType": "interface{Error() string}", + "argNum": 2, + "expr": "err" + } + ], + "fuzzy": true + }, + { + "id": "Unable to start LocalDB instance {Instance}: {Message}", + "message": "Unable to start LocalDB instance {Instance}: {Message}", + "translation": "Unable to start LocalDB instance {Instance}: {Message}", + "translatorComment": "Copied from source.", + "placeholders": [ + { + "id": "Instance", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "instance" + }, + { + "id": "Message", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "message" + } + ], + "fuzzy": true + }, + { + "id": "SQL Server Express LocalDB is not installed", + "message": "SQL Server Express LocalDB is not installed", + "translation": "SQL Server Express LocalDB is not installed", + "translatorComment": "Copied from source.", + "fuzzy": true + }, { "id": "Server name override is not supported with the current authentication method", "message": "Server name override is not supported with the current authentication method", diff --git a/internal/translations/locales/es-ES/out.gotext.json b/internal/translations/locales/es-ES/out.gotext.json index 66b51962..7d44f5d8 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", @@ -3655,6 +3683,57 @@ ], "fuzzy": true }, + { + "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "translation": "", + "placeholders": [ + { + "id": "ApiPath", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "apiPath" + }, + { + "id": "Err", + "string": "%[2]v", + "type": "error", + "underlyingType": "interface{Error() string}", + "argNum": 2, + "expr": "err" + } + ] + }, + { + "id": "Unable to start LocalDB instance {Instance}: {Message}", + "message": "Unable to start LocalDB instance {Instance}: {Message}", + "translation": "", + "placeholders": [ + { + "id": "Instance", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "instance" + }, + { + "id": "Message", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "message" + } + ] + }, + { + "id": "SQL Server Express LocalDB is not installed", + "message": "SQL Server Express LocalDB is not installed", + "translation": "" + }, { "id": "Server name override is not supported with the current authentication method", "message": "Server name override is not supported with the current authentication method", diff --git a/internal/translations/locales/fr-FR/out.gotext.json b/internal/translations/locales/fr-FR/out.gotext.json index d09d0a6d..303aab9c 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", @@ -3655,6 +3683,57 @@ ], "fuzzy": true }, + { + "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "translation": "", + "placeholders": [ + { + "id": "ApiPath", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "apiPath" + }, + { + "id": "Err", + "string": "%[2]v", + "type": "error", + "underlyingType": "interface{Error() string}", + "argNum": 2, + "expr": "err" + } + ] + }, + { + "id": "Unable to start LocalDB instance {Instance}: {Message}", + "message": "Unable to start LocalDB instance {Instance}: {Message}", + "translation": "", + "placeholders": [ + { + "id": "Instance", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "instance" + }, + { + "id": "Message", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "message" + } + ] + }, + { + "id": "SQL Server Express LocalDB is not installed", + "message": "SQL Server Express LocalDB is not installed", + "translation": "" + }, { "id": "Server name override is not supported with the current authentication method", "message": "Server name override is not supported with the current authentication method", diff --git a/internal/translations/locales/it-IT/out.gotext.json b/internal/translations/locales/it-IT/out.gotext.json index b320dd5c..74fc460f 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", @@ -3655,6 +3683,57 @@ ], "fuzzy": true }, + { + "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "translation": "", + "placeholders": [ + { + "id": "ApiPath", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "apiPath" + }, + { + "id": "Err", + "string": "%[2]v", + "type": "error", + "underlyingType": "interface{Error() string}", + "argNum": 2, + "expr": "err" + } + ] + }, + { + "id": "Unable to start LocalDB instance {Instance}: {Message}", + "message": "Unable to start LocalDB instance {Instance}: {Message}", + "translation": "", + "placeholders": [ + { + "id": "Instance", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "instance" + }, + { + "id": "Message", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "message" + } + ] + }, + { + "id": "SQL Server Express LocalDB is not installed", + "message": "SQL Server Express LocalDB is not installed", + "translation": "" + }, { "id": "Server name override is not supported with the current authentication method", "message": "Server name override is not supported with the current authentication method", diff --git a/internal/translations/locales/ja-JP/out.gotext.json b/internal/translations/locales/ja-JP/out.gotext.json index 55cd0a6c..45186a44 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", @@ -3655,6 +3683,57 @@ ], "fuzzy": true }, + { + "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "translation": "", + "placeholders": [ + { + "id": "ApiPath", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "apiPath" + }, + { + "id": "Err", + "string": "%[2]v", + "type": "error", + "underlyingType": "interface{Error() string}", + "argNum": 2, + "expr": "err" + } + ] + }, + { + "id": "Unable to start LocalDB instance {Instance}: {Message}", + "message": "Unable to start LocalDB instance {Instance}: {Message}", + "translation": "", + "placeholders": [ + { + "id": "Instance", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "instance" + }, + { + "id": "Message", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "message" + } + ] + }, + { + "id": "SQL Server Express LocalDB is not installed", + "message": "SQL Server Express LocalDB is not installed", + "translation": "" + }, { "id": "Server name override is not supported with the current authentication method", "message": "Server name override is not supported with the current authentication method", diff --git a/internal/translations/locales/ko-KR/out.gotext.json b/internal/translations/locales/ko-KR/out.gotext.json index c7bfe94a..4b0cdd98 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", @@ -3655,6 +3683,57 @@ ], "fuzzy": true }, + { + "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "translation": "", + "placeholders": [ + { + "id": "ApiPath", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "apiPath" + }, + { + "id": "Err", + "string": "%[2]v", + "type": "error", + "underlyingType": "interface{Error() string}", + "argNum": 2, + "expr": "err" + } + ] + }, + { + "id": "Unable to start LocalDB instance {Instance}: {Message}", + "message": "Unable to start LocalDB instance {Instance}: {Message}", + "translation": "", + "placeholders": [ + { + "id": "Instance", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "instance" + }, + { + "id": "Message", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "message" + } + ] + }, + { + "id": "SQL Server Express LocalDB is not installed", + "message": "SQL Server Express LocalDB is not installed", + "translation": "" + }, { "id": "Server name override is not supported with the current authentication method", "message": "Server name override is not supported with the current authentication method", diff --git a/internal/translations/locales/pt-BR/out.gotext.json b/internal/translations/locales/pt-BR/out.gotext.json index 6ca60db9..1822bc72 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", @@ -3655,6 +3683,57 @@ ], "fuzzy": true }, + { + "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "translation": "", + "placeholders": [ + { + "id": "ApiPath", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "apiPath" + }, + { + "id": "Err", + "string": "%[2]v", + "type": "error", + "underlyingType": "interface{Error() string}", + "argNum": 2, + "expr": "err" + } + ] + }, + { + "id": "Unable to start LocalDB instance {Instance}: {Message}", + "message": "Unable to start LocalDB instance {Instance}: {Message}", + "translation": "", + "placeholders": [ + { + "id": "Instance", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "instance" + }, + { + "id": "Message", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "message" + } + ] + }, + { + "id": "SQL Server Express LocalDB is not installed", + "message": "SQL Server Express LocalDB is not installed", + "translation": "" + }, { "id": "Server name override is not supported with the current authentication method", "message": "Server name override is not supported with the current authentication method", diff --git a/internal/translations/locales/ru-RU/out.gotext.json b/internal/translations/locales/ru-RU/out.gotext.json index e57c1ca7..d3c028ec 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", @@ -3655,6 +3683,57 @@ ], "fuzzy": true }, + { + "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "translation": "", + "placeholders": [ + { + "id": "ApiPath", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "apiPath" + }, + { + "id": "Err", + "string": "%[2]v", + "type": "error", + "underlyingType": "interface{Error() string}", + "argNum": 2, + "expr": "err" + } + ] + }, + { + "id": "Unable to start LocalDB instance {Instance}: {Message}", + "message": "Unable to start LocalDB instance {Instance}: {Message}", + "translation": "", + "placeholders": [ + { + "id": "Instance", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "instance" + }, + { + "id": "Message", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "message" + } + ] + }, + { + "id": "SQL Server Express LocalDB is not installed", + "message": "SQL Server Express LocalDB is not installed", + "translation": "" + }, { "id": "Server name override is not supported with the current authentication method", "message": "Server name override is not supported with the current authentication method", diff --git a/internal/translations/locales/zh-CN/out.gotext.json b/internal/translations/locales/zh-CN/out.gotext.json index 145eb3ac..6812bdaf 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", @@ -3655,6 +3683,57 @@ ], "fuzzy": true }, + { + "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "translation": "", + "placeholders": [ + { + "id": "ApiPath", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "apiPath" + }, + { + "id": "Err", + "string": "%[2]v", + "type": "error", + "underlyingType": "interface{Error() string}", + "argNum": 2, + "expr": "err" + } + ] + }, + { + "id": "Unable to start LocalDB instance {Instance}: {Message}", + "message": "Unable to start LocalDB instance {Instance}: {Message}", + "translation": "", + "placeholders": [ + { + "id": "Instance", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "instance" + }, + { + "id": "Message", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "message" + } + ] + }, + { + "id": "SQL Server Express LocalDB is not installed", + "message": "SQL Server Express LocalDB is not installed", + "translation": "" + }, { "id": "Server name override is not supported with the current authentication method", "message": "Server name override is not supported with the current authentication method", diff --git a/internal/translations/locales/zh-TW/out.gotext.json b/internal/translations/locales/zh-TW/out.gotext.json index ee4e808c..4fa2d458 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", @@ -3655,6 +3683,57 @@ ], "fuzzy": true }, + { + "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", + "translation": "", + "placeholders": [ + { + "id": "ApiPath", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "apiPath" + }, + { + "id": "Err", + "string": "%[2]v", + "type": "error", + "underlyingType": "interface{Error() string}", + "argNum": 2, + "expr": "err" + } + ] + }, + { + "id": "Unable to start LocalDB instance {Instance}: {Message}", + "message": "Unable to start LocalDB instance {Instance}: {Message}", + "translation": "", + "placeholders": [ + { + "id": "Instance", + "string": "%[1]s", + "type": "string", + "underlyingType": "string", + "argNum": 1, + "expr": "instance" + }, + { + "id": "Message", + "string": "%[2]s", + "type": "string", + "underlyingType": "string", + "argNum": 2, + "expr": "message" + } + ] + }, + { + "id": "SQL Server Express LocalDB is not installed", + "message": "SQL Server Express LocalDB is not installed", + "translation": "" + }, { "id": "Server name override is not supported with the current authentication method", "message": "Server name override is not supported with the current authentication method", diff --git a/pkg/sqlcmd/connect.go b/pkg/sqlcmd/connect.go index e2fde19f..c1965bcc 100644 --- a/pkg/sqlcmd/connect.go +++ b/pkg/sqlcmd/connect.go @@ -105,6 +105,19 @@ func (connect ConnectSettings) ConnectionString() (connectionString string, err return "", err } + if isLocalDB(serverName) { + if protocol != "" && protocol != "np" { + return "", &InvalidServerName + } + pipeName, err := resolveLocalDBPipe(instance) + if err != nil { + return "", err + } + serverName = pipeName + instance = "" + protocol = "np" + } + if connect.useServerNameOverride(protocol, connect.ServerName) { overrideName, overrideInstance, _, _, err := splitServer(connect.ServerNameOverride) if err != nil { @@ -200,7 +213,7 @@ func (connect ConnectSettings) useServerNameOverride(protocol string, serverName if connect.ServerNameOverride == "" { return false } - if protocol == "np" || strings.HasPrefix(serverName, `\\`) { + if protocol == "np" || strings.HasPrefix(serverName, `\\`) || isLocalDB(serverName) { return false } return true diff --git a/pkg/sqlcmd/localdb.go b/pkg/sqlcmd/localdb.go new file mode 100644 index 00000000..ac737a56 --- /dev/null +++ b/pkg/sqlcmd/localdb.go @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package sqlcmd + +import "strings" + +// localDBServerName is the pseudo server name used to address SQL Server Express LocalDB instances +const localDBServerName = "(localdb)" + +// defaultLocalDBInstance is the automatic LocalDB instance used when no instance name is given +const defaultLocalDBInstance = "MSSQLLocalDB" + +// isLocalDB returns true if serverName is of the form (localdb) or (localdb)\instance +func isLocalDB(serverName string) bool { + if len(serverName) < len(localDBServerName) || !strings.EqualFold(serverName[:len(localDBServerName)], localDBServerName) { + return false + } + return len(serverName) == len(localDBServerName) || serverName[len(localDBServerName)] == '\\' +} + +// resolveLocalDBPipe starts the given LocalDB instance if needed and returns its named pipe +// in the form \\.\pipe\LOCALDB#xxxxxxxx\tsql\query. It is a variable so tests can replace it. +var resolveLocalDBPipe = func(instance string) (string, error) { + if instance == "" { + instance = defaultLocalDBInstance + } + pipeName, err := startLocalDBInstance(instance) + return strings.TrimPrefix(pipeName, "np:"), err +} diff --git a/pkg/sqlcmd/localdb_other.go b/pkg/sqlcmd/localdb_other.go new file mode 100644 index 00000000..5b0fc6de --- /dev/null +++ b/pkg/sqlcmd/localdb_other.go @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +//go:build !windows + +package sqlcmd + +import "github.com/microsoft/go-sqlcmd/internal/localizer" + +func startLocalDBInstance(instance string) (string, error) { + return "", localizer.Errorf("LocalDB is only supported on Windows") +} diff --git a/pkg/sqlcmd/localdb_test.go b/pkg/sqlcmd/localdb_test.go new file mode 100644 index 00000000..5f2db87a --- /dev/null +++ b/pkg/sqlcmd/localdb_test.go @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package sqlcmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestIsLocalDB(t *testing.T) { + assert.True(t, isLocalDB(`(localdb)`)) + assert.True(t, isLocalDB(`(LocalDB)\MSSQLLocalDB`)) + assert.True(t, isLocalDB(`(localdb)\.\shared`)) + assert.False(t, isLocalDB(`(localdb)x`)) + assert.False(t, isLocalDB(`localdb`)) + assert.False(t, isLocalDB(`someserver\instance`)) +} + +func TestSplitServerLocalDB(t *testing.T) { + tests := []struct { + input string + server string + instance string + protocol string + }{ + {`(localdb)\MSSQLLocalDB`, `(localdb)`, `MSSQLLocalDB`, ``}, + {`(LocalDb)\.\shared`, `(LocalDb)`, `.\shared`, ``}, + {`np:(localdb)\myinstance`, `(localdb)`, `myinstance`, `np`}, + {`(localdb)`, `(localdb)`, ``, ``}, + } + for _, test := range tests { + serverName, instance, port, protocol, err := splitServer(test.input) + if assert.NoError(t, err, test.input) { + assert.Equal(t, test.server, serverName, test.input) + assert.Equal(t, test.instance, instance, test.input) + assert.Equal(t, uint64(0), port, test.input) + assert.Equal(t, test.protocol, protocol, test.input) + } + } +} + +func TestConnectionStringLocalDB(t *testing.T) { + original := resolveLocalDBPipe + defer func() { resolveLocalDBPipe = original }() + var resolved string + resolveLocalDBPipe = func(instance string) (string, error) { + resolved = instance + return `\\.\pipe\LOCALDB#12345678\tsql\query`, nil + } + + settings := ConnectSettings{ServerName: `(localdb)\MSSQLLocalDB`, Database: "master"} + connectionString, err := settings.ConnectionString() + if assert.NoError(t, err) { + assert.Equal(t, "MSSQLLocalDB", resolved, "instance passed to the LocalDB resolver") + assert.Equal(t, `sqlserver://.?database=master&pipe=LOCALDB%2312345678%5Ctsql%5Cquery&protocol=np`, connectionString) + } + + settings = ConnectSettings{ServerName: `tcp:(localdb)\MSSQLLocalDB`} + _, err = settings.ConnectionString() + assert.Error(t, err, "LocalDB only supports named pipes") +} diff --git a/pkg/sqlcmd/localdb_windows.go b/pkg/sqlcmd/localdb_windows.go new file mode 100644 index 00000000..a1dfe97d --- /dev/null +++ b/pkg/sqlcmd/localdb_windows.go @@ -0,0 +1,130 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package sqlcmd + +import ( + "strconv" + "strings" + "unsafe" + + "github.com/microsoft/go-sqlcmd/internal/localizer" + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" +) + +const ( + localDBInstalledVersionsKey = `SOFTWARE\Microsoft\Microsoft SQL Server Local DB\Installed Versions` + // LOCALDB_MAX_SQLCONNECTION_BUFFER_SIZE from sqluserinstance.h + localDBMaxSQLConnectionBufferSize = 260 + // LOCALDB_TRUNCATE_ERR_MESSAGE from sqluserinstance.h + localDBTruncateErrMessage = 1 + localDBMaxErrorMessageSize = 1024 +) + +// startLocalDBInstance uses the LocalDB instance API to start the named instance, +// creating it first if it's an automatic instance, and returns its pipe name +func startLocalDBInstance(instance string) (string, error) { + apiPath, err := localDBInstanceAPIPath() + if err != nil { + return "", err + } + dll, err := windows.LoadDLL(apiPath) + if err != nil { + return "", localizer.Errorf("Unable to load the LocalDB instance API %s: %v", apiPath, err) + } + defer func() { _ = dll.Release() }() + start, err := dll.FindProc("LocalDBStartInstance") + if err != nil { + return "", err + } + instanceName, err := windows.UTF16PtrFromString(instance) + if err != nil { + return "", err + } + buf := make([]uint16, localDBMaxSQLConnectionBufferSize+1) + size := uint32(len(buf)) + hr, _, _ := start.Call( + uintptr(unsafe.Pointer(instanceName)), + 0, + uintptr(unsafe.Pointer(&buf[0])), + uintptr(unsafe.Pointer(&size))) + if int32(hr) < 0 { + message := localDBErrorMessage(dll, hr) + return "", localizer.Errorf("Unable to start LocalDB instance %s: %s", instance, message) + } + return windows.UTF16ToString(buf), nil +} + +// localDBInstanceAPIPath returns the path of SqlUserInstance.dll from the newest installed LocalDB version +func localDBInstanceAPIPath() (string, error) { + key, err := registry.OpenKey(registry.LOCAL_MACHINE, localDBInstalledVersionsKey, registry.ENUMERATE_SUB_KEYS) + if err != nil { + return "", errLocalDBNotInstalled() + } + defer func() { _ = key.Close() }() + versions, err := key.ReadSubKeyNames(-1) + if err != nil || len(versions) == 0 { + return "", errLocalDBNotInstalled() + } + newest := "" + for _, v := range versions { + if newest == "" || compareVersions(v, newest) > 0 { + newest = v + } + } + versionKey, err := registry.OpenKey(key, newest, registry.QUERY_VALUE) + if err != nil { + return "", err + } + defer func() { _ = versionKey.Close() }() + apiPath, _, err := versionKey.GetStringValue("InstanceAPIPath") + if err != nil { + return "", errLocalDBNotInstalled() + } + return apiPath, nil +} + +func errLocalDBNotInstalled() error { + return localizer.Errorf("SQL Server Express LocalDB is not installed") +} + +// compareVersions compares dotted numeric version strings such as "15.0" and "16.0" +func compareVersions(a, b string) int { + aParts := strings.Split(a, ".") + bParts := strings.Split(b, ".") + for i := 0; i < len(aParts) || i < len(bParts); i++ { + var x, y int + if i < len(aParts) { + x, _ = strconv.Atoi(aParts[i]) + } + if i < len(bParts) { + y, _ = strconv.Atoi(bParts[i]) + } + if x != y { + return x - y + } + } + return 0 +} + +// localDBErrorMessage returns the LocalDB API's description of hr +func localDBErrorMessage(dll *windows.DLL, hr uintptr) string { + fallback := "HRESULT 0x" + strconv.FormatUint(uint64(uint32(hr)), 16) + format, err := dll.FindProc("LocalDBFormatMessage") + if err != nil { + return fallback + } + buf := make([]uint16, localDBMaxErrorMessageSize) + size := uint32(len(buf)) + ret, _, _ := format.Call( + hr, + localDBTruncateErrMessage, + 0, + uintptr(unsafe.Pointer(&buf[0])), + uintptr(unsafe.Pointer(&size))) + if int32(ret) < 0 { + return fallback + } + return strings.TrimSpace(windows.UTF16ToString(buf)) +} diff --git a/pkg/sqlcmd/localdb_windows_test.go b/pkg/sqlcmd/localdb_windows_test.go new file mode 100644 index 00000000..60160fe9 --- /dev/null +++ b/pkg/sqlcmd/localdb_windows_test.go @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +package sqlcmd + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestResolveLocalDBPipe(t *testing.T) { + if _, err := localDBInstanceAPIPath(); err != nil { + t.Skip("LocalDB is not installed") + } + pipeName, err := resolveLocalDBPipe("") + if assert.NoError(t, err) { + assert.True(t, strings.HasPrefix(pipeName, `\\.\pipe\LOCALDB#`), "unexpected pipe name %s", pipeName) + } + _, err = resolveLocalDBPipe("no_such_instance_for_sqlcmd_tests") + assert.Error(t, err, "starting a nonexistent instance should fail") +} + +func TestCompareVersions(t *testing.T) { + assert.Greater(t, compareVersions("16.0", "15.0"), 0) + assert.Greater(t, compareVersions("110.0", "16.0"), 0) + assert.Less(t, compareVersions("13.0", "13.1"), 0) + assert.Equal(t, 0, compareVersions("15.0", "15.0")) +} diff --git a/pkg/sqlcmd/util.go b/pkg/sqlcmd/util.go index aa2932b9..597aefbd 100644 --- a/pkg/sqlcmd/util.go +++ b/pkg/sqlcmd/util.go @@ -33,6 +33,10 @@ func splitServer(serverName string) (string, instance string, port uint64, proto return "", "", 0, "", &InvalidServerName } protocol = "np" + } else if isLocalDB(serverName) { + // (localdb)\instance or (localdb)\.\sharedinstance; resolved to a named pipe at connect time + instance = strings.TrimPrefix(serverName[len(localDBServerName):], `\`) + serverName = serverName[:len(localDBServerName)] } else { serverNameParts := strings.Split(serverName, ",") if len(serverNameParts) > 2 { From a5ee119c60345fb324345718e01ae464cfeed1a3 Mon Sep 17 00:00:00 2001 From: Arthur Stankevich Date: Wed, 14 Oct 2026 12:14:00 +0200 Subject: [PATCH 2/2] fix: reject DAC for LocalDB and localize unsupported-platform error -A with a (localdb) server produced a LocalDB pipe with protocol=admin; it now returns InvalidServerName like other non-named-pipe protocols. The non-Windows "LocalDB is only supported on Windows" message lived in a !windows file, so catalog extraction on Windows never saw it. The stub now returns errors.ErrUnsupported and the shared resolver produces the localized message. --- internal/translations/catalog.go | 90 ++++++++++--------- .../locales/de-DE/out.gotext.json | 5 ++ .../locales/en-US/out.gotext.json | 7 ++ .../locales/es-ES/out.gotext.json | 5 ++ .../locales/fr-FR/out.gotext.json | 5 ++ .../locales/it-IT/out.gotext.json | 5 ++ .../locales/ja-JP/out.gotext.json | 5 ++ .../locales/ko-KR/out.gotext.json | 5 ++ .../locales/pt-BR/out.gotext.json | 5 ++ .../locales/ru-RU/out.gotext.json | 5 ++ .../locales/zh-CN/out.gotext.json | 5 ++ .../locales/zh-TW/out.gotext.json | 5 ++ pkg/sqlcmd/connect.go | 2 +- pkg/sqlcmd/localdb.go | 10 ++- pkg/sqlcmd/localdb_other.go | 4 +- pkg/sqlcmd/localdb_other_test.go | 17 ++++ pkg/sqlcmd/localdb_test.go | 18 +++- 17 files changed, 149 insertions(+), 49 deletions(-) create mode 100644 pkg/sqlcmd/localdb_other_test.go diff --git a/internal/translations/catalog.go b/internal/translations/catalog.go index 3f7ab703..148dc435 100644 --- a/internal/translations/catalog.go +++ b/internal/translations/catalog.go @@ -203,6 +203,7 @@ var messageKeyToIndex = map[string]int{ "List all the users in your sqlconfig file": 143, "List connection strings for all client drivers": 103, "List tags": 213, + "LocalDB is only supported on Windows": 308, "Minimum number of numeric characters": 166, "Minimum number of special characters": 165, "Minimum number of upper characters": 167, @@ -250,10 +251,10 @@ var messageKeyToIndex = map[string]int{ "Run a query": 12, "Run a query against the current context": 11, "Run a query using [%s] database": 13, - "SQL Server Express LocalDB is not installed": 310, + "SQL Server Express LocalDB is not installed": 311, "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": 311, + "Server name override is not supported with the current authentication method": 312, "Servers:": 222, "Set new default database": 14, "Set the current context": 149, @@ -320,8 +321,8 @@ var messageKeyToIndex = map[string]int{ "Unable to continue, a user (non-system) database (%s) is present": 49, "Unable to download file": 205, "Unable to download image %s": 203, - "Unable to load the LocalDB instance API %s: %v": 308, - "Unable to start LocalDB instance %s: %s": 309, + "Unable to load the LocalDB instance API %s: %v": 309, + "Unable to start LocalDB instance %s: %s": 310, "Uninstall/Delete the current context": 28, "Uninstall/Delete the current context, no user prompt": 29, "Uninstall/Delete the current context, no user prompt and override safety check for user databases": 30, @@ -362,7 +363,7 @@ var messageKeyToIndex = map[string]int{ "sqlcmd: Install/Create/Query SQL Server, Azure SQL, and Tools": 285, } -var de_DEIndex = []uint32{ // 313 elements +var de_DEIndex = []uint32{ // 314 elements // Entry 0 - 1F 0x00000000, 0x0000003c, 0x0000007e, 0x00000096, 0x000000d1, 0x000000e9, 0x000000fd, 0x00000148, @@ -451,8 +452,8 @@ var de_DEIndex = []uint32{ // 313 elements 0x00004d83, 0x00004d9c, 0x00004dc2, 0x00004de2, 0x00004de2, 0x00004de2, 0x00004de2, 0x00004de2, 0x00004de2, 0x00004de2, 0x00004de2, 0x00004de2, - 0x00004de2, -} // Size: 1276 bytes + 0x00004de2, 0x00004de2, +} // Size: 1280 bytes const de_DEData string = "" + // Size: 19938 bytes "\x02SQL Server installieren/erstellen, abfragen, deinstallieren\x02Konfi" + @@ -745,7 +746,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{ // 313 elements +var en_USIndex = []uint32{ // 314 elements // Entry 0 - 1F 0x00000000, 0x0000002c, 0x00000062, 0x0000007a, 0x000000b3, 0x000000cb, 0x000000de, 0x00000113, @@ -833,11 +834,11 @@ var en_USIndex = []uint32{ // 313 elements 0x00003ca5, 0x00003cfb, 0x00003d40, 0x00003d4a, 0x00003d5b, 0x00003d71, 0x00003d93, 0x00003db0, 0x00003e0a, 0x00003eba, 0x00003fb5, 0x00004034, - 0x0000406a, 0x0000409f, 0x000040cd, 0x000040f9, - 0x00004146, -} // Size: 1276 bytes + 0x0000406a, 0x0000408f, 0x000040c4, 0x000040f2, + 0x0000411e, 0x0000416b, +} // Size: 1280 bytes -const en_USData string = "" + // Size: 16710 bytes +const en_USData string = "" + // Size: 16747 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.)" + @@ -1082,12 +1083,13 @@ const en_USData string = "" + // Size: 16710 bytes " 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\x02Unable to load the LocalDB" + - " instance API %[1]s: %[2]v\x02Unable to start LocalDB instance %[1]s: %[" + - "2]s\x02SQL Server Express LocalDB is not installed\x02Server name overri" + - "de is not supported with the current authentication method" + "\x22mssql: \x22 prefix from error messages\x02LocalDB is only supported " + + "on Windows\x02Unable to load the LocalDB instance API %[1]s: %[2]v\x02Un" + + "able to start LocalDB instance %[1]s: %[2]s\x02SQL Server Express LocalD" + + "B is not installed\x02Server name override is not supported with the cur" + + "rent authentication method" -var es_ESIndex = []uint32{ // 313 elements +var es_ESIndex = []uint32{ // 314 elements // Entry 0 - 1F 0x00000000, 0x00000032, 0x00000081, 0x0000009c, 0x000000ec, 0x0000010d, 0x00000127, 0x0000017f, @@ -1176,8 +1178,8 @@ var es_ESIndex = []uint32{ // 313 elements 0x00004d3c, 0x00004d54, 0x00004d7f, 0x00004da2, 0x00004da2, 0x00004da2, 0x00004da2, 0x00004da2, 0x00004da2, 0x00004da2, 0x00004da2, 0x00004da2, - 0x00004da2, -} // Size: 1276 bytes + 0x00004da2, 0x00004da2, +} // Size: 1280 bytes const es_ESData string = "" + // Size: 19874 bytes "\x02Instalar/Crear, Consultar, Desinstalar SQL Server\x02Visualización d" + @@ -1471,7 +1473,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{ // 313 elements +var fr_FRIndex = []uint32{ // 314 elements // Entry 0 - 1F 0x00000000, 0x00000037, 0x0000007f, 0x0000009d, 0x000000e1, 0x000000fe, 0x00000117, 0x00000169, @@ -1560,8 +1562,8 @@ var fr_FRIndex = []uint32{ // 313 elements 0x0000507e, 0x00005098, 0x000050bf, 0x000050e1, 0x000050e1, 0x000050e1, 0x000050e1, 0x000050e1, 0x000050e1, 0x000050e1, 0x000050e1, 0x000050e1, - 0x000050e1, -} // Size: 1276 bytes + 0x000050e1, 0x000050e1, +} // Size: 1280 bytes const fr_FRData string = "" + // Size: 20705 bytes "\x02Installer/créer, interroger, désinstaller SQL Server\x02Afficher les" + @@ -1865,7 +1867,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{ // 313 elements +var it_ITIndex = []uint32{ // 314 elements // Entry 0 - 1F 0x00000000, 0x0000003c, 0x00000088, 0x000000a0, 0x000000f7, 0x00000114, 0x0000012b, 0x0000016a, @@ -1954,8 +1956,8 @@ var it_ITIndex = []uint32{ // 313 elements 0x00004ae0, 0x00004afa, 0x00004b2a, 0x00004b52, 0x00004b52, 0x00004b52, 0x00004b52, 0x00004b52, 0x00004b52, 0x00004b52, 0x00004b52, 0x00004b52, - 0x00004b52, -} // Size: 1276 bytes + 0x00004b52, 0x00004b52, +} // Size: 1280 bytes const it_ITData string = "" + // Size: 19282 bytes "\x02Installare/creare, eseguire query, disinstallare SQL Server\x02Visua" + @@ -2241,7 +2243,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{ // 313 elements +var ja_JPIndex = []uint32{ // 314 elements // Entry 0 - 1F 0x00000000, 0x0000004f, 0x00000077, 0x0000009d, 0x000000d8, 0x000000f8, 0x0000010b, 0x0000014c, @@ -2330,8 +2332,8 @@ var ja_JPIndex = []uint32{ // 313 elements 0x00005e0c, 0x00005e30, 0x00005e56, 0x00005e79, 0x00005e79, 0x00005e79, 0x00005e79, 0x00005e79, 0x00005e79, 0x00005e79, 0x00005e79, 0x00005e79, - 0x00005e79, -} // Size: 1276 bytes + 0x00005e79, 0x00005e79, +} // Size: 1280 bytes const ja_JPData string = "" + // Size: 24185 bytes "\x02インストール/作成、クエリ、SQL Server のアンインストール\x02構成情報と接続文字列の表示\x04\x02\x0a\x0a" + @@ -2496,7 +2498,7 @@ const ja_JPData string = "" + // Size: 24185 bytes "\x02パスワード:\x02(1 行が影響を受けます)\x02(%[1]d 行が影響を受けます)\x02変数識別子 %[1]s が無効です" + "\x02変数値の %[1]s が無効です" -var ko_KRIndex = []uint32{ // 313 elements +var ko_KRIndex = []uint32{ // 314 elements // Entry 0 - 1F 0x00000000, 0x00000029, 0x00000053, 0x0000006c, 0x000000b8, 0x000000d0, 0x000000de, 0x00000121, @@ -2585,8 +2587,8 @@ var ko_KRIndex = []uint32{ // 313 elements 0x00004d8e, 0x00004dae, 0x00004dcf, 0x00004dea, 0x00004dea, 0x00004dea, 0x00004dea, 0x00004dea, 0x00004dea, 0x00004dea, 0x00004dea, 0x00004dea, - 0x00004dea, -} // Size: 1276 bytes + 0x00004dea, 0x00004dea, +} // Size: 1280 bytes const ko_KRData string = "" + // Size: 19946 bytes "\x02SQL Server 설치/생성, 쿼리, 제거\x02구성 정보 및 연결 문자열 보기\x04\x02\x0a\x0a\x00" + @@ -2743,7 +2745,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{ // 313 elements +var pt_BRIndex = []uint32{ // 314 elements // Entry 0 - 1F 0x00000000, 0x00000034, 0x00000071, 0x0000008d, 0x000000e3, 0x00000103, 0x0000011e, 0x0000016d, @@ -2832,8 +2834,8 @@ var pt_BRIndex = []uint32{ // 313 elements 0x000049e1, 0x000049f9, 0x00004a24, 0x00004a47, 0x00004a47, 0x00004a47, 0x00004a47, 0x00004a47, 0x00004a47, 0x00004a47, 0x00004a47, 0x00004a47, - 0x00004a47, -} // Size: 1276 bytes + 0x00004a47, 0x00004a47, +} // Size: 1280 bytes const pt_BRData string = "" + // Size: 19015 bytes "\x02Instalar/Criar, Consultar, Desinstalar o SQL Server\x02Exibir inform" + @@ -3113,7 +3115,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{ // 313 elements +var ru_RUIndex = []uint32{ // 314 elements // Entry 0 - 1F 0x00000000, 0x00000056, 0x000000c1, 0x000000ec, 0x00000151, 0x00000172, 0x00000195, 0x0000023b, @@ -3202,8 +3204,8 @@ var ru_RUIndex = []uint32{ // 313 elements 0x00007f7d, 0x00007fa4, 0x00007ff3, 0x00008038, 0x00008038, 0x00008038, 0x00008038, 0x00008038, 0x00008038, 0x00008038, 0x00008038, 0x00008038, - 0x00008038, -} // Size: 1276 bytes + 0x00008038, 0x00008038, +} // Size: 1280 bytes const ru_RUData string = "" + // Size: 32824 bytes "\x02Установка или создание, запрос, удаление SQL Server\x02Просмотреть с" + @@ -3492,7 +3494,7 @@ const ru_RUData string = "" + // Size: 32824 bytes "идентификатор переменной %[1]s\x02Недопустимое значение переменной %[1]" + "s" -var zh_CNIndex = []uint32{ // 313 elements +var zh_CNIndex = []uint32{ // 314 elements // Entry 0 - 1F 0x00000000, 0x0000002b, 0x00000050, 0x00000065, 0x00000096, 0x000000ab, 0x000000b8, 0x000000fc, @@ -3581,8 +3583,8 @@ var zh_CNIndex = []uint32{ // 313 elements 0x000038c7, 0x000038dc, 0x000038f9, 0x00003910, 0x00003910, 0x00003910, 0x00003910, 0x00003910, 0x00003910, 0x00003910, 0x00003910, 0x00003910, - 0x00003910, -} // Size: 1276 bytes + 0x00003910, 0x00003910, +} // Size: 1280 bytes const zh_CNData string = "" + // Size: 14608 bytes "\x02安装/创建、查询、卸载 SQL Server\x02查看配置信息和连接字符串\x04\x02\x0a\x0a\x00\x0f\x02反馈" + @@ -3703,7 +3705,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{ // 313 elements +var zh_TWIndex = []uint32{ // 314 elements // Entry 0 - 1F 0x00000000, 0x00000031, 0x00000053, 0x0000006e, 0x000000a1, 0x000000b8, 0x000000c2, 0x00000106, @@ -3792,8 +3794,8 @@ var zh_TWIndex = []uint32{ // 313 elements 0x00003924, 0x00003942, 0x00003961, 0x00003978, 0x00003978, 0x00003978, 0x00003978, 0x00003978, 0x00003978, 0x00003978, 0x00003978, 0x00003978, - 0x00003978, -} // Size: 1276 bytes + 0x00003978, 0x00003978, +} // Size: 1280 bytes const zh_TWData string = "" + // Size: 14712 bytes "\x02安裝/建立、查詢、解除安裝 SQL Server\x02檢視組態資訊和連接字串\x04\x02\x0a\x0a\x00\x15\x02意" + @@ -3912,4 +3914,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 235835 bytes (230KiB); checksum: 144F38D1 + // Total table size 235916 bytes (230KiB); checksum: 6594D58E diff --git a/internal/translations/locales/de-DE/out.gotext.json b/internal/translations/locales/de-DE/out.gotext.json index d22e7f56..7adca2c0 100644 --- a/internal/translations/locales/de-DE/out.gotext.json +++ b/internal/translations/locales/de-DE/out.gotext.json @@ -3683,6 +3683,11 @@ ], "fuzzy": true }, + { + "id": "LocalDB is only supported on Windows", + "message": "LocalDB is only supported on Windows", + "translation": "" + }, { "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", diff --git a/internal/translations/locales/en-US/out.gotext.json b/internal/translations/locales/en-US/out.gotext.json index c3096d22..ac024a30 100644 --- a/internal/translations/locales/en-US/out.gotext.json +++ b/internal/translations/locales/en-US/out.gotext.json @@ -3693,6 +3693,13 @@ ], "fuzzy": true }, + { + "id": "LocalDB is only supported on Windows", + "message": "LocalDB is only supported on Windows", + "translation": "LocalDB is only supported on Windows", + "translatorComment": "Copied from source.", + "fuzzy": true + }, { "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", diff --git a/internal/translations/locales/es-ES/out.gotext.json b/internal/translations/locales/es-ES/out.gotext.json index 7d44f5d8..4e74e1d7 100644 --- a/internal/translations/locales/es-ES/out.gotext.json +++ b/internal/translations/locales/es-ES/out.gotext.json @@ -3683,6 +3683,11 @@ ], "fuzzy": true }, + { + "id": "LocalDB is only supported on Windows", + "message": "LocalDB is only supported on Windows", + "translation": "" + }, { "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", diff --git a/internal/translations/locales/fr-FR/out.gotext.json b/internal/translations/locales/fr-FR/out.gotext.json index 303aab9c..219719c8 100644 --- a/internal/translations/locales/fr-FR/out.gotext.json +++ b/internal/translations/locales/fr-FR/out.gotext.json @@ -3683,6 +3683,11 @@ ], "fuzzy": true }, + { + "id": "LocalDB is only supported on Windows", + "message": "LocalDB is only supported on Windows", + "translation": "" + }, { "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", diff --git a/internal/translations/locales/it-IT/out.gotext.json b/internal/translations/locales/it-IT/out.gotext.json index 74fc460f..cf6b7404 100644 --- a/internal/translations/locales/it-IT/out.gotext.json +++ b/internal/translations/locales/it-IT/out.gotext.json @@ -3683,6 +3683,11 @@ ], "fuzzy": true }, + { + "id": "LocalDB is only supported on Windows", + "message": "LocalDB is only supported on Windows", + "translation": "" + }, { "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", diff --git a/internal/translations/locales/ja-JP/out.gotext.json b/internal/translations/locales/ja-JP/out.gotext.json index 45186a44..77348992 100644 --- a/internal/translations/locales/ja-JP/out.gotext.json +++ b/internal/translations/locales/ja-JP/out.gotext.json @@ -3683,6 +3683,11 @@ ], "fuzzy": true }, + { + "id": "LocalDB is only supported on Windows", + "message": "LocalDB is only supported on Windows", + "translation": "" + }, { "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", diff --git a/internal/translations/locales/ko-KR/out.gotext.json b/internal/translations/locales/ko-KR/out.gotext.json index 4b0cdd98..be7beaea 100644 --- a/internal/translations/locales/ko-KR/out.gotext.json +++ b/internal/translations/locales/ko-KR/out.gotext.json @@ -3683,6 +3683,11 @@ ], "fuzzy": true }, + { + "id": "LocalDB is only supported on Windows", + "message": "LocalDB is only supported on Windows", + "translation": "" + }, { "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", diff --git a/internal/translations/locales/pt-BR/out.gotext.json b/internal/translations/locales/pt-BR/out.gotext.json index 1822bc72..1c7d7e7c 100644 --- a/internal/translations/locales/pt-BR/out.gotext.json +++ b/internal/translations/locales/pt-BR/out.gotext.json @@ -3683,6 +3683,11 @@ ], "fuzzy": true }, + { + "id": "LocalDB is only supported on Windows", + "message": "LocalDB is only supported on Windows", + "translation": "" + }, { "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", diff --git a/internal/translations/locales/ru-RU/out.gotext.json b/internal/translations/locales/ru-RU/out.gotext.json index d3c028ec..2597cb32 100644 --- a/internal/translations/locales/ru-RU/out.gotext.json +++ b/internal/translations/locales/ru-RU/out.gotext.json @@ -3683,6 +3683,11 @@ ], "fuzzy": true }, + { + "id": "LocalDB is only supported on Windows", + "message": "LocalDB is only supported on Windows", + "translation": "" + }, { "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", diff --git a/internal/translations/locales/zh-CN/out.gotext.json b/internal/translations/locales/zh-CN/out.gotext.json index 6812bdaf..cb52a6bd 100644 --- a/internal/translations/locales/zh-CN/out.gotext.json +++ b/internal/translations/locales/zh-CN/out.gotext.json @@ -3683,6 +3683,11 @@ ], "fuzzy": true }, + { + "id": "LocalDB is only supported on Windows", + "message": "LocalDB is only supported on Windows", + "translation": "" + }, { "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", diff --git a/internal/translations/locales/zh-TW/out.gotext.json b/internal/translations/locales/zh-TW/out.gotext.json index 4fa2d458..0dbfb2a0 100644 --- a/internal/translations/locales/zh-TW/out.gotext.json +++ b/internal/translations/locales/zh-TW/out.gotext.json @@ -3683,6 +3683,11 @@ ], "fuzzy": true }, + { + "id": "LocalDB is only supported on Windows", + "message": "LocalDB is only supported on Windows", + "translation": "" + }, { "id": "Unable to load the LocalDB instance API {ApiPath}: {Err}", "message": "Unable to load the LocalDB instance API {ApiPath}: {Err}", diff --git a/pkg/sqlcmd/connect.go b/pkg/sqlcmd/connect.go index c1965bcc..77541daf 100644 --- a/pkg/sqlcmd/connect.go +++ b/pkg/sqlcmd/connect.go @@ -106,7 +106,7 @@ func (connect ConnectSettings) ConnectionString() (connectionString string, err } if isLocalDB(serverName) { - if protocol != "" && protocol != "np" { + if protocol != "" && protocol != "np" || connect.DedicatedAdminConnection { return "", &InvalidServerName } pipeName, err := resolveLocalDBPipe(instance) diff --git a/pkg/sqlcmd/localdb.go b/pkg/sqlcmd/localdb.go index ac737a56..43b38208 100644 --- a/pkg/sqlcmd/localdb.go +++ b/pkg/sqlcmd/localdb.go @@ -3,7 +3,12 @@ package sqlcmd -import "strings" +import ( + "errors" + "strings" + + "github.com/microsoft/go-sqlcmd/internal/localizer" +) // localDBServerName is the pseudo server name used to address SQL Server Express LocalDB instances const localDBServerName = "(localdb)" @@ -26,5 +31,8 @@ var resolveLocalDBPipe = func(instance string) (string, error) { instance = defaultLocalDBInstance } pipeName, err := startLocalDBInstance(instance) + if errors.Is(err, errors.ErrUnsupported) { + return "", localizer.Errorf("LocalDB is only supported on Windows") + } return strings.TrimPrefix(pipeName, "np:"), err } diff --git a/pkg/sqlcmd/localdb_other.go b/pkg/sqlcmd/localdb_other.go index 5b0fc6de..78af7e9f 100644 --- a/pkg/sqlcmd/localdb_other.go +++ b/pkg/sqlcmd/localdb_other.go @@ -5,8 +5,8 @@ package sqlcmd -import "github.com/microsoft/go-sqlcmd/internal/localizer" +import "errors" func startLocalDBInstance(instance string) (string, error) { - return "", localizer.Errorf("LocalDB is only supported on Windows") + return "", errors.ErrUnsupported } diff --git a/pkg/sqlcmd/localdb_other_test.go b/pkg/sqlcmd/localdb_other_test.go new file mode 100644 index 00000000..08827bff --- /dev/null +++ b/pkg/sqlcmd/localdb_other_test.go @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +//go:build !windows + +package sqlcmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestResolveLocalDBPipeIsUnsupported(t *testing.T) { + _, err := resolveLocalDBPipe("MSSQLLocalDB") + assert.EqualError(t, err, "LocalDB is only supported on Windows") +} diff --git a/pkg/sqlcmd/localdb_test.go b/pkg/sqlcmd/localdb_test.go index 5f2db87a..63b92635 100644 --- a/pkg/sqlcmd/localdb_test.go +++ b/pkg/sqlcmd/localdb_test.go @@ -4,6 +4,7 @@ package sqlcmd import ( + "runtime" "testing" "github.com/stretchr/testify/assert" @@ -27,7 +28,6 @@ func TestSplitServerLocalDB(t *testing.T) { }{ {`(localdb)\MSSQLLocalDB`, `(localdb)`, `MSSQLLocalDB`, ``}, {`(LocalDb)\.\shared`, `(LocalDb)`, `.\shared`, ``}, - {`np:(localdb)\myinstance`, `(localdb)`, `myinstance`, `np`}, {`(localdb)`, `(localdb)`, ``, ``}, } for _, test := range tests { @@ -41,6 +41,18 @@ func TestSplitServerLocalDB(t *testing.T) { } } +func TestSplitServerLocalDBWithNamedPipePrefix(t *testing.T) { + if runtime.GOOS != "windows" || runtime.GOARCH != "amd64" { + t.Skip("The np protocol is only registered on Windows amd64") + } + serverName, instance, _, protocol, err := splitServer(`np:(localdb)\myinstance`) + if assert.NoError(t, err) { + assert.Equal(t, `(localdb)`, serverName) + assert.Equal(t, `myinstance`, instance) + assert.Equal(t, `np`, protocol) + } +} + func TestConnectionStringLocalDB(t *testing.T) { original := resolveLocalDBPipe defer func() { resolveLocalDBPipe = original }() @@ -60,4 +72,8 @@ func TestConnectionStringLocalDB(t *testing.T) { settings = ConnectSettings{ServerName: `tcp:(localdb)\MSSQLLocalDB`} _, err = settings.ConnectionString() assert.Error(t, err, "LocalDB only supports named pipes") + + settings = ConnectSettings{ServerName: `(localdb)\MSSQLLocalDB`, DedicatedAdminConnection: true} + _, err = settings.ConnectionString() + assert.Error(t, err, "LocalDB does not support the dedicated admin connection") }