Skip to content

Commit 40db3a6

Browse files
committed
test(gfql): cover index scan declines
1 parent 9d7a767 commit 40db3a6

1 file changed

Lines changed: 70 additions & 1 deletion

File tree

graphistry/tests/compute/gfql/index/test_index.py

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
importorskip so GPU lanes run only where available.
66
"""
77
import importlib
8+
from copy import copy
89

910
import numpy as np
1011
import pandas as pd
1112
import pytest
1213

1314
import graphistry
1415
from graphistry.compute.ast import n, e_forward, e_reverse
15-
from graphistry.compute.gfql.index.api import _engine_mismatch_reason
16+
from graphistry.compute.gfql.index.api import _engine_mismatch_reason, maybe_index_hop
1617
from graphistry.compute.gfql.index import (
1718
CreateIndex, DropIndex, ShowIndexes, index_op_from_json, parse_index_ddl,
1819
get_registry,
@@ -242,6 +243,74 @@ def test_index_policy_force_and_explain(graph, engine):
242243
assert rep_force["error"] is None
243244

244245

246+
def test_maybe_index_hop_reports_no_resident_index(graph):
247+
"""A direct planner caller gets a named scan decline when no index is resident."""
248+
from graphistry.Engine import Engine
249+
from graphistry.compute.gfql.index import index_trace
250+
251+
with index_trace() as steps:
252+
result = maybe_index_hop(
253+
graph,
254+
Engine.PANDAS,
255+
nodes=pd.DataFrame({"id": [0]}),
256+
hops=1,
257+
direction="forward",
258+
return_as_wave_front=False,
259+
policy="use",
260+
)
261+
262+
assert result is None
263+
assert steps[-1]["decision_code"] == "no_resident_index"
264+
265+
266+
def test_maybe_index_hop_reports_missing_graph_columns(graph):
267+
"""A resident index cannot make an unbound graph use a different query path."""
268+
from graphistry.Engine import Engine
269+
from graphistry.compute.gfql.index import index_trace
270+
271+
unbound = copy(graph.gfql_index_all(engine="pandas"))
272+
unbound._nodes = None
273+
with index_trace() as steps:
274+
result = maybe_index_hop(
275+
unbound,
276+
Engine.PANDAS,
277+
nodes=pd.DataFrame({"id": [0]}),
278+
hops=1,
279+
direction="forward",
280+
return_as_wave_front=False,
281+
policy="use",
282+
)
283+
284+
assert result is None
285+
assert steps[-1]["decision_code"] == "missing_graph_columns"
286+
287+
288+
def test_maybe_index_hop_reports_auto_build_decline_with_scan_parity(graph):
289+
"""An unselective auto request declines the build and preserves scan results."""
290+
from graphistry.Engine import Engine
291+
from graphistry.compute.gfql.index import index_trace
292+
293+
seeds = graph._nodes.copy()
294+
with index_trace() as steps:
295+
result = maybe_index_hop(
296+
graph,
297+
Engine.PANDAS,
298+
nodes=seeds,
299+
hops=1,
300+
direction="forward",
301+
return_as_wave_front=False,
302+
policy="auto",
303+
)
304+
305+
auto_graph = graph.bind()
306+
auto_graph._gfql_index_policy = "auto"
307+
auto_result = auto_graph.hop(nodes=seeds, engine="pandas", hops=1)
308+
scan_result = graph.hop(nodes=seeds, engine="pandas", hops=1)
309+
assert result is None
310+
assert steps[-1]["decision_code"] == "index_build_declined"
311+
assert _sig(auto_result) == _sig(scan_result)
312+
313+
245314
@pytest.mark.parametrize("engine", ENGINES)
246315
def test_explain_exposes_planner_diagnostics(graph, engine):
247316
"""LP1: gfql_explain surfaces the planner's cost signal — seed cardinality, the

0 commit comments

Comments
 (0)