44
55use Exception ;
66use GuzzleHttp \Client ;
7- use GuzzleHttp \Exception \GuzzleException ;
8- use GuzzleHttp \Exception \RequestException ;
9- use Neo4j \QueryAPI \Objects \ChildQueryPlan ;
10- use Neo4j \QueryAPI \Objects \QueryArguments ;
7+ use Neo4j \QueryAPI \Objects \ProfiledQueryPlanArguments ;
118use Neo4j \QueryAPI \Objects \ResultCounters ;
129use Neo4j \QueryAPI \Objects \ProfiledQueryPlan ;
1310use Neo4j \QueryAPI \Results \ResultRow ;
@@ -26,18 +23,9 @@ public function __construct(Client $client)
2623 {
2724 $ this ->client = $ client ;
2825 }
29- /**
30- * @api
31- */
26+
3227 public static function login (string $ address , string $ username , string $ password ): self
3328 {
34- if (empty ($ address )) {
35- throw new RuntimeException ('Address cannot be empty ' );
36- }
37- if (empty ($ username ) || empty ($ password )) {
38- throw new RuntimeException ('Missing username or password ' );
39- }
40-
4129 $ client = new Client ([
4230 'base_uri ' => rtrim ($ address , '/ ' ),
4331 'timeout ' => 10.0 ,
@@ -54,7 +42,6 @@ public static function login(string $address, string $username, string $password
5442 /**
5543 * @throws Neo4jException
5644 * @throws RequestExceptionInterface
57- * @api
5845 */
5946 public function run (string $ cypher , array $ parameters = [], string $ database = 'neo4j ' , Bookmarks $ bookmark = null ): ResultSet
6047 {
@@ -69,15 +56,21 @@ public function run(string $cypher, array $parameters = [], string $database = '
6956 $ payload ['bookmarks ' ] = $ bookmark ->getBookmarks ();
7057 }
7158
72- $ response = $ this ->client ->post ( '/db/ ' . $ database . '/query/v2 ' , [
59+ $ response = $ this ->client ->request ( ' POST ' , '/db/ ' . $ database . '/query/v2 ' , [
7360 'json ' => $ payload ,
7461 ]);
7562
76- $ data = json_decode ($ response ->getBody ()->getContents (), true );
63+ $ contents = $ response ->getBody ()->getContents ();
64+ $ data = json_decode ($ contents , true , flags: JSON_THROW_ON_ERROR );
7765 $ ogm = new OGM ();
7866
79- $ keys = $ data ['data ' ]['fields ' ];
80- $ values = $ data ['data ' ]['values ' ];
67+ $ keys = $ data ['data ' ]['fields ' ] ?? [];
68+ $ values = $ data ['data ' ]['values ' ] ?? []; // Ensure $values is an array
69+
70+ if (!is_array ($ values )) {
71+ throw new RuntimeException ('Unexpected response format: values is not an array. ' );
72+ }
73+
8174 $ rows = array_map (function ($ resultRow ) use ($ ogm , $ keys ) {
8275 $ data = [];
8376 foreach ($ keys as $ index => $ key ) {
@@ -86,10 +79,7 @@ public function run(string $cypher, array $parameters = [], string $database = '
8679 }
8780 return new ResultRow ($ data );
8881 }, $ values );
89-
90- if (isset ($ data ['profiledQueryPlan ' ])) {
91- $ profile = $ this ->createProfileData ($ data ['profiledQueryPlan ' ]);
92- }
82+ $ profile = isset ($ data ['profiledQueryPlan ' ]) ? $ this ->createProfileData ($ data ['profiledQueryPlan ' ]) : null ;
9383
9484 $ resultCounters = new ResultCounters (
9585 containsUpdates: $ data ['counters ' ]['containsUpdates ' ] ?? false ,
@@ -119,19 +109,14 @@ public function run(string $cypher, array $parameters = [], string $database = '
119109 if ($ response !== null ) {
120110 $ contents = $ response ->getBody ()->getContents ();
121111 $ errorResponse = json_decode ($ contents , true );
122-
123112 throw Neo4jException::fromNeo4jResponse ($ errorResponse , $ e );
124113 }
114+ throw $ e ;
125115 }
126- throw new RuntimeException ('Error executing query: ' . $ e ->getMessage (), 0 , $ e );
127116 }
128117
129- /**
130- * @api
131- */
132118 public function beginTransaction (string $ database = 'neo4j ' ): Transaction
133119 {
134- unset($ database );
135120 $ response = $ this ->client ->post ("/db/neo4j/query/v2/tx " );
136121
137122 $ clusterAffinity = $ response ->getHeaderLine ('neo4j-cluster-affinity ' );
@@ -143,27 +128,43 @@ public function beginTransaction(string $database = 'neo4j'): Transaction
143128
144129 private function createProfileData (array $ data ): ProfiledQueryPlan
145130 {
131+ $ ogm = new OGM ();
132+
133+ // Map arguments using OGM
146134 $ arguments = $ data ['arguments ' ];
135+ $ mappedArguments = [];
136+ foreach ($ arguments as $ key => $ value ) {
137+ if (is_array ($ value ) && array_key_exists ('$type ' , $ value ) && array_key_exists ('_value ' , $ value )) {
138+ $ mappedArguments [$ key ] = $ ogm ->map ($ value );
139+ } else {
140+ $ mappedArguments [$ key ] = $ value ;
141+ }
142+ }
147143
148- $ queryArguments = new QueryArguments (
149- $ arguments ['globalMemory ' ] ?? 0 ,
150- $ arguments ['plannerImpl ' ] ?? '' ,
151- $ arguments ['memory ' ] ?? 0 ,
152- $ arguments ['stringRepresentation ' ] ?? '' ,
153- is_string ($ arguments ['runtime ' ] ?? '' ) ? $ arguments ['runtime ' ] : json_encode ($ arguments ['runtime ' ]),
154- $ arguments ['runtimeImpl ' ] ?? '' ,
155- $ arguments ['dbHits ' ] ?? 0 ,
156- $ arguments ['batchSize ' ] ?? 0 ,
157- $ arguments ['details ' ] ?? '' ,
158- $ arguments ['plannerVersion ' ] ?? '' ,
159- $ arguments ['pipelineInfo ' ] ?? '' ,
160- $ arguments ['runtimeVersion ' ] ?? '' ,
161- $ arguments ['id ' ] ?? 0 ,
162- $ arguments ['estimatedRows ' ] ?? 0.0 ,
163- is_string ($ arguments ['planner ' ] ?? '' ) ? $ arguments ['planner ' ] : json_encode ($ arguments ['planner ' ]),
164- $ arguments ['rows ' ] ?? 0
144+ $ queryArguments = new ProfiledQueryPlanArguments (
145+ globalMemory: $ mappedArguments ['GlobalMemory ' ] ?? null ,
146+ plannerImpl: $ mappedArguments ['planner-impl ' ] ?? null ,
147+ memory: $ mappedArguments ['Memory ' ] ?? null ,
148+ stringRepresentation: $ mappedArguments ['string-representation ' ] ?? null ,
149+ runtime: $ mappedArguments ['runtime ' ] ?? null ,
150+ time: $ mappedArguments ['Time ' ] ?? null ,
151+ pageCacheMisses: $ mappedArguments ['PageCacheMisses ' ] ?? null ,
152+ pageCacheHits: $ mappedArguments ['PageCacheHits ' ] ?? null ,
153+ runtimeImpl: $ mappedArguments ['runtime-impl ' ] ?? null ,
154+ version: $ mappedArguments ['version ' ] ?? null ,
155+ dbHits: $ mappedArguments ['DbHits ' ] ?? null ,
156+ batchSize: $ mappedArguments ['batch-size ' ] ?? null ,
157+ details: $ mappedArguments ['Details ' ] ?? null ,
158+ plannerVersion: $ mappedArguments ['planner-version ' ] ?? null ,
159+ pipelineInfo: $ mappedArguments ['PipelineInfo ' ] ?? null ,
160+ runtimeVersion: $ mappedArguments ['runtime-version ' ] ?? null ,
161+ id: $ mappedArguments ['Id ' ] ?? null ,
162+ estimatedRows: $ mappedArguments ['EstimatedRows ' ] ?? null ,
163+ planner: $ mappedArguments ['planner ' ] ?? null ,
164+ rows: $ mappedArguments ['Rows ' ?? null ]
165165 );
166166
167+ $ identifiers = $ data ['identifiers ' ] ?? [];
167168 $ profiledQueryPlan = new ProfiledQueryPlan (
168169 $ data ['dbHits ' ],
169170 $ data ['records ' ],
@@ -173,17 +174,17 @@ private function createProfileData(array $data): ProfiledQueryPlan
173174 $ data ['pageCacheHitRatio ' ],
174175 $ data ['time ' ],
175176 $ data ['operatorType ' ],
176- $ queryArguments
177+ $ queryArguments ,
178+ children: [],
179+ identifiers: $ identifiers
177180 );
178-
181+ // Process children recursively
179182 foreach ($ data ['children ' ] as $ child ) {
180183 $ childQueryPlan = $ this ->createProfileData ($ child );
181-
182184 $ profiledQueryPlan ->addChild ($ childQueryPlan );
183185 }
184186
185187 return $ profiledQueryPlan ;
186188 }
187189
188-
189190}
0 commit comments