UNPKG

4.65 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.parseSingle = exports.parse = exports.assertNoErrors = exports.ResultError = void 0;
4const grammar_1 = require("./grammar");
5/**
6 * A ResultError is thrown when a query generates errorful results from Influx.
7 */
8class ResultError extends Error {
9 constructor(message) {
10 super();
11 this.message = `Error from InfluxDB: ${message}`;
12 }
13}
14exports.ResultError = ResultError;
15function groupMethod(matcher) {
16 // We do a tiny bit of 'custom' deep equality checking here, taking
17 // advantage of the fact that the tag keys are consistent across all
18 // series results. This lets us match groupings much more efficiently,
19 // ~6000x faster than the fastest vanilla equality checker (lodash)
20 // when operating on large (~100,000 grouping) sets.
21 const srcKeys = this.groupsTagsKeys;
22 const dstKeys = Object.keys(matcher);
23 if (srcKeys.length === 0 || srcKeys.length !== dstKeys.length) {
24 return [];
25 }
26 L: for (let row of this.groupRows) {
27 // eslint-disable-line no-labels
28 for (let src of srcKeys) {
29 if (row.tags[src] !== matcher[src]) {
30 continue L; // eslint-disable-line no-labels
31 }
32 }
33 return row.rows;
34 }
35 return [];
36}
37function groupsMethod() {
38 return this.groupRows;
39}
40/**
41 * Inner parsing function which unpacks the series into a table and attaches
42 * methods to the array. This is quite optimized and a bit of a mess to read,
43 * but it's all fairly easy procedural logic.
44 *
45 * We do this instead of subclassing Array since subclassing has some
46 * undesirable side-effects. For example, calling .slice() on the array
47 * makes it impossible to preserve groups as would be necessary if it's
48 * subclassed.
49 */
50function parseInner(series = [], precision) {
51 const results = [];
52 results.groupsTagsKeys =
53 series.length && series[0].tags ? Object.keys(series[0].tags) : [];
54 const tags = results.groupsTagsKeys;
55 let nextGroup = [];
56 results.groupRows = new Array(series.length); // Tslint:disable-line
57 for (let i = 0; i < series.length; i += 1, results.length) {
58 const { columns = [], values = [] } = series[i];
59 for (let value of values) {
60 const obj = {};
61 for (let j = 0; j < columns.length; j += 1) {
62 if (columns[j] === "time") {
63 obj.time = grammar_1.isoOrTimeToDate(value[j], precision);
64 }
65 else {
66 obj[columns[j]] = value[j];
67 }
68 }
69 for (let tag of tags) {
70 obj[tag] = series[i].tags[tag];
71 }
72 results.push(obj);
73 nextGroup.push(obj);
74 }
75 results.groupRows[i] = {
76 name: series[i].name,
77 rows: nextGroup,
78 tags: series[i].tags || {},
79 };
80 nextGroup = [];
81 }
82 results.group = groupMethod;
83 results.groups = groupsMethod;
84 return results;
85}
86/**
87 * Checks if there are any errors in the IResponse and, if so, it throws them.
88 * @private
89 * @throws {ResultError}
90 */
91function assertNoErrors(res) {
92 for (let result of res.results) {
93 const { error } = result;
94 if (error) {
95 throw new ResultError(error);
96 }
97 }
98 return res;
99}
100exports.assertNoErrors = assertNoErrors;
101/**
102 * From parses out a response to a result or list of responses.
103 * There are three situations we cover here:
104 * 1. A single query without groups, like `select * from myseries`
105 * 2. A single query with groups, generated with a `group by` statement
106 * which groups by series *tags*, grouping by times is case (1)
107 * 3. Multiple queries of types 1 and 2
108 * @private
109 */
110function parse(res, precision) {
111 assertNoErrors(res);
112 if (res.results.length === 1) {
113 // Normalize case 3
114 return parseInner(res.results[0].series, precision);
115 }
116 return res.results.map((result) => parseInner(result.series, precision));
117}
118exports.parse = parse;
119/**
120 * ParseSingle asserts that the response contains a single result,
121 * and returns that result.
122 * @throws {Error} if the number of results is not exactly one
123 * @private
124 */
125function parseSingle(res, precision) {
126 assertNoErrors(res);
127 if (res.results.length !== 1) {
128 throw new Error("node-influx expected the results length to equal 1, but " +
129 `it was ${0}. Please report this here: https://git.io/influx-err`);
130 }
131 return parseInner(res.results[0].series, precision);
132}
133exports.parseSingle = parseSingle;