graflo.db.edge_direction_support¶
Backend support for edge directionality (advisory — never raises).
Edge.directed is a statement about the model: when false, endpoint order
carries no meaning and the two orientations denote one relationship. Backends
express that to wildly different degrees, and the difference matters mostly on
the read path — reaching an edge from its target endpoint is free on some
backends, needs an unemitted clause on others, and is a schema-time decision
that cannot be retrofitted on TigerGraph.
This module records that matrix so callers (schema application, traversal planning, capability reporting) can consult one table instead of re-deriving per-backend behaviour inline.
Unlike :mod:graflo.db.field_type_support, nothing here raises.
directed=False is already expressible in shipped manifests and is silently
ignored by seven of the eight targets; refusing it now would reject working
schemas. Callers get diagnostics and decide.
EdgeDirectionDiagnostic
dataclass
¶
One finding about how a backend will treat a logically undirected edge.
Source code in graflo/db/edge_direction_support.py
ReverseTraversalCost
¶
Bases: StrEnum
What it costs to reach an edge from its target endpoint.
Source code in graflo/db/edge_direction_support.py
CHEAP = 'cheap'
class-attribute
instance-attribute
¶
Relationships are stored bidirectionally; the reverse pattern is legal and fast.
CLAUSE_REQUIRED = 'clause_required'
class-attribute
instance-attribute
¶
Cheap once asked for, but only via an explicit reverse/bidirectional clause.
FREE = 'free'
class-attribute
instance-attribute
¶
Both endpoints are indexed; the reverse query is the same price.
INDEX_REQUIRED = 'index_required'
class-attribute
instance-attribute
¶
Needs a secondary index on the target column before it is affordable.
MATERIALIZATION_REQUIRED = 'materialization_required'
class-attribute
instance-attribute
¶
Direction is the storage partition key; the reverse view must be written out.
SCHEMA_TIME_ONLY = 'schema_time_only'
class-attribute
instance-attribute
¶
Decided at DDL time; no query rewrite can recover it afterwards.
UnsupportedEdgeDirectionError
¶
Bases: ValueError
Raised when a backend cannot answer a read in the requested direction.
Only TigerGraph can reach this: reverse reachability there is fixed when the
edge type is created (WITH REVERSE_EDGE), so no query rewrite recovers it.
Failing loudly is deliberate — silently returning outgoing edges for an
ANY request would under-report the neighbourhood with no signal.
Source code in graflo/db/edge_direction_support.py
assert_direction_supported(db_type, direction, *, has_reverse_edge=False, edge_is_undirected=False)
¶
Raise if db_type cannot answer a read in direction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
db_type
|
DBType
|
Backend being queried. |
required |
direction
|
EdgeDirection
|
Requested orientation. |
required |
has_reverse_edge
|
bool
|
Whether a paired reverse edge type is declared for the
edge ( |
False
|
edge_is_undirected
|
bool
|
Whether the edge type itself was created undirected. On a backend with native undirected edges that already answers both orientations, so no reverse type is needed. |
False
|
Raises:
| Type | Description |
|---|---|
UnsupportedEdgeDirectionError
|
when the backend physically cannot follow the edge backwards. |
Source code in graflo/db/edge_direction_support.py
check_schema_edge_directions(db_type, schema)
¶
Report how db_type will treat each logically undirected edge.
Returns an empty list when the schema declares no undirected edges, or when the backend represents them natively. Never raises: an unknown backend yields no diagnostics rather than blocking a schema application.
Source code in graflo/db/edge_direction_support.py
default_direction_for_edge(edge)
¶
The direction a read should follow for edge when none is requested.
This is where Edge.directed stops being an annotation and starts
steering queries: an undirected edge reads as :attr:EdgeDirection.ANY,
because both orientations denote the same relationship and anchoring on
source alone would drop half the neighbourhood.
Source code in graflo/db/edge_direction_support.py
iter_undirected_edges(schema)
¶
Yield the id of every edge in schema declared logically undirected.
Source code in graflo/db/edge_direction_support.py
reverse_traversal_cost(db_type)
¶
What it costs to reach an edge from its target endpoint on db_type.
Raises:
| Type | Description |
|---|---|
KeyError
|
if |
Source code in graflo/db/edge_direction_support.py
supports_native_undirected(db_type)
¶
Whether the backend has an undirected edge type in its schema language.