result-summary.js•14.4 kB
"use strict";
/**
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Stats = exports.QueryStatistics = exports.ProfiledPlan = exports.Plan = exports.ServerInfo = exports.queryType = void 0;
var internal_1 = require("./internal");
var notification_1 = require("./notification");
/**
* A ResultSummary instance contains structured metadata for a {@link Result}.
* @access public
*/
var ResultSummary = /** @class */ (function () {
/**
* @constructor
* @param {string} query - The query this summary is for
* @param {Object} parameters - Parameters for the query
* @param {Object} metadata - Query metadata
* @param {number|undefined} protocolVersion - Bolt Protocol Version
*/
function ResultSummary(query, parameters, metadata, protocolVersion) {
var _a, _b, _c;
/**
* The query and parameters this summary is for.
* @type {{text: string, parameters: Object}}
* @public
*/
this.query = { text: query, parameters: parameters };
/**
* The type of query executed. Can be "r" for read-only query, "rw" for read-write query,
* "w" for write-only query and "s" for schema-write query.
* String constants are available in {@link queryType} object.
* @type {string}
* @public
*/
this.queryType = metadata.type;
/**
* Counters for operations the query triggered.
* @type {QueryStatistics}
* @public
*/
this.counters = new QueryStatistics((_a = metadata.stats) !== null && _a !== void 0 ? _a : {});
// for backwards compatibility, remove in future version
/**
* Use {@link ResultSummary.counters} instead.
* @type {QueryStatistics}
* @deprecated
*/
this.updateStatistics = this.counters;
/**
* This describes how the database will execute the query.
* Query plan for the executed query if available, otherwise undefined.
* Will only be populated for queries that start with "EXPLAIN".
* @type {Plan|false}
* @public
*/
this.plan =
metadata.plan != null || metadata.profile != null
? new Plan((_b = metadata.plan) !== null && _b !== void 0 ? _b : metadata.profile)
: false;
/**
* This describes how the database did execute your query. This will contain detailed information about what
* each step of the plan did. Profiled query plan for the executed query if available, otherwise undefined.
* Will only be populated for queries that start with "PROFILE".
* @type {ProfiledPlan}
* @public
*/
this.profile = metadata.profile != null ? new ProfiledPlan(metadata.profile) : false;
/**
* An array of notifications that might arise when executing the query. Notifications can be warnings about
* problematic queries or other valuable information that can be presented in a client. Unlike failures
* or errors, notifications do not affect the execution of a query.
* @type {Array<Notification>}
* @public
*/
this.notifications = (0, notification_1.buildNotificationsFromMetadata)(metadata);
/**
* A list of GqlStatusObjects that arise when executing the query.
*
* The list always contains at least 1 status representing the Success, No Data or Omitted Result.
*
* When discarding records while connected to a non-gql aware server and using a RxSession,
* the driver might not be able to tell apart Success and No Data.
*
* All other status are notifications like warnings about problematic queries or other valuable
* information that can be presented in a client.
*
* The GqlStatusObjects will be presented in the following order:
*
* - A “no data” (02xxx) has precedence over a warning;
* - A warning (01xxx) has precedence over a success.
* - A success (00xxx) has precedence over anything informational (03xxx)
*
* @type {Array<GqlStatusObject>}
* @public
* @experimental
*/
this.gqlStatusObjects = (0, notification_1.buildGqlStatusObjectFromMetadata)(metadata);
/**
* The basic information of the server where the result is obtained from.
* @type {ServerInfo}
* @public
*/
this.server = new ServerInfo(metadata.server, protocolVersion);
/**
* The time it took the server to consume the result.
* @type {number}
* @public
*/
this.resultConsumedAfter = metadata.result_consumed_after;
/**
* The time it took the server to make the result available for consumption in milliseconds.
* @type {number}
* @public
*/
this.resultAvailableAfter = metadata.result_available_after;
/**
* The database name where this summary is obtained from.
* @type {{name: string}}
* @public
*/
this.database = { name: (_c = metadata.db) !== null && _c !== void 0 ? _c : null };
}
/**
* Check if the result summary has a plan
* @return {boolean}
*/
ResultSummary.prototype.hasPlan = function () {
return this.plan instanceof Plan;
};
/**
* Check if the result summary has a profile
* @return {boolean}
*/
ResultSummary.prototype.hasProfile = function () {
return this.profile instanceof ProfiledPlan;
};
return ResultSummary;
}());
/**
* Class for execution plan received by prepending Cypher with EXPLAIN.
* @access public
*/
var Plan = /** @class */ (function () {
/**
* Create a Plan instance
* @constructor
* @param {Object} plan - Object with plan data
*/
function Plan(plan) {
this.operatorType = plan.operatorType;
this.identifiers = plan.identifiers;
this.arguments = plan.args;
this.children = plan.children != null
? plan.children.map(function (child) { return new Plan(child); })
: [];
}
return Plan;
}());
exports.Plan = Plan;
/**
* Class for execution plan received by prepending Cypher with PROFILE.
* @access public
*/
var ProfiledPlan = /** @class */ (function () {
/**
* Create a ProfiledPlan instance
* @constructor
* @param {Object} profile - Object with profile data
*/
function ProfiledPlan(profile) {
this.operatorType = profile.operatorType;
this.identifiers = profile.identifiers;
this.arguments = profile.args;
this.dbHits = valueOrDefault('dbHits', profile);
this.rows = valueOrDefault('rows', profile);
this.pageCacheMisses = valueOrDefault('pageCacheMisses', profile);
this.pageCacheHits = valueOrDefault('pageCacheHits', profile);
this.pageCacheHitRatio = valueOrDefault('pageCacheHitRatio', profile);
this.time = valueOrDefault('time', profile);
this.children = profile.children != null
? profile.children.map(function (child) { return new ProfiledPlan(child); })
: [];
}
ProfiledPlan.prototype.hasPageCacheStats = function () {
return (this.pageCacheMisses > 0 ||
this.pageCacheHits > 0 ||
this.pageCacheHitRatio > 0);
};
return ProfiledPlan;
}());
exports.ProfiledPlan = ProfiledPlan;
/**
* Stats Query statistics dictionary for a {@link QueryStatistics}
* @public
*/
var Stats = /** @class */ (function () {
/**
* @constructor
* @private
*/
function Stats() {
/**
* nodes created
* @type {number}
* @public
*/
this.nodesCreated = 0;
/**
* nodes deleted
* @type {number}
* @public
*/
this.nodesDeleted = 0;
/**
* relationships created
* @type {number}
* @public
*/
this.relationshipsCreated = 0;
/**
* relationships deleted
* @type {number}
* @public
*/
this.relationshipsDeleted = 0;
/**
* properties set
* @type {number}
* @public
*/
this.propertiesSet = 0;
/**
* labels added
* @type {number}
* @public
*/
this.labelsAdded = 0;
/**
* labels removed
* @type {number}
* @public
*/
this.labelsRemoved = 0;
/**
* indexes added
* @type {number}
* @public
*/
this.indexesAdded = 0;
/**
* indexes removed
* @type {number}
* @public
*/
this.indexesRemoved = 0;
/**
* constraints added
* @type {number}
* @public
*/
this.constraintsAdded = 0;
/**
* constraints removed
* @type {number}
* @public
*/
this.constraintsRemoved = 0;
}
return Stats;
}());
exports.Stats = Stats;
/**
* Get statistical information for a {@link Result}.
* @access public
*/
var QueryStatistics = /** @class */ (function () {
/**
* Structurize the statistics
* @constructor
* @param {Object} statistics - Result statistics
*/
function QueryStatistics(statistics) {
var _this = this;
this._stats = {
nodesCreated: 0,
nodesDeleted: 0,
relationshipsCreated: 0,
relationshipsDeleted: 0,
propertiesSet: 0,
labelsAdded: 0,
labelsRemoved: 0,
indexesAdded: 0,
indexesRemoved: 0,
constraintsAdded: 0,
constraintsRemoved: 0
};
this._systemUpdates = 0;
Object.keys(statistics).forEach(function (index) {
// To camelCase
var camelCaseIndex = index.replace(/(-\w)/g, function (m) { return m[1].toUpperCase(); });
if (camelCaseIndex in _this._stats) {
_this._stats[camelCaseIndex] = internal_1.util.toNumber(statistics[index]);
}
else if (camelCaseIndex === 'systemUpdates') {
_this._systemUpdates = internal_1.util.toNumber(statistics[index]);
}
else if (camelCaseIndex === 'containsSystemUpdates') {
_this._containsSystemUpdates = statistics[index];
}
else if (camelCaseIndex === 'containsUpdates') {
_this._containsUpdates = statistics[index];
}
});
this._stats = Object.freeze(this._stats);
}
/**
* Did the database get updated?
* @return {boolean}
*/
QueryStatistics.prototype.containsUpdates = function () {
var _this = this;
return this._containsUpdates !== undefined
? this._containsUpdates
: (Object.keys(this._stats).reduce(function (last, current) {
return last + _this._stats[current];
}, 0) > 0);
};
/**
* Returns the query statistics updates in a dictionary.
* @returns {Stats}
*/
QueryStatistics.prototype.updates = function () {
return this._stats;
};
/**
* Return true if the system database get updated, otherwise false
* @returns {boolean} - If the system database get updated or not.
*/
QueryStatistics.prototype.containsSystemUpdates = function () {
return this._containsSystemUpdates !== undefined
? this._containsSystemUpdates
: this._systemUpdates > 0;
};
/**
* @returns {number} - Number of system updates
*/
QueryStatistics.prototype.systemUpdates = function () {
return this._systemUpdates;
};
return QueryStatistics;
}());
exports.QueryStatistics = QueryStatistics;
/**
* Class for exposing server info from a result.
* @access public
*/
var ServerInfo = /** @class */ (function () {
/**
* Create a ServerInfo instance
* @constructor
* @param {Object} serverMeta - Object with serverMeta data
* @param {Object} connectionInfo - Bolt connection info
* @param {number} protocolVersion - Bolt Protocol Version
*/
function ServerInfo(serverMeta, protocolVersion) {
if (serverMeta != null) {
/**
* The server adress
* @type {string}
* @public
*/
this.address = serverMeta.address;
/**
* The server user agent string
* @type {string}
* @public
*/
this.agent = serverMeta.version;
}
/**
* The protocol version used by the connection
* @type {number}
* @public
*/
this.protocolVersion = protocolVersion;
}
return ServerInfo;
}());
exports.ServerInfo = ServerInfo;
function valueOrDefault(key, values, defaultValue) {
if (defaultValue === void 0) { defaultValue = 0; }
if (values !== false && key in values) {
var value = values[key];
return internal_1.util.toNumber(value);
}
else {
return defaultValue;
}
}
/**
* The constants for query types
* @type {{SCHEMA_WRITE: string, WRITE_ONLY: string, READ_ONLY: string, READ_WRITE: string}}
*/
var queryType = {
READ_ONLY: 'r',
READ_WRITE: 'rw',
WRITE_ONLY: 'w',
SCHEMA_WRITE: 's'
};
exports.queryType = queryType;
exports.default = ResultSummary;