json-fs-query 2.3.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -6
- package/browser/jsonFsQuery.js +485 -208
- package/browser/jsonFsQuery.min.js +1 -1
- package/dist/data/queries/groupBy.d.ts +20 -1
- package/dist/data/queries/groupBy.js +71 -9
- package/dist/data/queries/groupBy.min.js +1 -1
- package/dist/data/queries/limitOffset.d.ts +1 -1
- package/dist/data/queries/limitOffset.js +1 -1
- package/dist/data/queries/selectFields.d.ts +6 -4
- package/dist/data/queries/selectFields.js +15 -10
- package/dist/data/queries/selectFields.min.js +1 -1
- package/dist/data/utilities/parsers/findCommand.d.ts +2 -1
- package/dist/data/utilities/parsers/findCommand.js +4 -4
- package/dist/data/utilities/parsers/findCommand.min.js +1 -1
- package/dist/data/utilities/parsers/findConditions.d.ts +8 -9
- package/dist/data/utilities/parsers/findConditions.js +29 -41
- package/dist/data/utilities/parsers/findConditions.min.js +1 -1
- package/dist/data/utilities/parsers/findGroupBy.d.ts +6 -4
- package/dist/data/utilities/parsers/findGroupBy.js +17 -9
- package/dist/data/utilities/parsers/findGroupBy.min.js +1 -1
- package/dist/data/utilities/parsers/findInsertValues.d.ts +4 -3
- package/dist/data/utilities/parsers/findInsertValues.js +9 -9
- package/dist/data/utilities/parsers/findInsertValues.min.js +1 -1
- package/dist/data/utilities/parsers/findJoinClauses.d.ts +4 -3
- package/dist/data/utilities/parsers/findJoinClauses.js +20 -13
- package/dist/data/utilities/parsers/findJoinClauses.min.js +1 -1
- package/dist/data/utilities/parsers/findJoinEntity.d.ts +1 -1
- package/dist/data/utilities/parsers/findJoinEntity.js +3 -5
- package/dist/data/utilities/parsers/findJoinEntity.min.js +1 -1
- package/dist/data/utilities/parsers/findLimit.d.ts +4 -3
- package/dist/data/utilities/parsers/findLimit.js +8 -8
- package/dist/data/utilities/parsers/findLimit.min.js +1 -1
- package/dist/data/utilities/parsers/findMergeJoins.d.ts +4 -3
- package/dist/data/utilities/parsers/findMergeJoins.js +19 -12
- package/dist/data/utilities/parsers/findMergeJoins.min.js +1 -1
- package/dist/data/utilities/parsers/findOffset.d.ts +4 -3
- package/dist/data/utilities/parsers/findOffset.js +8 -8
- package/dist/data/utilities/parsers/findOffset.min.js +1 -1
- package/dist/data/utilities/parsers/findSelects.d.ts +4 -3
- package/dist/data/utilities/parsers/findSelects.js +13 -14
- package/dist/data/utilities/parsers/findSelects.min.js +1 -1
- package/dist/data/utilities/parsers/findSortClauses.d.ts +4 -3
- package/dist/data/utilities/parsers/findSortClauses.js +12 -12
- package/dist/data/utilities/parsers/findSortClauses.min.js +1 -1
- package/dist/data/utilities/parsers/findUpdateValues.d.ts +5 -7
- package/dist/data/utilities/parsers/findUpdateValues.js +10 -13
- package/dist/data/utilities/parsers/findUpdateValues.min.js +1 -1
- package/dist/data/utilities/parsers/parseQuery.js +83 -9
- package/dist/data/utilities/parsers/parseQuery.min.js +1 -1
- package/dist/data/utilities/parsers/splitClauses.d.ts +29 -0
- package/dist/data/utilities/parsers/splitClauses.js +139 -0
- package/dist/data/utilities/parsers/splitClauses.min.js +1 -0
- package/dist/data/utilities/runQuery.js +5 -4
- package/dist/data/utilities/runQuery.min.js +1 -1
- package/package.json +1 -1
- package/dist/data/utilities/parsers/removeFromQuery.d.ts +0 -2
- package/dist/data/utilities/parsers/removeFromQuery.js +0 -8
- package/dist/data/utilities/parsers/removeFromQuery.min.js +0 -1
package/browser/jsonFsQuery.js
CHANGED
|
@@ -793,23 +793,85 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
793
793
|
value: true
|
|
794
794
|
});
|
|
795
795
|
exports.groupBy = void 0;
|
|
796
|
+
require("core-js/modules/es.json.stringify.js");
|
|
796
797
|
require("core-js/modules/esnext.iterator.constructor.js");
|
|
798
|
+
require("core-js/modules/esnext.iterator.map.js");
|
|
797
799
|
require("core-js/modules/esnext.iterator.reduce.js");
|
|
798
|
-
|
|
799
|
-
|
|
800
|
+
require("core-js/modules/esnext.map.delete-all.js");
|
|
801
|
+
require("core-js/modules/esnext.map.every.js");
|
|
802
|
+
require("core-js/modules/esnext.map.filter.js");
|
|
803
|
+
require("core-js/modules/esnext.map.find.js");
|
|
804
|
+
require("core-js/modules/esnext.map.find-key.js");
|
|
805
|
+
require("core-js/modules/esnext.map.includes.js");
|
|
806
|
+
require("core-js/modules/esnext.map.key-of.js");
|
|
807
|
+
require("core-js/modules/esnext.map.map-keys.js");
|
|
808
|
+
require("core-js/modules/esnext.map.map-values.js");
|
|
809
|
+
require("core-js/modules/esnext.map.merge.js");
|
|
810
|
+
require("core-js/modules/esnext.map.reduce.js");
|
|
811
|
+
require("core-js/modules/esnext.map.some.js");
|
|
812
|
+
require("core-js/modules/esnext.map.update.js");
|
|
813
|
+
// An object's keys in sorted order, at any depth, so { a, b } and { b, a } are the same value; arrays keep their order
|
|
814
|
+
const sortedKeys = value => {
|
|
815
|
+
if (Array.isArray(value)) {
|
|
816
|
+
return value.map(sortedKeys);
|
|
817
|
+
}
|
|
818
|
+
if (value !== null && typeof value === 'object') {
|
|
819
|
+
return Object.keys(value).sort().reduce((sorted, key) => {
|
|
820
|
+
sorted[key] = sortedKeys(value[key]);
|
|
821
|
+
return sorted;
|
|
822
|
+
}, {});
|
|
823
|
+
}
|
|
824
|
+
return value;
|
|
825
|
+
};
|
|
826
|
+
// Rows share a group when their values are the same, type included: 1 and '1' are two groups, as are null and missing
|
|
827
|
+
const groupKey = (row, field) => {
|
|
828
|
+
if (!Object.prototype.hasOwnProperty.call(row, field)) {
|
|
829
|
+
return 'missing';
|
|
830
|
+
}
|
|
831
|
+
const value = row[field];
|
|
832
|
+
return value !== null && typeof value === 'object' ? `json:${JSON.stringify(sortedKeys(value))}` : `${typeof value}:${String(value)}`;
|
|
833
|
+
};
|
|
834
|
+
/**
|
|
835
|
+
* Group rows by each field in turn. The groups are a list in the order their first row came, so a sort before
|
|
836
|
+
* grouping orders the groups too (and the rows within each one).
|
|
837
|
+
* @param dataSet
|
|
838
|
+
* @param fields
|
|
839
|
+
* @returns The rows as they were when there's no field, otherwise the groups.
|
|
840
|
+
*/
|
|
841
|
+
const groupBy = (dataSet = [], fields = []) => {
|
|
842
|
+
if (!fields.length) {
|
|
800
843
|
return dataSet;
|
|
801
844
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
845
|
+
const [field, ...rest] = fields;
|
|
846
|
+
const groups = new Map();
|
|
847
|
+
for (const row of dataSet) {
|
|
848
|
+
const key = groupKey(row, field);
|
|
849
|
+
if (!groups.has(key)) {
|
|
850
|
+
groups.set(key, key === 'missing' ? {
|
|
851
|
+
field,
|
|
852
|
+
missing: true,
|
|
853
|
+
rows: []
|
|
854
|
+
} : {
|
|
855
|
+
field,
|
|
856
|
+
value: row[field],
|
|
857
|
+
rows: []
|
|
858
|
+
});
|
|
806
859
|
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
860
|
+
groups.get(key).rows.push(row);
|
|
861
|
+
}
|
|
862
|
+
return [...groups.values()].map(({
|
|
863
|
+
rows,
|
|
864
|
+
...group
|
|
865
|
+
}) => rest.length ? {
|
|
866
|
+
...group,
|
|
867
|
+
groups: groupBy(rows, rest)
|
|
868
|
+
} : {
|
|
869
|
+
...group,
|
|
870
|
+
rows
|
|
871
|
+
});
|
|
810
872
|
};
|
|
811
873
|
exports.groupBy = groupBy;
|
|
812
|
-
},{"core-js/modules/esnext.iterator.constructor.js":237,"core-js/modules/esnext.iterator.reduce.js":245}],20:[function(require,module,exports){
|
|
874
|
+
},{"core-js/modules/es.json.stringify.js":233,"core-js/modules/esnext.iterator.constructor.js":237,"core-js/modules/esnext.iterator.map.js":244,"core-js/modules/esnext.iterator.reduce.js":245,"core-js/modules/esnext.map.delete-all.js":247,"core-js/modules/esnext.map.every.js":248,"core-js/modules/esnext.map.filter.js":249,"core-js/modules/esnext.map.find-key.js":250,"core-js/modules/esnext.map.find.js":251,"core-js/modules/esnext.map.includes.js":252,"core-js/modules/esnext.map.key-of.js":253,"core-js/modules/esnext.map.map-keys.js":254,"core-js/modules/esnext.map.map-values.js":255,"core-js/modules/esnext.map.merge.js":256,"core-js/modules/esnext.map.reduce.js":257,"core-js/modules/esnext.map.some.js":258,"core-js/modules/esnext.map.update.js":259}],20:[function(require,module,exports){
|
|
813
875
|
"use strict";
|
|
814
876
|
|
|
815
877
|
Object.defineProperty(exports, "__esModule", {
|
|
@@ -977,7 +1039,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
977
1039
|
});
|
|
978
1040
|
exports.limitOffset = void 0;
|
|
979
1041
|
/**
|
|
980
|
-
* Slice a dataSet down to at most `limit` rows, starting after the first `offset` of them.
|
|
1042
|
+
* Slice a dataSet down to at most `limit` rows (or groups, after group by), starting after the first `offset` of them.
|
|
981
1043
|
* @param dataSet
|
|
982
1044
|
* @param offset
|
|
983
1045
|
* @param limit
|
|
@@ -1115,7 +1177,7 @@ const queryStatus = (text = '') => {
|
|
|
1115
1177
|
};
|
|
1116
1178
|
};
|
|
1117
1179
|
exports.queryStatus = queryStatus;
|
|
1118
|
-
},{"../utilities/parsers/scanQuery":
|
|
1180
|
+
},{"../utilities/parsers/scanQuery":66}],27:[function(require,module,exports){
|
|
1119
1181
|
"use strict";
|
|
1120
1182
|
|
|
1121
1183
|
Object.defineProperty(exports, "__esModule", {
|
|
@@ -1165,24 +1227,29 @@ const shapeRow = (row, selectClauses) => selectClauses.reduce((shaped, {
|
|
|
1165
1227
|
shaped[alias || property] = row[property];
|
|
1166
1228
|
return shaped;
|
|
1167
1229
|
}, {});
|
|
1230
|
+
const shapeGroup = (group, selectClauses) => group.groups ? {
|
|
1231
|
+
...group,
|
|
1232
|
+
groups: group.groups.map(inner => shapeGroup(inner, selectClauses))
|
|
1233
|
+
} : {
|
|
1234
|
+
...group,
|
|
1235
|
+
rows: group.rows.map(row => shapeRow(row, selectClauses))
|
|
1236
|
+
};
|
|
1168
1237
|
/**
|
|
1169
|
-
* Shape each row down to only the selected properties (aliased, when given). dataSet is either a
|
|
1170
|
-
*
|
|
1171
|
-
*
|
|
1238
|
+
* Shape each row down to only the selected properties (aliased, when given). dataSet is either a list of rows, or
|
|
1239
|
+
* (once groupBy has run) a list of groups, whose rows are shaped the same way at any depth; the groups keep their
|
|
1240
|
+
* field and value, selected or not.
|
|
1172
1241
|
* @param dataSet
|
|
1173
1242
|
* @param selectClauses
|
|
1243
|
+
* @param grouped Whether dataSet is a list of groups (see groupBy)
|
|
1174
1244
|
*/
|
|
1175
|
-
const selectFields = (dataSet = [], selectClauses = []) => {
|
|
1245
|
+
const selectFields = (dataSet = [], selectClauses = [], grouped = false) => {
|
|
1176
1246
|
if (!selectClauses.length) {
|
|
1177
1247
|
return dataSet;
|
|
1178
1248
|
}
|
|
1179
|
-
if (
|
|
1180
|
-
return dataSet.map(
|
|
1249
|
+
if (grouped) {
|
|
1250
|
+
return dataSet.map(group => shapeGroup(group, selectClauses));
|
|
1181
1251
|
}
|
|
1182
|
-
return
|
|
1183
|
-
shaped[key] = dataSet[key].map(row => shapeRow(row, selectClauses));
|
|
1184
|
-
return shaped;
|
|
1185
|
-
}, {});
|
|
1252
|
+
return dataSet.map(row => shapeRow(row, selectClauses));
|
|
1186
1253
|
};
|
|
1187
1254
|
exports.selectFields = selectFields;
|
|
1188
1255
|
},{"core-js/modules/esnext.iterator.constructor.js":237,"core-js/modules/esnext.iterator.map.js":244,"core-js/modules/esnext.iterator.reduce.js":245}],30:[function(require,module,exports){
|
|
@@ -2536,12 +2603,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
2536
2603
|
value: true
|
|
2537
2604
|
});
|
|
2538
2605
|
exports.findCommand = void 0;
|
|
2539
|
-
|
|
2540
|
-
const commandMatch = /^(delete|insert|read|update)\s+([a-z0-9_-]+)[\w\n]*/i;
|
|
2606
|
+
const commandMatch = /^(delete|insert|read|update)\s+([a-z0-9_-]+)/i;
|
|
2541
2607
|
/**
|
|
2542
|
-
*
|
|
2608
|
+
* Read the command and record name from the start of a query's head (see splitClauses).
|
|
2543
2609
|
* @param parsed
|
|
2544
2610
|
* @param query
|
|
2611
|
+
* @returns The rest of the head (a joined record, `.joined`, for findJoinEntity).
|
|
2545
2612
|
*/
|
|
2546
2613
|
const findCommand = (parsed, query) => {
|
|
2547
2614
|
const commandFound = query.match(commandMatch);
|
|
@@ -2550,12 +2617,12 @@ const findCommand = (parsed, query) => {
|
|
|
2550
2617
|
if (commandFound) {
|
|
2551
2618
|
parsed['command'] = commandFound[1].toLowerCase();
|
|
2552
2619
|
parsed['entity'] = commandFound[2];
|
|
2553
|
-
return
|
|
2620
|
+
return query.slice(commandFound[0].length).trim();
|
|
2554
2621
|
}
|
|
2555
2622
|
return query;
|
|
2556
2623
|
};
|
|
2557
2624
|
exports.findCommand = findCommand;
|
|
2558
|
-
},{
|
|
2625
|
+
},{}],49:[function(require,module,exports){
|
|
2559
2626
|
"use strict";
|
|
2560
2627
|
|
|
2561
2628
|
Object.defineProperty(exports, "__esModule", {
|
|
@@ -2568,15 +2635,13 @@ require("core-js/modules/esnext.iterator.flat-map.js");
|
|
|
2568
2635
|
var _parseLiteralValue = require("./parseLiteralValue");
|
|
2569
2636
|
var _conditionTree = require("../conditionTree");
|
|
2570
2637
|
var _maskStrings = require("./maskStrings");
|
|
2638
|
+
var _splitClauses = require("./splitClauses");
|
|
2571
2639
|
// Keywords count only as whole words: in `on t.x = u.color where ...` the `or` is part of the name `color`
|
|
2572
2640
|
const wordEnd = '(?![a-z0-9_.-])';
|
|
2573
2641
|
const keyword = words => new RegExp(`^(?:${words})${wordEnd}`, 'i');
|
|
2574
2642
|
// One condition, at the start of the text: a field, then `is [not] null` / `exists` / `does not exist`, or a comparator
|
|
2575
2643
|
// and a value (strings and arrays are placeholders by then, see maskStrings)
|
|
2576
2644
|
const conditionMatch = new RegExp(`^([a-z0-9_-]+\\.?[a-z0-9_-]*)\\s+(?:(is\\s+not\\s+null|is\\s+null|exists|does\\s+not\\s+exist)${wordEnd}|(<>|!=|>=|<=|=|>|<|in|between|like)\\s+(${_maskStrings.placeholderSource}|(${_parseLiteralValue.numberSource})|${_maskStrings.arraySource}|(null)|(true)|(false)))`, 'i');
|
|
2577
|
-
// The clause keywords that end a where expression (outside brackets), and `and on` (a join clause's own `and`)
|
|
2578
|
-
const expressionEnd = keyword('sort|group|limit|offset|select|merge|on|where|and\\s+on');
|
|
2579
|
-
const whereMatch = new RegExp(`(^|[^a-z0-9._-])((?:(and|or)\\s+)?where)${wordEnd}`, 'i');
|
|
2580
2645
|
/**
|
|
2581
2646
|
* Read one condition from a match of conditionMatch.
|
|
2582
2647
|
* @param match
|
|
@@ -2620,15 +2685,15 @@ const join = (kind, nodes) => {
|
|
|
2620
2685
|
};
|
|
2621
2686
|
};
|
|
2622
2687
|
/**
|
|
2623
|
-
* Read one where expression from the
|
|
2624
|
-
* first: `or`, `and`, `not`; brackets group.
|
|
2688
|
+
* Read one where expression from the start of a where clause body (masked, see maskStrings). Precedence, loosest
|
|
2689
|
+
* first: `or`, `and`, `not`; brackets group.
|
|
2625
2690
|
* @param text
|
|
2626
|
-
* @
|
|
2627
|
-
* @
|
|
2628
|
-
*
|
|
2691
|
+
* @returns The expression's tree and where it ends (at the first text that can't carry it on, or the end).
|
|
2692
|
+
* @throws {Error} For an unbalanced bracket, empty brackets, an operator with no condition after it, or two conditions
|
|
2693
|
+
* with no and/or between them.
|
|
2629
2694
|
*/
|
|
2630
|
-
const readExpression =
|
|
2631
|
-
let at =
|
|
2695
|
+
const readExpression = text => {
|
|
2696
|
+
let at = 0;
|
|
2632
2697
|
const rest = () => text.slice(at);
|
|
2633
2698
|
const skipSpace = () => {
|
|
2634
2699
|
at += rest().length - rest().trimStart().length;
|
|
@@ -2651,6 +2716,10 @@ const readExpression = (text, start) => {
|
|
|
2651
2716
|
at += condition[0].length;
|
|
2652
2717
|
return readCondition(condition);
|
|
2653
2718
|
}
|
|
2719
|
+
// The 2.x `and where` / `or where` inside brackets, where splitClauses doesn't look
|
|
2720
|
+
if ((after === 'and' || after === 'or') && keyword('where').test(rest())) {
|
|
2721
|
+
throw new Error(`"${after} where" is no longer supported: ${_splitClauses.whereHint}`);
|
|
2722
|
+
}
|
|
2654
2723
|
if (take(keyword('not'))) {
|
|
2655
2724
|
return {
|
|
2656
2725
|
not: factor('not')
|
|
@@ -2673,11 +2742,7 @@ const readExpression = (text, start) => {
|
|
|
2673
2742
|
const term = after => {
|
|
2674
2743
|
const nodes = [factor(after)];
|
|
2675
2744
|
for (;;) {
|
|
2676
|
-
|
|
2677
|
-
if (keyword('and\\s+on').test(rest())) {
|
|
2678
|
-
break;
|
|
2679
|
-
}
|
|
2680
|
-
const connector = take(keyword('and(?:\\s+where)?'));
|
|
2745
|
+
const connector = take(keyword('and'));
|
|
2681
2746
|
if (!connector) {
|
|
2682
2747
|
break;
|
|
2683
2748
|
}
|
|
@@ -2688,7 +2753,7 @@ const readExpression = (text, start) => {
|
|
|
2688
2753
|
const expression = after => {
|
|
2689
2754
|
const nodes = [term(after)];
|
|
2690
2755
|
for (;;) {
|
|
2691
|
-
const connector = take(keyword('or
|
|
2756
|
+
const connector = take(keyword('or'));
|
|
2692
2757
|
if (!connector) {
|
|
2693
2758
|
break;
|
|
2694
2759
|
}
|
|
@@ -2701,7 +2766,7 @@ const readExpression = (text, start) => {
|
|
|
2701
2766
|
if (rest().startsWith(')')) {
|
|
2702
2767
|
throw new Error(`Unexpected ) in a where clause: ${shown()}`);
|
|
2703
2768
|
}
|
|
2704
|
-
if (
|
|
2769
|
+
if (conditionMatch.test(rest())) {
|
|
2705
2770
|
throw new Error(`Missing and/or before: ${shown()}`);
|
|
2706
2771
|
}
|
|
2707
2772
|
return {
|
|
@@ -2710,134 +2775,137 @@ const readExpression = (text, start) => {
|
|
|
2710
2775
|
};
|
|
2711
2776
|
};
|
|
2712
2777
|
/**
|
|
2713
|
-
*
|
|
2714
|
-
* `
|
|
2715
|
-
*
|
|
2716
|
-
*
|
|
2717
|
-
* outside brackets, so clauses may come in any order; several separate `where`s (or `and where` after another clause)
|
|
2718
|
-
* are joined with `and`, as before.
|
|
2778
|
+
* Read a where clause body (see splitClauses) into a tree (see ConditionNode): conditions joined with `and` / `or`,
|
|
2779
|
+
* `not`, and brackets, nested to any depth. Each condition is `<field> <comparator> <value>`, or `<field> is null`,
|
|
2780
|
+
* `is not null`, `exists` or `does not exist`. A comparison with the literal null (`= null`) is refused: it would never
|
|
2781
|
+
* match, as null equals nothing (see where).
|
|
2719
2782
|
* @param parsed
|
|
2720
|
-
* @param
|
|
2721
|
-
* @
|
|
2783
|
+
* @param body
|
|
2784
|
+
* @returns The rest of the body, after the expression.
|
|
2785
|
+
* @throws {Error} For the errors readExpression and readCondition describe.
|
|
2722
2786
|
*/
|
|
2723
|
-
const findConditions = (parsed,
|
|
2724
|
-
const
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
const {
|
|
2731
|
-
node,
|
|
2732
|
-
end
|
|
2733
|
-
} = readExpression(query, whereStart + found[2].length);
|
|
2734
|
-
expressions.push(node);
|
|
2735
|
-
query = `${query.slice(0, whereStart)} ${query.slice(end)}`.replace(/\s+/g, ' ').trim();
|
|
2736
|
-
}
|
|
2737
|
-
parsed['where'] = expressions.length ? join('and', expressions) : (0, _conditionTree.allOf)([]);
|
|
2738
|
-
return query;
|
|
2787
|
+
const findConditions = (parsed, body) => {
|
|
2788
|
+
const {
|
|
2789
|
+
node,
|
|
2790
|
+
end
|
|
2791
|
+
} = readExpression(body);
|
|
2792
|
+
parsed['where'] = node;
|
|
2793
|
+
return body.slice(end).trim();
|
|
2739
2794
|
};
|
|
2740
2795
|
exports.findConditions = findConditions;
|
|
2741
|
-
},{"../conditionTree":37,"./maskStrings":61,"./parseLiteralValue":63,"core-js/modules/es.array.includes.js":222,"core-js/modules/esnext.iterator.constructor.js":237,"core-js/modules/esnext.iterator.flat-map.js":242}],50:[function(require,module,exports){
|
|
2796
|
+
},{"../conditionTree":37,"./maskStrings":61,"./parseLiteralValue":63,"./splitClauses":67,"core-js/modules/es.array.includes.js":222,"core-js/modules/esnext.iterator.constructor.js":237,"core-js/modules/esnext.iterator.flat-map.js":242}],50:[function(require,module,exports){
|
|
2742
2797
|
"use strict";
|
|
2743
2798
|
|
|
2744
2799
|
Object.defineProperty(exports, "__esModule", {
|
|
2745
2800
|
value: true
|
|
2746
2801
|
});
|
|
2747
2802
|
exports.findGroupBy = void 0;
|
|
2748
|
-
|
|
2749
|
-
|
|
2803
|
+
require("core-js/modules/esnext.iterator.constructor.js");
|
|
2804
|
+
require("core-js/modules/esnext.iterator.find.js");
|
|
2805
|
+
const groupMatch = /^[a-z0-9._-]+(?:\s*,\s*[a-z0-9._-]+)*/i;
|
|
2750
2806
|
/**
|
|
2751
|
-
*
|
|
2807
|
+
* Read a group by clause body (`a, b`, see splitClauses).
|
|
2752
2808
|
* @param parsed
|
|
2753
|
-
* @param
|
|
2809
|
+
* @param body
|
|
2810
|
+
* @returns The rest of the body, after the last field.
|
|
2811
|
+
* @throws {Error} For a field named twice.
|
|
2754
2812
|
*/
|
|
2755
|
-
const findGroupBy = (parsed,
|
|
2756
|
-
const groupFound =
|
|
2813
|
+
const findGroupBy = (parsed, body) => {
|
|
2814
|
+
const groupFound = body.match(groupMatch);
|
|
2757
2815
|
if (groupFound) {
|
|
2758
|
-
|
|
2759
|
-
|
|
2816
|
+
const fields = groupFound[0].split(/\s*,\s*/);
|
|
2817
|
+
const repeated = fields.find((field, index) => fields.indexOf(field) !== index);
|
|
2818
|
+
if (repeated) {
|
|
2819
|
+
throw new Error(`"${repeated}" is in group by twice`);
|
|
2820
|
+
}
|
|
2821
|
+
parsed['groupBy'] = fields;
|
|
2822
|
+
return body.slice(groupFound[0].length).trim();
|
|
2760
2823
|
}
|
|
2761
|
-
return
|
|
2824
|
+
return body;
|
|
2762
2825
|
};
|
|
2763
2826
|
exports.findGroupBy = findGroupBy;
|
|
2764
|
-
},{"
|
|
2827
|
+
},{"core-js/modules/esnext.iterator.constructor.js":237,"core-js/modules/esnext.iterator.find.js":241}],51:[function(require,module,exports){
|
|
2765
2828
|
"use strict";
|
|
2766
2829
|
|
|
2767
2830
|
Object.defineProperty(exports, "__esModule", {
|
|
2768
2831
|
value: true
|
|
2769
2832
|
});
|
|
2770
2833
|
exports.findInsertValues = void 0;
|
|
2771
|
-
var _removeFromQuery = require("./removeFromQuery");
|
|
2772
2834
|
var _parseLiteralValue = require("./parseLiteralValue");
|
|
2773
2835
|
var _maskStrings = require("./maskStrings");
|
|
2774
2836
|
const literal = `(?:${_maskStrings.placeholderSource.replace('(', '(?:')}|${_parseLiteralValue.numberSource}|${_maskStrings.arraySource.replace('(', '(?:')}|null|true|false)`;
|
|
2775
|
-
const
|
|
2837
|
+
const valuesMatch = new RegExp(`^([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`, 'i');
|
|
2776
2838
|
const assignmentMatch = new RegExp(`([a-z0-9_-]+)\\s*=\\s*(${_maskStrings.placeholderSource}|(${_parseLiteralValue.numberSource})|${_maskStrings.arraySource}|(null)|(true)|(false))`, 'ig');
|
|
2777
2839
|
/**
|
|
2778
|
-
*
|
|
2840
|
+
* Read an insert's values clause body (`field = value, field2 = value2`, see splitClauses), the same way
|
|
2779
2841
|
* findUpdateValues() does for "set". insertEntity() accepts an array of rows for bulk inserts, but
|
|
2780
2842
|
* a query string only describes a single row for now - wrapped in a one-element array to match.
|
|
2781
2843
|
* @param parsed
|
|
2782
|
-
* @param
|
|
2844
|
+
* @param body
|
|
2845
|
+
* @returns The rest of the body, after the last assignment.
|
|
2783
2846
|
*/
|
|
2784
|
-
const findInsertValues = (parsed,
|
|
2785
|
-
const clauseFound =
|
|
2847
|
+
const findInsertValues = (parsed, body) => {
|
|
2848
|
+
const clauseFound = body.match(valuesMatch);
|
|
2786
2849
|
parsed['insertValues'] = [];
|
|
2787
2850
|
if (!clauseFound) {
|
|
2788
|
-
return
|
|
2851
|
+
return body;
|
|
2789
2852
|
}
|
|
2790
2853
|
const row = {};
|
|
2791
|
-
const assignmentsFound = clauseFound[
|
|
2854
|
+
const assignmentsFound = clauseFound[1].matchAll(assignmentMatch);
|
|
2792
2855
|
// @ts-ignore
|
|
2793
2856
|
for (const assignment of assignmentsFound) {
|
|
2794
2857
|
row[assignment[1]] = (0, _parseLiteralValue.parseLiteralValue)(assignment, 3);
|
|
2795
2858
|
}
|
|
2796
2859
|
parsed['insertValues'] = [row];
|
|
2797
|
-
return
|
|
2860
|
+
return body.slice(clauseFound[0].length).trim();
|
|
2798
2861
|
};
|
|
2799
2862
|
exports.findInsertValues = findInsertValues;
|
|
2800
|
-
},{"./maskStrings":61,"./parseLiteralValue":63
|
|
2863
|
+
},{"./maskStrings":61,"./parseLiteralValue":63}],52:[function(require,module,exports){
|
|
2801
2864
|
"use strict";
|
|
2802
2865
|
|
|
2803
2866
|
Object.defineProperty(exports, "__esModule", {
|
|
2804
2867
|
value: true
|
|
2805
2868
|
});
|
|
2806
2869
|
exports.findJoinClauses = void 0;
|
|
2807
|
-
|
|
2808
|
-
const joinClauseMatch =
|
|
2870
|
+
// One join condition, at the start of the text; every one after the first starts with `and on` (see splitClauses)
|
|
2871
|
+
const joinClauseMatch = /^([a-z0-9_-]+\.[a-z0-9_-]+)\s+(=|!=|>|<|>=|<=|in|between|like)\s+([a-z0-9_-]+\.[a-z0-9_-]+)(?![a-z0-9._-])/i;
|
|
2872
|
+
const nextMatch = /^and\s+on\s+/i;
|
|
2809
2873
|
/**
|
|
2810
|
-
*
|
|
2874
|
+
* Read an on clause body (`a.x = b.y and on b.z = c.w`, see splitClauses).
|
|
2811
2875
|
* @param parsed
|
|
2812
|
-
* @param
|
|
2876
|
+
* @param body
|
|
2877
|
+
* @returns The rest of the body, after the last join condition.
|
|
2813
2878
|
*/
|
|
2814
|
-
const findJoinClauses = (parsed,
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
for (const joinClause of joinClausesFound) {
|
|
2879
|
+
const findJoinClauses = (parsed, body) => {
|
|
2880
|
+
let rest = body;
|
|
2881
|
+
for (let joinClause = rest.match(joinClauseMatch); joinClause; joinClause = rest.match(joinClauseMatch)) {
|
|
2818
2882
|
parsed['joinClauses'].push({
|
|
2819
|
-
propertyA: joinClause[
|
|
2820
|
-
comparator: joinClause[
|
|
2821
|
-
propertyB: joinClause[
|
|
2883
|
+
propertyA: joinClause[1],
|
|
2884
|
+
comparator: joinClause[2],
|
|
2885
|
+
propertyB: joinClause[3]
|
|
2822
2886
|
});
|
|
2823
|
-
|
|
2887
|
+
rest = rest.slice(joinClause[0].length).trim();
|
|
2888
|
+
// The connector only with another one after it, so a bad one is shown with its connector
|
|
2889
|
+
const next = rest.match(nextMatch);
|
|
2890
|
+
if (!next || !joinClauseMatch.test(rest.slice(next[0].length))) {
|
|
2891
|
+
break;
|
|
2892
|
+
}
|
|
2893
|
+
rest = rest.slice(next[0].length);
|
|
2824
2894
|
}
|
|
2825
|
-
return
|
|
2895
|
+
return rest;
|
|
2826
2896
|
};
|
|
2827
2897
|
exports.findJoinClauses = findJoinClauses;
|
|
2828
|
-
},{
|
|
2898
|
+
},{}],53:[function(require,module,exports){
|
|
2829
2899
|
"use strict";
|
|
2830
2900
|
|
|
2831
2901
|
Object.defineProperty(exports, "__esModule", {
|
|
2832
2902
|
value: true
|
|
2833
2903
|
});
|
|
2834
2904
|
exports.findJoinEntity = void 0;
|
|
2835
|
-
|
|
2836
|
-
// Only straight after the entity (findCommand leaves `.joined ...`): a `.` later on is a number's (`1.5`) or a
|
|
2837
|
-
// condition's `entity.field`, not the join
|
|
2905
|
+
// What findCommand leaves of the head: `.joined`
|
|
2838
2906
|
const joinEntityMatch = /^\.([a-z0-9_-]+)/i;
|
|
2839
2907
|
/**
|
|
2840
|
-
*
|
|
2908
|
+
* Read the joined record from what findCommand left of the head.
|
|
2841
2909
|
* @param parsed
|
|
2842
2910
|
* @param query
|
|
2843
2911
|
*/
|
|
@@ -2845,189 +2913,192 @@ const findJoinEntity = (parsed, query) => {
|
|
|
2845
2913
|
const joinEntityFound = query.match(joinEntityMatch);
|
|
2846
2914
|
if (joinEntityFound) {
|
|
2847
2915
|
parsed['joinEntity'] = joinEntityFound ? joinEntityFound[1] : undefined;
|
|
2848
|
-
return
|
|
2916
|
+
return query.slice(joinEntityFound[0].length).trim();
|
|
2849
2917
|
}
|
|
2850
2918
|
return query;
|
|
2851
2919
|
};
|
|
2852
2920
|
exports.findJoinEntity = findJoinEntity;
|
|
2853
|
-
},{
|
|
2921
|
+
},{}],54:[function(require,module,exports){
|
|
2854
2922
|
"use strict";
|
|
2855
2923
|
|
|
2856
2924
|
Object.defineProperty(exports, "__esModule", {
|
|
2857
2925
|
value: true
|
|
2858
2926
|
});
|
|
2859
2927
|
exports.findLimit = void 0;
|
|
2860
|
-
|
|
2861
|
-
const limitMatch = /limit\s*(\d+)/i;
|
|
2928
|
+
const limitMatch = /^(\d+)/;
|
|
2862
2929
|
/**
|
|
2863
|
-
*
|
|
2930
|
+
* Read a limit clause body (a whole number, see splitClauses).
|
|
2864
2931
|
* @param parsed
|
|
2865
|
-
* @param
|
|
2932
|
+
* @param body
|
|
2933
|
+
* @returns The rest of the body, after the number.
|
|
2866
2934
|
*/
|
|
2867
|
-
const findLimit = (parsed,
|
|
2868
|
-
const limitFound =
|
|
2935
|
+
const findLimit = (parsed, body) => {
|
|
2936
|
+
const limitFound = body.match(limitMatch);
|
|
2869
2937
|
if (limitFound) {
|
|
2870
2938
|
parsed['limit'] = limitFound ? parseInt(limitFound[1]) : undefined;
|
|
2871
|
-
return
|
|
2939
|
+
return body.slice(limitFound[0].length).trim();
|
|
2872
2940
|
}
|
|
2873
|
-
return
|
|
2941
|
+
return body;
|
|
2874
2942
|
};
|
|
2875
2943
|
exports.findLimit = findLimit;
|
|
2876
|
-
},{
|
|
2944
|
+
},{}],55:[function(require,module,exports){
|
|
2877
2945
|
"use strict";
|
|
2878
2946
|
|
|
2879
2947
|
Object.defineProperty(exports, "__esModule", {
|
|
2880
2948
|
value: true
|
|
2881
2949
|
});
|
|
2882
2950
|
exports.findMergeJoins = void 0;
|
|
2883
|
-
|
|
2884
|
-
const mergeJoinMatch =
|
|
2951
|
+
// One merge, at the start of the text; every one after the first starts with `merge` or `and merge` (see splitClauses)
|
|
2952
|
+
const mergeJoinMatch = /^([a-z0-9_-]+\.[a-z0-9_-]+)\s+with\s+([a-z0-9_-]+\.[a-z0-9_-]+)(?![a-z0-9._-])/i;
|
|
2953
|
+
const nextMatch = /^(?:and\s+)?merge\s+/i;
|
|
2885
2954
|
/**
|
|
2886
|
-
*
|
|
2955
|
+
* Read a merge clause body (`a.x with b.y merge c.z with d.w`, see splitClauses).
|
|
2887
2956
|
* @param parsed
|
|
2888
|
-
* @param
|
|
2957
|
+
* @param body
|
|
2958
|
+
* @returns The rest of the body, after the last merge.
|
|
2889
2959
|
*/
|
|
2890
|
-
const findMergeJoins = (parsed,
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
for (const mergeJoin of mergeJoinsFound) {
|
|
2960
|
+
const findMergeJoins = (parsed, body) => {
|
|
2961
|
+
let rest = body;
|
|
2962
|
+
for (let mergeJoin = rest.match(mergeJoinMatch); mergeJoin; mergeJoin = rest.match(mergeJoinMatch)) {
|
|
2894
2963
|
parsed['mergeJoins'].push({
|
|
2895
|
-
propertyA: mergeJoin[
|
|
2896
|
-
propertyB: mergeJoin[
|
|
2964
|
+
propertyA: mergeJoin[1],
|
|
2965
|
+
propertyB: mergeJoin[2]
|
|
2897
2966
|
});
|
|
2898
|
-
|
|
2967
|
+
rest = rest.slice(mergeJoin[0].length).trim();
|
|
2968
|
+
// The connector only with another one after it, so a bad one is shown with its connector
|
|
2969
|
+
const next = rest.match(nextMatch);
|
|
2970
|
+
if (!next || !mergeJoinMatch.test(rest.slice(next[0].length))) {
|
|
2971
|
+
break;
|
|
2972
|
+
}
|
|
2973
|
+
rest = rest.slice(next[0].length);
|
|
2899
2974
|
}
|
|
2900
|
-
return
|
|
2975
|
+
return rest;
|
|
2901
2976
|
};
|
|
2902
2977
|
exports.findMergeJoins = findMergeJoins;
|
|
2903
|
-
},{
|
|
2978
|
+
},{}],56:[function(require,module,exports){
|
|
2904
2979
|
"use strict";
|
|
2905
2980
|
|
|
2906
2981
|
Object.defineProperty(exports, "__esModule", {
|
|
2907
2982
|
value: true
|
|
2908
2983
|
});
|
|
2909
2984
|
exports.findOffset = void 0;
|
|
2910
|
-
|
|
2911
|
-
const offsetMatch = /offset\s*(\d+)/i;
|
|
2985
|
+
const offsetMatch = /^(\d+)/;
|
|
2912
2986
|
/**
|
|
2913
|
-
*
|
|
2987
|
+
* Read a offset clause body (a whole number, see splitClauses).
|
|
2914
2988
|
* @param parsed
|
|
2915
|
-
* @param
|
|
2989
|
+
* @param body
|
|
2990
|
+
* @returns The rest of the body, after the number.
|
|
2916
2991
|
*/
|
|
2917
|
-
const findOffset = (parsed,
|
|
2918
|
-
const offsetFound =
|
|
2992
|
+
const findOffset = (parsed, body) => {
|
|
2993
|
+
const offsetFound = body.match(offsetMatch);
|
|
2919
2994
|
if (offsetFound) {
|
|
2920
2995
|
parsed['offset'] = offsetFound ? parseInt(offsetFound[1]) : undefined;
|
|
2921
|
-
return
|
|
2996
|
+
return body.slice(offsetFound[0].length).trim();
|
|
2922
2997
|
}
|
|
2923
|
-
return
|
|
2998
|
+
return body;
|
|
2924
2999
|
};
|
|
2925
3000
|
exports.findOffset = findOffset;
|
|
2926
|
-
},{
|
|
3001
|
+
},{}],57:[function(require,module,exports){
|
|
2927
3002
|
"use strict";
|
|
2928
3003
|
|
|
2929
3004
|
Object.defineProperty(exports, "__esModule", {
|
|
2930
3005
|
value: true
|
|
2931
3006
|
});
|
|
2932
3007
|
exports.findSelects = void 0;
|
|
2933
|
-
|
|
2934
|
-
// One field is a name, then optionally `as <alias>` (`as` as a whole word); fields are separated by commas. The first
|
|
2935
|
-
// field used to accept an alias without `as`, so in `select name where a = 1` the word `where` became the alias.
|
|
3008
|
+
// One field is a name, then optionally `as <alias>` (`as` as a whole word); fields are separated by commas
|
|
2936
3009
|
const selectField = '[a-z0-9=._-]+(?:\\s+as\\s+[a-z0-9_-]+)?';
|
|
2937
|
-
const
|
|
2938
|
-
const
|
|
3010
|
+
const selectsMatch = new RegExp(`^${selectField}(?:\\s*,\\s*${selectField})*`, 'i');
|
|
3011
|
+
const selectFieldMatch = /,?\s*([a-z0-9=._-]+)(?:\s+as\s+([a-z0-9_-]+))?/ig;
|
|
2939
3012
|
/**
|
|
2940
|
-
*
|
|
3013
|
+
* Read a select clause body (`a, b as c`, see splitClauses).
|
|
2941
3014
|
* @param parsed
|
|
2942
|
-
* @param
|
|
3015
|
+
* @param body
|
|
3016
|
+
* @returns The rest of the body, after the last field.
|
|
2943
3017
|
*/
|
|
2944
|
-
const findSelects = (parsed,
|
|
2945
|
-
const selectsFound =
|
|
3018
|
+
const findSelects = (parsed, body) => {
|
|
3019
|
+
const selectsFound = body.match(selectsMatch);
|
|
2946
3020
|
if (selectsFound) {
|
|
2947
|
-
const selectClausesFound = selectsFound[0].matchAll(
|
|
3021
|
+
const selectClausesFound = selectsFound[0].matchAll(selectFieldMatch);
|
|
2948
3022
|
// @ts-ignore
|
|
2949
3023
|
for (const selectClause of selectClausesFound) {
|
|
2950
3024
|
parsed['selectClauses'].push({
|
|
2951
|
-
property: selectClause[
|
|
2952
|
-
alias: selectClause[
|
|
3025
|
+
property: selectClause[1],
|
|
3026
|
+
alias: selectClause[2]
|
|
2953
3027
|
});
|
|
2954
3028
|
}
|
|
2955
|
-
return
|
|
3029
|
+
return body.slice(selectsFound[0].length).trim();
|
|
2956
3030
|
}
|
|
2957
|
-
return
|
|
3031
|
+
return body;
|
|
2958
3032
|
};
|
|
2959
3033
|
exports.findSelects = findSelects;
|
|
2960
|
-
},{
|
|
3034
|
+
},{}],58:[function(require,module,exports){
|
|
2961
3035
|
"use strict";
|
|
2962
3036
|
|
|
2963
3037
|
Object.defineProperty(exports, "__esModule", {
|
|
2964
3038
|
value: true
|
|
2965
3039
|
});
|
|
2966
3040
|
exports.findSortClauses = void 0;
|
|
2967
|
-
var _removeFromQuery = require("./removeFromQuery");
|
|
2968
3041
|
// One rule is a field, then optionally asc or desc as a whole word. Rules are separated by commas, so the list ends
|
|
2969
|
-
// at the first word that doesn't follow a comma: in `sort a
|
|
3042
|
+
// at the first word that doesn't follow a comma: in `sort a b`, `b` is left over.
|
|
2970
3043
|
const sortRule = '[a-z0-9._-]+(?:\\s+(?:asc|desc)(?![a-z0-9._-]))?';
|
|
2971
|
-
const sortMatch = new RegExp(
|
|
2972
|
-
const sortRuleMatch =
|
|
3044
|
+
const sortMatch = new RegExp(`^${sortRule}(?:\\s*,\\s*${sortRule})*`, 'i');
|
|
3045
|
+
const sortRuleMatch = /,?\s*([a-z0-9._-]+)(?:\s+(asc|desc)(?![a-z0-9._-]))?/ig;
|
|
2973
3046
|
/**
|
|
2974
|
-
*
|
|
3047
|
+
* Read a sort clause body (`a, b desc`, see splitClauses).
|
|
2975
3048
|
* @param parsed
|
|
2976
|
-
* @param
|
|
3049
|
+
* @param body
|
|
3050
|
+
* @returns The rest of the body, after the last rule.
|
|
2977
3051
|
*/
|
|
2978
|
-
const findSortClauses = (parsed,
|
|
2979
|
-
const sortFound =
|
|
3052
|
+
const findSortClauses = (parsed, body) => {
|
|
3053
|
+
const sortFound = body.match(sortMatch);
|
|
2980
3054
|
if (sortFound) {
|
|
2981
3055
|
const sortRulesFound = sortFound[0].matchAll(sortRuleMatch);
|
|
2982
3056
|
// @ts-ignore
|
|
2983
3057
|
for (const sortClause of sortRulesFound) {
|
|
2984
3058
|
parsed['sortClauses'].push({
|
|
2985
|
-
property: sortClause[
|
|
2986
|
-
direction: (sortClause[
|
|
3059
|
+
property: sortClause[1],
|
|
3060
|
+
direction: (sortClause[2] || 'asc').toLowerCase()
|
|
2987
3061
|
});
|
|
2988
3062
|
}
|
|
2989
|
-
return
|
|
3063
|
+
return body.slice(sortFound[0].length).trim();
|
|
2990
3064
|
}
|
|
2991
|
-
return
|
|
3065
|
+
return body;
|
|
2992
3066
|
};
|
|
2993
3067
|
exports.findSortClauses = findSortClauses;
|
|
2994
|
-
},{
|
|
3068
|
+
},{}],59:[function(require,module,exports){
|
|
2995
3069
|
"use strict";
|
|
2996
3070
|
|
|
2997
3071
|
Object.defineProperty(exports, "__esModule", {
|
|
2998
3072
|
value: true
|
|
2999
3073
|
});
|
|
3000
3074
|
exports.findUpdateValues = void 0;
|
|
3001
|
-
var _removeFromQuery = require("./removeFromQuery");
|
|
3002
3075
|
var _parseLiteralValue = require("./parseLiteralValue");
|
|
3003
3076
|
var _maskStrings = require("./maskStrings");
|
|
3004
3077
|
const literal = `(?:${_maskStrings.placeholderSource.replace('(', '(?:')}|${_parseLiteralValue.numberSource}|${_maskStrings.arraySource.replace('(', '(?:')}|null|true|false)`;
|
|
3005
|
-
const
|
|
3078
|
+
const setMatch = new RegExp(`^([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`, 'i');
|
|
3006
3079
|
const assignmentMatch = new RegExp(`([a-z0-9_-]+)\\s*=\\s*(${_maskStrings.placeholderSource}|(${_parseLiteralValue.numberSource})|${_maskStrings.arraySource}|(null)|(true)|(false))`, 'ig');
|
|
3007
3080
|
/**
|
|
3008
|
-
*
|
|
3009
|
-
*
|
|
3010
|
-
* be removed from the query as a whole, and so the comma-separated list doesn't get confused with
|
|
3011
|
-
* anything that follows, like a where clause), then each individual assignment is parsed out of
|
|
3012
|
-
* that captured substring.
|
|
3081
|
+
* Read an update's set clause body (`field = value, field2 = value2`, see splitClauses). Uses a two-pass match: the
|
|
3082
|
+
* whole comma-separated list first, so anything after it is left over, then each assignment out of that list.
|
|
3013
3083
|
* @param parsed
|
|
3014
|
-
* @param
|
|
3084
|
+
* @param body
|
|
3085
|
+
* @returns The rest of the body, after the last assignment.
|
|
3015
3086
|
*/
|
|
3016
|
-
const findUpdateValues = (parsed,
|
|
3017
|
-
const clauseFound =
|
|
3087
|
+
const findUpdateValues = (parsed, body) => {
|
|
3088
|
+
const clauseFound = body.match(setMatch);
|
|
3018
3089
|
parsed['updateValues'] = {};
|
|
3019
3090
|
if (!clauseFound) {
|
|
3020
|
-
return
|
|
3091
|
+
return body;
|
|
3021
3092
|
}
|
|
3022
|
-
const assignmentsFound = clauseFound[
|
|
3093
|
+
const assignmentsFound = clauseFound[1].matchAll(assignmentMatch);
|
|
3023
3094
|
// @ts-ignore
|
|
3024
3095
|
for (const assignment of assignmentsFound) {
|
|
3025
3096
|
parsed['updateValues'][assignment[1]] = (0, _parseLiteralValue.parseLiteralValue)(assignment, 3);
|
|
3026
3097
|
}
|
|
3027
|
-
return
|
|
3098
|
+
return body.slice(clauseFound[0].length).trim();
|
|
3028
3099
|
};
|
|
3029
3100
|
exports.findUpdateValues = findUpdateValues;
|
|
3030
|
-
},{"./maskStrings":61,"./parseLiteralValue":63
|
|
3101
|
+
},{"./maskStrings":61,"./parseLiteralValue":63}],60:[function(require,module,exports){
|
|
3031
3102
|
"use strict";
|
|
3032
3103
|
|
|
3033
3104
|
Object.defineProperty(exports, "__esModule", {
|
|
@@ -3164,7 +3235,7 @@ const maskArrays = masked => {
|
|
|
3164
3235
|
return depth > 0 ? result + masked.slice(start) : result;
|
|
3165
3236
|
};
|
|
3166
3237
|
exports.maskArrays = maskArrays;
|
|
3167
|
-
},{"./scanQuery":
|
|
3238
|
+
},{"./scanQuery":66,"core-js/modules/es.json.stringify.js":233,"core-js/modules/esnext.iterator.constructor.js":237,"core-js/modules/esnext.iterator.map.js":244,"core-js/modules/esnext.iterator.some.js":246}],62:[function(require,module,exports){
|
|
3168
3239
|
"use strict";
|
|
3169
3240
|
|
|
3170
3241
|
Object.defineProperty(exports, "__esModule", {
|
|
@@ -3568,13 +3639,13 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
3568
3639
|
value: true
|
|
3569
3640
|
});
|
|
3570
3641
|
exports.parseQuery = void 0;
|
|
3571
|
-
var _siFunciona = _interopRequireDefault(require("si-funciona"));
|
|
3572
3642
|
var _findCommand = require("./findCommand");
|
|
3573
3643
|
var _findInsertValues = require("./findInsertValues");
|
|
3574
3644
|
var _findUpdateValues = require("./findUpdateValues");
|
|
3575
3645
|
var _findJoinEntity = require("./findJoinEntity");
|
|
3576
3646
|
var _findSelects = require("./findSelects");
|
|
3577
3647
|
var _findConditions = require("./findConditions");
|
|
3648
|
+
var _conditionTree = require("../conditionTree");
|
|
3578
3649
|
var _findJoinClauses = require("./findJoinClauses");
|
|
3579
3650
|
var _findMergeJoins = require("./findMergeJoins");
|
|
3580
3651
|
var _findSortClauses = require("./findSortClauses");
|
|
@@ -3584,8 +3655,63 @@ var _findOffset = require("./findOffset");
|
|
|
3584
3655
|
var _maskStrings = require("./maskStrings");
|
|
3585
3656
|
var _parseCreate = require("./parseCreate");
|
|
3586
3657
|
var _parseSchemaStatement = require("./parseSchemaStatement");
|
|
3658
|
+
var _splitClauses = require("./splitClauses");
|
|
3587
3659
|
var _startsQuery = require("./startsQuery");
|
|
3588
|
-
|
|
3660
|
+
// Each clause's own step, and what its body must start with (for the error when it doesn't)
|
|
3661
|
+
const clauseSteps = {
|
|
3662
|
+
values: {
|
|
3663
|
+
step: _findInsertValues.findInsertValues,
|
|
3664
|
+
expected: 'an assignment (field = value)'
|
|
3665
|
+
},
|
|
3666
|
+
set: {
|
|
3667
|
+
step: _findUpdateValues.findUpdateValues,
|
|
3668
|
+
expected: 'an assignment (field = value)'
|
|
3669
|
+
},
|
|
3670
|
+
select: {
|
|
3671
|
+
step: _findSelects.findSelects,
|
|
3672
|
+
expected: 'a field'
|
|
3673
|
+
},
|
|
3674
|
+
on: {
|
|
3675
|
+
step: _findJoinClauses.findJoinClauses,
|
|
3676
|
+
expected: 'a join condition (a.x = b.y)'
|
|
3677
|
+
},
|
|
3678
|
+
merge: {
|
|
3679
|
+
step: _findMergeJoins.findMergeJoins,
|
|
3680
|
+
expected: 'a merge (a.x with b.y)'
|
|
3681
|
+
},
|
|
3682
|
+
where: {
|
|
3683
|
+
step: _findConditions.findConditions,
|
|
3684
|
+
expected: 'a condition'
|
|
3685
|
+
},
|
|
3686
|
+
'group by': {
|
|
3687
|
+
step: _findGroupBy.findGroupBy,
|
|
3688
|
+
expected: 'a field'
|
|
3689
|
+
},
|
|
3690
|
+
sort: {
|
|
3691
|
+
step: _findSortClauses.findSortClauses,
|
|
3692
|
+
expected: 'a field'
|
|
3693
|
+
},
|
|
3694
|
+
limit: {
|
|
3695
|
+
step: _findLimit.findLimit,
|
|
3696
|
+
expected: 'a whole number'
|
|
3697
|
+
},
|
|
3698
|
+
offset: {
|
|
3699
|
+
step: _findOffset.findOffset,
|
|
3700
|
+
expected: 'a whole number'
|
|
3701
|
+
}
|
|
3702
|
+
};
|
|
3703
|
+
/**
|
|
3704
|
+
* The error for text a step couldn't read: another query run on without a `;`, or text that doesn't belong.
|
|
3705
|
+
* @param rest The text left over, masked
|
|
3706
|
+
* @param after What was read before it, masked
|
|
3707
|
+
*/
|
|
3708
|
+
const leftoverError = (rest, after) => {
|
|
3709
|
+
const shown = text => (0, _maskStrings.unmaskStrings)(text, '\'');
|
|
3710
|
+
if (_startsQuery.startsQueryMatch.test(rest)) {
|
|
3711
|
+
return new Error(`Missing ; before: ${shown(rest)}`);
|
|
3712
|
+
}
|
|
3713
|
+
return new Error(`Unexpected "${shown(rest)}" after "${shown(after)}"`);
|
|
3714
|
+
};
|
|
3589
3715
|
/**
|
|
3590
3716
|
* Break a query down into its components.
|
|
3591
3717
|
* @param query
|
|
@@ -3608,10 +3734,6 @@ const parseQuery = query => {
|
|
|
3608
3734
|
create: undefined,
|
|
3609
3735
|
ifExists: undefined
|
|
3610
3736
|
};
|
|
3611
|
-
const {
|
|
3612
|
-
curry,
|
|
3613
|
-
pipe
|
|
3614
|
-
} = _siFunciona.default;
|
|
3615
3737
|
// No find* step may see inside a string or an array: each one becomes a placeholder holding its value
|
|
3616
3738
|
query = (0, _maskStrings.maskArrays)((0, _maskStrings.maskStrings)(query));
|
|
3617
3739
|
// A create statement has its own shape (a bracketed list of fields and keys), so it gets its own parser
|
|
@@ -3629,17 +3751,40 @@ const parseQuery = query => {
|
|
|
3629
3751
|
if (_parseSchemaStatement.schemaStatementMatch.test(query)) {
|
|
3630
3752
|
return Object.assign(parsedQuery, (0, _parseSchemaStatement.parseSchemaStatement)(query));
|
|
3631
3753
|
}
|
|
3632
|
-
|
|
3633
|
-
|
|
3754
|
+
// Clauses come at most once each, in a fixed order (see clauseOrder); each step reads only its own clause's body
|
|
3755
|
+
const split = (0, _splitClauses.splitClauses)(query);
|
|
3756
|
+
if (!split) {
|
|
3757
|
+
query = query.trim();
|
|
3634
3758
|
if (_startsQuery.startsQueryMatch.test(query)) {
|
|
3635
|
-
throw new Error(`Missing ; before: ${(0, _maskStrings.unmaskStrings)(query
|
|
3759
|
+
throw new Error(`Missing ; before: ${(0, _maskStrings.unmaskStrings)(query, '\'')}`);
|
|
3636
3760
|
}
|
|
3637
3761
|
throw new Error(`Unrecognized query value: ${(0, _maskStrings.unmaskStrings)(query, '\'')}`);
|
|
3638
3762
|
}
|
|
3763
|
+
(0, _findJoinEntity.findJoinEntity)(parsedQuery, (0, _findCommand.findCommand)(parsedQuery, split.head));
|
|
3764
|
+
parsedQuery.where = (0, _conditionTree.allOf)([]);
|
|
3765
|
+
if (split.leading) {
|
|
3766
|
+
throw leftoverError(split.leading, split.head);
|
|
3767
|
+
}
|
|
3768
|
+
for (const {
|
|
3769
|
+
keyword,
|
|
3770
|
+
body
|
|
3771
|
+
} of split.clauses) {
|
|
3772
|
+
const {
|
|
3773
|
+
step,
|
|
3774
|
+
expected
|
|
3775
|
+
} = clauseSteps[keyword];
|
|
3776
|
+
const rest = step(parsedQuery, body);
|
|
3777
|
+
if (rest === body) {
|
|
3778
|
+
throw new Error(`Missing ${expected} after ${keyword}${body ? `: ${(0, _maskStrings.unmaskStrings)(body, '\'')}` : ''}`);
|
|
3779
|
+
}
|
|
3780
|
+
if (rest) {
|
|
3781
|
+
throw leftoverError(rest, `${keyword} ${body.slice(0, body.length - rest.length).trim()}`);
|
|
3782
|
+
}
|
|
3783
|
+
}
|
|
3639
3784
|
return parsedQuery;
|
|
3640
3785
|
};
|
|
3641
3786
|
exports.parseQuery = parseQuery;
|
|
3642
|
-
},{"./findCommand":48,"./findConditions":49,"./findGroupBy":50,"./findInsertValues":51,"./findJoinClauses":52,"./findJoinEntity":53,"./findLimit":54,"./findMergeJoins":55,"./findOffset":56,"./findSelects":57,"./findSortClauses":58,"./findUpdateValues":59,"./maskStrings":61,"./parseCreate":62,"./parseSchemaStatement":65,"./
|
|
3787
|
+
},{"../conditionTree":37,"./findCommand":48,"./findConditions":49,"./findGroupBy":50,"./findInsertValues":51,"./findJoinClauses":52,"./findJoinEntity":53,"./findLimit":54,"./findMergeJoins":55,"./findOffset":56,"./findSelects":57,"./findSortClauses":58,"./findUpdateValues":59,"./maskStrings":61,"./parseCreate":62,"./parseSchemaStatement":65,"./splitClauses":67,"./startsQuery":70}],65:[function(require,module,exports){
|
|
3643
3788
|
"use strict";
|
|
3644
3789
|
|
|
3645
3790
|
Object.defineProperty(exports, "__esModule", {
|
|
@@ -3725,15 +3870,6 @@ exports.parseSchemaStatement = parseSchemaStatement;
|
|
|
3725
3870
|
},{"./maskStrings":61,"./startsQuery":70}],66:[function(require,module,exports){
|
|
3726
3871
|
"use strict";
|
|
3727
3872
|
|
|
3728
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3729
|
-
value: true
|
|
3730
|
-
});
|
|
3731
|
-
exports.removeFromQuery = void 0;
|
|
3732
|
-
const removeFromQuery = (substring, query) => query.replace(substring, '').trim();
|
|
3733
|
-
exports.removeFromQuery = removeFromQuery;
|
|
3734
|
-
},{}],67:[function(require,module,exports){
|
|
3735
|
-
"use strict";
|
|
3736
|
-
|
|
3737
3873
|
Object.defineProperty(exports, "__esModule", {
|
|
3738
3874
|
value: true
|
|
3739
3875
|
});
|
|
@@ -3890,7 +4026,147 @@ const assertClosed = scanned => {
|
|
|
3890
4026
|
return scanned;
|
|
3891
4027
|
};
|
|
3892
4028
|
exports.assertClosed = assertClosed;
|
|
3893
|
-
},{}],
|
|
4029
|
+
},{}],67:[function(require,module,exports){
|
|
4030
|
+
"use strict";
|
|
4031
|
+
|
|
4032
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4033
|
+
value: true
|
|
4034
|
+
});
|
|
4035
|
+
exports.whereHint = exports.splitClauses = exports.clauseOrder = void 0;
|
|
4036
|
+
require("core-js/modules/es.array.includes.js");
|
|
4037
|
+
require("core-js/modules/esnext.set.add-all.js");
|
|
4038
|
+
require("core-js/modules/esnext.set.delete-all.js");
|
|
4039
|
+
require("core-js/modules/esnext.set.difference.js");
|
|
4040
|
+
require("core-js/modules/esnext.set.every.js");
|
|
4041
|
+
require("core-js/modules/esnext.set.filter.js");
|
|
4042
|
+
require("core-js/modules/esnext.set.find.js");
|
|
4043
|
+
require("core-js/modules/esnext.set.intersection.js");
|
|
4044
|
+
require("core-js/modules/esnext.set.is-disjoint-from.js");
|
|
4045
|
+
require("core-js/modules/esnext.set.is-subset-of.js");
|
|
4046
|
+
require("core-js/modules/esnext.set.is-superset-of.js");
|
|
4047
|
+
require("core-js/modules/esnext.set.join.js");
|
|
4048
|
+
require("core-js/modules/esnext.set.map.js");
|
|
4049
|
+
require("core-js/modules/esnext.set.reduce.js");
|
|
4050
|
+
require("core-js/modules/esnext.set.some.js");
|
|
4051
|
+
require("core-js/modules/esnext.set.symmetric-difference.js");
|
|
4052
|
+
require("core-js/modules/esnext.set.union.js");
|
|
4053
|
+
var _maskStrings = require("./maskStrings");
|
|
4054
|
+
/**
|
|
4055
|
+
* The clauses each command allows, in the order they must come. create, drop, describe and show have their own
|
|
4056
|
+
* parsers and never get here.
|
|
4057
|
+
*/
|
|
4058
|
+
const clauseOrder = exports.clauseOrder = {
|
|
4059
|
+
read: ['select', 'on', 'merge', 'where', 'group by', 'sort', 'limit', 'offset'],
|
|
4060
|
+
insert: ['values'],
|
|
4061
|
+
update: ['set', 'where'],
|
|
4062
|
+
delete: ['where']
|
|
4063
|
+
};
|
|
4064
|
+
const clauseWords = [...new Set(Object.values(clauseOrder).flat())];
|
|
4065
|
+
// The command, the record name and an optional joined record (`read workouts.exercises`, or `read workouts .exercises`)
|
|
4066
|
+
const headMatch = /^\s*(delete|insert|read|update)\s+([a-z0-9_-]+(\s*\.[a-z0-9_-]+)?)/i;
|
|
4067
|
+
// Placeholders (see maskStrings) as one token each, so their hex can't read as a word; words; then the two-character
|
|
4068
|
+
// comparators before any other single character
|
|
4069
|
+
const tokenMatch = new RegExp(`${_maskStrings.placeholderSource}|${_maskStrings.arraySource}|[a-z0-9_.-]+|<>|!=|>=|<=|\\S`, 'gi');
|
|
4070
|
+
// What can follow a field in a condition: a clause word followed by one of these is a field (`where limit = 1`)
|
|
4071
|
+
const conditionWords = ['=', '!=', '<>', '>', '<', '>=', '<=', 'in', 'between', 'like', 'is', 'exists', 'does'];
|
|
4072
|
+
// `and on` carries on the on clause instead of starting another; so does a merge straight after another
|
|
4073
|
+
// (`merge a.x with b.y merge c.z with d.w`, with or without `and`)
|
|
4074
|
+
const continues = {
|
|
4075
|
+
on: previous => previous === 'and',
|
|
4076
|
+
merge: () => true
|
|
4077
|
+
};
|
|
4078
|
+
// What a second where clause should have been: its conditions joined with and / or inside the first
|
|
4079
|
+
const whereHint = exports.whereHint = 'use and / or inside one where clause (where a = 1 and b = 2)';
|
|
4080
|
+
/**
|
|
4081
|
+
* Split a masked query (see maskStrings) into its clauses, reading its top-level words once, left to right. A clause
|
|
4082
|
+
* word counts only as a whole word outside brackets, and not where it must be a name: as a clause's first word
|
|
4083
|
+
* (`sort limit`), after a comma or `as`, or before a comparator (`where limit = 1`).
|
|
4084
|
+
* @param query
|
|
4085
|
+
* @returns undefined when the query doesn't start with read, insert, update or delete (left to the find* steps).
|
|
4086
|
+
* @throws {Error} For a joined record outside read, a clause the command doesn't allow, a repeated clause, a clause out
|
|
4087
|
+
* of order, or the 2.x forms of a second where (`and where`, `or where`, or a plain repeat).
|
|
4088
|
+
*/
|
|
4089
|
+
const splitClauses = query => {
|
|
4090
|
+
const head = query.match(headMatch);
|
|
4091
|
+
if (!head) {
|
|
4092
|
+
return undefined;
|
|
4093
|
+
}
|
|
4094
|
+
const command = head[1].toLowerCase();
|
|
4095
|
+
const allowed = clauseOrder[command];
|
|
4096
|
+
const article = /^[aeiou]/.test(command) ? 'an' : 'a';
|
|
4097
|
+
if (head[3] && command !== 'read') {
|
|
4098
|
+
throw new Error(`A joined record (${head[2]}) isn't allowed in ${article} ${command} query`);
|
|
4099
|
+
}
|
|
4100
|
+
const tokens = [...query.slice(head[0].length).matchAll(tokenMatch)].map(({
|
|
4101
|
+
0: text,
|
|
4102
|
+
index
|
|
4103
|
+
}) => ({
|
|
4104
|
+
text,
|
|
4105
|
+
lower: text.toLowerCase(),
|
|
4106
|
+
start: head[0].length + index
|
|
4107
|
+
}));
|
|
4108
|
+
const found = [];
|
|
4109
|
+
let depth = 0;
|
|
4110
|
+
let bodyStarts = false;
|
|
4111
|
+
for (let index = 0; index < tokens.length; index++) {
|
|
4112
|
+
const {
|
|
4113
|
+
lower,
|
|
4114
|
+
start
|
|
4115
|
+
} = tokens[index];
|
|
4116
|
+
const previous = tokens[index - 1]?.lower;
|
|
4117
|
+
const next = tokens[index + 1]?.lower;
|
|
4118
|
+
if (lower === '(' || lower === ')') {
|
|
4119
|
+
depth += lower === '(' ? 1 : -1;
|
|
4120
|
+
}
|
|
4121
|
+
const keyword = lower === 'group' && next === 'by' ? 'group by' : lower;
|
|
4122
|
+
const isName = bodyStarts || previous === ',' || previous === 'as' || conditionWords.includes(next);
|
|
4123
|
+
bodyStarts = false;
|
|
4124
|
+
if (depth > 0 || keyword === 'by' || !clauseWords.includes(keyword) || isName) {
|
|
4125
|
+
continue;
|
|
4126
|
+
}
|
|
4127
|
+
const current = found[found.length - 1]?.keyword;
|
|
4128
|
+
if (current === keyword && continues[keyword]?.(previous)) {
|
|
4129
|
+
continue;
|
|
4130
|
+
}
|
|
4131
|
+
// 2.x read `and where` / `or where` as `and` / `or`, and a second where as `and`
|
|
4132
|
+
const hasWhere = found.some(clause => clause.keyword === 'where');
|
|
4133
|
+
if (keyword === 'where' && hasWhere && (previous === 'and' || previous === 'or')) {
|
|
4134
|
+
throw new Error(`"${previous} where" is no longer supported: ${whereHint}`);
|
|
4135
|
+
}
|
|
4136
|
+
if (!allowed.includes(keyword)) {
|
|
4137
|
+
throw new Error(`"${keyword}" isn't allowed in ${article} ${command} query (allowed: ${allowed.join(', ')})`);
|
|
4138
|
+
}
|
|
4139
|
+
if (current && allowed.indexOf(keyword) < allowed.indexOf(current)) {
|
|
4140
|
+
throw new Error(`"${keyword}" can't come after "${current}" (order: ${allowed.join(', ')})`);
|
|
4141
|
+
}
|
|
4142
|
+
if (found.some(clause => clause.keyword === keyword)) {
|
|
4143
|
+
throw new Error(`Only one "${keyword}" clause is allowed${keyword === 'where' ? `: ${whereHint}` : ''}`);
|
|
4144
|
+
}
|
|
4145
|
+
if (keyword === 'group by') {
|
|
4146
|
+
index++;
|
|
4147
|
+
}
|
|
4148
|
+
found.push({
|
|
4149
|
+
keyword,
|
|
4150
|
+
start,
|
|
4151
|
+
end: tokens[index].start + tokens[index].text.length
|
|
4152
|
+
});
|
|
4153
|
+
bodyStarts = true;
|
|
4154
|
+
}
|
|
4155
|
+
return {
|
|
4156
|
+
command,
|
|
4157
|
+
head: head[0].trim(),
|
|
4158
|
+
leading: query.slice(head[0].length, found[0]?.start ?? query.length).trim(),
|
|
4159
|
+
clauses: found.map(({
|
|
4160
|
+
keyword,
|
|
4161
|
+
end
|
|
4162
|
+
}, index) => ({
|
|
4163
|
+
keyword,
|
|
4164
|
+
body: query.slice(end, found[index + 1]?.start ?? query.length).trim()
|
|
4165
|
+
}))
|
|
4166
|
+
};
|
|
4167
|
+
};
|
|
4168
|
+
exports.splitClauses = splitClauses;
|
|
4169
|
+
},{"./maskStrings":61,"core-js/modules/es.array.includes.js":222,"core-js/modules/esnext.set.add-all.js":260,"core-js/modules/esnext.set.delete-all.js":261,"core-js/modules/esnext.set.difference.js":262,"core-js/modules/esnext.set.every.js":263,"core-js/modules/esnext.set.filter.js":264,"core-js/modules/esnext.set.find.js":265,"core-js/modules/esnext.set.intersection.js":266,"core-js/modules/esnext.set.is-disjoint-from.js":267,"core-js/modules/esnext.set.is-subset-of.js":268,"core-js/modules/esnext.set.is-superset-of.js":269,"core-js/modules/esnext.set.join.js":270,"core-js/modules/esnext.set.map.js":271,"core-js/modules/esnext.set.reduce.js":272,"core-js/modules/esnext.set.some.js":273,"core-js/modules/esnext.set.symmetric-difference.js":274,"core-js/modules/esnext.set.union.js":275}],68:[function(require,module,exports){
|
|
3894
4170
|
"use strict";
|
|
3895
4171
|
|
|
3896
4172
|
Object.defineProperty(exports, "__esModule", {
|
|
@@ -3944,7 +4220,7 @@ const splitQueries = (queries = '') => {
|
|
|
3944
4220
|
return [...semicolons, uncommented.length].map((end, index) => uncommented.slice(index === 0 ? 0 : semicolons[index - 1] + 1, end).trim()).filter(query => query.length > 0);
|
|
3945
4221
|
};
|
|
3946
4222
|
exports.splitQueries = splitQueries;
|
|
3947
|
-
},{"./scanQuery":
|
|
4223
|
+
},{"./scanQuery":66,"core-js/modules/esnext.iterator.constructor.js":237,"core-js/modules/esnext.iterator.filter.js":240,"core-js/modules/esnext.iterator.reduce.js":245}],70:[function(require,module,exports){
|
|
3948
4224
|
"use strict";
|
|
3949
4225
|
|
|
3950
4226
|
Object.defineProperty(exports, "__esModule", {
|
|
@@ -4379,8 +4655,8 @@ const runQuery = async parsed => {
|
|
|
4379
4655
|
// anything has looked at it at all. readEntity() (below) can't tell those two states apart on its own (it reloads
|
|
4380
4656
|
// whenever the array is empty), so getConditionIndexedList reports which entities it resolved: once any indexed
|
|
4381
4657
|
// condition has narrowed entity's rows, they are the candidates (every condition is applied to them below) and
|
|
4382
|
-
// must not be reloaded. This used to ask whether EVERY condition was indexed, so `where date = 'none' and
|
|
4383
|
-
//
|
|
4658
|
+
// must not be reloaded. This used to ask whether EVERY condition was indexed, so `where date = 'none' and reps =
|
|
4659
|
+
// 10` reloaded every row and returned, updated or deleted all rows with reps 10.
|
|
4384
4660
|
const resolved = new Set();
|
|
4385
4661
|
parsed = await (0, _getConditionIndexedList.getConditionIndexedList)(parsed, recordData, dataSet, resolved);
|
|
4386
4662
|
const entityResolved = resolved.has(parsed.entity);
|
|
@@ -4422,10 +4698,11 @@ const runQuery = async parsed => {
|
|
|
4422
4698
|
if (parsed.command !== 'delete' && parsed.command !== 'update') {
|
|
4423
4699
|
dataSet[parsed.entity] = (0, _where.whereTree)(dataSet[parsed.entity], parsed.where, perPair ? parsed.joinEntity : undefined);
|
|
4424
4700
|
}
|
|
4701
|
+
// Sorted before grouping, so the groups come in sorted order; limit and offset count groups once there are any
|
|
4425
4702
|
dataSet[parsed.entity] = (0, _sortBy.sortBy)(dataSet[parsed.entity], parsed.sortClauses);
|
|
4426
|
-
dataSet[parsed.entity] = (0, _limitOffset.limitOffset)(dataSet[parsed.entity], parsed.offset, parsed.limit);
|
|
4427
4703
|
dataSet[parsed.entity] = (0, _groupBy.groupBy)(dataSet[parsed.entity], parsed.groupBy);
|
|
4428
|
-
dataSet[parsed.entity] = (0,
|
|
4704
|
+
dataSet[parsed.entity] = (0, _limitOffset.limitOffset)(dataSet[parsed.entity], parsed.offset, parsed.limit);
|
|
4705
|
+
dataSet[parsed.entity] = (0, _selectFields.selectFields)(dataSet[parsed.entity], parsed.selectClauses, Boolean(parsed.groupBy?.length));
|
|
4429
4706
|
return dataSet;
|
|
4430
4707
|
};
|
|
4431
4708
|
exports.runQuery = runQuery;
|