- name
- databricks-isv-go-sql-driver
- description
- PWAF-compliant Databricks SQL Driver for Go (databricks-sql-go): PAT, OAuth M2M, OAuth U2M (browser + token-env + custom OAuth app PKCE), WithUserAgentEntry. Use when building or testing integrations that run SQL queries via a Databricks SQL warehouse.
<!-- skill-version: 1.0.0 -->
# Databricks SQL Driver for Go (ISV)
Use this skill when implementing or testing **Databricks SQL Driver for Go** (`databricks-sql-go`) integrations for PWAF-compliant SQL query execution via a Databricks SQL warehouse.
## PWAF Documentation Links
| Resource | URL |
|----------|-----|
| **PWAF Home** | https://databrickslabs.github.io/partner-architecture/ |
| **Authentication Best Practices** | https://databrickslabs.github.io/partner-architecture/isv-partners/lakehouse-patterns/access-auth/ |
| **OAuth M2M Guide** | https://databrickslabs.github.io/partner-architecture/isv-partners/lakehouse-patterns/access-auth/oauth-m2m |
| **OAuth U2M Guide** | https://databrickslabs.github.io/partner-architecture/isv-partners/lakehouse-patterns/access-auth/oauth-u2m |
| **User-Agent (SQL Drivers)** | https://databrickslabs.github.io/partner-architecture/isv-partners/telemetry-attribution/sql-drivers |
| **Databricks SQL Driver for Go** | https://docs.databricks.com/aws/en/dev-tools/go-sql-driver |
| **GitHub** | https://github.com/databricks/databricks-sql-go |
## Requirements
- **Driver:** `github.com/databricks/databricks-sql-go` v1.5.2+
- **Go:** 1.20+
- **SQL Warehouse:** Required (`DATABRICKS_HTTP_PATH`)
- **Install:** `go get github.com/databricks/databricks-sql-go@latest`
## Authentication Comparison
| Method | PWAF Status | Auto Token Refresh | Browser Required | Use Case |
|--------|-------------|-------------------|------------------|----------|
| PAT | ⚠️ Limited | No | No | Testing only |
| OAuth M2M | ✅ Recommended | Yes (driver-native) | No | Production/automated |
| U2M Custom OAuth | ✅ Recommended (ISV) | No | Yes | Interactive (custom app) |
| U2M Token-Env | ✅ Supported | No | No | Headless/CI |
**ISV Note:** For user-interactive flows, use **U2M Custom OAuth** with your registered OAuth app (Account Console → App connections). This provides custom branding, audit trails, and scoped permissions. The driver's built-in U2M browser auth uses a generic `databricks-sql-connector` app which is not appropriate for ISV applications.
---
## Host Normalization Helper
The driver's `WithServerHostname` expects a **bare hostname** (no `https://`):
```go
import "strings"
func serverHostname(host string) string {
s := strings.TrimPrefix(host, "https://")
s = strings.TrimPrefix(s, "http://")
if idx := strings.Index(s, "/"); idx >= 0 {
s = s[:idx]
}
return s
}
```
---
## Environment Variables Reference
| Variable | Required For | Description |
|----------|-------------|-------------|
| `DATABRICKS_HOST` | All | Workspace URL (e.g., `https://myworkspace.cloud.databricks.com`) |
| `DATABRICKS_HTTP_PATH` | All | SQL warehouse HTTP path (e.g., `/sql/1.0/warehouses/abc123`) |
| `DATABRICKS_TOKEN` | PAT | Personal access token |
| `DATABRICKS_CLIENT_ID` | OAuth M2M | Service principal UUID |
| `DATABRICKS_CLIENT_SECRET` | OAuth M2M | Service principal OAuth secret |
| `DATABRICKS_U2M_CLIENT_ID` | U2M Custom OAuth | Custom OAuth app client ID from App connections |
| `DATABRICKS_U2M_CLIENT_SECRET` | U2M Custom OAuth (optional) | Custom OAuth app client secret |
| `DATABRICKS_REDIRECT_URI` | U2M Custom OAuth (optional) | Custom redirect URI (default: `http://localhost:8040/callback`) |
| `DATABRICKS_ACCESS_TOKEN` | U2M Token-Env | Pre-obtained OAuth access token |
| `DATABRICKS_AUTH_TYPE` | Multi-auth | Auth type selector: `pat`, `oauth_m2m`, `u2m_browser`, `u2m_custom_oauth`, `u2m_token_env` |
**Important:** Do not mix M2M and U2M environment variables. Use `env -i` for clean test environments.
---
## Complete Examples
### PAT Authentication (Testing Only)
```go
package main
import (
"database/sql"
"fmt"
"os"
"strings"
dbsql "github.com/databricks/databricks-sql-go"
)
func main() {
host := os.Getenv("DATABRICKS_HOST")
httpPath := os.Getenv("DATABRICKS_HTTP_PATH")
token := os.Getenv("DATABRICKS_TOKEN")
connector, err := dbsql.NewConnector(
dbsql.WithServerHostname(serverHostname(host)),
dbsql.WithPort(443),
dbsql.WithHTTPPath(httpPath),
dbsql.WithAccessToken(token),
dbsql.WithUserAgentEntry("YourCompany_YourProduct/1.0.0"),
)
if err != nil {
panic(err)
}
db := sql.OpenDB(connector)
defer db.Close()
rows, err := db.Query("SELECT COUNT(*) FROM samples.nyctaxi.trips")
if err != nil {
panic(err)
}
defer rows.Close()
var count int64
rows.Next()
rows.Scan(&count)
fmt.Printf("PAT OK: %d trips\n", count)
}
func serverHostname(host string) string {
s := strings.TrimPrefix(host, "https://")
s = strings.TrimPrefix(s, "http://")
if idx := strings.Index(s, "/"); idx >= 0 {
s = s[:idx]
}
return s
}
```
**Env vars:** `DATABRICKS_HOST`, `DATABRICKS_HTTP_PATH`, `DATABRICKS_TOKEN`
---
### OAuth M2M Authentication (Production Recommended)
Uses the driver's **built-in M2M authenticator** that handles token fetch and refresh:
```go
package main
import (
"database/sql"
"fmt"
"os"
"strings"
dbsql "github.com/databricks/databricks-sql-go"
"github.com/databricks/databricks-sql-go/auth/oauth/m2m"
)
func main() {
host := os.Getenv("DATABRICKS_HOST")
httpPath := os.Getenv("DATABRICKS_HTTP_PATH")
clientID := os.Getenv("DATABRICKS_CLIENT_ID")
clientSecret := os.Getenv("DATABRICKS_CLIENT_SECRET")
authenticator := m2m.NewAuthenticator(clientID, clientSecret, serverHostname(host))
connector, err := dbsql.NewConnector(
dbsql.WithServerHostname(serverHostname(host)),
dbsql.WithPort(443),
dbsql.WithHTTPPath(httpPath),
dbsql.WithAuthenticator(authenticator),
dbsql.WithUserAgentEntry("YourCompany_YourProduct/1.0.0"),
)
if err != nil {
panic(err)
}
db := sql.OpenDB(connector)
defer db.Close()
rows, err := db.Query("SELECT COUNT(*) FROM samples.nyctaxi.trips")
if err != nil {
panic(err)
}
defer rows.Close()
var count int64
rows.Next()
rows.Scan(&count)
fmt.Printf("OAuth M2M OK: %d trips\n", count)
}
func serverHostname(host string) string {
s := strings.TrimPrefix(host, "https://")
s = strings.TrimPrefix(s, "http://")
if idx := strings.Index(s, "/"); idx >= 0 {
s = s[:idx]
}
return s
}
```
**Env vars:** `DATABRICKS_HOST`, `DATABRICKS_HTTP_PATH`, `DATABRICKS_CLIENT_ID`, `DATABRICKS_CLIENT_SECRET`
**Setup:** Create service principal in Account Console → Settings → Service principals. Generate OAuth secret. Grant `CAN_USE` on the SQL warehouse.
---
### U2M Browser Authentication (Driver-Native)
Uses the driver's **built-in U2M authenticator** that opens the user's default browser:
```go
package main
import (
"database/sql"
"fmt"
"os"
"strings"
"time"
dbsql "github.com/databricks/databricks-sql-go"
"github.com/databricks/databricks-sql-go/auth/oauth/u2m"
)
func main() {
host := os.Getenv("DATABRICKS_HOST")
httpPath := os.Getenv("DATABRICKS_HTTP_PATH")
authenticator, err := u2m.NewAuthenticator(serverHostname(host), 2*time.Minute)
if err != nil {
panic(err)
}
connector, err := dbsql.NewConnector(
dbsql.WithServerHostname(serverHostname(host)),
dbsql.WithPort(443),
dbsql.WithHTTPPath(httpPath),
dbsql.WithAuthenticator(authenticator),
dbsql.WithUserAgentEntry("YourCompany_YourProduct/1.0.0"),
)
if err != nil {
panic(err)
}
db := sql.OpenDB(connector)
defer db.Close()
rows, err := db.Query("SELECT COUNT(*) FROM samples.nyctaxi.trips")
if err != nil {
panic(err)
}
defer rows.Close()
var count int64
rows.Next()
rows.Scan(&count)
fmt.Printf("U2M Browser OK: %d trips\n", count)
}
func serverHostname(host string) string {
s := strings.TrimPrefix(host, "https://")
s = strings.TrimPrefix(s, "http://")
if idx := strings.Index(s, "/"); idx >= 0 {
s = s[:idx]
}
return s
}
```
**Env vars:** `DATABRICKS_HOST`, `DATABRICKS_HTTP_PATH`
**Notes:**
- Uses Databricks' built-in OAuth app (client_id=`databricks-sql-connector`)
- Do NOT set `DATABRICKS_CLIENT_ID` or `DATABRICKS_TOKEN`
- Driver picks an available localhost port at runtime
---
### U2M Token-Env Authentication (Headless/CI)
Pass a pre-obtained OAuth access token:
```go
package main
import (
"database/sql"
"fmt"
"os"
"strings"
dbsql "github.com/databricks/databricks-sql-go"
)
func main() {
host := os.Getenv("DATABRICKS_HOST")
httpPath := os.Getenv("DATABRICKS_HTTP_PATH")
token := os.Getenv("DATABRICKS_ACCESS_TOKEN")
if token == "" {
token = os.Getenv("DATABRICKS_TOKEN")
}
connector, err := dbsql.NewConnector(
dbsql.WithServerHostname(serverHostname(host)),
dbsql.WithPort(443),
dbsql.WithHTTPPath(httpPath),
dbsql.WithAccessToken(token),
dbsql.WithUserAgentEntry("YourCompany_YourProduct/1.0.0"),
)
if err != nil {
panic(err)
}
db := sql.OpenDB(connector)
defer db.Close()
rows, err := db.Query("SELECT COUNT(*) FROM samples.nyctaxi.trips")
if err != nil {
panic(err)
}
defer rows.Close()
var count int64
rows.Next()
rows.Scan(&count)
fmt.Printf("U2M Token-Env OK: %d trips\n", count)
}
func serverHostname(host string) string {
s := strings.TrimPrefix(host, "https://")
s = strings.TrimPrefix(s, "http://")
if idx := strings.Index(s, "/"); idx >= 0 {
s = s[:idx]
}
return s
}
```
**Env vars:** `DATABRICKS_HOST`, `DATABRICKS_HTTP_PATH`, `DATABRICKS_ACCESS_TOKEN` (or `DATABRICKS_TOKEN`)
---
### U2M Custom OAuth App (PKCE) - Interactive
For user-interactive flows with a custom OAuth app:
```go
package main
import (
"context"
"crypto/rand"
"crypto/sha256"
"database/sql"
"encoding/base64"
"encoding/json"
"fmt"
GitHub에서 보기