json-fs-query 2.1.0 → 2.2.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 +8 -0
- package/browser/jsonFsQuery.js +562 -390
- package/browser/jsonFsQuery.min.js +1 -1
- package/dist/data/queries/sortBy.d.ts +6 -0
- package/dist/data/queries/sortBy.js +13 -4
- package/dist/data/queries/sortBy.min.js +1 -1
- package/dist/data/queries/where.js +8 -6
- package/dist/data/queries/where.min.js +1 -1
- package/dist/data/utilities/getConditionIndexedList.d.ts +13 -1
- package/dist/data/utilities/getConditionIndexedList.js +46 -11
- package/dist/data/utilities/getConditionIndexedList.min.js +1 -1
- package/dist/data/utilities/getMatchingIndexes.js +2 -2
- package/dist/data/utilities/getMatchingIndexes.min.js +1 -1
- package/dist/data/utilities/isSingleFieldKey.d.ts +10 -0
- package/dist/data/utilities/isSingleFieldKey.js +15 -0
- package/dist/data/utilities/isSingleFieldKey.min.js +1 -0
- package/dist/data/utilities/parsers/findSortClauses.d.ts +1 -0
- package/dist/data/utilities/retrieveIndexes.js +2 -2
- package/dist/data/utilities/retrieveIndexes.min.js +1 -1
- package/dist/data/utilities/runQuery.js +35 -18
- package/dist/data/utilities/runQuery.min.js +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sort by each clause in turn: missing, then null, then the values, compared by the field's declared type when the
|
|
3
|
+
* clause has one (see compareAs), so a string field sorts as text ('10' before '9') and an int field as numbers.
|
|
4
|
+
* @param dataSet
|
|
5
|
+
* @param sortClauses
|
|
6
|
+
*/
|
|
1
7
|
export declare const sortBy: (dataSet?: any[], sortClauses?: any[]) => any[];
|
|
2
8
|
//# sourceMappingURL=sortBy.d.ts.map
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.sortBy = void 0;
|
|
7
|
+
var _compareAs = require("../utilities/compareAs");
|
|
7
8
|
// Where a value sorts before any other, ascending: missing first, then null, then the values (MySQL's null placement,
|
|
8
9
|
// with missing below null). Descending reverses it.
|
|
9
10
|
const presence = (data, property) => {
|
|
@@ -12,6 +13,12 @@ const presence = (data, property) => {
|
|
|
12
13
|
}
|
|
13
14
|
return data[property] === null ? 1 : 2;
|
|
14
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* Sort by each clause in turn: missing, then null, then the values, compared by the field's declared type when the
|
|
18
|
+
* clause has one (see compareAs), so a string field sorts as text ('10' before '9') and an int field as numbers.
|
|
19
|
+
* @param dataSet
|
|
20
|
+
* @param sortClauses
|
|
21
|
+
*/
|
|
15
22
|
const sortBy = (dataSet = [], sortClauses = []) => {
|
|
16
23
|
if (!sortClauses.length) {
|
|
17
24
|
return dataSet;
|
|
@@ -25,13 +32,15 @@ const sortBy = (dataSet = [], sortClauses = []) => {
|
|
|
25
32
|
if (rankA !== rankB) {
|
|
26
33
|
return direction === 'asc' ? rankA - rankB : rankB - rankA;
|
|
27
34
|
}
|
|
28
|
-
//
|
|
29
|
-
//
|
|
35
|
+
// Values compare by the declared type, so numeric ids in a string field sort as text ('10' before '9'). Loose so
|
|
36
|
+
// '3' and 3 still tie in an untyped field, as do two nulls or two missing.
|
|
37
|
+
const valueA = (0, _compareAs.compareAs)(sortClause.type, a[property]);
|
|
38
|
+
const valueB = (0, _compareAs.compareAs)(sortClause.type, b[property]);
|
|
30
39
|
// eslint-disable-next-line eqeqeq
|
|
31
|
-
if (
|
|
40
|
+
if (valueA == valueB) {
|
|
32
41
|
continue;
|
|
33
42
|
}
|
|
34
|
-
const result =
|
|
43
|
+
const result = valueA < valueB ? -1 : 1;
|
|
35
44
|
return direction === 'asc' ? result : result * -1;
|
|
36
45
|
}
|
|
37
46
|
return 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.sortBy=void 0;const presence=(e,r)=>Object.prototype.hasOwnProperty.call(e,r)?null===e[r]?1:2:0,sortBy=(e=[],r=[])=>r.length?(e.sort(((e,t)=>{for(const o of r){const r=o.property,s=o.direction,
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.sortBy=void 0;var _compareAs=require("../utilities/compareAs");const presence=(e,r)=>Object.prototype.hasOwnProperty.call(e,r)?null===e[r]?1:2:0,sortBy=(e=[],r=[])=>r.length?(e.sort(((e,t)=>{for(const o of r){const r=o.property,s=o.direction,c=presence(e,r),p=presence(t,r);if(c!==p)return"asc"===s?c-p:p-c;const n=(0,_compareAs.compareAs)(o.type,e[r]),a=(0,_compareAs.compareAs)(o.type,t[r]);if(n==a)continue;const i=n<a?-1:1;return"asc"===s?i:-1*i}return 0})),e):e;exports.sortBy=sortBy;
|
|
@@ -18,7 +18,8 @@ const likeMatch = (dataValue, pattern) => {
|
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
20
|
* Equality (=, !=, <>, in) compares by the field's declared type when given one (see sameValue), so
|
|
21
|
-
* '3' and 3 match in a string or int field. Ordering (>, <, between
|
|
21
|
+
* '3' and 3 match in a string or int field. Ordering (>, >=, <, <=, between) compares by it too (see compareAs): a
|
|
22
|
+
* string field orders as text ('10' < '9'), an int field as numbers. like compares the raw values.
|
|
22
23
|
*
|
|
23
24
|
* Null and missing are their own cases, as in SQL: a field that is null or missing matches no comparison (not even
|
|
24
25
|
* `!=`), and a null never equals anything, not even another null. Only these test for them:
|
|
@@ -47,6 +48,7 @@ const makeCondition = (data, property, comparator, value, type = undefined) => {
|
|
|
47
48
|
return false;
|
|
48
49
|
}
|
|
49
50
|
const dataValue = data[property];
|
|
51
|
+
const typedValue = (0, _compareAs.compareAs)(type, dataValue);
|
|
50
52
|
switch (comparator) {
|
|
51
53
|
case '=':
|
|
52
54
|
return (0, _compareAs.sameValue)(type, dataValue, value);
|
|
@@ -54,18 +56,18 @@ const makeCondition = (data, property, comparator, value, type = undefined) => {
|
|
|
54
56
|
case '<>':
|
|
55
57
|
return !(0, _compareAs.sameValue)(type, dataValue, value);
|
|
56
58
|
case '>':
|
|
57
|
-
return
|
|
59
|
+
return typedValue > (0, _compareAs.compareAs)(type, value);
|
|
58
60
|
case '>=':
|
|
59
|
-
return
|
|
61
|
+
return typedValue >= (0, _compareAs.compareAs)(type, value);
|
|
60
62
|
case '<':
|
|
61
|
-
return
|
|
63
|
+
return typedValue < (0, _compareAs.compareAs)(type, value);
|
|
62
64
|
case '<=':
|
|
63
|
-
return
|
|
65
|
+
return typedValue <= (0, _compareAs.compareAs)(type, value);
|
|
64
66
|
case 'in':
|
|
65
67
|
return Array.isArray(value) && (type ? value.some(item => (0, _compareAs.sameValue)(type, dataValue, item)) : value.includes(dataValue));
|
|
66
68
|
case 'between':
|
|
67
69
|
// A null bound would act as 0 in >= / <=: it bounds nothing, so nothing matches (the parser refuses it)
|
|
68
|
-
return Array.isArray(value) && value.length === 2 && !value.includes(null) &&
|
|
70
|
+
return Array.isArray(value) && value.length === 2 && !value.includes(null) && typedValue >= (0, _compareAs.compareAs)(type, value[0]) && typedValue <= (0, _compareAs.compareAs)(type, value[1]);
|
|
69
71
|
case 'like':
|
|
70
72
|
return likeMatch(dataValue, value);
|
|
71
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.where=void 0,require("core-js/modules/es.array.includes.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.filter.js"),require("core-js/modules/esnext.iterator.some.js");var _compareAs=require("../utilities/compareAs");const likeMatch=(e,r)=>{if("string"!=typeof e||"string"!=typeof r)return!1;const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.where=void 0,require("core-js/modules/es.array.includes.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.filter.js"),require("core-js/modules/esnext.iterator.some.js");var _compareAs=require("../utilities/compareAs");const likeMatch=(e,r)=>{if("string"!=typeof e||"string"!=typeof r)return!1;const s=r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/%/g,".*").replace(/_/g,".");return new RegExp(`^${s}$`,"i").test(e)},makeCondition=(e,r,s,t,a=void 0)=>{const o=Object.prototype.hasOwnProperty.call(e,r);switch(s){case"exists":return o;case"does not exist":return!o;case"is null":return o&&null===e[r];case"is not null":return o&&null!==e[r]}if(!o||null===e[r]||null===t)return!1;const c=e[r],n=(0,_compareAs.compareAs)(a,c);switch(s){case"=":return(0,_compareAs.sameValue)(a,c,t);case"!=":case"<>":return!(0,_compareAs.sameValue)(a,c,t);case">":return n>(0,_compareAs.compareAs)(a,t);case">=":return n>=(0,_compareAs.compareAs)(a,t);case"<":return n<(0,_compareAs.compareAs)(a,t);case"<=":return n<=(0,_compareAs.compareAs)(a,t);case"in":return Array.isArray(t)&&(a?t.some((e=>(0,_compareAs.sameValue)(a,c,e))):t.includes(c));case"between":return Array.isArray(t)&&2===t.length&&!t.includes(null)&&n>=(0,_compareAs.compareAs)(a,t[0])&&n<=(0,_compareAs.compareAs)(a,t[1]);case"like":return likeMatch(c,t)}return!1},where=(e=[],{property:r="",joinEntity:s,comparator:t="=",value:a=null,type:o}={})=>e.filter((e=>makeCondition(e,s?`${s}.${r}`:r,t,a,o)));exports.where=where;
|
|
@@ -1,3 +1,15 @@
|
|
|
1
1
|
import { ParsedQuery } from './parsers/parseQuery';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Load only the rows the indexed conditions match, and leave the other conditions for where() to apply later.
|
|
4
|
+
* Conditions are joined by `and`, so a row is loaded only when every indexed condition on its entity matched it: each
|
|
5
|
+
* condition narrows the files the ones before it matched. (Each indexed condition used to replace the rows of the one
|
|
6
|
+
* before, so `where date = 'x' and where exercise_id = 1` returned every row with exercise_id 1, whatever its date.)
|
|
7
|
+
* @param parsed
|
|
8
|
+
* @param recordData
|
|
9
|
+
* @param dataSet
|
|
10
|
+
* @param resolved - Filled with each entity whose rows were loaded here: its rows in dataSet are final (possibly none)
|
|
11
|
+
* and must not be reloaded, even when other conditions are left for where() (an empty list otherwise reads as "not
|
|
12
|
+
* loaded yet", see readEntity).
|
|
13
|
+
*/
|
|
14
|
+
export declare const getConditionIndexedList: (parsed: ParsedQuery, recordData: any, dataSet: any, resolved?: Set<string>) => Promise<ParsedQuery>;
|
|
3
15
|
//# sourceMappingURL=getConditionIndexedList.d.ts.map
|
|
@@ -4,14 +4,47 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.getConditionIndexedList = void 0;
|
|
7
|
+
require("core-js/modules/esnext.iterator.constructor.js");
|
|
8
|
+
require("core-js/modules/esnext.iterator.filter.js");
|
|
9
|
+
require("core-js/modules/esnext.iterator.flat-map.js");
|
|
10
|
+
require("core-js/modules/esnext.set.add-all.js");
|
|
11
|
+
require("core-js/modules/esnext.set.delete-all.js");
|
|
12
|
+
require("core-js/modules/esnext.set.difference.js");
|
|
13
|
+
require("core-js/modules/esnext.set.every.js");
|
|
14
|
+
require("core-js/modules/esnext.set.filter.js");
|
|
15
|
+
require("core-js/modules/esnext.set.find.js");
|
|
16
|
+
require("core-js/modules/esnext.set.intersection.js");
|
|
17
|
+
require("core-js/modules/esnext.set.is-disjoint-from.js");
|
|
18
|
+
require("core-js/modules/esnext.set.is-subset-of.js");
|
|
19
|
+
require("core-js/modules/esnext.set.is-superset-of.js");
|
|
20
|
+
require("core-js/modules/esnext.set.join.js");
|
|
21
|
+
require("core-js/modules/esnext.set.map.js");
|
|
22
|
+
require("core-js/modules/esnext.set.reduce.js");
|
|
23
|
+
require("core-js/modules/esnext.set.some.js");
|
|
24
|
+
require("core-js/modules/esnext.set.symmetric-difference.js");
|
|
25
|
+
require("core-js/modules/esnext.set.union.js");
|
|
7
26
|
var _isEntityProperty = require("./parsers/isEntityProperty");
|
|
8
27
|
var _splitEntityProperty = require("./parsers/splitEntityProperty");
|
|
9
28
|
var _retrieveRecord = require("./retrieveRecord");
|
|
10
29
|
var _where = require("../queries/where");
|
|
11
30
|
var _retrieveFile = require("./retrieveFile");
|
|
12
31
|
var _getMatchingIndexes = require("./getMatchingIndexes");
|
|
13
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Load only the rows the indexed conditions match, and leave the other conditions for where() to apply later.
|
|
34
|
+
* Conditions are joined by `and`, so a row is loaded only when every indexed condition on its entity matched it: each
|
|
35
|
+
* condition narrows the files the ones before it matched. (Each indexed condition used to replace the rows of the one
|
|
36
|
+
* before, so `where date = 'x' and where exercise_id = 1` returned every row with exercise_id 1, whatever its date.)
|
|
37
|
+
* @param parsed
|
|
38
|
+
* @param recordData
|
|
39
|
+
* @param dataSet
|
|
40
|
+
* @param resolved - Filled with each entity whose rows were loaded here: its rows in dataSet are final (possibly none)
|
|
41
|
+
* and must not be reloaded, even when other conditions are left for where() (an empty list otherwise reads as "not
|
|
42
|
+
* loaded yet", see readEntity).
|
|
43
|
+
*/
|
|
44
|
+
const getConditionIndexedList = async (parsed, recordData, dataSet, resolved = new Set()) => {
|
|
14
45
|
const reducedConditions = [];
|
|
46
|
+
const matchedFiles = {};
|
|
47
|
+
const indexed = {};
|
|
15
48
|
for (const condition of parsed.conditions) {
|
|
16
49
|
let entity = parsed.entity;
|
|
17
50
|
let property = condition.property;
|
|
@@ -23,25 +56,27 @@ const getConditionIndexedList = async (parsed, recordData, dataSet) => {
|
|
|
23
56
|
if (!Object.prototype.hasOwnProperty.call(recordData, entity)) {
|
|
24
57
|
recordData[entity] = await (0, _retrieveRecord.retrieveRecord)(entity);
|
|
25
58
|
}
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
const matchedRecords = (0, _where.where)(indexed[entity][property], {
|
|
59
|
+
const narrowMatchedFiles = async (entity, property, recordData, condition, dataSet, indexed) => {
|
|
60
|
+
const files = new Set((0, _where.where)(indexed[entity][property], {
|
|
29
61
|
property: 'value',
|
|
30
62
|
comparator: condition.comparator,
|
|
31
63
|
value: condition.value,
|
|
32
64
|
type: condition.type
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
for (const file of matchedRecord.record) {
|
|
36
|
-
dataSet[entity].push(await (0, _retrieveFile.retrieveFile)(`${entity}/${file}`));
|
|
37
|
-
}
|
|
38
|
-
}
|
|
65
|
+
}).flatMap(matchedRecord => matchedRecord.record));
|
|
66
|
+
matchedFiles[entity] = Object.prototype.hasOwnProperty.call(matchedFiles, entity) ? matchedFiles[entity].filter(file => files.has(file)) : [...files];
|
|
39
67
|
};
|
|
40
|
-
const isIndexed = await (0, _getMatchingIndexes.getMatchingIndexes)(entity, property, recordData, condition, dataSet, indexed,
|
|
68
|
+
const isIndexed = await (0, _getMatchingIndexes.getMatchingIndexes)(entity, property, recordData, condition, dataSet, indexed, narrowMatchedFiles);
|
|
41
69
|
if (!isIndexed) {
|
|
42
70
|
reducedConditions.push(condition);
|
|
43
71
|
}
|
|
44
72
|
}
|
|
73
|
+
for (const entity of Object.keys(matchedFiles)) {
|
|
74
|
+
resolved.add(entity);
|
|
75
|
+
dataSet[entity] = [];
|
|
76
|
+
for (const file of matchedFiles[entity]) {
|
|
77
|
+
dataSet[entity].push(await (0, _retrieveFile.retrieveFile)(`${entity}/${file}`));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
45
80
|
parsed.conditions = reducedConditions;
|
|
46
81
|
return parsed;
|
|
47
82
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getConditionIndexedList=void 0;var _isEntityProperty=require("./parsers/isEntityProperty"),_splitEntityProperty=require("./parsers/splitEntityProperty"),_retrieveRecord=require("./retrieveRecord"),_where=require("../queries/where"),_retrieveFile=require("./retrieveFile"),_getMatchingIndexes=require("./getMatchingIndexes");const getConditionIndexedList=async(e,t,
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getConditionIndexedList=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.filter.js"),require("core-js/modules/esnext.iterator.flat-map.js"),require("core-js/modules/esnext.set.add-all.js"),require("core-js/modules/esnext.set.delete-all.js"),require("core-js/modules/esnext.set.difference.js"),require("core-js/modules/esnext.set.every.js"),require("core-js/modules/esnext.set.filter.js"),require("core-js/modules/esnext.set.find.js"),require("core-js/modules/esnext.set.intersection.js"),require("core-js/modules/esnext.set.is-disjoint-from.js"),require("core-js/modules/esnext.set.is-subset-of.js"),require("core-js/modules/esnext.set.is-superset-of.js"),require("core-js/modules/esnext.set.join.js"),require("core-js/modules/esnext.set.map.js"),require("core-js/modules/esnext.set.reduce.js"),require("core-js/modules/esnext.set.some.js"),require("core-js/modules/esnext.set.symmetric-difference.js"),require("core-js/modules/esnext.set.union.js");var _isEntityProperty=require("./parsers/isEntityProperty"),_splitEntityProperty=require("./parsers/splitEntityProperty"),_retrieveRecord=require("./retrieveRecord"),_where=require("../queries/where"),_retrieveFile=require("./retrieveFile"),_getMatchingIndexes=require("./getMatchingIndexes");const getConditionIndexedList=async(e,r,t,s=new Set)=>{const o=[],i={},n={};for(const s of e.conditions){let u=e.entity,c=s.property;if((0,_isEntityProperty.isEntityProperty)(c)){const e=(0,_splitEntityProperty.splitEntityProperty)(c);u=e.entity,c=e.property}Object.prototype.hasOwnProperty.call(r,u)||(r[u]=await(0,_retrieveRecord.retrieveRecord)(u));const d=async(e,r,t,s,o,n)=>{const u=new Set((0,_where.where)(n[e][r],{property:"value",comparator:s.comparator,value:s.value,type:s.type}).flatMap((e=>e.record)));i[e]=Object.prototype.hasOwnProperty.call(i,e)?i[e].filter((e=>u.has(e))):[...u]};await(0,_getMatchingIndexes.getMatchingIndexes)(u,c,r,s,t,n,d)||o.push(s)}for(const e of Object.keys(i)){s.add(e),t[e]=[];for(const r of i[e])t[e].push(await(0,_retrieveFile.retrieveFile)(`${e}/${r}`))}return e.conditions=o,e};exports.getConditionIndexedList=getConditionIndexedList;
|
|
@@ -4,12 +4,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.getMatchingIndexes = void 0;
|
|
7
|
-
require("core-js/modules/es.array.includes.js");
|
|
8
7
|
var _retrieveIndexes = require("./retrieveIndexes");
|
|
8
|
+
var _isSingleFieldKey = require("./isSingleFieldKey");
|
|
9
9
|
const getMatchingIndexes = async (entity, property, recordData, clause, dataSet, indexed, cb = null) => {
|
|
10
10
|
let isIndexed = false;
|
|
11
11
|
for (const key of recordData[entity].keys) {
|
|
12
|
-
if (
|
|
12
|
+
if ((0, _isSingleFieldKey.isSingleFieldKey)(key, property)) {
|
|
13
13
|
dataSet[entity] = [];
|
|
14
14
|
if (!Object.prototype.hasOwnProperty.call(indexed, entity)) {
|
|
15
15
|
indexed[entity] = {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getMatchingIndexes=void 0
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getMatchingIndexes=void 0;var _retrieveIndexes=require("./retrieveIndexes"),_isSingleFieldKey=require("./isSingleFieldKey");const getMatchingIndexes=async(e,t,i,r,n,s,o=null)=>{let l=!1;for(const a of i[e].keys)(0,_isSingleFieldKey.isSingleFieldKey)(a,t)&&(n[e]=[],Object.prototype.hasOwnProperty.call(s,e)||(s[e]={}),Object.prototype.hasOwnProperty.call(s[e],t)||(s[e][t]=(await(0,_retrieveIndexes.retrieveIndexes)(e,[t],i))[t]),"function"==typeof o&&await o(e,t,i,r,n,s),l=!0);return l};exports.getMatchingIndexes=getMatchingIndexes;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { keyDefinition } from '../introspect/definitions/key';
|
|
2
|
+
/**
|
|
3
|
+
* Whether a key indexes exactly this one field, so its index file can answer a condition or join on that field. A
|
|
4
|
+
* composite key's index holds combined values (`["a",1]`, see computeKeyValue), which never equal one field's value:
|
|
5
|
+
* using it for that field matched nothing. (Using a composite index for its leftmost field is a planned improvement.)
|
|
6
|
+
* @param key
|
|
7
|
+
* @param property
|
|
8
|
+
*/
|
|
9
|
+
export declare const isSingleFieldKey: (key: keyDefinition, property: string) => boolean;
|
|
10
|
+
//# sourceMappingURL=isSingleFieldKey.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.isSingleFieldKey = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Whether a key indexes exactly this one field, so its index file can answer a condition or join on that field. A
|
|
9
|
+
* composite key's index holds combined values (`["a",1]`, see computeKeyValue), which never equal one field's value:
|
|
10
|
+
* using it for that field matched nothing. (Using a composite index for its leftmost field is a planned improvement.)
|
|
11
|
+
* @param key
|
|
12
|
+
* @param property
|
|
13
|
+
*/
|
|
14
|
+
const isSingleFieldKey = (key, property) => key.fields.length === 1 && key.fields[0] === property;
|
|
15
|
+
exports.isSingleFieldKey = isSingleFieldKey;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.isSingleFieldKey=void 0;const isSingleFieldKey=(e,i)=>1===e.fields.length&&e.fields[0]===i;exports.isSingleFieldKey=isSingleFieldKey;
|
|
@@ -4,9 +4,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.retrieveIndexes = void 0;
|
|
7
|
-
require("core-js/modules/es.array.includes.js");
|
|
8
7
|
var _retrieveFile = require("./retrieveFile");
|
|
9
8
|
var _retrieveRecord = require("./retrieveRecord");
|
|
9
|
+
var _isSingleFieldKey = require("./isSingleFieldKey");
|
|
10
10
|
const retrieveIndexes = async (entity = '', properties = [], recordData = {}) => {
|
|
11
11
|
if (!Object.prototype.hasOwnProperty.call(recordData, entity)) {
|
|
12
12
|
recordData[entity] = await (0, _retrieveRecord.retrieveRecord)(entity);
|
|
@@ -14,7 +14,7 @@ const retrieveIndexes = async (entity = '', properties = [], recordData = {}) =>
|
|
|
14
14
|
const indexSet = {};
|
|
15
15
|
for (const property of properties) {
|
|
16
16
|
for (const key of recordData[entity].keys) {
|
|
17
|
-
if (
|
|
17
|
+
if ((0, _isSingleFieldKey.isSingleFieldKey)(key, property)) {
|
|
18
18
|
indexSet[property] = await (0, _retrieveFile.retrieveFile)(`__indexes/${entity}/${key.lookup}`);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.retrieveIndexes=void 0
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.retrieveIndexes=void 0;var _retrieveFile=require("./retrieveFile"),_retrieveRecord=require("./retrieveRecord"),_isSingleFieldKey=require("./isSingleFieldKey");const retrieveIndexes=async(e="",r=[],i={})=>{Object.prototype.hasOwnProperty.call(i,e)||(i[e]=await(0,_retrieveRecord.retrieveRecord)(e));const t={};for(const o of r)for(const r of i[e].keys)(0,_isSingleFieldKey.isSingleFieldKey)(r,o)&&(t[o]=await(0,_retrieveFile.retrieveFile)(`__indexes/${e}/${r.lookup}`));return t};exports.retrieveIndexes=retrieveIndexes;
|
|
@@ -6,6 +6,22 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.runQuery = void 0;
|
|
7
7
|
require("core-js/modules/esnext.iterator.constructor.js");
|
|
8
8
|
require("core-js/modules/esnext.iterator.reduce.js");
|
|
9
|
+
require("core-js/modules/esnext.set.add-all.js");
|
|
10
|
+
require("core-js/modules/esnext.set.delete-all.js");
|
|
11
|
+
require("core-js/modules/esnext.set.difference.js");
|
|
12
|
+
require("core-js/modules/esnext.set.every.js");
|
|
13
|
+
require("core-js/modules/esnext.set.filter.js");
|
|
14
|
+
require("core-js/modules/esnext.set.find.js");
|
|
15
|
+
require("core-js/modules/esnext.set.intersection.js");
|
|
16
|
+
require("core-js/modules/esnext.set.is-disjoint-from.js");
|
|
17
|
+
require("core-js/modules/esnext.set.is-subset-of.js");
|
|
18
|
+
require("core-js/modules/esnext.set.is-superset-of.js");
|
|
19
|
+
require("core-js/modules/esnext.set.join.js");
|
|
20
|
+
require("core-js/modules/esnext.set.map.js");
|
|
21
|
+
require("core-js/modules/esnext.set.reduce.js");
|
|
22
|
+
require("core-js/modules/esnext.set.some.js");
|
|
23
|
+
require("core-js/modules/esnext.set.symmetric-difference.js");
|
|
24
|
+
require("core-js/modules/esnext.set.union.js");
|
|
9
25
|
var _deleteEntity = require("../queries/deleteEntity");
|
|
10
26
|
var _insertEntity = require("../queries/insertEntity");
|
|
11
27
|
var _readEntity = require("../queries/readEntity");
|
|
@@ -28,15 +44,15 @@ var _isEntityProperty = require("./parsers/isEntityProperty");
|
|
|
28
44
|
var _splitEntityProperty = require("./parsers/splitEntityProperty");
|
|
29
45
|
var _fieldType = require("./fieldType");
|
|
30
46
|
/**
|
|
31
|
-
* Give each condition its field's declared type, so where
|
|
32
|
-
* is looked up on that entity's record).
|
|
47
|
+
* Give each condition and sort clause its field's declared type, so where and sortBy compare by it
|
|
48
|
+
* (a joined entity's field is looked up on that entity's record).
|
|
33
49
|
* @param parsed
|
|
34
50
|
* @param recordData
|
|
35
51
|
*/
|
|
36
|
-
const
|
|
37
|
-
for (const
|
|
52
|
+
const typeClauses = async (parsed, recordData) => {
|
|
53
|
+
for (const clause of [...parsed.conditions, ...parsed.sortClauses]) {
|
|
38
54
|
let entity = parsed.entity;
|
|
39
|
-
let property =
|
|
55
|
+
let property = clause.property;
|
|
40
56
|
if ((0, _isEntityProperty.isEntityProperty)(property)) {
|
|
41
57
|
({
|
|
42
58
|
entity,
|
|
@@ -46,7 +62,7 @@ const typeConditions = async (parsed, recordData) => {
|
|
|
46
62
|
if (!Object.prototype.hasOwnProperty.call(recordData, entity)) {
|
|
47
63
|
recordData[entity] = await (0, _retrieveRecord.retrieveRecord)(entity);
|
|
48
64
|
}
|
|
49
|
-
|
|
65
|
+
clause.type = (0, _fieldType.fieldType)(recordData[entity], property);
|
|
50
66
|
}
|
|
51
67
|
};
|
|
52
68
|
const runQuery = async parsed => {
|
|
@@ -75,25 +91,26 @@ const runQuery = async parsed => {
|
|
|
75
91
|
if (typeof parsed.joinEntity !== 'undefined') {
|
|
76
92
|
recordData[parsed.joinEntity] = await (0, _retrieveRecord.retrieveRecord)(parsed.joinEntity);
|
|
77
93
|
}
|
|
78
|
-
await
|
|
94
|
+
await typeClauses(parsed, recordData);
|
|
79
95
|
let dataSet = {
|
|
80
96
|
[parsed.entity]: []
|
|
81
97
|
};
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
98
|
+
// An indexed condition that matches nothing leaves dataSet[entity] at [] - the same state it starts in before
|
|
99
|
+
// anything has looked at it at all. readEntity() (below) can't tell those two states apart on its own (it reloads
|
|
100
|
+
// whenever the array is empty), so getConditionIndexedList reports which entities it resolved: once any indexed
|
|
101
|
+
// condition has narrowed entity's rows, they are final (the conditions left over are applied to them below) and
|
|
102
|
+
// must not be reloaded. This used to ask whether EVERY condition was indexed, so `where date = 'none' and where
|
|
103
|
+
// reps = 10` reloaded every row and returned, updated or deleted all rows with reps 10.
|
|
104
|
+
const resolved = new Set();
|
|
105
|
+
parsed = await (0, _getConditionIndexedList.getConditionIndexedList)(parsed, recordData, dataSet, resolved);
|
|
106
|
+
const entityResolved = resolved.has(parsed.entity);
|
|
90
107
|
parsed = await (0, _getJoinIndexedList.getJoinIndexedList)(parsed, recordData, dataSet);
|
|
91
108
|
// delete/update act on whatever is already in dataSet[entity] - unlike read, which loads
|
|
92
109
|
// everything and lets the where-reduce below narrow it down afterward, they never get a second
|
|
93
110
|
// pass. So the matching rows have to be fully resolved (indexed conditions already are, via
|
|
94
111
|
// getConditionIndexedList above; anything left in parsed.conditions is not) before either runs.
|
|
95
112
|
if (parsed.command === 'delete' || parsed.command === 'update') {
|
|
96
|
-
if (!
|
|
113
|
+
if (!entityResolved) {
|
|
97
114
|
dataSet = await (0, _readEntity.readEntity)(parsed.entity, dataSet);
|
|
98
115
|
}
|
|
99
116
|
dataSet[parsed.entity] = parsed.conditions.reduce((remainingData, condition) => (0, _where.where)(remainingData, condition), dataSet[parsed.entity]);
|
|
@@ -106,7 +123,7 @@ const runQuery = async parsed => {
|
|
|
106
123
|
dataSet = await (0, _insertEntity.insertEntity)(parsed.entity, parsed.insertValues, dataSet);
|
|
107
124
|
break;
|
|
108
125
|
case 'read':
|
|
109
|
-
if (!
|
|
126
|
+
if (!entityResolved) {
|
|
110
127
|
dataSet = await (0, _readEntity.readEntity)(parsed.entity, dataSet);
|
|
111
128
|
}
|
|
112
129
|
break;
|
|
@@ -116,7 +133,7 @@ const runQuery = async parsed => {
|
|
|
116
133
|
default:
|
|
117
134
|
throw new Error(`Unknown command: ${parsed.command}`);
|
|
118
135
|
}
|
|
119
|
-
dataSet = await (0, _joinEntity.joinEntity)(parsed.entity, parsed.joinEntity, dataSet, parsed.joinClauses,
|
|
136
|
+
dataSet = await (0, _joinEntity.joinEntity)(parsed.entity, parsed.joinEntity, dataSet, parsed.joinClauses, entityResolved);
|
|
120
137
|
dataSet = await (0, _mergeJoins.mergeJoins)(dataSet, parsed.mergeJoins);
|
|
121
138
|
// delete/update already had parsed.conditions applied above, before they ran. Re-applying the
|
|
122
139
|
// same conditions here would be wrong, not just redundant, for update specifically: if the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.runQuery=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.reduce.js");var _deleteEntity=require("../queries/deleteEntity"),_insertEntity=require("../queries/insertEntity"),_readEntity=require("../queries/readEntity"),_updateEntity=require("../queries/updateEntity"),_createRecord=require("../queries/createRecord"),_dropRecord=require("../queries/dropRecord"),_describeRecord=require("../queries/describeRecord"),_showRecords=require("../queries/showRecords"),_joinEntity=require("../queries/joinEntity"),_mergeJoins=require("../queries/mergeJoins"),_where=require("../queries/where"),_sortBy=require("../queries/sortBy"),_groupBy=require("../queries/groupBy"),_limitOffset=require("../queries/limitOffset"),_selectFields=require("../queries/selectFields"),_retrieveRecord=require("./retrieveRecord"),_getConditionIndexedList=require("./getConditionIndexedList"),_getJoinIndexedList=require("./getJoinIndexedList"),_isEntityProperty=require("./parsers/isEntityProperty"),_splitEntityProperty=require("./parsers/splitEntityProperty"),_fieldType=require("./fieldType");const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.runQuery=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.reduce.js"),require("core-js/modules/esnext.set.add-all.js"),require("core-js/modules/esnext.set.delete-all.js"),require("core-js/modules/esnext.set.difference.js"),require("core-js/modules/esnext.set.every.js"),require("core-js/modules/esnext.set.filter.js"),require("core-js/modules/esnext.set.find.js"),require("core-js/modules/esnext.set.intersection.js"),require("core-js/modules/esnext.set.is-disjoint-from.js"),require("core-js/modules/esnext.set.is-subset-of.js"),require("core-js/modules/esnext.set.is-superset-of.js"),require("core-js/modules/esnext.set.join.js"),require("core-js/modules/esnext.set.map.js"),require("core-js/modules/esnext.set.reduce.js"),require("core-js/modules/esnext.set.some.js"),require("core-js/modules/esnext.set.symmetric-difference.js"),require("core-js/modules/esnext.set.union.js");var _deleteEntity=require("../queries/deleteEntity"),_insertEntity=require("../queries/insertEntity"),_readEntity=require("../queries/readEntity"),_updateEntity=require("../queries/updateEntity"),_createRecord=require("../queries/createRecord"),_dropRecord=require("../queries/dropRecord"),_describeRecord=require("../queries/describeRecord"),_showRecords=require("../queries/showRecords"),_joinEntity=require("../queries/joinEntity"),_mergeJoins=require("../queries/mergeJoins"),_where=require("../queries/where"),_sortBy=require("../queries/sortBy"),_groupBy=require("../queries/groupBy"),_limitOffset=require("../queries/limitOffset"),_selectFields=require("../queries/selectFields"),_retrieveRecord=require("./retrieveRecord"),_getConditionIndexedList=require("./getConditionIndexedList"),_getJoinIndexedList=require("./getJoinIndexedList"),_isEntityProperty=require("./parsers/isEntityProperty"),_splitEntityProperty=require("./parsers/splitEntityProperty"),_fieldType=require("./fieldType");const typeClauses=async(e,t)=>{for(const r of[...e.conditions,...e.sortClauses]){let i=e.entity,s=r.property;(0,_isEntityProperty.isEntityProperty)(s)&&({entity:i,property:s}=(0,_splitEntityProperty.splitEntityProperty)(s)),Object.prototype.hasOwnProperty.call(t,i)||(t[i]=await(0,_retrieveRecord.retrieveRecord)(i)),r.type=(0,_fieldType.fieldType)(t[i],s)}},runQuery=async e=>{switch(e.command){case"create":return{[e.entity]:await(0,_createRecord.createRecord)(e.entity,e.create)};case"drop":return{[e.entity]:await(0,_dropRecord.dropRecord)(e.entity,e.ifExists)};case"describe":return{[e.entity]:await(0,_describeRecord.describeRecord)(e.entity)};case"show":return{[e.entity]:await(0,_showRecords.showRecords)()}}const t={[e.entity]:await(0,_retrieveRecord.retrieveRecord)(e.entity)};void 0!==e.joinEntity&&(t[e.joinEntity]=await(0,_retrieveRecord.retrieveRecord)(e.joinEntity)),await typeClauses(e,t);let r={[e.entity]:[]};const i=new Set;e=await(0,_getConditionIndexedList.getConditionIndexedList)(e,t,r,i);const s=i.has(e.entity);switch("delete"!==(e=await(0,_getJoinIndexedList.getJoinIndexedList)(e,t,r)).command&&"update"!==e.command||(s||(r=await(0,_readEntity.readEntity)(e.entity,r)),r[e.entity]=e.conditions.reduce(((e,t)=>(0,_where.where)(e,t)),r[e.entity])),e.command){case"delete":r=await(0,_deleteEntity.deleteEntity)(e.entity,r);break;case"insert":r=await(0,_insertEntity.insertEntity)(e.entity,e.insertValues,r);break;case"read":s||(r=await(0,_readEntity.readEntity)(e.entity,r));break;case"update":r=await(0,_updateEntity.updateEntity)(e.entity,e.updateValues,r);break;default:throw new Error(`Unknown command: ${e.command}`)}return r=await(0,_joinEntity.joinEntity)(e.entity,e.joinEntity,r,e.joinClauses,s),r=await(0,_mergeJoins.mergeJoins)(r,e.mergeJoins),"delete"!==e.command&&"update"!==e.command&&(r[e.entity]=e.conditions.reduce(((e,t)=>(0,_where.where)(e,t)),r[e.entity])),r[e.entity]=(0,_sortBy.sortBy)(r[e.entity],e.sortClauses),r[e.entity]=(0,_limitOffset.limitOffset)(r[e.entity],e.offset,e.limit),r[e.entity]=(0,_groupBy.groupBy)(r[e.entity],e.groupBy),r[e.entity]=(0,_selectFields.selectFields)(r[e.entity],e.selectClauses),r};exports.runQuery=runQuery;
|