Repository navigation
0.61.0
Release PR: #2191
Added
-
GFQL relationship-type adjacency sidecars (#2184):
gfql_index_edges(..., type_column=..., type_values=...)explicitly builds forward and reverse adjacency indexes for selected string or integer relationship values. Matching queries can narrow candidate edge rows while retaining the full edge predicate and canonical results; queries without a live sidecar use ordinary adjacency. Sidecars are built at graph setup, share neighbor arrays with ordinary indexes, and appear astyped:rows with incremental CSR bytes inshow_indexes(). Typed options are keyword-only. cuDF builds may add overhead on dense-community shapes, and sidecars must be rebuilt after rebinding or changing edges. -
GFQL Cypher backtick identifiers: property names, aliases, labels, relationship types, and map keys can preserve spaces, dots, hyphens, escaped backticks, and reserved words through parsing, binding, lowering, and rendering. Unterminated backticks remain syntax errors, and unquoted dotted-property semantics are unchanged (#2198).
-
GFQL node-type segments and indexed destination filtering (#2192, #2193):
gfql_index_node_types(..., type_column=..., type_values=...)explicitly builds node row-position segments for selected scalar types or Boolean labels. Matching seeded wavefront hops can narrow source and destination candidates while retaining canonical node filters and results; queries without a live segment use the ordinary paths. A simple Polars plain-chain destination node predicate may additionally lower into an indexed direct hop; this narrow lowering is separate from general node-segment support. Segments are built at graph setup, appear astyped_node:node_type_segmentrows inshow_indexes(), and selective drop supports all segments, one column, or one segment. -
GFQL Cypher aggregates over relationship rows: in a single required
MATCH, aggregates such asMATCH (a)-[r]->(b) RETURN a, count(*), sum(r.w), collect(b.id)run on per-path binding rows, so group keys and arguments can reference any node or relationship alias, includingDISTINCT, post-aggregate arithmetic (count(b) + 1) and multi-alias keys. These shapes previously raised unsupported-query errors. -
GFQL
DateTimeValue.from_epoch(#2197): construct an explicit UTC instant from epoch seconds or milliseconds withunit="s"|"ms"; typed wire datetime values accept the equivalent{"type": "datetime", "value": ..., "unit": "s"|"ms"}form.
Fixed
-
GFQL comparison predicates and typed wire inputs reject numeric-versus-datetime comparisons: a bare integer no longer silently compares as an opaque unitless value against a datetime column. Use a typed ISO datetime value or explicit
DateTimeValue.from_epochUTC epoch units. There is no default epoch unit, andepoch_mspredicate flags are rejected (#2197). This boundary does not change all mixed-type CypherEQ/NEsemantics. -
GFQL Call runtime failures use structured
E306: exceptions from safelisted handlers are wrapped asGFQLCallExecutionErrorwith the handler name, requested engine, original exception type, and original exception as__cause__; input/reference validation retains its existing structured codes (#2199). -
GFQL index byte reporting is engine-aware (#2201):
show_indexes()reports Polars and cuDF sidecar/segment bytes without assuming a pandas-only Series interface. -
GFQL Polars indexed connected bindings: the default planner gate now admits moderately sized key frontiers and edge gathers. Measured on LDBC SF1 IC4; other families showed no regression, and the relaxation is not claimed to generalize. Explicit cost-gate overrides still take precedence; other index paths and engines retain their defaults.
-
GFQL indexed traversal uses faster sorted uniqueness: integer index arrays with at least 128 entries and Boolean arrays with more than one entry use sorted deduplication, avoiding the slower
numpy.uniquepath. Measured on NumPy 2.4; applies on all versions. Tiny integer arrays retain nativeuniquebecause the extra sort/mask setup can cost more there; tiny Boolean arrays favor sorting. Other dtypes and cuPy retain their existing uniqueness semantics. IC4 benchmark evidence and follow-up are tracked in graphistry/pyg-bench#303. -
Graph algorithms on Polars-bound graphs (#2025):
compute_igraph,layout_igraph,compute_cugraphandlayout_cugraphaccept graphs bound to PolarsDataFrameorLazyFrameframes. igraph runs on pandas and cuGraph on cuDF (via Arrow); results return as eager Polars frames with node id, source, destination and edge id dtypes preserved. The frame conversion helper is shared with GFQLcall(). -
Layouts on Polars-bound graphs (#1966):
circle_layout,tree_layout,ring_categorical_layout,ring_continuous_layout,time_ring_layout,group_in_a_box_layout,modularity_weighted_layout,mercator_layoutandfa2_layoutaccept PolarsDataFrameorLazyFrameframes. They run on pandas and return eager Polars frames, instead of crashing or silently returning pandas. Layouts with backend support honor an explicit engine; Mercator has noengineparameter, and tree's legacyengine='cudf'keyword still runs on pandas. -
GFQL indexed bindings relationship uniqueness (#2177): the indexed connected-bindings and array path-bag routes could bind one relationship to two hops of a Cypher MATCH pattern (for example
(a)-[:K]->(b)<-[:K]-(c)returnedc = athrough a single edge) under the defaultuse/autoindex policies. Both routes now drop paths that reuse an edge whenever two hops could match the same relationship; hops with pairwise-distinct edge types skip the check. With uniqueness enforced, undirected hops in multi-hop patterns are admitted to the indexed path. -
GFQL Cypher
count(DISTINCT <alias>)on binding rows: counted the active alias instead of the named one, soMATCH (a)-[r]->(b) WITH a, count(DISTINCT b) AS creturned 1 per group. It now counts distinctb; on Polars the shape runs natively instead of declining.