60 lines
1.5 KiB
Go
60 lines
1.5 KiB
Go
package jdbc
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
mssql "github.com/denisenkom/go-mssqldb"
|
|
"strings"
|
|
)
|
|
|
|
type sqlServerJDBC struct {
|
|
conn string
|
|
params map[string]string
|
|
}
|
|
|
|
func (s *sqlServerJDBC) ping(ctx context.Context) pingResult {
|
|
return ping(ctx, "mssql", isSqlServerErrorDeterminate,
|
|
joinKeyValues(s.params, ";"),
|
|
s.conn,
|
|
"sqlserver://"+s.conn)
|
|
}
|
|
|
|
func isSqlServerErrorDeterminate(err error) bool {
|
|
// Error numbers from https://learn.microsoft.com/en-us/sql/relational-databases/errors-events/database-engine-events-and-errors?view=sql-server-ver16
|
|
if mssqlError, isMssqlError := err.(mssql.Error); isMssqlError {
|
|
switch mssqlError.Number {
|
|
case 18456:
|
|
// Login failed
|
|
// This is a determinate failure iff we tried to use a real user
|
|
return mssqlError.Message != "login error: Login failed for user ''."
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func parseSqlServer(subname string) (jdbc, error) {
|
|
if !strings.HasPrefix(subname, "//") {
|
|
return nil, errors.New("expected connection to start with //")
|
|
}
|
|
conn := strings.TrimPrefix(subname, "//")
|
|
params := map[string]string{
|
|
"user id": "sa",
|
|
"database": "master",
|
|
}
|
|
for _, param := range strings.Split(conn, ";") {
|
|
key, value, found := strings.Cut(param, "=")
|
|
if !found {
|
|
continue
|
|
}
|
|
params[key] = value
|
|
if key != "password" && strings.Contains(strings.ToLower(key), "password") {
|
|
params["password"] = value
|
|
}
|
|
}
|
|
return &sqlServerJDBC{
|
|
conn: strings.TrimPrefix(subname, "//"),
|
|
params: params,
|
|
}, nil
|
|
}
|