Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ linux-s390x/sqlcmd
# Build artifacts in root
/sqlcmd
/sqlcmd_binary
/modern

# certificates used for local testing
*.der
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ The Homebrew package manager may be used on Linux and Windows Subsystem for Linu

Use `sqlcmd` to create SQL Server and Azure SQL Edge instances using a local container runtime (e.g. [Docker][] or [Podman][])

### Create SQL Server instance using local container runtime and connect using Azure Data Studio
### Create SQL Server instance using local container runtime and connect using Visual Studio Code

To create a local SQL Server instance with the AdventureWorksLT database restored, query it, and connect to it using Azure Data Studio, run:
To create a local SQL Server instance with the AdventureWorksLT database restored, query it, and connect to it using Visual Studio Code with the MSSQL extension, run:

```
sqlcmd create mssql --accept-eula --using https://aka.ms/AdventureWorksLT.bak
sqlcmd query "SELECT DB_NAME()"
sqlcmd open ads
sqlcmd open vscode
```

Use `sqlcmd --help` to view all the available sub-commands. Use `sqlcmd -?` to view the original ODBC `sqlcmd` flags.
Expand Down
6 changes: 4 additions & 2 deletions cmd/modern/root/open.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,21 @@ type Open struct {
func (c *Open) DefineCommand(...cmdparser.CommandOptions) {
options := cmdparser.CommandOptions{
Use: "open",
Short: localizer.Sprintf("Open tools (e.g Azure Data Studio) for current context"),
Short: localizer.Sprintf("Open tools (e.g Visual Studio Code, SSMS) for current context"),
SubCommands: c.SubCommands(),
}

c.Cmd.DefineCommand(options)
}

// SubCommands sets up the sub-commands for `sqlcmd open` such as
// `sqlcmd open ads`
// `sqlcmd open ads`, `sqlcmd open vscode`, and `sqlcmd open ssms`
func (c *Open) SubCommands() []cmdparser.Command {
dependencies := c.Dependencies()

return []cmdparser.Command{
cmdparser.New[*open.Ads](dependencies),
cmdparser.New[*open.VSCode](dependencies),
cmdparser.New[*open.Ssms](dependencies),
}
}
95 changes: 95 additions & 0 deletions cmd/modern/root/open/ssms.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package open

import (
"fmt"
"runtime"
"strings"

"github.com/microsoft/go-sqlcmd/cmd/modern/sqlconfig"
"github.com/microsoft/go-sqlcmd/internal/cmdparser"
"github.com/microsoft/go-sqlcmd/internal/config"
"github.com/microsoft/go-sqlcmd/internal/container"
"github.com/microsoft/go-sqlcmd/internal/localizer"
"github.com/microsoft/go-sqlcmd/internal/tools"
)

// Ssms implements the `sqlcmd open ssms` command. It opens
// SQL Server Management Studio and connects to the current context using the
// credentials specified in the context.
func (c *Ssms) DefineCommand(...cmdparser.CommandOptions) {
options := cmdparser.CommandOptions{
Use: "ssms",
Short: localizer.Sprintf("Open SQL Server Management Studio and connect to current context"),
Examples: []cmdparser.ExampleOptions{{
Description: localizer.Sprintf("Open SSMS and connect using the current context"),
Steps: []string{"sqlcmd open ssms"}}},
Run: c.run,
}

c.Cmd.DefineCommand(options)
}

// Launch SSMS and connect to the current context
func (c *Ssms) run() {
endpoint, user := config.CurrentContext()

// If the context has a local container, ensure it is running, otherwise bail out
if endpoint.ContainerDetails != nil {
c.ensureContainerIsRunning(endpoint)
}

// Launch SSMS with connection parameters
c.launchSsms(endpoint.Address, endpoint.Port, user)
}

func (c *Ssms) ensureContainerIsRunning(endpoint sqlconfig.Endpoint) {
output := c.Output()
controller := container.NewController()
if !controller.ContainerRunning(endpoint.Id) {
output.FatalWithHintExamples([][]string{
{localizer.Sprintf("To start the container"), localizer.Sprintf("sqlcmd start")},
}, localizer.Sprintf("Container is not running"))
}
}

// launchSsms launches SQL Server Management Studio using the specified server and user credentials.
func (c *Ssms) launchSsms(host string, port int, user *sqlconfig.User) {
output := c.Output()

// Build server connection string
serverArg := fmt.Sprintf("%s,%d", host, port)

args := []string{
"-S", serverArg,
"-nosplash",
}

// Add authentication parameters
if user != nil && user.AuthenticationType == "basic" {
// SQL Server authentication
// Escape double quotes in username (SQL Server allows " in login names)
username := strings.ReplaceAll(user.BasicAuth.Username, `"`, `\"`)
args = append(args, "-U", username)
// Note: -P parameter was removed in SSMS 18+ for security reasons
// User will need to enter password in the login dialog
output.Info(localizer.Sprintf("Note: You will need to enter the password in the SSMS login dialog"))
} else {
// Windows integrated authentication
if runtime.GOOS == "windows" {
args = append(args, "-E")
}
}

tool := tools.NewTool("ssms")
if !tool.IsInstalled() {
output.Fatal(tool.HowToInstall())
}

c.displayPreLaunchInfo()

_, err := tool.Run(args)
c.CheckErr(err)
}
22 changes: 22 additions & 0 deletions cmd/modern/root/open/ssms_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package open

import (
"github.com/microsoft/go-sqlcmd/internal/cmdparser"
"github.com/microsoft/go-sqlcmd/internal/localizer"
)

// Type Ssms is used to implement the "open ssms" which launches SQL Server
// Management Studio and establishes a connection to the SQL Server for the current
// context
type Ssms struct {
cmdparser.Cmd
}

func (c *Ssms) displayPreLaunchInfo() {
output := c.Output()
output.Info(localizer.Sprintf("SSMS is only available on Windows"))
output.Info(localizer.Sprintf("Please use 'sqlcmd open vscode' or 'sqlcmd open ads' instead"))
}
22 changes: 22 additions & 0 deletions cmd/modern/root/open/ssms_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package open

import (
"github.com/microsoft/go-sqlcmd/internal/cmdparser"
"github.com/microsoft/go-sqlcmd/internal/localizer"
)

// Type Ssms is used to implement the "open ssms" which launches SQL Server
// Management Studio and establishes a connection to the SQL Server for the current
// context
type Ssms struct {
cmdparser.Cmd
}

func (c *Ssms) displayPreLaunchInfo() {
output := c.Output()
output.Info(localizer.Sprintf("SSMS is only available on Windows"))
output.Info(localizer.Sprintf("Please use 'sqlcmd open vscode' or 'sqlcmd open ads' instead"))
}
36 changes: 36 additions & 0 deletions cmd/modern/root/open/ssms_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package open

import (
"github.com/microsoft/go-sqlcmd/cmd/modern/sqlconfig"
"github.com/microsoft/go-sqlcmd/internal/cmdparser"
"github.com/microsoft/go-sqlcmd/internal/config"
"runtime"
"testing"
)

// TestSsms runs a sanity test of `sqlcmd open ssms`
func TestSsms(t *testing.T) {
if runtime.GOOS != "windows" {
t.Skip("SSMS is only available on Windows")
}

cmdparser.TestSetup(t)
config.AddEndpoint(sqlconfig.Endpoint{
AssetDetails: nil,
EndpointDetails: sqlconfig.EndpointDetails{},
Name: "endpoint",
})
config.AddContext(sqlconfig.Context{
ContextDetails: sqlconfig.ContextDetails{
Endpoint: "endpoint",
User: nil,
},
Name: "context",
})
config.SetCurrentContextName("context")

cmdparser.TestCmd[*Ssms]()
}
22 changes: 22 additions & 0 deletions cmd/modern/root/open/ssms_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package open

import (
"github.com/microsoft/go-sqlcmd/internal/cmdparser"
"github.com/microsoft/go-sqlcmd/internal/localizer"
)

// Type Ssms is used to implement the "open ssms" which launches SQL Server
// Management Studio and establishes a connection to the SQL Server for the current
// context
type Ssms struct {
cmdparser.Cmd
}

// On Windows, display info before launching
func (c *Ssms) displayPreLaunchInfo() {
output := c.Output()
output.Info(localizer.Sprintf("Launching SQL Server Management Studio..."))
}
Loading
Loading