Skip to content

Statement level query tag in NodeJS connector#339

Open
jiabin-hu wants to merge 5 commits intodatabricks:mainfrom
jiabin-hu:main
Open

Statement level query tag in NodeJS connector#339
jiabin-hu wants to merge 5 commits intodatabricks:mainfrom
jiabin-hu:main

Conversation

@jiabin-hu
Copy link
Copy Markdown

Summary

  • Adds queryTags option to ExecuteStatementOptions for per-statement query tagging
  • Implements serializeQueryTags() utility that converts a key/value dict to a comma-separated key:value string (matching the Python connector's format), with backslash-escaping for special characters in values
  • Serialized tags are passed via confOverlay["query_tags"] on TExecuteStatementReq, consistent with the Python connector
    implementation

Test plan

  • Unit tests for serializeQueryTags covering null/empty input, basic serialization, null values, and special character escaping (tests/unit/utils/queryTags.test.ts)
  • Unit tests for executeStatement verifying confOverlay.query_tags is set/unset correctly (tests/unit/DBSQLSession.test.ts)
  • Run npm test to confirm all unit tests pass

vikrantpuppala added a commit to databricks/databricks-sql-go that referenced this pull request Apr 6, 2026
## Summary
- Adds per-statement query tag support via
`driverctx.NewContextWithQueryTags`, allowing users to attach query tags
to individual SQL statements through context
- Tags are serialized into
`TExecuteStatementReq.ConfOverlay["query_tags"]`, consistent with the
Python
([#736](databricks/databricks-sql-python#736))
and NodeJS
([#339](databricks/databricks-sql-nodejs#339))
connector implementations
- Previously only session-level query tags were supported (set once via
`WithSessionParams` at connection time)

## Usage
```go
ctx := driverctx.NewContextWithQueryTags(context.Background(), map[string]string{
    "team": "data-eng",
    "app":  "etl-pipeline",
})
rows, err := db.QueryContext(ctx, "SELECT * FROM table")
```

## Changes
| File | Description |
|------|-------------|
| `driverctx/ctx.go` | `NewContextWithQueryTags`,
`QueryTagsFromContext`, propagation in `NewContextFromBackground` |
| `query_tags.go` *(new)* | `SerializeQueryTags` — map to wire format
with escaping |
| `connection.go` | Read tags from context → serialize → set
`ConfOverlay["query_tags"]` |
| `driverctx/ctx_test.go` | 5 tests for context helpers |
| `query_tags_test.go` *(new)* | 13 tests for serialization (escaping,
edge cases) |
| `connection_test.go` | 6 integration tests verifying ConfOverlay
behavior |
| `examples/query_tags/main.go` | Updated with session + statement-level
examples |

## Test plan
- [x] Unit tests for `SerializeQueryTags` covering nil, empty,
single/multi tags, escaping of `\`, `:`, `,` in values and keys
- [x] Unit tests for `NewContextWithQueryTags` / `QueryTagsFromContext`
including nil context, missing key, timeout preservation, background
propagation
- [x] Integration tests verifying `ConfOverlay["query_tags"]` is
correctly set (or absent) in captured `TExecuteStatementReq`
- [ ] Verify existing tests still pass (CI)

This pull request was AI-assisted by Isaac.

---------

Signed-off-by: Jooho Yeo <jooho.yeo@databricks.com>
Co-authored-by: Jooho Yeo <jooho.yeo@databricks.com>
Co-authored-by: Vikrant Puppala <vikrant.puppala@databricks.com>
Comment thread lib/utils/queryTags.ts
if (value == null) {
return escapedKey;
}
const escapedValue = value.replace(/[\\:,]/g, (c) => `\\${c}`);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be doing escaping on the client/driver end ? I remember in SEA escaping happens on the server end. Although currently we only support thrift in node driver, lets confirm if server needs escaping in input.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should. Thrift layer requires escaped and serialized string as query tags. That's why SEA, built on top of thrift, is doing the escaping. Connectors, which are on top of thrift now, should also do the escaping.

If they were to move to SEA in the future, they can let SEA take care of the escaping, and just pass the dict to SEA.

Copy link
Copy Markdown
Contributor

@sreekanth-db sreekanth-db left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description only mentions about unit tests. Have we tested the changes on a real warehouse ?

@samikshya-db
Copy link
Copy Markdown
Collaborator

samikshya-db commented Apr 17, 2026

Hello @jiabin-hu - Can you confirm Sreekanth's point above and we can merge this?

@jiabin-hu
Copy link
Copy Markdown
Author

PR description only mentions about unit tests. Have we tested the changes on a real warehouse ?

Yes, ran the newly added query tags sample code and it worked fine.

Signed-off-by: Jiabin Hu <jiabin.hu@databricks.com>
Co-authored-by: Isaac
Signed-off-by: Jiabin Hu <jiabin.hu@databricks.com>
Signed-off-by: Jiabin Hu <jiabin.hu@databricks.com>
Signed-off-by: Jiabin Hu <jiabin.hu@databricks.com>
Signed-off-by: Jiabin Hu <jiabin.hu@databricks.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants