Skip to content

Commit 45dbd7a

Browse files
authored
Merge pull request #6 from nagels-tech/create-query-profile-1951106664
2 parents 78b7002 + 903e46f commit 45dbd7a

File tree

10 files changed

+587
-290
lines changed

10 files changed

+587
-290
lines changed

src/Neo4jQueryAPI.php

Lines changed: 66 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
use GuzzleHttp\Client;
77
use GuzzleHttp\Exception\GuzzleException;
88
use GuzzleHttp\Exception\RequestException;
9+
use Neo4j\QueryAPI\Objects\ChildQueryPlan;
10+
use Neo4j\QueryAPI\Objects\QueryArguments;
911
use Neo4j\QueryAPI\Objects\ResultCounters;
12+
use Neo4j\QueryAPI\Objects\ProfiledQueryPlan;
1013
use Neo4j\QueryAPI\Results\ResultRow;
1114
use Neo4j\QueryAPI\Results\ResultSet;
1215
use Neo4j\QueryAPI\Exception\Neo4jException;
@@ -27,18 +30,13 @@ public function __construct(Client $client)
2730

2831
public static function login(string $address, string $username, string $password): self
2932
{
30-
$username = 'neo4j';
31-
$password = '9lWmptqBgxBOz8NVcTJjgs3cHPyYmsy63ui6Spmw1d0';
32-
$connectionUrl = 'https://6f72daa1.databases.neo4j.io/db/neo4j/query/v2';
33-
34-
3533
$client = new Client([
3634
'base_uri' => rtrim($address, '/'),
3735
'timeout' => 10.0,
3836
'headers' => [
3937
'Authorization' => 'Basic ' . base64_encode("$username:$password"),
4038
'Content-Type' => 'application/vnd.neo4j.query',
41-
'Accept'=>'application/vnd.neo4j.query',
39+
'Accept' => 'application/vnd.neo4j.query',
4240
],
4341
]);
4442

@@ -80,6 +78,10 @@ public function run(string $cypher, array $parameters = [], string $database = '
8078
return new ResultRow($data);
8179
}, $values);
8280

81+
if (isset($data['profiledQueryPlan'])) {
82+
$profile = $this->createProfileData($data['profiledQueryPlan']);
83+
}
84+
8385
$resultCounters = new ResultCounters(
8486
containsUpdates: $data['counters']['containsUpdates'] ?? false,
8587
nodesCreated: $data['counters']['nodesCreated'] ?? 0,
@@ -97,30 +99,25 @@ public function run(string $cypher, array $parameters = [], string $database = '
9799
systemUpdates: $data['counters']['systemUpdates'] ?? 0
98100
);
99101

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);
102+
return new ResultSet(
103+
$rows,
104+
$resultCounters,
105+
new Bookmarks($data['bookmarks'] ?? []),
106+
$profile
107+
);
108+
} catch (RequestExceptionInterface $e) {
109+
$response = $e->getResponse();
110+
if ($response !== null) {
111+
$contents = $response->getBody()->getContents();
112+
$errorResponse = json_decode($contents, true);
111113

112114
throw Neo4jException::fromNeo4jResponse($errorResponse, $e);
113-
}
114-
115-
throw $e;
116115
}
117-
throw new RuntimeException('Error executing query: ' . $e->getMessage(), 0, $e);
116+
117+
throw $e;
118118
}
119119
}
120120

121-
122-
123-
124121
public function beginTransaction(string $database = 'neo4j'): Transaction
125122
{
126123
$response = $this->client->post("/db/neo4j/query/v2/tx");
@@ -129,8 +126,52 @@ public function beginTransaction(string $database = 'neo4j'): Transaction
129126
$responseData = json_decode($response->getBody(), true);
130127
$transactionId = $responseData['transaction']['id'];
131128

129+
return new Transaction($this->client, $clusterAffinity, $transactionId);
130+
}
132131

132+
private function createProfileData(array $data): ProfiledQueryPlan
133+
{
134+
$arguments = $data['arguments'];
135+
136+
$queryArguments = new QueryArguments(
137+
$arguments['globalMemory'] ?? 0,
138+
$arguments['plannerImpl'] ?? '',
139+
$arguments['memory'] ?? 0,
140+
$arguments['stringRepresentation'] ?? '',
141+
is_string($arguments['runtime'] ?? '') ? $arguments['runtime'] : json_encode($arguments['runtime']),
142+
$arguments['runtimeImpl'] ?? '',
143+
$arguments['dbHits'] ?? 0,
144+
$arguments['batchSize'] ?? 0,
145+
$arguments['details'] ?? '',
146+
$arguments['plannerVersion'] ?? '',
147+
$arguments['pipelineInfo'] ?? '',
148+
$arguments['runtimeVersion'] ?? '',
149+
$arguments['id'] ?? 0,
150+
$arguments['estimatedRows'] ?? 0.0,
151+
is_string($arguments['planner'] ?? '') ? $arguments['planner'] : json_encode($arguments['planner']),
152+
$arguments['rows'] ?? 0
153+
);
154+
155+
$profiledQueryPlan = new ProfiledQueryPlan(
156+
$data['dbHits'],
157+
$data['records'],
158+
$data['hasPageCacheStats'],
159+
$data['pageCacheHits'],
160+
$data['pageCacheMisses'],
161+
$data['pageCacheHitRatio'],
162+
$data['time'],
163+
$data['operatorType'],
164+
$queryArguments
165+
);
166+
167+
foreach($data['children'] as $child) {
168+
$childQueryPlan = $this->createProfileData($child);
169+
170+
$profiledQueryPlan->addChild($childQueryPlan);
171+
}
133172

134-
return new Transaction($this->client, $clusterAffinity, $transactionId);
173+
return $profiledQueryPlan;
135174
}
175+
176+
136177
}

src/Objects/ProfiledQueryPlan.php

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
3+
namespace Neo4j\QueryAPI\Objects;
4+
5+
class ProfiledQueryPlan
6+
{
7+
private int $dbHits;
8+
private int $records;
9+
private bool $hasPageCacheStats;
10+
private int $pageCacheHits;
11+
private int $pageCacheMisses;
12+
private float $pageCacheHitRatio;
13+
private int $time;
14+
private string $operatorType;
15+
private QueryArguments $arguments;
16+
17+
/**
18+
* @var list<ProfiledQueryPlan>
19+
*/
20+
private array $children;
21+
22+
public function __construct(
23+
?int $dbHits = 0, // Default to 0 if null
24+
?int $records = 0,
25+
?bool $hasPageCacheStats = false,
26+
?int $pageCacheHits = 0,
27+
?int $pageCacheMisses = 0,
28+
?float $pageCacheHitRatio = 0.0,
29+
?int $time = 0,
30+
?string $operatorType = '',
31+
QueryArguments $arguments
32+
) {
33+
$this->dbHits = $dbHits ?? 0;
34+
$this->records = $records ?? 0;
35+
$this->hasPageCacheStats = $hasPageCacheStats ?? false;
36+
$this->pageCacheHits = $pageCacheHits ?? 0;
37+
$this->pageCacheMisses = $pageCacheMisses ?? 0;
38+
$this->pageCacheHitRatio = $pageCacheHitRatio ?? 0.0;
39+
$this->time = $time ?? 0;
40+
$this->operatorType = $operatorType ?? '';
41+
$this->arguments = $arguments;
42+
}
43+
44+
public function getDbHits(): int
45+
{
46+
return $this->dbHits;
47+
}
48+
49+
public function getRecords(): int
50+
{
51+
return $this->records;
52+
}
53+
54+
public function hasPageCacheStats(): bool
55+
{
56+
return $this->hasPageCacheStats;
57+
}
58+
59+
public function getPageCacheHits(): int
60+
{
61+
return $this->pageCacheHits;
62+
}
63+
64+
public function getPageCacheMisses(): int
65+
{
66+
return $this->pageCacheMisses;
67+
}
68+
69+
public function getPageCacheHitRatio(): float
70+
{
71+
return $this->pageCacheHitRatio;
72+
}
73+
74+
public function getTime(): int
75+
{
76+
return $this->time;
77+
}
78+
79+
public function getOperatorType(): string
80+
{
81+
return $this->operatorType;
82+
}
83+
84+
public function getArguments(): QueryArguments
85+
{
86+
return $this->arguments;
87+
}
88+
89+
/**
90+
* @return list<ProfiledQueryPlan>
91+
*/
92+
public function getChildren(): array
93+
{
94+
return $this->children;
95+
}
96+
97+
public function addChild(ProfiledQueryPlan $child): void
98+
{
99+
$this->children[] = $child;
100+
}
101+
}

src/Objects/QueryArguments.php

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<?php
2+
3+
namespace Neo4j\QueryAPI\Objects;
4+
5+
class QueryArguments
6+
{
7+
private int $globalMemory;
8+
private string $plannerImpl;
9+
private int $memory;
10+
private string $stringRepresentation;
11+
private string $runtime;
12+
private string $runtimeImpl;
13+
private int $dbHits;
14+
private int $batchSize;
15+
private string $details;
16+
private string $plannerVersion;
17+
private string $pipelineInfo;
18+
private string $runtimeVersion;
19+
private int $id;
20+
private float $estimatedRows;
21+
private string $planner;
22+
private int $rows;
23+
24+
public function __construct(
25+
?int $globalMemory = 0,
26+
?string $plannerImpl = '',
27+
?int $memory = 0,
28+
?string $stringRepresentation = '',
29+
$runtime = '',
30+
?string $runtimeImpl = '',
31+
?int $dbHits = 0,
32+
?int $batchSize = 0,
33+
?string $details = '',
34+
?string $plannerVersion = '',
35+
?string $pipelineInfo = '',
36+
?string $runtimeVersion = '',
37+
?int $id = 0,
38+
?float $estimatedRows = 0.0,
39+
?string $planner = '',
40+
?int $rows = 0
41+
) {
42+
$this->globalMemory = $globalMemory ?? 0;
43+
$this->plannerImpl = $plannerImpl ?? '';
44+
$this->memory = $memory ?? 0;
45+
$this->stringRepresentation = $stringRepresentation ?? '';
46+
$this->runtime = is_string($runtime) ? $runtime : json_encode($runtime);
47+
$this->runtimeImpl = $runtimeImpl ?? '';
48+
$this->dbHits = $dbHits ?? 0;
49+
$this->batchSize = $batchSize ?? 0;
50+
$this->details = $details ?? '';
51+
$this->plannerVersion = $plannerVersion ?? '';
52+
$this->pipelineInfo = $pipelineInfo ?? '';
53+
$this->runtimeVersion = $runtimeVersion ?? '';
54+
$this->id = $id ?? 0;
55+
$this->estimatedRows = $estimatedRows ?? 0.0;
56+
$this->planner = $planner ?? '';
57+
$this->rows = $rows ?? 0;
58+
}
59+
60+
public function getGlobalMemory(): int
61+
{
62+
return $this->globalMemory;
63+
}
64+
65+
public function getPlannerImpl(): string
66+
{
67+
return $this->plannerImpl;
68+
}
69+
70+
public function getMemory(): int
71+
{
72+
return $this->memory;
73+
}
74+
75+
public function getStringRepresentation(): string
76+
{
77+
return $this->stringRepresentation;
78+
}
79+
80+
public function getRuntime(): string
81+
{
82+
return $this->runtime;
83+
}
84+
85+
public function getRuntimeImpl(): string
86+
{
87+
return $this->runtimeImpl;
88+
}
89+
90+
public function getDbHits(): int
91+
{
92+
return $this->dbHits;
93+
}
94+
95+
public function getBatchSize(): int
96+
{
97+
return $this->batchSize;
98+
}
99+
100+
public function getDetails(): string
101+
{
102+
return $this->details;
103+
}
104+
105+
public function getPlannerVersion(): string
106+
{
107+
return $this->plannerVersion;
108+
}
109+
110+
public function getPipelineInfo(): string
111+
{
112+
return $this->pipelineInfo;
113+
}
114+
115+
public function getRuntimeVersion(): string
116+
{
117+
return $this->runtimeVersion;
118+
}
119+
120+
public function getId(): int
121+
{
122+
return $this->id;
123+
}
124+
125+
public function getEstimatedRows(): float
126+
{
127+
return $this->estimatedRows;
128+
}
129+
130+
public function getPlanner(): string
131+
{
132+
return $this->planner;
133+
}
134+
135+
public function getRows(): int
136+
{
137+
return $this->rows;
138+
}
139+
}

0 commit comments

Comments
 (0)