infiniflow / infiniflow/infinity

[Bug]: embedded SDK rejects IS NULL filters ("unknown binary expression: is")

Open Beginner friendly
#3,471 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.