Skip to content

Commit 2b052e8

Browse files
committed
address review comments
Signed-off-by: Jiabin Hu <jiabin.hu@databricks.com>
1 parent bc13cc1 commit 2b052e8

File tree

3 files changed

+17
-16
lines changed

3 files changed

+17
-16
lines changed

examples/query_tags_example.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
1717
Special cases:
1818
- If a value is None, only the key is included (no colon or value)
19-
- Special characters (:, ,, \\) in values are automatically escaped
19+
- Special characters (comma, colon and backslash) in values are automatically escaped
2020
- Keys are not escaped (should be controlled identifiers)
2121
"""
2222

@@ -118,4 +118,4 @@
118118
result = cursor.fetchone()
119119
print(f" Executemany Query Result (last): {result[0]}")
120120

121-
print("\n=== Query Tags Example Complete ===")
121+
print("\n=== Query Tags Example Complete ===")

src/databricks/sql/utils.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -908,7 +908,7 @@ def serialize_query_tags(
908908
Special cases:
909909
- If value is None, omit the colon and value (e.g., "key1:value1,key2,key3:value3")
910910
- Escape special characters (:, ,, \\) in values with a leading backslash
911-
- Keys are not escaped (assumed to be controlled identifiers)
911+
- Backslashes in keys are escaped; other special characters in keys are not escaped
912912
913913
Args:
914914
query_tags: Dictionary of query tags where keys are strings and values are optional strings
@@ -922,20 +922,21 @@ def serialize_query_tags(
922922
def escape_value(value: str) -> str:
923923
"""Escape special characters in tag values."""
924924
# Escape backslash first to avoid double-escaping
925-
value = value.replace("\\", "\\\\")
925+
value = value.replace("\\", r"\\")
926926
# Escape colon and comma
927-
value = value.replace(":", "\\:")
928-
value = value.replace(",", "\\,")
927+
value = value.replace(":", r"\:")
928+
value = value.replace(",", r"\,")
929929
return value
930930

931931
serialized_parts = []
932932
for key, value in query_tags.items():
933+
escaped_key = key.replace("\\", r"\\")
933934
if value is None:
934935
# No colon or value when value is None
935-
serialized_parts.append(key)
936+
serialized_parts.append(escaped_key)
936937
else:
937938
escaped_value = escape_value(value)
938-
serialized_parts.append(f"{key}:{escaped_value}")
939+
serialized_parts.append(f"{escaped_key}:{escaped_value}")
939940

940941
return ",".join(serialized_parts)
941942

tests/unit/test_util.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,19 +180,19 @@ def test_serialize_query_tags_with_special_chars(self):
180180
query_tags = {
181181
"key1": "value:with:colons",
182182
"key2": "value,with,commas",
183-
"key3": "value\\with\\backslashes",
183+
"key3": r"value\with\backslashes",
184184
}
185185
result = serialize_query_tags(query_tags)
186186
assert (
187187
result
188-
== "key1:value\\:with\\:colons,key2:value\\,with\\,commas,key3:value\\\\with\\\\backslashes"
188+
== r"key1:value\:with\:colons,key2:value\,with\,commas,key3:value\\with\\backslashes"
189189
)
190190

191191
def test_serialize_query_tags_with_mixed_special_chars(self):
192192
"""Test query tags with mixed special characters"""
193-
query_tags = {"key1": "a:b,c\\d"}
193+
query_tags = {"key1": r"a:b,c\d"}
194194
result = serialize_query_tags(query_tags)
195-
assert result == "key1:a\\:b\\,c\\\\d"
195+
assert result == r"key1:a\:b\,c\\d"
196196

197197
def test_serialize_query_tags_empty_dict(self):
198198
"""Test serialization with empty dictionary"""
@@ -206,17 +206,17 @@ def test_serialize_query_tags_none(self):
206206
assert result is None
207207

208208
def test_serialize_query_tags_with_special_chars_in_key(self):
209-
"""Test query tags with special characters in keys (keys are not escaped)"""
209+
"""Test query tags with special characters in keys (only backslashes are escaped in keys)"""
210210
query_tags = {
211211
"key:with:colons": "value1",
212212
"key,with,commas": "value2",
213-
"key\\with\\backslashes": "value3",
213+
r"key\with\backslashes": "value3",
214214
}
215215
result = serialize_query_tags(query_tags)
216-
# Keys are not escaped, only values are
216+
# Only backslashes are escaped in keys; colons and commas in keys are not escaped
217217
assert (
218218
result
219-
== "key:with:colons:value1,key,with,commas:value2,key\\with\\backslashes:value3"
219+
== r"key:with:colons:value1,key,with,commas:value2,key\\with\\backslashes:value3"
220220
)
221221

222222
def test_serialize_query_tags_all_none_values(self):

0 commit comments

Comments
 (0)