22
33from __future__ import annotations
44
5- from typing import Any , Dict , Optional , Union
5+ from typing import Any , AsyncIterator , Dict , List , Optional , Union
66
77from ..parsing .ast_node import ASTNode
88from .node import Node
@@ -48,35 +48,57 @@ def add_relationship(self, relationship: 'Relationship', statement: ASTNode) ->
4848 physical = PhysicalRelationship ()
4949 physical .type = relationship .type
5050 physical .statement = statement
51+ if relationship .source is not None :
52+ physical .source = relationship .source
53+ if relationship .target is not None :
54+ physical .target = relationship .target
5155 Database ._relationships [relationship .type ] = physical
5256
5357 def get_relationship (self , relationship : 'Relationship' ) -> Optional ['PhysicalRelationship' ]:
5458 """Gets a relationship from the database."""
5559 return Database ._relationships .get (relationship .type ) if relationship .type else None
5660
57- async def schema (self ) -> list [dict [str , Any ]]:
61+ def get_relationships (self , relationship : 'Relationship' ) -> list ['PhysicalRelationship' ]:
62+ """Gets multiple physical relationships for ORed types."""
63+ result = []
64+ for rel_type in relationship .types :
65+ physical = Database ._relationships .get (rel_type )
66+ if physical :
67+ result .append (physical )
68+ return result
69+
70+ async def schema (self ) -> List [Dict [str , Any ]]:
5871 """Returns the graph schema with node/relationship labels and sample data."""
59- result : list [ dict [ str , Any ]] = [ ]
72+ return [ item async for item in self . _schema () ]
6073
74+ async def _schema (self ) -> AsyncIterator [Dict [str , Any ]]:
75+ """Async generator for graph schema with node/relationship labels and sample data."""
6176 for label , physical_node in Database ._nodes .items ():
6277 records = await physical_node .data ()
63- entry : dict [str , Any ] = {"kind" : "node " , "label" : label }
78+ entry : Dict [str , Any ] = {"kind" : "Node " , "label" : label }
6479 if records :
6580 sample = {k : v for k , v in records [0 ].items () if k != "id" }
66- if sample :
81+ properties = list (sample .keys ())
82+ if properties :
83+ entry ["properties" ] = properties
6784 entry ["sample" ] = sample
68- result . append ( entry )
85+ yield entry
6986
7087 for rel_type , physical_rel in Database ._relationships .items ():
7188 records = await physical_rel .data ()
72- entry_rel : dict [str , Any ] = {"kind" : "relationship" , "type" : rel_type }
89+ entry_rel : Dict [str , Any ] = {
90+ "kind" : "Relationship" ,
91+ "type" : rel_type ,
92+ "from_label" : physical_rel .source .label if physical_rel .source else None ,
93+ "to_label" : physical_rel .target .label if physical_rel .target else None ,
94+ }
7395 if records :
7496 sample = {k : v for k , v in records [0 ].items () if k not in ("left_id" , "right_id" )}
75- if sample :
97+ properties = list (sample .keys ())
98+ if properties :
99+ entry_rel ["properties" ] = properties
76100 entry_rel ["sample" ] = sample
77- result .append (entry_rel )
78-
79- return result
101+ yield entry_rel
80102
81103 async def get_data (self , element : Union ['Node' , 'Relationship' ]) -> Union ['NodeData' , 'RelationshipData' ]:
82104 """Gets data for a node or relationship."""
@@ -87,6 +109,17 @@ async def get_data(self, element: Union['Node', 'Relationship']) -> Union['NodeD
87109 data = await node .data ()
88110 return NodeData (data )
89111 elif isinstance (element , Relationship ):
112+ if len (element .types ) > 1 :
113+ physicals = self .get_relationships (element )
114+ if not physicals :
115+ raise ValueError (f"No physical relationships found for types { ', ' .join (element .types )} " )
116+ all_records = []
117+ for i , physical in enumerate (physicals ):
118+ records = await physical .data ()
119+ type_name = element .types [i ]
120+ for record in records :
121+ all_records .append ({** record , "_type" : type_name })
122+ return RelationshipData (all_records )
90123 relationship = self .get_relationship (element )
91124 if relationship is None :
92125 raise ValueError (f"Physical relationship not found for type { element .type } " )
0 commit comments