[Bug]: Python SDKs lowercase output expressions, silently corrupting string literals
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- Half a day
- Newbie friendliness
- 88/100
Research direction
Inspect output() in python/infinity_sdk/infinity/remote_thrift/query_builder.py and python/infinity_embedded/local_infinity/query_builder.py, then read test_output_preserves_string_literal_case in python/test_pysdk/test_condition.py. Verify that special tokens remain case-insensitive while string literals retain their original case, identifiers still normalize, and the existing regression test passes in both builders.
Written by the indexing model from the issue text.
Description
Problem
Both Python SDKs (thrift and embedded) lowercase every output() column string before parsing it:
table.output(["'ACTIVE'"]) # silently selects 'active'
The lowering is meant to make the special output tokens (*, _row_id, _score, _distance, ...) case-insensitive, but it rewrites the whole expression string, including string literals inside it. Any literal with uppercase characters is corrupted before the server ever sees it - and once json_extract(...) parses through the SDKs (currently blocked by #3463), a call like json_extract(data, '$.UserName') would silently query the key $.username and return NULL.
The HTTP API is not affected: it forwards output strings to the server, which parses them case-correctly. So the same query returns different data depending on which client you use.
Root cause
python/infinity_sdk/infinity/remote_thrift/query_builder.py and python/infinity_embedded/local_infinity/query_builder.py, output():
for column in columns:
if isinstance(column, str):
column = column.lower() # rewrites the expression itself
match column:
...
case _:
... maybe_parse(column) ... # parses the lowered string
Fix
Match the special tokens against a lowercased copy and parse the original string:
key = column.lower() if isinstance(column, str) else column
match key:
...
case _:
... maybe_parse(column) ... # original case preserved
Plain identifiers are still lowercased later by the exp.Column arm (alias_or_name.lower()), so column-name handling is unchanged; only string literals keep their case.
Testing
- Reproduced on current main (eca7266), sqlglot 30.18.0: before the fix
output(["'ACTIVE'"])built a constant expression holding'active'in both SDKs; after the fix it holds'ACTIVE'._SCOREstill maps to thescorefunction,MyColstill normalizes tomycol, and*still selects all. - Added regression test
test_output_preserves_string_literal_caseinpython/test_pysdk/test_condition.pycovering the thrift builder directly and the embedded builder in embedded mode. - Full pysdk suite not run locally; it needs a running server / built embedded engine.
- Dominant language
- C++
- Stars
- 4.7k
- Forks
- 445
- Avg merge
- 2d 9h
- Merged PRs (30d)
- 8
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from infiniflow/infinity
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
infiniflow/infinity#3502 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
infiniflow/infinity#3500 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
infiniflow/infinity#3492 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
infiniflow/infinity#3491 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
infiniflow/infinity#3484 ·
All issues in infiniflow/infinity
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
AXERA-TECH/ax-llm#77 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
games-on-whales/wolf#509 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
bug-unconfirmed
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
NVIDIA/cuda-samples#453 ·