66use GuzzleHttp \Client ;
77use GuzzleHttp \Exception \GuzzleException ;
88use GuzzleHttp \Exception \RequestException ;
9+ use Neo4j \QueryAPI \Objects \ChildQueryPlan ;
10+ use Neo4j \QueryAPI \Objects \QueryArguments ;
911use Neo4j \QueryAPI \Objects \ResultCounters ;
12+ use Neo4j \QueryAPI \Objects \ProfiledQueryPlan ;
1013use Neo4j \QueryAPI \Results \ResultRow ;
1114use Neo4j \QueryAPI \Results \ResultSet ;
1215use Neo4j \QueryAPI \Exception \Neo4jException ;
@@ -37,7 +40,7 @@ public static function login(string $address, string $username, string $password
3740 'headers ' => [
3841 'Authorization ' => 'Basic ' . base64_encode ("$ username: $ password " ),
3942 'Content-Type ' => 'application/vnd.neo4j.query ' ,
40- 'Accept ' => 'application/vnd.neo4j.query ' ,
43+ 'Accept ' => 'application/vnd.neo4j.query ' ,
4144 ],
4245 ]);
4346
@@ -80,6 +83,10 @@ public function run(string $cypher, array $parameters = [], string $database = '
8083 return new ResultRow ($ data );
8184 }, $ values );
8285
86+ if (isset ($ data ['profiledQueryPlan ' ])) {
87+ $ profile = $ this ->createProfileData ($ data ['profiledQueryPlan ' ]);
88+ }
89+
8390 $ resultCounters = new ResultCounters (
8491 containsUpdates: $ data ['counters ' ]['containsUpdates ' ] ?? false ,
8592 nodesCreated: $ data ['counters ' ]['nodesCreated ' ] ?? 0 ,
@@ -97,22 +104,79 @@ public function run(string $cypher, array $parameters = [], string $database = '
97104 systemUpdates: $ data ['counters ' ]['systemUpdates ' ] ?? 0
98105 );
99106
100- $ resultSet = new ResultSet ($ rows , $ resultCounters , new Bookmarks ( $ data [ ' bookmarks ' ] ?? []));
101-
102-
103- return $ resultSet ;
104-
105- } catch ( RequestException $ e ) {
106- {
107- $ response = $ e ->getResponse ();
108- if ($ response !== null ) {
109- $ contents = $ response ->getBody ()->getContents ();
110- $ errorResponse = json_decode ($ contents , true );
107+ return new ResultSet (
108+ $ rows ,
109+ $ resultCounters ,
110+ new Bookmarks ( $ data [ ' bookmarks ' ] ?? []),
111+ $ profile
112+ );
113+ } catch ( RequestExceptionInterface $ e ) {
114+ $ response = $ e ->getResponse ();
115+ if ($ response !== null ) {
116+ $ contents = $ response ->getBody ()->getContents ();
117+ $ errorResponse = json_decode ($ contents , true );
111118
112119 throw Neo4jException::fromNeo4jResponse ($ errorResponse , $ e );
113120 }
114121 }
115122 throw new RuntimeException ('Error executing query: ' . $ e ->getMessage (), 0 , $ e );
116123 }
124+
125+
126+ public function beginTransaction (string $ database = 'neo4j ' ): Transaction
127+ {
128+ $ response = $ this ->client ->post ("/db/neo4j/query/v2/tx " );
129+
130+ $ clusterAffinity = $ response ->getHeaderLine ('neo4j-cluster-affinity ' );
131+ $ responseData = json_decode ($ response ->getBody (), true );
132+ $ transactionId = $ responseData ['transaction ' ]['id ' ];
133+
134+ return new Transaction ($ this ->client , $ clusterAffinity , $ transactionId );
135+ }
136+
137+ private function createProfileData (array $ data ): ProfiledQueryPlan
138+ {
139+ $ arguments = $ data ['arguments ' ];
140+
141+ $ queryArguments = new QueryArguments (
142+ $ arguments ['globalMemory ' ] ?? 0 ,
143+ $ arguments ['plannerImpl ' ] ?? '' ,
144+ $ arguments ['memory ' ] ?? 0 ,
145+ $ arguments ['stringRepresentation ' ] ?? '' ,
146+ is_string ($ arguments ['runtime ' ] ?? '' ) ? $ arguments ['runtime ' ] : json_encode ($ arguments ['runtime ' ]),
147+ $ arguments ['runtimeImpl ' ] ?? '' ,
148+ $ arguments ['dbHits ' ] ?? 0 ,
149+ $ arguments ['batchSize ' ] ?? 0 ,
150+ $ arguments ['details ' ] ?? '' ,
151+ $ arguments ['plannerVersion ' ] ?? '' ,
152+ $ arguments ['pipelineInfo ' ] ?? '' ,
153+ $ arguments ['runtimeVersion ' ] ?? '' ,
154+ $ arguments ['id ' ] ?? 0 ,
155+ $ arguments ['estimatedRows ' ] ?? 0.0 ,
156+ is_string ($ arguments ['planner ' ] ?? '' ) ? $ arguments ['planner ' ] : json_encode ($ arguments ['planner ' ]),
157+ $ arguments ['rows ' ] ?? 0
158+ );
159+
160+ $ profiledQueryPlan = new ProfiledQueryPlan (
161+ $ data ['dbHits ' ],
162+ $ data ['records ' ],
163+ $ data ['hasPageCacheStats ' ],
164+ $ data ['pageCacheHits ' ],
165+ $ data ['pageCacheMisses ' ],
166+ $ data ['pageCacheHitRatio ' ],
167+ $ data ['time ' ],
168+ $ data ['operatorType ' ],
169+ $ queryArguments
170+ );
171+
172+ foreach ($ data ['children ' ] as $ child ) {
173+ $ childQueryPlan = $ this ->createProfileData ($ child );
174+
175+ $ profiledQueryPlan ->addChild ($ childQueryPlan );
176+ }
177+
178+ return $ profiledQueryPlan ;
117179 }
180+
181+
118182}
0 commit comments