Skip to content

Commit ada30cb

Browse files
authored
Fix named pipe path handling to preserve "." (#178)
* Fix:Enable connection to WID
1 parent 80b58f2 commit ada30cb

File tree

2 files changed

+76
-6
lines changed

2 files changed

+76
-6
lines changed

namedpipe/namedpipe_windows.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,26 +28,34 @@ func (n namedPipeDialer) ParseServer(server string, p *msdsn.Config) error {
2828
if strings.HasPrefix(server, `\\`) {
2929
// assume a server name starting with \\ is the full named pipe path
3030
p.ProtocolParameters[n.Protocol()] = namedPipeData{PipeName: server}
31-
} else if p.Host == "" { // if the string specifies np:host\instance, tcpParser won't have filled in p.Host
31+
return nil
32+
}
33+
pipeHost := "."
34+
if p.Host == "" { // if the string specifies np:host\instance, tcpParser won't have filled in p.Host
3235
parts := strings.SplitN(server, `\`, 2)
33-
p.Host = parts[0]
34-
if p.Host == "." || strings.ToUpper(p.Host) == "(LOCAL)" {
36+
host := parts[0]
37+
if host == "." || strings.ToUpper(host) == "(LOCAL)" {
38+
// localhost replaces . to query the browser service but some SQL instances
39+
// like Windows Internal Database require the . in the pipe name to connect
3540
p.Host = "localhost"
41+
} else {
42+
p.Host = host
43+
pipeHost = host
3644
}
3745
if len(parts) > 1 {
3846
p.Instance = parts[1]
3947
}
4048
} else {
41-
host := strings.ToLower(p.Host)
49+
pipeHost = strings.ToLower(p.Host)
4250
for _, domain := range azureDomains {
43-
if strings.HasSuffix(host, domain) {
51+
if strings.HasSuffix(pipeHost, domain) {
4452
return fmt.Errorf("Named pipes disallowed for Azure SQL Database connections")
4553
}
4654
}
4755
}
4856
pipe, ok := p.Parameters["pipe"]
4957
if ok {
50-
p.ProtocolParameters[n.Protocol()] = namedPipeData{PipeName: fmt.Sprintf(`\\%s\pipe\%s`, p.Host, pipe)}
58+
p.ProtocolParameters[n.Protocol()] = namedPipeData{PipeName: fmt.Sprintf(`\\%s\pipe\%s`, pipeHost, pipe)}
5159
}
5260
return nil
5361
}

namedpipe/namepipe_windows_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package namedpipe
2+
3+
import (
4+
"testing"
5+
6+
"github.com/microsoft/go-mssqldb/msdsn"
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestParseServer(t *testing.T) {
11+
c := &msdsn.Config{
12+
Port: 1000,
13+
}
14+
n := &namedPipeDialer{}
15+
err := n.ParseServer("server", c)
16+
assert.Errorf(t, err, "ParseServer with a Port")
17+
18+
c = &msdsn.Config{
19+
Parameters: make(map[string]string),
20+
ProtocolParameters: make(map[string]interface{}),
21+
}
22+
err = n.ParseServer(`\\.\pipe\MSSQL$Instance\sql\query`, c)
23+
assert.NoError(t, err, "ParseServer with a full pipe name")
24+
assert.Equal(t, "", c.Host, "Config Host with a full pipe name")
25+
data, ok := c.ProtocolParameters[n.Protocol()]
26+
assert.True(t, ok, "Should have added ProtocolParameters when server is pipe name")
27+
switch d := data.(type) {
28+
case namedPipeData:
29+
assert.Equal(t, `\\.\pipe\MSSQL$Instance\sql\query`, d.PipeName, "Pipe name in ProtocolParameters when server is pipe name")
30+
default:
31+
assert.Fail(t, "Incorrect protocol parameters type:", d)
32+
}
33+
34+
c = &msdsn.Config{
35+
Parameters: make(map[string]string),
36+
ProtocolParameters: make(map[string]interface{}),
37+
}
38+
err = n.ParseServer(`.\instance`, c)
39+
assert.NoError(t, err, "ParseServer .")
40+
assert.Equal(t, "localhost", c.Host, `Config Host with server == .\instance`)
41+
assert.Equal(t, "instance", c.Instance, `Config Instance with server == .\instance`)
42+
_, ok = c.ProtocolParameters[n.Protocol()]
43+
assert.Equal(t, ok, false, "Should have no namedPipeData when pipe name omitted")
44+
45+
c = &msdsn.Config{
46+
Host: "server",
47+
Parameters: make(map[string]string),
48+
ProtocolParameters: make(map[string]interface{}),
49+
}
50+
c.Parameters["pipe"] = `myinstance\sql\query`
51+
err = n.ParseServer(`anything`, c)
52+
assert.NoError(t, err, "ParseServer anything")
53+
data, ok = c.ProtocolParameters[n.Protocol()]
54+
assert.True(t, ok, "Should have added ProtocolParameters when pipe name is provided")
55+
switch d := data.(type) {
56+
case namedPipeData:
57+
assert.Equal(t, `\\server\pipe\myinstance\sql\query`, d.PipeName, "Pipe name in ProtocolParameters")
58+
default:
59+
assert.Fail(t, "Incorrect protocol parameters type:", d)
60+
}
61+
62+
}

0 commit comments

Comments
 (0)