Skip to content

GFQL polars: LazyFrame node input crashes undirected single-hop Cypher (TypeError, not parity/NIE) #1740

Description

@lmeyerov

Found by the #1737 seam re-review's input-type probes; pre-existing (the crash site is untouched by #1737's diff and predates it).

Repro

import polars as pl, graphistry
nodes = pl.DataFrame({"id": [1, 2], "label__Person": [True, True]}).lazy()  # LazyFrame nodes
edges = pl.DataFrame({"src": [1], "dst": [2], "type": ["KNOWS"]})
g = graphistry.nodes(nodes, "id").edges(edges, "src", "dst")
g.gfql("MATCH (a:Person)-[:KNOWS]-(b) RETURN b.id AS x", engine="polars")
# TypeError: expected `other` to be a 'LazyFrame', not 'DataFrame'

Matrix (undirected single-hop shape): lazy nodes + eager edges → crash; eager nodes + lazy edges → OK; lazy both → crash. Directed hops with LazyFrame inputs work fine.

Cause

_chain_traversal_polars's undirected single-hop node override (graphistry/compute/gfql/lazy/engine/polars/chain.py:~720):

_both = endpoint_ids(rev._edges, src, dst, node_col).unique(subset=[node_col])
rev = rev.nodes(g._nodes.join(_both, on=node_col, how="semi"), node_col)

g._nodes is the user's LazyFrame while _both is eager (or vice versa) — polars refuses mixed-laziness joins. Uncaught TypeError violates the parity-or-honest-NIE contract (should be a correct result or an NIE, never a crash).

Fix sketch

Normalize laziness at the join (_both.lazy() when g._nodes is a LazyFrame, or .lazy() both sides and keep the plan deferred). Add a lazy/eager input matrix test for the undirected shape.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions