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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions