infiniflow / infiniflow/infinity
[Bug]: embedded SDK rejects IS NULL filters ("unknown binary expression: is")
- Dominant language
- C++
- Stars
- 4.7k
- Forks
- 445
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 7
Description
## Problem
In the embedded SDK, a simple `IS NULL` filter crashes:
```python
from sqlglot import condition
from infinity_embedded.local_infinity.utils import traverse_conditions
traverse_conditions(condition("c1 IS NULL"))
# InfinityException: 3069, unknown binary expression: is
```
while `c1 IS NOT NULL` works, and the same `IS NULL` filter works fine through the thrift SDK and the HTTP API.
## Root cause
`python/infinity_embedded/local_infinity/utils.py`, `traverse_conditions()`:
sqlglot parses `c1 IS NULL` as `exp.Is`, and `exp.Is` is a subclass of `exp.Binary`. The dedicated `exp.Is` arm (which builds the `is_null` function the engine provides, `src/function/scalar/is_null.cppm`) sits *after* the generic `exp.Binary` arm, so it is unreachable: every `IS NULL` hits the binary arm first and `binary_exp_to_paser_exp("is")` raises `unknown binary expression: is`.
`IS NOT NULL` survives only because sqlglot wraps it in `exp.Not`, which is not a `Binary`, so the `Not + Is` arm still fires.
## Fix
Move the `exp.Is` / `exp.Not + exp.Is` arms above the generic `exp.Binary` arm so they are reachable. No behavior change for any other expression.
## Testing
- Verified on current main (eca7266) with sqlglot 30.18.0: `IS NULL` raised before the change, and builds the same `is_null` / `is_not_null` function expressions as the intended arms after it; `IS TRUE` still raises the intended "Unsupported IS expression" error.
- Added regression test `test_condition_embedded_is_null` in `python/test_pysdk/test_condition.py` (embedded-only, checks both `IS NULL` and `IS NOT NULL`).
- Full pysdk suite not run locally; it needs a built embedded engine. The change is confined to arm ordering in the embedded SDK's condition traversal.
Contributor guide
Research direction
Start in python/infinity_embedded/local_infinity/utils.py at traverse_conditions(), then review the regression test test_condition_embedded_is_null in python/test_pysdk/test_condition.py. Run that test with a built embedded engine and verify both IS NULL and IS NOT NULL produce the expected expressions while IS TRUE retains its unsupported-expression error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend, databases
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 91/100