From 61ee28dcf2f1bd9a29cad9d500b9777197d06513 Mon Sep 17 00:00:00 2001 From: Cathleen Yan <58714163+cathleeny@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:44:36 +0000 Subject: [PATCH 1/2] fix: default geospatial results to strings Signed-off-by: Cathleen Yan <58714163+cathleeny@users.noreply.github.com> --- CHANGELOG.md | 2 +- CONNECTION_PARAMETERS.md | 6 +++--- README.md | 6 +++--- connector.go | 7 ++++--- internal/backend/kernel/config.go | 2 +- internal/config/config.go | 4 ++-- kernel_config.go | 6 +++--- kernel_config_test.go | 6 +++--- kernel_geospatial_e2e_test.go | 2 +- 9 files changed, 21 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 017b3f3d..8baa5014 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Release History ## Unreleased -- Add default-enabled kernel-backed GEOMETRY / GEOGRAPHY results, selected with `WithEnableGeoSpatialSupport` or the `enableGeoSpatialSupport` DSN parameter. Enabled mode returns EWKB with its per-row SRID and logical geo column metadata from `database/sql`; disabled mode returns WKT / EWKT reported as `STRING`. Arrow batch access retains the canonical `struct` value with separate OGC WKB in enabled mode. +- Add opt-in kernel-backed GEOMETRY / GEOGRAPHY results, selected with `WithEnableGeoSpatialSupport` or the `enableGeoSpatialSupport` DSN parameter (default `false`). Enabled mode returns EWKB with its per-row SRID and logical geo column metadata from `database/sql`; disabled mode returns WKT / EWKT reported as `STRING`. Arrow batch access retains the canonical `struct` value with separate OGC WKB in enabled mode. - **Behavior change:** `m2m.NewAuthenticatorWithScopes` now requests exactly the given scopes instead of always appending `all-apis`, so service principals with scoped OAuth secrets (e.g. `sql` only) can authenticate (databricks/databricks-sql-go#476). Empty scopes and `m2m.NewAuthenticator` still request `all-apis`; callers that relied on it being appended should pass no scopes, or add `all-apis` to their list if they need both. The SEA/kernel backend now forwards custom M2M scopes instead of rejecting them. - Let the kernel telemetry feature flag decide enablement when `enableTelemetry` is unset; explicit `true` and `false` continue to override it. diff --git a/CONNECTION_PARAMETERS.md b/CONNECTION_PARAMETERS.md index 89aae8f4..422eaf5e 100644 --- a/CONNECTION_PARAMETERS.md +++ b/CONNECTION_PARAMETERS.md @@ -155,14 +155,14 @@ ignored with a warning and still stripped from the SEA wire. |---|---|:---:|:---:|---|---| | `useArrowNativeDecimal` | `WithArrowNativeDecimal` | ✅ | ⚠️ | `false` | Thrift: return DECIMAL as native Arrow `decimal128` (lossless string when scanned via `database/sql`). The kernel path already renders DECIMAL as the exact string regardless, so the flag is inert there. | | | `WithKernelDecimalAsFloat(b)` | ❌ | ✅ | `false` | Scan top-level DECIMAL as lossy `float64` instead of the exact string. | -| `enableGeoSpatialSupport` | `WithEnableGeoSpatialSupport(b)` | ❌ | ✅ | `true` | `true`: return top-level GEOMETRY / GEOGRAPHY as EWKB `[]byte` with the per-row SRID embedded and logical geo column metadata; `GetArrowBatches` retains the full `{srid,wkb}` struct with OGC WKB. `false`: return WKT / EWKT strings reported as `STRING`. | +| `enableGeoSpatialSupport` | `WithEnableGeoSpatialSupport(b)` | ❌ | ✅ | `false` | `true`: return top-level GEOMETRY / GEOGRAPHY as EWKB `[]byte` with the per-row SRID embedded and logical geo column metadata; `GetArrowBatches` retains the full `{srid,wkb}` struct with OGC WKB. `false`: return WKT / EWKT strings reported as `STRING`. | Apart from the geospatial representation selected above, results render **byte-for-byte identically** on both backends (scalars, DECIMAL as exact string, TIMESTAMP / TIMESTAMP_NTZ shifted into the session time zone, INTERVAL, nested ARRAY / MAP / STRUCT and VARIANT as JSON, and BINARY as -`sql.RawBytes`). Set `enableGeoSpatialSupport=false` on the kernel path to match -the Thrift path's WKT / EWKT geospatial values. +`sql.RawBytes`). The default `enableGeoSpatialSupport=false` on the kernel path +matches the Thrift path's WKT / EWKT geospatial values. ## Cloud Fetch diff --git a/README.md b/README.md index 4bae2a09..d59054af 100644 --- a/README.md +++ b/README.md @@ -270,7 +270,7 @@ session parameter on both backends. |---|---|---|---|---| | `useArrowNativeDecimal` | `WithArrowNativeDecimal` | Thrift only (inert on kernel) | `false` | Thrift: return DECIMAL as native Arrow `decimal128` (lossless string when scanned via `database/sql`). The kernel path already renders DECIMAL as the exact string regardless. | | | `WithKernelDecimalAsFloat(b)` | SEA only | `false` | Scan top-level DECIMAL as lossy `float64` instead of the exact string. | -| `enableGeoSpatialSupport` | `WithEnableGeoSpatialSupport(b)` | SEA only | `true` | `true`: return top-level GEOMETRY / GEOGRAPHY as EWKB `[]byte` with the per-row SRID embedded and logical geo column metadata; `GetArrowBatches` retains the full `{srid,wkb}` struct with OGC WKB. `false`: return WKT / EWKT strings reported as `STRING`. | +| `enableGeoSpatialSupport` | `WithEnableGeoSpatialSupport(b)` | SEA only | `false` | `true`: return top-level GEOMETRY / GEOGRAPHY as EWKB `[]byte` with the per-row SRID embedded and logical geo column metadata; `GetArrowBatches` retains the full `{srid,wkb}` struct with OGC WKB. `false`: return WKT / EWKT strings reported as `STRING`. | See [Cloud Fetch](#cloud-fetch), [TLS](#tls), and [Proxy](#proxy) for the remaining groups. Telemetry parameters are covered under [Telemetry](#telemetry). @@ -363,8 +363,8 @@ Apart from the configurable geospatial representation, results render **byte-for identically** on both backends. Scalars, DECIMAL (exact string), TIMESTAMP / TIMESTAMP_NTZ (shifted into the session time zone), INTERVAL, and nested ARRAY / MAP / STRUCT and VARIANT (as JSON) are supported. BINARY is returned as `sql.RawBytes`. -Thrift returns GEOMETRY / GEOGRAPHY as WKT / EWKT; the kernel defaults to EWKB and -matches Thrift when `enableGeoSpatialSupport=false`. +Both backends return GEOMETRY / GEOGRAPHY as WKT / EWKT by default. +Set `enableGeoSpatialSupport=true` on the kernel path to opt into EWKB. Metadata is reached through SQL (`SHOW`, `DESCRIBE`, `information_schema`) on both backends — the driver exposes no `GetCatalogs`/`GetSchemas`/`GetTables`/`GetColumns` API diff --git a/connector.go b/connector.go index 296d80ec..4ef687e2 100644 --- a/connector.go +++ b/connector.go @@ -676,10 +676,11 @@ func WithKernelDecimalAsFloat(asFloat bool) ConnOption { } // WithEnableGeoSpatialSupport selects how the kernel path exposes top-level -// GEOMETRY and GEOGRAPHY result values. True (the default) returns EWKB bytes +// GEOMETRY and GEOGRAPHY result values. True returns EWKB bytes // ([]byte), including the per-row SRID, and reports the logical GEOMETRY / -// GEOGRAPHY type through database/sql metadata. False returns WKT / EWKT strings and reports STRING, matching the -// existing string-mode driver contract. The per-row SRID remains present in the +// GEOGRAPHY type through database/sql metadata. False (the default) returns +// WKT / EWKT strings and reports STRING, matching the existing string-mode +// driver contract. The per-row SRID remains present in the // Arrow struct returned by the driver's GetArrowBatches API in enabled mode; // that raw Arrow value retains Databricks' separate SRID and OGC WKB children. // diff --git a/internal/backend/kernel/config.go b/internal/backend/kernel/config.go index 1e8c254b..5a68ce0d 100644 --- a/internal/backend/kernel/config.go +++ b/internal/backend/kernel/config.go @@ -102,7 +102,7 @@ type Config struct { // EnableGeoSpatialSupport selects the local GEOMETRY / GEOGRAPHY result // representation. True requests the canonical struct Arrow // representation; false requests WKT / EWKT strings. The connector always - // sets this field and defaults it to true. + // sets this field and defaults it to false. EnableGeoSpatialSupport bool // TokenCacheEnabled controls the kernel's on-disk OAuth U2M token-cache persistence diff --git a/internal/config/config.go b/internal/config/config.go index cf5ba575..a0ace461 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -141,7 +141,7 @@ type KernelExperimentalConfig struct { // EnableGeoSpatialSupport selects the kernel's client-side GEOMETRY / // GEOGRAPHY result representation. True requests the canonical // struct Arrow value; false requests WKT / EWKT strings. A pointer - // preserves the default-enabled value versus explicitly false. + // distinguishes the omitted value (default false) from an explicit setting. EnableGeoSpatialSupport *bool } @@ -314,7 +314,7 @@ type UserConfig struct { TokenCacheEnabledDSN bool // EnableGeoSpatialSupportDSN is a DSN-only carrier for // enableGeoSpatialSupport=true|false. Nil means omitted (the default is - // true); the connector copies a present value into KernelExperimental. + // false); the connector copies a present value into KernelExperimental. EnableGeoSpatialSupportDSN *bool } diff --git a/kernel_config.go b/kernel_config.go index b4a1238e..9db5d154 100644 --- a/kernel_config.go +++ b/kernel_config.go @@ -176,9 +176,9 @@ func buildKernelConfig(cfg *config.Config, kauth kernel.Auth) kernel.Config { // this binding's system identity for its own runtime. Telemetry: kernelTelemetryConfig(cfg), DriverSystemConfiguration: kernelDriverSystemConfiguration(cfg), - // Match the public contract and the kernel default. An explicit false - // below selects WKT / EWKT instead. - EnableGeoSpatialSupport: true, + // Preserve string results by default, including automatic kernel recovery. + // An explicit true below opts into native geospatial values. + EnableGeoSpatialSupport: false, } if cfg.ClientQueryTimeout != nil { timeout := *cfg.ClientQueryTimeout diff --git a/kernel_config_test.go b/kernel_config_test.go index 6b5a59fa..d669a023 100644 --- a/kernel_config_test.go +++ b/kernel_config_test.go @@ -559,11 +559,11 @@ func TestBuildKernelConfig(t *testing.T) { } }) - t.Run("geospatial support defaults true and preserves explicit values", func(t *testing.T) { + t.Run("geospatial support defaults false and preserves explicit values", func(t *testing.T) { c := baseKernelConfig() kc := buildKernelConfig(c, kernel.Auth{Mode: kernel.AuthPAT, Token: "dapi-x"}) - if !kc.EnableGeoSpatialSupport { - t.Fatal("omitted EnableGeoSpatialSupport = false, want default true") + if kc.EnableGeoSpatialSupport { + t.Fatal("omitted EnableGeoSpatialSupport = true, want default false") } WithEnableGeoSpatialSupport(false)(c) diff --git a/kernel_geospatial_e2e_test.go b/kernel_geospatial_e2e_test.go index 248139d2..41d1c53f 100644 --- a/kernel_geospatial_e2e_test.go +++ b/kernel_geospatial_e2e_test.go @@ -34,7 +34,7 @@ func TestKernelE2EGeospatialRepresentations(t *testing.T) { native bool extra []ConnOption }{ - {"default", true, nil}, + {"default", false, nil}, {"enabled", true, []ConnOption{WithEnableGeoSpatialSupport(true)}}, {"disabled", false, []ConnOption{WithEnableGeoSpatialSupport(false)}}, } { From 24aa6efbbd04baab2d522be8c395a93d58d930e3 Mon Sep 17 00:00:00 2001 From: Cathleen Yan <58714163+cathleeny@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:50:48 +0000 Subject: [PATCH 2/2] docs: align geospatial default comment Signed-off-by: Cathleen Yan <58714163+cathleeny@users.noreply.github.com> --- internal/backend/kernel/backend.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/backend/kernel/backend.go b/internal/backend/kernel/backend.go index 610c9539..f8e6ebb7 100644 --- a/internal/backend/kernel/backend.go +++ b/internal/backend/kernel/backend.go @@ -439,7 +439,7 @@ func (k *KernelBackend) applyMaxConnections(cfg *C.KernelSessionConfig) error { } // applyEnableGeoSpatialSupport selects the kernel's client-side representation -// for GEOMETRY / GEOGRAPHY results. The connector supplies the default-enabled +// for GEOMETRY / GEOGRAPHY results. The connector supplies the default-disabled // value explicitly, and an explicit false crosses the ABI unchanged. func (k *KernelBackend) applyEnableGeoSpatialSupport(cfg *C.KernelSessionConfig) error { if err := call(func() C.KernelStatusCode {