Skip to content

Commit 1986809

Browse files
committed
feat(thrift): per-statement metricViewMetadata knob on ExecuteStatementOptions
Add `metricViewMetadata?: boolean` to `ExecuteStatementOptions`. When true, the Thrift backend forwards `spark.databricks.optimizer.enableMetricViewMetadata=true` via the request `confOverlay`, alongside any `query_tags` already serialized there. The option is per-statement only and does not persist across queries. The SEA backend will route the same key through napi `statementConf` once the kernel statement-options surface lands; until then the option is honored only on Thrift. Documented in the public option JSDoc so users do not silently lose the conf on SEA. Unit tests assert the option appears in the outgoing `TExecuteStatementReq` when set, is omitted when unset or `false`, and coexists with `queryTags` in the same `confOverlay`. Audit refs: rows 1.17 and 2.18 of sea-workflow/audits/2026-05-28-cross-driver-audit.md (F12 in the PR #347 audit). Co-authored-by: Isaac Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
1 parent a3bf320 commit 1986809

3 files changed

Lines changed: 76 additions & 0 deletions

File tree

lib/contracts/IDBSQLSession.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ export type ExecuteStatementOptions = {
2727
* These tags apply only to this statement and do not persist across queries.
2828
*/
2929
queryTags?: Record<string, string | null | undefined>;
30+
/**
31+
* Enable metric-view metadata expansion for this statement. When `true`, the
32+
* Spark conf `spark.databricks.optimizer.enableMetricViewMetadata=true` is
33+
* forwarded via the Thrift `confOverlay`. Applies to a single statement only;
34+
* does not persist across queries.
35+
*
36+
* Equivalent SEA wiring will route the same key through napi `statementConf`
37+
* once the kernel statement-options surface lands — until then this knob is
38+
* honored only on the Thrift backend.
39+
*/
40+
metricViewMetadata?: boolean;
3041
};
3142

3243
export type TypeInfoRequest = {

lib/thrift-backend/ThriftSessionBackend.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,13 @@ export default class ThriftSessionBackend implements ISessionBackend {
188188
request.confOverlay = { ...request.confOverlay, query_tags: serializedQueryTags };
189189
}
190190

191+
if (options.metricViewMetadata === true) {
192+
request.confOverlay = {
193+
...request.confOverlay,
194+
'spark.databricks.optimizer.enableMetricViewMetadata': 'true',
195+
};
196+
}
197+
191198
if (ProtocolVersion.supportsCloudFetch(this.serverProtocolVersion)) {
192199
request.canDownloadResult = options.useCloudFetch ?? clientConfig.useCloudFetch;
193200
}

tests/unit/DBSQLSession.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,64 @@ describe('DBSQLSession', () => {
298298
});
299299
});
300300

301+
describe('executeStatement with metricViewMetadata', () => {
302+
const metricViewConfKey = 'spark.databricks.optimizer.enableMetricViewMetadata';
303+
304+
it('should forward the metric-view conf via confOverlay when metricViewMetadata is true', async () => {
305+
const context = new ClientContextStub();
306+
const driver = sinon.spy(context.driver);
307+
const session = new DBSQLSession({ handle: sessionHandleStub, context });
308+
309+
await session.executeStatement('SELECT * FROM my_metric_view', { metricViewMetadata: true });
310+
311+
expect(driver.executeStatement.callCount).to.eq(1);
312+
const req = driver.executeStatement.firstCall.args[0];
313+
expect(req.confOverlay).to.deep.include({ [metricViewConfKey]: 'true' });
314+
});
315+
316+
it('should not set the metric-view conf when metricViewMetadata is omitted', async () => {
317+
const context = new ClientContextStub();
318+
const driver = sinon.spy(context.driver);
319+
const session = new DBSQLSession({ handle: sessionHandleStub, context });
320+
321+
await session.executeStatement('SELECT 1');
322+
323+
expect(driver.executeStatement.callCount).to.eq(1);
324+
const req = driver.executeStatement.firstCall.args[0];
325+
expect(req.confOverlay?.[metricViewConfKey]).to.be.undefined;
326+
});
327+
328+
it('should not set the metric-view conf when metricViewMetadata is false', async () => {
329+
const context = new ClientContextStub();
330+
const driver = sinon.spy(context.driver);
331+
const session = new DBSQLSession({ handle: sessionHandleStub, context });
332+
333+
await session.executeStatement('SELECT 1', { metricViewMetadata: false });
334+
335+
expect(driver.executeStatement.callCount).to.eq(1);
336+
const req = driver.executeStatement.firstCall.args[0];
337+
expect(req.confOverlay?.[metricViewConfKey]).to.be.undefined;
338+
});
339+
340+
it('should coexist with queryTags in the same confOverlay', async () => {
341+
const context = new ClientContextStub();
342+
const driver = sinon.spy(context.driver);
343+
const session = new DBSQLSession({ handle: sessionHandleStub, context });
344+
345+
await session.executeStatement('SELECT 1', {
346+
metricViewMetadata: true,
347+
queryTags: { team: 'eng' },
348+
});
349+
350+
expect(driver.executeStatement.callCount).to.eq(1);
351+
const req = driver.executeStatement.firstCall.args[0];
352+
expect(req.confOverlay).to.deep.include({
353+
[metricViewConfKey]: 'true',
354+
query_tags: 'team:eng',
355+
});
356+
});
357+
});
358+
301359
describe('getTypeInfo', () => {
302360
it('should run operation', async () => {
303361
const session = createSessionForTest({ handle: sessionHandleStub, context: new ClientContextStub() });

0 commit comments

Comments
 (0)