infiniflow / infiniflow/infinity
[Bug]: embedded SDK crashes on count(*) / count(col) in output columns ("unknown expression type: True")
- Dominant language
- C++
- Stars
- 4.7k
- Forks
- 445
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 7
Description
## Problem
Any `count(...)` in the embedded SDK's output columns crashes:
```python
from sqlglot import parse_one
from infinity_embedded.local_infinity.utils import parse_expr
parse_expr(parse_one("count(*)"))
# Exception: unknown expression type: True
parse_expr(parse_one("count(c1)"))
# Exception: unknown expression type: True
```
so `table.output(["count(*)"])` / `table.output(["count(c1)"])` can never be used with the embedded engine, while the same expressions work through the thrift SDK and HTTP API.
## Root cause
`python/infinity_embedded/local_infinity/utils.py`, the generic `exp.Func` arm of `traverse_conditions()`:
```python
for arg in cons.args.values():
if arg:
parsed_expr = parse_expr(arg) # crashes
```
sqlglot's `Count` node is `Count(this=Star(), expressions=[], big_int=True)`: next to the real argument it carries an empty `expressions` list and a `big_int` **boolean flag**. `big_int=True` is truthy, so it is fed straight into `parse_expr(True)`, which hits the fallback and raises `unknown expression type: True`. The flag is node metadata, not a function argument.
The thrift SDK does not hit this because its Func arm only passes `exp.Expression` values on.
## Fix
In the generic Func arm, skip `None` entries, empty lists, and non-expression node flags (bools/strings like `Count.big_int`); keep raising on non-empty list args so expressions that need a dedicated arm (e.g. `UNNEST`) still fail loudly instead of being silently dropped.
## Testing
- Verified on current main (eca7266) with sqlglot 30.18.0: `count(*)` and `count(c1)` raised before the change; after it they build the same `count` function expression the thrift SDK produces (single star/column argument). `sum`, `abs`, `round`, `substring`, `length`, `upper` and list-arg cases (`unnest`, `coalesce`) behave exactly as before.
- Added regression test `test_output_embedded_count` in `python/test_pysdk/test_condition.py` (embedded-only).
- Full pysdk suite not run locally; it needs a built embedded engine.
Contributor guide
Research direction
Start in python/infinity_embedded/local_infinity/utils.py at the generic exp.Func arm of traverse_conditions(), then review test_output_embedded_count in python/test_pysdk/test_condition.py. Run the embedded count regression test with a built embedded engine. Done means count(*) and count(c1) produce the expected function expressions while existing scalar and list-argument behavior remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 86/100