Skip to content
Open
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 CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Release History

## Unreleased
- Fix panic in `InitThriftClient` when the endpoint URL is malformed: the thrift transport was type-asserted to `*thrift.THttpClient` before the error from `NewTHttpClientWithOptions` was checked, so a URL that fails to parse (nil transport) caused `interface conversion: thrift.TTransport is nil, not *thrift.THttpClient`; the error is now returned instead (databricks/databricks-sql-go#394)
- Stop using `html/template` in the U2M OAuth callback page. Reachable use of `html/template` disabled the Go linker's dead-code elimination for the entire binary of any application importing this driver; the page is now rendered with plain string building and explicit HTML escaping, restoring full DCE (databricks/databricks-sql-go#343)
- Fix DECIMAL precision loss inside complex types: DECIMAL values nested in STRUCT, ARRAY, and MAP columns are now rendered losslessly with their exact scale (e.g. `19.99` instead of `19.990000000000002`), matching the behavior of top-level DECIMAL columns (databricks/databricks-sql-go#253)

Expand Down
6 changes: 3 additions & 3 deletions internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,16 +317,16 @@ func InitThriftClient(cfg *config.Config, httpclient *http.Client) (*ThriftServi
}

tTrans, err = thrift.NewTHttpClientWithOptions(endpoint, thrift.THttpClientOptions{Client: httpclient})
if err != nil {
return nil, dbsqlerrint.NewRequestError(context.TODO(), dbsqlerr.ErrInvalidURL, err)
}

thriftHttpClient := tTrans.(*thrift.THttpClient)
thriftHttpClient.SetHeader("User-Agent", BuildUserAgent(cfg))

default:
return nil, dbsqlerrint.NewDriverError(context.TODO(), fmt.Sprintf("unsupported transport `%s`", cfg.ThriftTransport), nil)
}
if err != nil {
return nil, dbsqlerrint.NewRequestError(context.TODO(), dbsqlerr.ErrInvalidURL, err)
}
if err = tTrans.Open(); err != nil {
return nil, dbsqlerrint.NewRequestError(context.TODO(), fmt.Sprintf("failed to open http transport for endpoint %s", endpoint), err)
}
Expand Down
29 changes: 29 additions & 0 deletions internal/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"

dbsqlerr "github.com/databricks/databricks-sql-go/errors"
"github.com/databricks/databricks-sql-go/internal/config"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -325,3 +326,31 @@ func TestRetryPolicy(t *testing.T) {
}
})
}

// TestInitThriftClientMalformedEndpointDoesNotPanic is a regression test: when the
// endpoint URL is malformed, thrift.NewTHttpClientWithOptions returns a nil
// TTransport and an error. InitThriftClient previously type-asserted that nil
// transport to *thrift.THttpClient before checking the error, panicking with
// "interface conversion: thrift.TTransport is nil, not *thrift.THttpClient".
// It must now surface the error instead.
func TestInitThriftClientMalformedEndpointDoesNotPanic(t *testing.T) {
cfg := &config.Config{
UserConfig: config.UserConfig{
Protocol: "https",
Host: "example.cloud.databricks.com",
Port: 443,
// A control character passes ToEndpointURL's non-empty check but
// makes url.Parse (inside NewTHttpClientWithOptions) fail.
HTTPPath: "/sql/1.0/warehouses/\x7f",
},
ThriftProtocol: "binary",
ThriftTransport: "http",
}

require.NotPanics(t, func() {
// Non-nil httpclient so we exercise the transport path, not the
// missing-authenticator early return.
_, err := InitThriftClient(cfg, &http.Client{})
require.Error(t, err)
})
}