Skip to content

Commit c269a31

Browse files
committed
Merge pull request #10 from oskarhane/add-warnings
Add support for Cypher notifications
2 parents 05f84be + cb92637 commit c269a31

File tree

3 files changed

+282
-205
lines changed

3 files changed

+282
-205
lines changed

lib/result-summary.js

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
/**
2+
* Copyright (c) 2002-2015 "Neo Technology,"
3+
* Network Engine for Objects in Lund AB [http://neotechnology.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
import neo4j from './neo4j';
21+
22+
/**
23+
* A ResultSummary instance contains structured metadata for a {Result}.
24+
* @access public
25+
*/
26+
class ResultSummary {
27+
/**
28+
* @constructor
29+
* @param {string} statement - The statement this summary is for
30+
* @param {Object} parameters - Parameters for the statement
31+
* @param {Object} metadata - Statement metadata
32+
*/
33+
constructor(statement, parameters, metadata) {
34+
this.statement = {text: statement, parameters};
35+
this.statementType = metadata.type;
36+
this.updateStatistics = new StatementStatistics(metadata.stats || {});
37+
this.plan = metadata.plan || metadata.profile ? new Plan(metadata.plan || metadata.profile) : false;
38+
this.profile = metadata.profile ? new ProfiledPlan(metadata.profile) : false;
39+
this.notifications = this._buildNotifications(metadata.notifications);
40+
}
41+
42+
_buildNotifications(notifications) {
43+
if(!notifications) {
44+
return [];
45+
}
46+
return notifications.map(function(n) { return new Notification(n) });
47+
}
48+
49+
/**
50+
* Check if the result summary has a plan
51+
* @return {boolean}
52+
*/
53+
hasPlan() {
54+
return this.plan instanceof Plan
55+
}
56+
57+
/**
58+
* Check if the result summary has a profile
59+
* @return {boolean}
60+
*/
61+
hasProfile() {
62+
return this.profile instanceof ProfiledPlan
63+
}
64+
}
65+
66+
/**
67+
* Class for execution plan received by prepending Cypher with EXPLAIN.
68+
* @access public
69+
*/
70+
class Plan {
71+
/**
72+
* Create a Plan instance
73+
* @constructor
74+
* @param {Object} plan - Object with plan data
75+
*/
76+
constructor(plan) {
77+
this.operatorType = plan.operatorType;
78+
this.identifiers = plan.identifiers;
79+
this.arguments = plan.args;
80+
this.children = plan.children ? plan.children.map((child) => new Plan(child)) : [];
81+
}
82+
}
83+
84+
/**
85+
* Class for execution plan received by prepending Cypher with PROFILE.
86+
* @access public
87+
*/
88+
class ProfiledPlan {
89+
/**
90+
* Create a ProfiledPlan instance
91+
* @constructor
92+
* @param {Object} plan - Object with plan data
93+
*/
94+
constructor(profile) {
95+
this.operatorType = profile.operatorType;
96+
this.identifiers = profile.identifiers;
97+
this.arguments = profile.args;
98+
this.dbHits = profile.args.DbHits.toInt();
99+
this.rows = profile.args.Rows.toInt();
100+
this.children = profile.children ? profile.children.map((child) => new ProfiledPlan(child)) : [];
101+
}
102+
}
103+
104+
/**
105+
* Get statistical information for a {Result}.
106+
* @access public
107+
*/
108+
class StatementStatistics {
109+
/**
110+
* Structurize the statistics
111+
* @constructor
112+
* @param {Object} statistics - Result statistics
113+
*/
114+
constructor(statistics) {
115+
this._stats = {
116+
nodesCreated: 0,
117+
nodesDelete: 0,
118+
relationshipsCreated: 0,
119+
relationshipsDeleted: 0,
120+
propertiesSet: 0,
121+
labelsAdded: 0,
122+
labelsRemoved: 0,
123+
indexesAdded: 0,
124+
indexesRemoved: 0,
125+
constraintsAdded: 0,
126+
constraintsRemoved: 0
127+
}
128+
Object.keys(statistics).forEach((index) => {
129+
let val = neo4j.isInt(statistics[index]) ? statistics[index].toInt() : statistics[index];
130+
//To camelCase
131+
this._stats[index.replace(/(\-\w)/g, (m) => m[1].toUpperCase())] = val;
132+
});
133+
}
134+
135+
/**
136+
* Did the database get updated?
137+
* @return {boolean}
138+
*/
139+
containsUpdates() {
140+
return Object.keys(this._stats).reduce((last, current) => {
141+
return last + this._stats[current];
142+
}, 0) > 0;
143+
}
144+
145+
/**
146+
* @return {Number} - Number of nodes created.
147+
*/
148+
nodesCreated() {
149+
return this._stats.nodesCreated;
150+
}
151+
152+
/**
153+
* @return {Number} - Number of nodes deleted.
154+
*/
155+
nodesDeleted() {
156+
return this._stats.nodesDeleted;
157+
}
158+
159+
/**
160+
* @return {Number} - Number of relationships created.
161+
*/
162+
relationshipsCreated() {
163+
return this._stats.relationshipsCreated;
164+
}
165+
166+
/**
167+
* @return {Number} - Number of nodes deleted.
168+
*/
169+
relationshipsDeleted() {
170+
return this._stats.relationshipsDeleted;
171+
}
172+
173+
/**
174+
* @return {Number} - Number of properties set.
175+
*/
176+
propertiesSet() {
177+
return this._stats.propertiesSet;
178+
}
179+
180+
/**
181+
* @return {Number} - Number of labels added.
182+
*/
183+
labelsAdded() {
184+
return this._stats.labelsAdded;
185+
}
186+
187+
/**
188+
* @return {Number} - Number of labels removed.
189+
*/
190+
labelsRemoved() {
191+
return this._stats.labelsRemoved;
192+
}
193+
194+
/**
195+
* @return {Number} - Number of indexes added.
196+
*/
197+
indexesAdded() {
198+
return this._stats.indexesAdded;
199+
}
200+
201+
/**
202+
* @return {Number} - Number of indexes removed.
203+
*/
204+
indexesRemoved() {
205+
return this._stats.indexesRemoved;
206+
}
207+
208+
/**
209+
* @return {Number} - Number of contraints added.
210+
*/
211+
constraintsAdded() {
212+
return this._stats.constraintsAdded;
213+
}
214+
215+
/**
216+
* @return {Number} - Number of contraints removed.
217+
*/
218+
constraintsRemoved() {
219+
return this._stats.constraintsRemoved;
220+
}
221+
}
222+
223+
/**
224+
* Class for Cypher notifications
225+
* @access public
226+
*/
227+
class Notification {
228+
/**
229+
* Create a Notification instance
230+
* @constructor
231+
* @param {Object} notification - Object with notification data
232+
*/
233+
constructor(notification) {
234+
this.code = notification.code;
235+
this.title = notification.title;
236+
this.description = notification.desciption;
237+
this.position = this._constructPosition(notification.position);
238+
}
239+
240+
_constructPosition(pos) {
241+
if(!pos) {
242+
return {};
243+
}
244+
return {
245+
offset: pos.offset.toInt(),
246+
line: pos.line.toInt(),
247+
column: pos.column.toInt()
248+
}
249+
}
250+
}
251+
252+
const statementType = {
253+
READ_ONLY: 'r',
254+
READ_WRITE: 'rw',
255+
WRITE_ONLY: 'w',
256+
SCHEMA_WRITE: 's'
257+
}
258+
259+
export default {
260+
ResultSummary,
261+
statementType
262+
}

0 commit comments

Comments
 (0)