Skip to content

Commit 4b7fa57

Browse files
committed
feat: support geospatial results on the kernel path
Signed-off-by: Cathleen Yan <58714163+cathleeny@users.noreply.github.com>
1 parent e3fcc82 commit 4b7fa57

9 files changed

Lines changed: 117 additions & 10 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Release History
22

3+
## Unreleased
4+
5+
- Add `geospatialAsString` for kernel-backed GEOMETRY / GEOGRAPHY results. String mode returns EWKT; binary mode returns the canonical `{ srid, wkb }` Arrow value.
6+
37
## 2.2.0
48

59
- Upgrade the kernel backend native packages to 1.1.0; the kernel dependency is now stable and no longer experimental.

‎CONNECTION_PARAMETERS.md‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,12 @@ disabling verification.
9898

9999
## Results and type rendering
100100

101-
| Option | Type | Thrift | Kernel | Default Value | Note |
102-
| ----------------------------- | --------- | :----: | :----: | ------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
103-
| `preserveBigNumericPrecision` | `boolean` | ✅ | ✅ | `false` | Returns DECIMAL as an exact string and BIGINT as `bigint` on both. |
104-
| `disableRowMaterialization` | `boolean` | ✅ | ✅ | `false` | Fetches and parses Arrow batches but returns `null` row placeholders instead of converting cells. Intended for fetch-throughput tests. |
105-
| `enableMetricViewMetadata` | `boolean` | ✅ | ⚠️ | `false` | Injected into session configuration on both paths. Kernel may drop its non-allowlisted configuration key. |
101+
| Option | Type | Thrift | Kernel | Default Value | Note |
102+
| ----------------------------- | --------- | :----: | :----: | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
103+
| `preserveBigNumericPrecision` | `boolean` | ✅ | ✅ | `false` | Returns DECIMAL as an exact string and BIGINT as `bigint` on both. |
104+
| `disableRowMaterialization` | `boolean` | ✅ | ✅ | `false` | Fetches and parses Arrow batches but returns `null` row placeholders instead of converting cells. Intended for fetch-throughput tests. |
105+
| `geospatialAsString` | `boolean` | ❌ | ✅ | Kernel default (`true`) | Returns GEOMETRY / GEOGRAPHY as EWKT strings when `true`, or canonical `{ srid: number, wkb: Buffer }` values when `false`. The choice is local and is not forwarded to SEA. |
106+
| `enableMetricViewMetadata` | `boolean` | ✅ | ⚠️ | `false` | Injected into session configuration on both paths. Kernel may drop its non-allowlisted configuration key. |
106107

107108
## Session defaults (`openSession(request)`)
108109

‎KERNEL_REV‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
80f2aee7d884994d7b0af9a9ea6078872859a9cd
1+
ad3bc6993bca95b810839feade77ccd0ab98ece5

‎lib/contracts/IDBSQLClient.ts‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,17 @@ export type ConnectionOptions = {
157157
*/
158158
disableRowMaterialization?: boolean;
159159

160+
/**
161+
* Select the kernel-backed result representation for `GEOMETRY` and
162+
* `GEOGRAPHY` columns. `true` returns EWKT strings; `false` returns the
163+
* canonical Arrow value as `{ srid: number, wkb: Buffer }`. Omitted uses the
164+
* kernel default (currently EWKT strings). This is a client-side conversion
165+
* choice and is never forwarded to the SQL Execution API.
166+
*
167+
* Only the kernel backend uses this option.
168+
*/
169+
geospatialAsString?: boolean;
170+
160171
/**
161172
* Extra HTTP headers attached to driver-owned out-of-band requests
162173
* (telemetry POSTs and feature-flag GETs). Not applied to the primary

‎lib/kernel/KernelAuth.ts‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ export interface KernelSessionDefaults {
115115
* remove one.
116116
*/
117117
complexTypesAsJson?: boolean;
118+
/**
119+
* Render GEOMETRY / GEOGRAPHY as EWKT strings (`true`) or canonical
120+
* `struct<srid:int32,wkb:binary>` values (`false`). Omitted keeps the kernel
121+
* string default. Applied locally by the kernel and never sent to SEA.
122+
*/
123+
geospatialAsString?: boolean;
118124
/**
119125
* Per-session kernel connection-pool size
120126
* (kernel `ConnectionOptions.max_connections`). Validated as a positive
@@ -819,6 +825,7 @@ export function buildKernelConnectionOptions(options: ConnectionOptions): Kernel
819825
hostName: string;
820826
httpPath: string;
821827
intervalsAsString: boolean;
828+
geospatialAsString?: boolean;
822829
maxConnections?: number;
823830
} & KernelTlsOptions &
824831
KernelHttpOptions &
@@ -843,6 +850,15 @@ export function buildKernelConnectionOptions(options: ConnectionOptions): Kernel
843850
...buildKernelProxyOptions(options),
844851
};
845852

853+
if (options.geospatialAsString !== undefined) {
854+
if (typeof options.geospatialAsString !== 'boolean') {
855+
throw new HiveDriverError(
856+
`kernel backend: \`geospatialAsString\` must be a boolean; got ${typeof options.geospatialAsString}.`,
857+
);
858+
}
859+
base.geospatialAsString = options.geospatialAsString;
860+
}
861+
846862
// kernel-only pool sizing; read via cast to match how this function reads the
847863
// other kernel-specific options (TLS) — they live on the internal options
848864
// surface, not the published public `ConnectionOptions` `.d.ts`.

‎native/kernel/index.d.ts‎

Lines changed: 13 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎tests/unit/kernel/KernelOperationBackend.test.ts‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,47 @@ describe('KernelOperationBackend — M0 datatype round-trip via napi → ArrowRe
257257
expect(row.s).to.deep.equal({ a: 1, b: 'hi' });
258258
});
259259

260+
it('surfaces geospatial string and binary values in idiomatic JS shapes', async () => {
261+
const wkb = new Uint8Array([
262+
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263+
0x00, 0x40,
264+
]);
265+
const geoType = new Struct([
266+
new Field('srid', new Int32(), false),
267+
new Field(
268+
'wkb',
269+
new Binary(),
270+
false,
271+
new Map([
272+
['geometry', 'true'],
273+
['srid', '-1'],
274+
]),
275+
),
276+
]);
277+
const schema = new Schema([
278+
withTypeName(new Field('geom_text', new Utf8(), true), 'GEOMETRY'),
279+
withTypeName(new Field('geom_binary', geoType, true), 'GEOMETRY'),
280+
]);
281+
const stub = new StatementStub(ipcSchemaOnly(schema), [
282+
ipcFromColumns(schema, {
283+
geom_text: ['SRID=4326;POINT(1 2)', null],
284+
geom_binary: [{ srid: 4326, wkb }, null],
285+
}),
286+
]);
287+
const backend = new KernelOperationBackend({
288+
statement: stub,
289+
context: new ClientContextStub(),
290+
});
291+
292+
const rows = (await backend.fetchChunk({ limit: 100 })) as Array<Record<string, unknown>>;
293+
expect(rows[0].geom_text).to.equal('SRID=4326;POINT(1 2)');
294+
expect(rows[0].geom_binary).to.deep.equal({
295+
srid: 4326,
296+
wkb: Buffer.from(wkb),
297+
});
298+
expect(rows[1]).to.deep.equal({ geom_text: null, geom_binary: null });
299+
});
300+
260301
it('streams multiple batches and reports hasMore correctly', async () => {
261302
const schema = new Schema([withTypeName(new Field('x', new Int32(), true), 'INT')]);
262303
const schemaIpc = ipcSchemaOnly(schema);

‎tests/unit/kernel/connectionOptions.test.ts‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,29 @@ describe('KernelAuth connection options — intervalsAsString default', () => {
4040
});
4141
});
4242

43+
describe('KernelAuth connection options — geospatial result representation', () => {
44+
it('omits geospatialAsString by default so the kernel owns its default', () => {
45+
const native = buildKernelConnectionOptions(opts({})) as { geospatialAsString?: boolean };
46+
expect(native.geospatialAsString).to.equal(undefined);
47+
});
48+
49+
for (const value of [true, false]) {
50+
it(`forwards geospatialAsString=${value}`, () => {
51+
const native = buildKernelConnectionOptions(opts({ geospatialAsString: value })) as {
52+
geospatialAsString?: boolean;
53+
};
54+
expect(native.geospatialAsString).to.equal(value);
55+
});
56+
}
57+
58+
it('rejects non-boolean values at runtime', () => {
59+
expect(() => buildKernelConnectionOptions(opts({ geospatialAsString: 'false' }))).to.throw(
60+
HiveDriverError,
61+
/must be a boolean/,
62+
);
63+
});
64+
});
65+
4366
describe('KernelAuth connection options — maxConnections', () => {
4467
it('forwards a valid positive integer', () => {
4568
const native = buildKernelConnectionOptions(opts({ maxConnections: 10 })) as { maxConnections?: number };

‎tests/unit/kernel/execution.test.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,7 @@ describe('KernelBackend', () => {
533533
host: 'workspace.example',
534534
path: '/sql/1.0/warehouses/xyz',
535535
token: 'dapi-token',
536+
geospatialAsString: false,
536537
} as ConnectionOptions);
537538

538539
await backend.openSession({});
@@ -549,6 +550,7 @@ describe('KernelBackend', () => {
549550
authMode: 'Pat',
550551
token: 'dapi-token',
551552
intervalsAsString: true,
553+
geospatialAsString: false,
552554
});
553555
});
554556

0 commit comments

Comments
 (0)