json-fs-query 0.1.0 → 0.1.1
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/dist/data/introspect/create.js +6 -4
- package/dist/data/introspect/create.min.js +1 -1
- package/dist/data/introspect/drop.js +2 -2
- package/dist/data/introspect/drop.min.js +1 -1
- package/dist/data/queries/deleteEntity.js +3 -3
- package/dist/data/queries/deleteEntity.min.js +1 -1
- package/dist/data/queries/groupBy.js +22 -22
- package/dist/data/queries/groupBy.min.js +1 -1
- package/dist/data/queries/insertEntity.js +5 -5
- package/dist/data/queries/insertEntity.min.js +1 -1
- package/dist/data/queries/readEntity.js +1 -1
- package/dist/data/queries/readEntity.min.js +1 -1
- package/dist/data/queries/updateEntity.js +6 -6
- package/dist/data/queries/updateEntity.min.js +1 -1
- package/dist/data/queries/where.js +1 -1
- package/dist/data/queries/where.min.js +1 -1
- package/dist/data/utilities/config.d.ts +22 -0
- package/dist/data/utilities/config.js +39 -0
- package/dist/data/utilities/config.min.js +1 -0
- package/dist/data/utilities/deregisterRecord.js +2 -2
- package/dist/data/utilities/deregisterRecord.min.js +1 -1
- package/dist/data/utilities/getConditionIndexedList.js +1 -1
- package/dist/data/utilities/getConditionIndexedList.min.js +1 -1
- package/dist/data/utilities/getJoinIndexedList.js +2 -2
- package/dist/data/utilities/getJoinIndexedList.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/matchIndexedJoins.js +2 -2
- package/dist/data/utilities/matchIndexedJoins.min.js +1 -1
- package/dist/data/utilities/reconcileJoin.js +26 -26
- package/dist/data/utilities/reconcileJoin.min.js +1 -1
- package/dist/data/utilities/reconcileJoins.js +26 -27
- package/dist/data/utilities/reconcileJoins.min.js +1 -1
- package/dist/data/utilities/registerRecord.js +2 -2
- package/dist/data/utilities/registerRecord.min.js +1 -1
- package/dist/data/utilities/removeFromIndex.js +2 -2
- package/dist/data/utilities/removeFromIndex.min.js +1 -1
- package/dist/data/utilities/restrictIndexedList.js +45 -45
- package/dist/data/utilities/restrictIndexedList.min.js +1 -1
- package/dist/data/utilities/retrieveFile.js +3 -3
- package/dist/data/utilities/retrieveFile.min.js +1 -1
- package/dist/data/utilities/retrieveIndexes.js +1 -1
- package/dist/data/utilities/retrieveIndexes.min.js +1 -1
- package/dist/data/utilities/updateIndex.js +2 -2
- package/dist/data/utilities/updateIndex.min.js +1 -1
- package/dist/data/utilities/useJoinClause.js +4 -4
- package/dist/data/utilities/useJoinClause.min.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -0
- package/dist/index.min.js +1 -1
- package/package.json +5 -1
- package/.browserslistrc +0 -1
- package/.nvmrc +0 -1
- package/MAIN.md +0 -15
- package/babel.config.js +0 -3
- package/build-tools.config.json +0 -30
- package/gulpfile.mjs +0 -15
- package/src/data/introspect/create.test.js +0 -67
- package/src/data/introspect/create.ts +0 -29
- package/src/data/introspect/definitions/field.test.js +0 -23
- package/src/data/introspect/definitions/field.ts +0 -48
- package/src/data/introspect/definitions/key.test.js +0 -100
- package/src/data/introspect/definitions/key.ts +0 -64
- package/src/data/introspect/definitions/keyReference.test.js +0 -8
- package/src/data/introspect/definitions/keyReference.ts +0 -23
- package/src/data/introspect/definitions/record.ts +0 -42
- package/src/data/introspect/describe.test.js +0 -36
- package/src/data/introspect/describe.ts +0 -9
- package/src/data/introspect/drop.test.js +0 -77
- package/src/data/introspect/drop.ts +0 -20
- package/src/data/introspect/index.ts +0 -8
- package/src/data/introspect/policies/foreignKeyExists.test.js +0 -44
- package/src/data/introspect/policies/foreignKeyExists.ts +0 -15
- package/src/data/introspect/policies/keyGenerate.ts +0 -11
- package/src/data/introspect/policies/keyUnique.ts +0 -11
- package/src/data/introspect/policies/typeCheck.test.js +0 -84
- package/src/data/introspect/policies/typeCheck.ts +0 -49
- package/src/data/introspect/policies/typeEnum.ts +0 -6
- package/src/data/introspect/policies/useDefault.ts +0 -6
- package/src/data/queries/deleteEntity.test.js +0 -86
- package/src/data/queries/deleteEntity.ts +0 -56
- package/src/data/queries/groupBy.test.js +0 -135
- package/src/data/queries/groupBy.ts +0 -16
- package/src/data/queries/insertEntity.test.js +0 -156
- package/src/data/queries/insertEntity.ts +0 -113
- package/src/data/queries/joinEntity.test.js +0 -109
- package/src/data/queries/joinEntity.ts +0 -20
- package/src/data/queries/mergeJoins.test.js +0 -174
- package/src/data/queries/mergeJoins.ts +0 -13
- package/src/data/queries/parser.test.js +0 -343
- package/src/data/queries/parser.ts +0 -24
- package/src/data/queries/query.test.js +0 -233
- package/src/data/queries/query.ts +0 -12
- package/src/data/queries/readEntity.test.js +0 -85
- package/src/data/queries/readEntity.ts +0 -8
- package/src/data/queries/sortBy.test.js +0 -131
- package/src/data/queries/sortBy.ts +0 -18
- package/src/data/queries/updateEntity.test.js +0 -228
- package/src/data/queries/updateEntity.ts +0 -162
- package/src/data/queries/where.test.js +0 -129
- package/src/data/queries/where.ts +0 -54
- package/src/data/utilities/deregisterRecord.test.js +0 -26
- package/src/data/utilities/deregisterRecord.ts +0 -24
- package/src/data/utilities/getConditionIndexedList.ts +0 -43
- package/src/data/utilities/getJoinIndexedList.ts +0 -53
- package/src/data/utilities/getMatchingIndexes.ts +0 -21
- package/src/data/utilities/matchIndexedJoins.ts +0 -45
- package/src/data/utilities/mergeJoin.test.js +0 -102
- package/src/data/utilities/mergeJoin.ts +0 -28
- package/src/data/utilities/parsers/findCommand.ts +0 -25
- package/src/data/utilities/parsers/findConditions.test.js +0 -38
- package/src/data/utilities/parsers/findConditions.ts +0 -32
- package/src/data/utilities/parsers/findGroupBy.ts +0 -20
- package/src/data/utilities/parsers/findInsertValues.test.js +0 -26
- package/src/data/utilities/parsers/findInsertValues.ts +0 -32
- package/src/data/utilities/parsers/findJoinClauses.ts +0 -29
- package/src/data/utilities/parsers/findJoinEntity.ts +0 -20
- package/src/data/utilities/parsers/findLimit.ts +0 -20
- package/src/data/utilities/parsers/findMergeJoins.ts +0 -27
- package/src/data/utilities/parsers/findOffset.ts +0 -20
- package/src/data/utilities/parsers/findSelects.ts +0 -31
- package/src/data/utilities/parsers/findSortClauses.ts +0 -31
- package/src/data/utilities/parsers/findUpdateValues.test.js +0 -37
- package/src/data/utilities/parsers/findUpdateValues.ts +0 -32
- package/src/data/utilities/parsers/isEntityProperty.ts +0 -1
- package/src/data/utilities/parsers/parseLiteralValue.test.js +0 -41
- package/src/data/utilities/parsers/parseLiteralValue.ts +0 -29
- package/src/data/utilities/parsers/parseQuery.ts +0 -73
- package/src/data/utilities/parsers/removeFromQuery.ts +0 -1
- package/src/data/utilities/parsers/splitEntityProperty.test.js +0 -8
- package/src/data/utilities/parsers/splitEntityProperty.ts +0 -17
- package/src/data/utilities/parsers/splitQueries.test.js +0 -33
- package/src/data/utilities/parsers/splitQueries.ts +0 -4
- package/src/data/utilities/reconcileJoin.test.js +0 -38
- package/src/data/utilities/reconcileJoin.ts +0 -23
- package/src/data/utilities/reconcileJoins.test.js +0 -160
- package/src/data/utilities/reconcileJoins.ts +0 -15
- package/src/data/utilities/registerRecord.test.js +0 -44
- package/src/data/utilities/registerRecord.ts +0 -44
- package/src/data/utilities/removeFromIndex.test.js +0 -44
- package/src/data/utilities/removeFromIndex.ts +0 -34
- package/src/data/utilities/restrictIndexedList.ts +0 -38
- package/src/data/utilities/retrieveFile.test.js +0 -49
- package/src/data/utilities/retrieveFile.ts +0 -19
- package/src/data/utilities/retrieveIndexes.ts +0 -17
- package/src/data/utilities/retrieveRecord.ts +0 -3
- package/src/data/utilities/retrieveRecords.test.js +0 -223
- package/src/data/utilities/retrieveRecords.ts +0 -16
- package/src/data/utilities/runQuery.test.js +0 -88
- package/src/data/utilities/runQuery.ts +0 -75
- package/src/data/utilities/updateIndex.test.js +0 -44
- package/src/data/utilities/updateIndex.ts +0 -45
- package/src/data/utilities/useJoinClause.test.js +0 -94
- package/src/data/utilities/useJoinClause.ts +0 -44
- package/src/global.d.ts +0 -1
- package/src/index.test.js +0 -52
- package/src/index.ts +0 -17
- package/test-data/__RECORDS.json +0 -32
- package/test-data/__indexes/exercise_muscle/fk_exercise_id.json +0 -14
- package/test-data/__indexes/exercise_muscle/fk_muscle_id.json +0 -14
- package/test-data/__indexes/exercise_muscle/pk__id.json +0 -14
- package/test-data/__indexes/exercises/pk__id.json +0 -14
- package/test-data/__indexes/muscles/pk__id.json +0 -58
- package/test-data/__indexes/workouts/fk_exercise_id.json +0 -23
- package/test-data/__indexes/workouts/index_date.json +0 -18
- package/test-data/__indexes/workouts/pk__id.json +0 -26
- package/test-data/copyDatabase.ts +0 -64
- package/test-data/exercise_muscle/bench_press_pectorals.json +0 -6
- package/test-data/exercise_muscle/deadlift_hamstrings.json +0 -6
- package/test-data/exercise_muscle/squat_quadriceps.json +0 -6
- package/test-data/exercise_muscle.json +0 -69
- package/test-data/exercises/bench_press.json +0 -5
- package/test-data/exercises/deadlift.json +0 -5
- package/test-data/exercises/squat.json +0 -5
- package/test-data/exercises.json +0 -34
- package/test-data/muscles/abdominal.json +0 -6
- package/test-data/muscles/biceps.json +0 -6
- package/test-data/muscles/calves.json +0 -6
- package/test-data/muscles/deltoids.json +0 -6
- package/test-data/muscles/erector_spinae.json +0 -6
- package/test-data/muscles/forearms.json +0 -6
- package/test-data/muscles/gluteus_maximus.json +0 -6
- package/test-data/muscles/hamstrings.json +0 -6
- package/test-data/muscles/latissimus_dorsi.json +0 -6
- package/test-data/muscles/obliques.json +0 -6
- package/test-data/muscles/pectorals.json +0 -6
- package/test-data/muscles/quadriceps.json +0 -6
- package/test-data/muscles/trapezius.json +0 -6
- package/test-data/muscles/triceps.json +0 -6
- package/test-data/muscles.json +0 -50
- package/test-data/workouts/2024-06-02-001.json +0 -10
- package/test-data/workouts/2024-06-02-002.json +0 -10
- package/test-data/workouts/2024-06-02-003.json +0 -10
- package/test-data/workouts/2024-06-05-001.json +0 -10
- package/test-data/workouts/2024-06-05-002.json +0 -10
- package/test-data/workouts/2024-06-05-003.json +0 -10
- package/test-data/workouts.json +0 -84
- package/tsconfig.json +0 -15
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import siFunciona from 'si-funciona'
|
|
2
|
-
import { splitEntityProperty } from './parsers/splitEntityProperty'
|
|
3
|
-
import { retrieveRecord } from './retrieveRecord'
|
|
4
|
-
import { ParsedQuery } from './parsers/parseQuery'
|
|
5
|
-
import { getMatchingIndexes } from './getMatchingIndexes'
|
|
6
|
-
import { matchIndexedJoins } from './matchIndexedJoins'
|
|
7
|
-
import { restrictIndexedList } from './restrictIndexedList'
|
|
8
|
-
|
|
9
|
-
export const getJoinIndexedList = async (parsed: ParsedQuery, recordData, dataSets) => {
|
|
10
|
-
let reducedJoins = []
|
|
11
|
-
const indexed = {}
|
|
12
|
-
let firstIteration = true
|
|
13
|
-
const entity = parsed.entity
|
|
14
|
-
const joinEntity = parsed.joinEntity
|
|
15
|
-
const joinClauses = parsed.joinClauses
|
|
16
|
-
for (const anEntity in dataSets[entity]) {
|
|
17
|
-
const currentEntity = dataSets[entity][anEntity]
|
|
18
|
-
// Loop over each of the main entities
|
|
19
|
-
let filterJoins = {}
|
|
20
|
-
filterJoins[entity] = [siFunciona.cloneObject(currentEntity)]
|
|
21
|
-
for (let joinClause of joinClauses) {
|
|
22
|
-
let indexedClone = siFunciona.cloneObject(indexed)
|
|
23
|
-
const { entity: entityA, property: propertyA } = splitEntityProperty(joinClause.propertyA)
|
|
24
|
-
const { entity: entityB, property: propertyB } = splitEntityProperty(joinClause.propertyB)
|
|
25
|
-
|
|
26
|
-
// Get the record for the entities A and B, store on the recordData
|
|
27
|
-
if (!recordData.hasOwnProperty(entityA)) {
|
|
28
|
-
recordData[entityA] = await retrieveRecord(entityA)
|
|
29
|
-
}
|
|
30
|
-
if (!recordData.hasOwnProperty(entityB)) {
|
|
31
|
-
recordData[entityB] = await retrieveRecord(entityB)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
indexedClone = restrictIndexedList(joinClause, filterJoins, indexedClone)
|
|
35
|
-
|
|
36
|
-
const retrieveMatchedFiles = matchIndexedJoins(entity, indexedClone, dataSets)
|
|
37
|
-
|
|
38
|
-
// Check if there are matching keys for the join condition
|
|
39
|
-
const matchAResult = await getMatchingIndexes(entityA, propertyA, recordData, joinClause, filterJoins, indexed)
|
|
40
|
-
const matchBResult = await getMatchingIndexes(entityB, propertyB, recordData, joinClause, filterJoins, indexed, retrieveMatchedFiles)
|
|
41
|
-
|
|
42
|
-
const isIndexed = matchAResult || matchBResult
|
|
43
|
-
|
|
44
|
-
if (!isIndexed && firstIteration) {
|
|
45
|
-
reducedJoins.push(joinClause)
|
|
46
|
-
firstIteration = false
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
dataSets[entity][anEntity][joinEntity] = filterJoins[joinEntity]
|
|
50
|
-
}
|
|
51
|
-
parsed.joinClauses = reducedJoins
|
|
52
|
-
return parsed
|
|
53
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { retrieveIndexes } from './retrieveIndexes'
|
|
2
|
-
|
|
3
|
-
export const getMatchingIndexes = async (entity: string, property: string, recordData: Object, clause: Object, dataSet: Object, indexed: Object, cb: Function = null): Promise<boolean> => {
|
|
4
|
-
let isIndexed = false
|
|
5
|
-
for (let key of recordData[entity].keys) {
|
|
6
|
-
if (key.fields.includes(property)) {
|
|
7
|
-
dataSet[entity] = []
|
|
8
|
-
if (!indexed.hasOwnProperty(entity)) {
|
|
9
|
-
indexed[entity] = {}
|
|
10
|
-
}
|
|
11
|
-
if (!indexed[entity].hasOwnProperty(property)) {
|
|
12
|
-
indexed[entity][property] = (await retrieveIndexes(entity, [property], recordData))[property]
|
|
13
|
-
}
|
|
14
|
-
if (typeof cb === 'function') {
|
|
15
|
-
await cb(entity, property, recordData, clause, dataSet, indexed)
|
|
16
|
-
}
|
|
17
|
-
isIndexed = true
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return isIndexed
|
|
21
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import siFunciona from 'si-funciona'
|
|
2
|
-
import { where } from '../queries/where'
|
|
3
|
-
import { retrieveFile } from './retrieveFile'
|
|
4
|
-
import { splitEntityProperty } from './parsers/splitEntityProperty'
|
|
5
|
-
|
|
6
|
-
export const matchIndexedJoins = (entity, indexedClone, dataSets) => async (focusEntity, property, recordData, joinClause, filterJoins, indexed) => {
|
|
7
|
-
const { entity: entityA, property: propertyA } = splitEntityProperty(joinClause.propertyA)
|
|
8
|
-
const { entity: entityB, property: propertyB } = splitEntityProperty(joinClause.propertyB)
|
|
9
|
-
const properties = [
|
|
10
|
-
{ entityFirst: entityA, propertyFirst: propertyA, entitySecond: entityB, propertySecond: propertyB },
|
|
11
|
-
{ entityFirst: entityB, propertyFirst: propertyB, entitySecond: entityA, propertySecond: propertyA },
|
|
12
|
-
]
|
|
13
|
-
for (let checkProp of properties) {
|
|
14
|
-
if (!indexedClone.hasOwnProperty(checkProp.entitySecond)) {
|
|
15
|
-
indexedClone[checkProp.entitySecond] = siFunciona.cloneObject(indexed[checkProp.entitySecond])
|
|
16
|
-
}
|
|
17
|
-
const matchedRecords = indexedClone[checkProp.entitySecond][checkProp.propertySecond].reduce(
|
|
18
|
-
(dataA, dataB) => siFunciona.mergeArrays(
|
|
19
|
-
dataA,
|
|
20
|
-
where(indexedClone[checkProp.entityFirst][checkProp.propertyFirst], {
|
|
21
|
-
property: 'value',
|
|
22
|
-
comparator: joinClause.comparator,
|
|
23
|
-
value: dataB.value
|
|
24
|
-
})
|
|
25
|
-
),
|
|
26
|
-
[]
|
|
27
|
-
)
|
|
28
|
-
let skipPush = checkProp.entityFirst === entity
|
|
29
|
-
if (!dataSets.hasOwnProperty(checkProp.entityFirst)) {
|
|
30
|
-
dataSets[checkProp.entityFirst] = []
|
|
31
|
-
}
|
|
32
|
-
for (let matchedRecord of matchedRecords) {
|
|
33
|
-
for (let file of matchedRecord.record) {
|
|
34
|
-
let entityRecord = file
|
|
35
|
-
if (typeof file === 'string') {
|
|
36
|
-
entityRecord = await retrieveFile(`${checkProp.entityFirst}/${file}`)
|
|
37
|
-
}
|
|
38
|
-
if (!skipPush) {
|
|
39
|
-
dataSets[checkProp.entityFirst].push(entityRecord)
|
|
40
|
-
}
|
|
41
|
-
filterJoins[checkProp.entityFirst].push(entityRecord)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { mergeJoin } from './mergeJoin'
|
|
2
|
-
import { testHelpers } from 'js-build-tools/testHelpers'
|
|
3
|
-
import { copyDatabase } from '../../../test-data/copyDatabase'
|
|
4
|
-
|
|
5
|
-
const databasePath = 'merge-join-database/'
|
|
6
|
-
const gulpConfig = testHelpers.gulpConfig
|
|
7
|
-
gulpConfig.set('databasePath', databasePath)
|
|
8
|
-
testHelpers.setDefaults(databasePath)
|
|
9
|
-
|
|
10
|
-
beforeEach(
|
|
11
|
-
() => testHelpers.beforeEach()
|
|
12
|
-
.then(() => copyDatabase(databasePath))
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
afterEach(testHelpers.afterEach)
|
|
16
|
-
|
|
17
|
-
describe('mergeJoin', () => {
|
|
18
|
-
test('can combine both entities', async () => {
|
|
19
|
-
const results = await mergeJoin('workouts.exercise_id', 'exercises._id')
|
|
20
|
-
expect(results).toEqual({
|
|
21
|
-
workouts: [
|
|
22
|
-
{
|
|
23
|
-
_id: 1,
|
|
24
|
-
exercise_id: 1,
|
|
25
|
-
weight_effort: '115lbs',
|
|
26
|
-
reps: 10,
|
|
27
|
-
sets: 3,
|
|
28
|
-
note: '',
|
|
29
|
-
order: 0,
|
|
30
|
-
date: '2024-06-02',
|
|
31
|
-
'exercises.name': 'Bench Press',
|
|
32
|
-
'exercises.description': ''
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
_id: 2,
|
|
36
|
-
exercise_id: 2,
|
|
37
|
-
weight_effort: '155lbs',
|
|
38
|
-
reps: 10,
|
|
39
|
-
sets: 3,
|
|
40
|
-
note: '',
|
|
41
|
-
order: 1,
|
|
42
|
-
date: '2024-06-02',
|
|
43
|
-
'exercises.name': 'Deadlift',
|
|
44
|
-
'exercises.description': ''
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
_id: 3,
|
|
48
|
-
exercise_id: 3,
|
|
49
|
-
weight_effort: '155lbs',
|
|
50
|
-
reps: 10,
|
|
51
|
-
sets: 3,
|
|
52
|
-
note: '',
|
|
53
|
-
order: 2,
|
|
54
|
-
date: '2024-06-02',
|
|
55
|
-
'exercises.name': 'Squat',
|
|
56
|
-
'exercises.description': ''
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
_id: 4,
|
|
60
|
-
exercise_id: 1,
|
|
61
|
-
weight_effort: '120lbs',
|
|
62
|
-
reps: 10,
|
|
63
|
-
sets: 3,
|
|
64
|
-
note: '',
|
|
65
|
-
order: 0,
|
|
66
|
-
date: '2024-06-05',
|
|
67
|
-
'exercises.name': 'Bench Press',
|
|
68
|
-
'exercises.description': ''
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
_id: 5,
|
|
72
|
-
exercise_id: 2,
|
|
73
|
-
weight_effort: '160lbs',
|
|
74
|
-
reps: 10,
|
|
75
|
-
sets: 3,
|
|
76
|
-
note: '',
|
|
77
|
-
order: 1,
|
|
78
|
-
date: '2024-06-05',
|
|
79
|
-
'exercises.name': 'Deadlift',
|
|
80
|
-
'exercises.description': ''
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
_id: 6,
|
|
84
|
-
exercise_id: 3,
|
|
85
|
-
weight_effort: '160lbs',
|
|
86
|
-
reps: 10,
|
|
87
|
-
sets: 3,
|
|
88
|
-
note: '',
|
|
89
|
-
order: 2,
|
|
90
|
-
date: '2024-06-05',
|
|
91
|
-
'exercises.name': 'Squat',
|
|
92
|
-
'exercises.description': ''
|
|
93
|
-
}
|
|
94
|
-
],
|
|
95
|
-
exercises: [
|
|
96
|
-
{ _id: 1, name: 'Bench Press', description: '' },
|
|
97
|
-
{ _id: 2, name: 'Deadlift', description: '' },
|
|
98
|
-
{ _id: 3, name: 'Squat', description: '' }
|
|
99
|
-
]
|
|
100
|
-
})
|
|
101
|
-
})
|
|
102
|
-
})
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { readEntity } from '../queries/readEntity'
|
|
2
|
-
import { splitEntityProperty } from './parsers/splitEntityProperty'
|
|
3
|
-
import { where } from '../queries/where'
|
|
4
|
-
|
|
5
|
-
export const mergeJoin = async (propertyA = '', propertyB = '', dataSets = {}) => {
|
|
6
|
-
const { entity: entityA, property: propA } = splitEntityProperty(propertyA)
|
|
7
|
-
const { entity: entityB, property: propB } = splitEntityProperty(propertyB)
|
|
8
|
-
|
|
9
|
-
dataSets = await readEntity(entityA, dataSets)
|
|
10
|
-
dataSets = await readEntity(entityB, dataSets)
|
|
11
|
-
|
|
12
|
-
dataSets[entityA] = dataSets[entityA].map((dataA) => {
|
|
13
|
-
const matches = where(dataSets[entityB], { property: propB, comparator: '=', value: dataA[propA] })
|
|
14
|
-
if (!matches.length) {
|
|
15
|
-
return dataA
|
|
16
|
-
}
|
|
17
|
-
const mergeMatch = matches[0]
|
|
18
|
-
for (let prop in mergeMatch) {
|
|
19
|
-
if (prop === propB) {
|
|
20
|
-
// Skip the condition property since it is irrelevant
|
|
21
|
-
continue
|
|
22
|
-
}
|
|
23
|
-
dataA[`${entityB}.${prop}`] = mergeMatch[prop]
|
|
24
|
-
}
|
|
25
|
-
return dataA
|
|
26
|
-
})
|
|
27
|
-
return dataSets
|
|
28
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { removeFromQuery } from './removeFromQuery'
|
|
2
|
-
import { ParsedQuery } from './parseQuery'
|
|
3
|
-
|
|
4
|
-
const commandMatch: RegExp = /^(delete|insert|read|update)\s+([a-z0-9_-]+)[\w\n]*/i
|
|
5
|
-
|
|
6
|
-
export type ParsedCommand = string | 'delete' | 'insert' | 'read' | 'update'
|
|
7
|
-
|
|
8
|
-
export type ParsedEntity = string
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Extract command clauses from the query.
|
|
12
|
-
* @param parsed
|
|
13
|
-
* @param query
|
|
14
|
-
*/
|
|
15
|
-
export const findCommand = (parsed: ParsedQuery, query: string): string => {
|
|
16
|
-
const commandFound: RegExpMatchArray = query.match(commandMatch)
|
|
17
|
-
parsed['command'] = undefined
|
|
18
|
-
parsed['entity'] = undefined
|
|
19
|
-
if (commandFound) {
|
|
20
|
-
parsed['command'] = commandFound[1]
|
|
21
|
-
parsed['entity'] = commandFound[2]
|
|
22
|
-
return removeFromQuery(commandFound[0], query)
|
|
23
|
-
}
|
|
24
|
-
return query
|
|
25
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { findConditions } from './findConditions'
|
|
2
|
-
|
|
3
|
-
const parse = (query) => {
|
|
4
|
-
const parsed = { conditions: [] }
|
|
5
|
-
const remaining = findConditions(parsed, query)
|
|
6
|
-
return { parsed, remaining }
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
describe('findConditions', () => {
|
|
10
|
-
test('extracts a quoted string value', () => {
|
|
11
|
-
const { parsed, remaining } = parse("where date = '2024-06-02'")
|
|
12
|
-
expect(parsed.conditions).toEqual([{ property: 'date', comparator: '=', value: '2024-06-02' }])
|
|
13
|
-
expect(remaining).toBe('')
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
test('extracts an unquoted number as a real number', () => {
|
|
17
|
-
const { parsed } = parse('where reps > 10')
|
|
18
|
-
expect(parsed.conditions).toEqual([{ property: 'reps', comparator: '>', value: 10 }])
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
test('extracts an array literal as a real array', () => {
|
|
22
|
-
const { parsed } = parse('where exercise_id in [1,2,3]')
|
|
23
|
-
expect(parsed.conditions).toEqual([{ property: 'exercise_id', comparator: 'in', value: [1, 2, 3] }])
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
test('extracts null as the real null value', () => {
|
|
27
|
-
const { parsed } = parse('where note = null')
|
|
28
|
-
expect(parsed.conditions).toEqual([{ property: 'note', comparator: '=', value: null }])
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
test('extracts true and false as real booleans', () => {
|
|
32
|
-
const { parsed } = parse('where active = true where archived = false')
|
|
33
|
-
expect(parsed.conditions).toEqual([
|
|
34
|
-
{ property: 'active', comparator: '=', value: true },
|
|
35
|
-
{ property: 'archived', comparator: '=', value: false }
|
|
36
|
-
])
|
|
37
|
-
})
|
|
38
|
-
})
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { removeFromQuery } from './removeFromQuery'
|
|
2
|
-
import { parseLiteralValue, LiteralValue } from './parseLiteralValue'
|
|
3
|
-
import { ParsedQuery } from './parseQuery'
|
|
4
|
-
|
|
5
|
-
const conditionMatch: RegExp = /(and|or)?\s*(where)\s+([a-z0-9_-]+\.?[a-z0-9_-]*)\s+(=|!=|>|<|>=|<=|in|between|like)\s+(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/ig
|
|
6
|
-
|
|
7
|
-
export type ConditionValue = LiteralValue
|
|
8
|
-
|
|
9
|
-
export type ParsedCondition = {
|
|
10
|
-
property: string
|
|
11
|
-
comparator: string
|
|
12
|
-
value: ConditionValue
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Extract condition clauses from the query.
|
|
17
|
-
* @param parsed
|
|
18
|
-
* @param query
|
|
19
|
-
*/
|
|
20
|
-
export const findConditions = (parsed: ParsedQuery, query: string): string => {
|
|
21
|
-
const conditionsFound: IterableIterator<RegExpMatchArray> = query.matchAll(conditionMatch)
|
|
22
|
-
// @ts-ignore
|
|
23
|
-
for (let condition of conditionsFound) {
|
|
24
|
-
parsed['conditions'].push({
|
|
25
|
-
property: condition[3],
|
|
26
|
-
comparator: condition[4],
|
|
27
|
-
value: parseLiteralValue(condition, 6)
|
|
28
|
-
})
|
|
29
|
-
query = removeFromQuery(condition[0], query)
|
|
30
|
-
}
|
|
31
|
-
return query
|
|
32
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { removeFromQuery } from './removeFromQuery'
|
|
2
|
-
import { ParsedQuery } from './parseQuery'
|
|
3
|
-
|
|
4
|
-
const groupMatch: RegExp = /group\s+by\s+(,?[a-z0-9._-]+)+/i
|
|
5
|
-
|
|
6
|
-
export type ParsedGroupBy = string
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Extract the group by clauses from the query.
|
|
10
|
-
* @param parsed
|
|
11
|
-
* @param query
|
|
12
|
-
*/
|
|
13
|
-
export const findGroupBy = (parsed: ParsedQuery, query: string): string => {
|
|
14
|
-
const groupFound: RegExpMatchArray = query.match(groupMatch)
|
|
15
|
-
if (groupFound) {
|
|
16
|
-
parsed['groupBy'] = groupFound ? groupFound[1] : undefined
|
|
17
|
-
return removeFromQuery(groupFound[0], query)
|
|
18
|
-
}
|
|
19
|
-
return query
|
|
20
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { findInsertValues } from './findInsertValues'
|
|
2
|
-
|
|
3
|
-
const parse = (query) => {
|
|
4
|
-
const parsed = {}
|
|
5
|
-
const remaining = findInsertValues(parsed, query)
|
|
6
|
-
return { parsed, remaining }
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
describe('findInsertValues', () => {
|
|
10
|
-
test('extracts a single row, wrapped in a one-element array', () => {
|
|
11
|
-
const { parsed, remaining } = parse("insert workouts values reps = 12, date = '2024-06-02'")
|
|
12
|
-
expect(parsed.insertValues).toEqual([{ reps: 12, date: '2024-06-02' }])
|
|
13
|
-
expect(remaining).toBe('insert workouts')
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
test('extracts every literal shape', () => {
|
|
17
|
-
const { parsed } = parse('values active = true, tags = [1,2,3], note = null')
|
|
18
|
-
expect(parsed.insertValues).toEqual([{ active: true, tags: [1, 2, 3], note: null }])
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
test('leaves the query untouched, with an empty insertValues, when there is no values clause', () => {
|
|
22
|
-
const { parsed, remaining } = parse("read workouts where date = '2024-06-02'")
|
|
23
|
-
expect(parsed.insertValues).toEqual([])
|
|
24
|
-
expect(remaining).toBe("read workouts where date = '2024-06-02'")
|
|
25
|
-
})
|
|
26
|
-
})
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { removeFromQuery } from './removeFromQuery'
|
|
2
|
-
import { parseLiteralValue } from './parseLiteralValue'
|
|
3
|
-
import { ParsedQuery } from './parseQuery'
|
|
4
|
-
|
|
5
|
-
const literal = '(?:["\'][^"\']*[\'"]|[0-9]+|\\[.*?]|null|true|false)'
|
|
6
|
-
const valuesClauseMatch: RegExp = new RegExp(`(values)\\s+([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`, 'i')
|
|
7
|
-
const assignmentMatch: RegExp = /([a-z0-9_-]+)\s*=\s*(["'](.*?)['"]|([0-9]+)|(\[.*?])|(null)|(true)|(false))/ig
|
|
8
|
-
|
|
9
|
-
export type ParsedInsertRow = { [field: string]: any }
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Extract an insert's "values field = value, field2 = value2" clause from the query, the same way
|
|
13
|
-
* findUpdateValues() does for "set". insertEntity() accepts an array of rows for bulk inserts, but
|
|
14
|
-
* a query string only describes a single row for now - wrapped in a one-element array to match.
|
|
15
|
-
* @param parsed
|
|
16
|
-
* @param query
|
|
17
|
-
*/
|
|
18
|
-
export const findInsertValues = (parsed: ParsedQuery, query: string): string => {
|
|
19
|
-
const clauseFound: RegExpMatchArray = query.match(valuesClauseMatch)
|
|
20
|
-
parsed['insertValues'] = []
|
|
21
|
-
if (!clauseFound) {
|
|
22
|
-
return query
|
|
23
|
-
}
|
|
24
|
-
const row = {}
|
|
25
|
-
const assignmentsFound: IterableIterator<RegExpMatchArray> = clauseFound[2].matchAll(assignmentMatch)
|
|
26
|
-
// @ts-ignore
|
|
27
|
-
for (const assignment of assignmentsFound) {
|
|
28
|
-
row[assignment[1]] = parseLiteralValue(assignment, 3)
|
|
29
|
-
}
|
|
30
|
-
parsed['insertValues'] = [row]
|
|
31
|
-
return removeFromQuery(clauseFound[0], query)
|
|
32
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { removeFromQuery } from './removeFromQuery'
|
|
2
|
-
import { ParsedQuery } from './parseQuery'
|
|
3
|
-
|
|
4
|
-
const joinClauseMatch: RegExp = /(and)?\s*on\s+([a-z0-9_-]+\.[a-z0-9_-]+)\s+(=|!=|>|<|>=|<=|in|between|like)\s+([a-z0-9_-]+\.[a-z0-9_-]+)/ig
|
|
5
|
-
|
|
6
|
-
export type ParsedJoinClause = {
|
|
7
|
-
propertyA: string
|
|
8
|
-
comparator: string
|
|
9
|
-
propertyB: string
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Extract condition clauses from the query.
|
|
14
|
-
* @param parsed
|
|
15
|
-
* @param query
|
|
16
|
-
*/
|
|
17
|
-
export const findJoinClauses = (parsed: ParsedQuery, query: string): string => {
|
|
18
|
-
const joinClausesFound: IterableIterator<RegExpMatchArray> = query.matchAll(joinClauseMatch)
|
|
19
|
-
// @ts-ignore
|
|
20
|
-
for (let joinClause of joinClausesFound) {
|
|
21
|
-
parsed['joinClauses'].push({
|
|
22
|
-
propertyA: joinClause[2],
|
|
23
|
-
comparator: joinClause[3],
|
|
24
|
-
propertyB: joinClause[4]
|
|
25
|
-
})
|
|
26
|
-
query = removeFromQuery(joinClause[0], query)
|
|
27
|
-
}
|
|
28
|
-
return query
|
|
29
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { removeFromQuery } from './removeFromQuery'
|
|
2
|
-
import { ParsedQuery } from './parseQuery'
|
|
3
|
-
|
|
4
|
-
const joinEntityMatch: RegExp = /\.([a-z0-9_-]+)/i
|
|
5
|
-
|
|
6
|
-
export type ParsedJoinEntity = string
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Extract the main join entity from the query.
|
|
10
|
-
* @param parsed
|
|
11
|
-
* @param query
|
|
12
|
-
*/
|
|
13
|
-
export const findJoinEntity = (parsed: ParsedQuery, query: string): string => {
|
|
14
|
-
const joinEntityFound: RegExpMatchArray = query.match(joinEntityMatch)
|
|
15
|
-
if (joinEntityFound) {
|
|
16
|
-
parsed['joinEntity'] = joinEntityFound ? joinEntityFound[1] : undefined
|
|
17
|
-
return removeFromQuery(joinEntityFound[0], query)
|
|
18
|
-
}
|
|
19
|
-
return query
|
|
20
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { removeFromQuery } from './removeFromQuery'
|
|
2
|
-
import { ParsedQuery } from './parseQuery'
|
|
3
|
-
|
|
4
|
-
const limitMatch: RegExp = /limit\s*(\d+)/i
|
|
5
|
-
|
|
6
|
-
export type ParsedLimit = number
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Extract the limit clauses from the query.
|
|
10
|
-
* @param parsed
|
|
11
|
-
* @param query
|
|
12
|
-
*/
|
|
13
|
-
export const findLimit = (parsed: ParsedQuery, query: string): string => {
|
|
14
|
-
const limitFound: RegExpMatchArray = query.match(limitMatch)
|
|
15
|
-
if (limitFound) {
|
|
16
|
-
parsed['limit'] = limitFound ? parseInt(limitFound[1]) : undefined
|
|
17
|
-
return removeFromQuery(limitFound[0], query)
|
|
18
|
-
}
|
|
19
|
-
return query
|
|
20
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { removeFromQuery } from './removeFromQuery'
|
|
2
|
-
import { ParsedQuery } from './parseQuery'
|
|
3
|
-
|
|
4
|
-
const mergeJoinMatch: RegExp = /(and)?\s*merge\s+([a-z0-9_-]+\.[a-z0-9_-]+)\s+with\s+([a-z0-9_-]+\.[a-z0-9_-]+)/ig
|
|
5
|
-
|
|
6
|
-
export type ParsedMergeJoin = {
|
|
7
|
-
propertyA: string
|
|
8
|
-
propertyB: string
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Extract merge-join clauses from the query.
|
|
13
|
-
* @param parsed
|
|
14
|
-
* @param query
|
|
15
|
-
*/
|
|
16
|
-
export const findMergeJoins = (parsed: ParsedQuery, query: string): string => {
|
|
17
|
-
const mergeJoinsFound: IterableIterator<RegExpMatchArray> = query.matchAll(mergeJoinMatch)
|
|
18
|
-
// @ts-ignore
|
|
19
|
-
for (let mergeJoin of mergeJoinsFound) {
|
|
20
|
-
parsed['mergeJoins'].push({
|
|
21
|
-
propertyA: mergeJoin[2],
|
|
22
|
-
propertyB: mergeJoin[3]
|
|
23
|
-
})
|
|
24
|
-
query = removeFromQuery(mergeJoin[0].trim(), query)
|
|
25
|
-
}
|
|
26
|
-
return query
|
|
27
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { removeFromQuery } from './removeFromQuery'
|
|
2
|
-
import { ParsedQuery } from './parseQuery'
|
|
3
|
-
|
|
4
|
-
const offsetMatch: RegExp = /offset\s*(\d+)/i
|
|
5
|
-
|
|
6
|
-
export type ParsedOffset = number
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Extract the offset clauses from the query.
|
|
10
|
-
* @param parsed
|
|
11
|
-
* @param query
|
|
12
|
-
*/
|
|
13
|
-
export const findOffset = (parsed: ParsedQuery, query: string): string => {
|
|
14
|
-
const offsetFound: RegExpMatchArray = query.match(offsetMatch)
|
|
15
|
-
if (offsetFound) {
|
|
16
|
-
parsed['offset'] = offsetFound ? parseInt(offsetFound[1]) : undefined
|
|
17
|
-
return removeFromQuery(offsetFound[0], query)
|
|
18
|
-
}
|
|
19
|
-
return query
|
|
20
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { removeFromQuery } from './removeFromQuery'
|
|
2
|
-
import { ParsedQuery } from './parseQuery'
|
|
3
|
-
|
|
4
|
-
const selectClausesMatch: RegExp = /select\s+([a-z0-9=._-]+\s*(as\s+)?([a-z0-9_-]+)?)+\s*(,\s*[a-z0-9=._-]+\s*(as\s*[a-z0-9_-]+)?)*/i
|
|
5
|
-
const selectClauseMatch: RegExp = /(select)?\s*,?\s*([a-z0-9=._-]+)\s*(as\s+)?([a-z0-9_-]+)?/ig
|
|
6
|
-
|
|
7
|
-
export type ParsedSelect = {
|
|
8
|
-
property: string
|
|
9
|
-
alias: string | undefined
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Extract select clauses from the query.
|
|
14
|
-
* @param parsed
|
|
15
|
-
* @param query
|
|
16
|
-
*/
|
|
17
|
-
export const findSelects = (parsed: ParsedQuery, query: string): string => {
|
|
18
|
-
const selectsFound: RegExpMatchArray = query.match(selectClausesMatch)
|
|
19
|
-
if (selectsFound) {
|
|
20
|
-
const selectClausesFound: IterableIterator<RegExpMatchArray> = selectsFound[0].matchAll(selectClauseMatch)
|
|
21
|
-
// @ts-ignore
|
|
22
|
-
for (let selectClause of selectClausesFound) {
|
|
23
|
-
parsed['selectClauses'].push({
|
|
24
|
-
property: selectClause[2],
|
|
25
|
-
alias: selectClause[4],
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
return removeFromQuery(selectsFound[0], query)
|
|
29
|
-
}
|
|
30
|
-
return query
|
|
31
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { removeFromQuery } from './removeFromQuery'
|
|
2
|
-
import { ParsedQuery } from './parseQuery'
|
|
3
|
-
|
|
4
|
-
const sortMatch: RegExp = /sort\s+([a-z0-9._-]+\s*(asc|desc)?)+\s*(,\s*[a-z0-9._-]+\s*(asc|desc)?)*/i
|
|
5
|
-
const sortRuleMatch: RegExp = /(sort)?\s*,?\s*([a-z0-9._-]+)\s*(asc|desc)?/ig
|
|
6
|
-
|
|
7
|
-
export type ParsedSortClause = {
|
|
8
|
-
property: string
|
|
9
|
-
direction: string | 'asc' | 'desc'
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Extract sort clauses from the query.
|
|
14
|
-
* @param parsed
|
|
15
|
-
* @param query
|
|
16
|
-
*/
|
|
17
|
-
export const findSortClauses = (parsed: ParsedQuery, query: string): string => {
|
|
18
|
-
const sortFound: RegExpMatchArray = query.match(sortMatch)
|
|
19
|
-
if (sortFound) {
|
|
20
|
-
const sortRulesFound: IterableIterator<RegExpMatchArray> = sortFound[0].matchAll(sortRuleMatch)
|
|
21
|
-
// @ts-ignore
|
|
22
|
-
for (let sortClause of sortRulesFound) {
|
|
23
|
-
parsed['sortClauses'].push({
|
|
24
|
-
property: sortClause[2],
|
|
25
|
-
direction: sortClause[3] || 'asc',
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
return removeFromQuery(sortFound[0], query)
|
|
29
|
-
}
|
|
30
|
-
return query
|
|
31
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { findUpdateValues } from './findUpdateValues'
|
|
2
|
-
|
|
3
|
-
const parse = (query) => {
|
|
4
|
-
const parsed = {}
|
|
5
|
-
const remaining = findUpdateValues(parsed, query)
|
|
6
|
-
return { parsed, remaining }
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
describe('findUpdateValues', () => {
|
|
10
|
-
test('extracts a single assignment', () => {
|
|
11
|
-
const { parsed, remaining } = parse("update workouts set reps = 12")
|
|
12
|
-
expect(parsed.updateValues).toEqual({ reps: 12 })
|
|
13
|
-
expect(remaining).toBe('update workouts')
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
test('extracts multiple comma-separated assignments', () => {
|
|
17
|
-
const { parsed } = parse("set reps = 12, note = 'done'")
|
|
18
|
-
expect(parsed.updateValues).toEqual({ reps: 12, note: 'done' })
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
test('stops before a following where clause', () => {
|
|
22
|
-
const { parsed, remaining } = parse("set reps = 12 where date = '2024-06-02'")
|
|
23
|
-
expect(parsed.updateValues).toEqual({ reps: 12 })
|
|
24
|
-
expect(remaining).toBe("where date = '2024-06-02'")
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
test('extracts every literal shape', () => {
|
|
28
|
-
const { parsed } = parse('set active = true, archived = false, note = null, tags = [1,2,3]')
|
|
29
|
-
expect(parsed.updateValues).toEqual({ active: true, archived: false, note: null, tags: [1, 2, 3] })
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
test('leaves the query untouched, with an empty updateValues, when there is no set clause', () => {
|
|
33
|
-
const { parsed, remaining } = parse("read workouts where date = '2024-06-02'")
|
|
34
|
-
expect(parsed.updateValues).toEqual({})
|
|
35
|
-
expect(remaining).toBe("read workouts where date = '2024-06-02'")
|
|
36
|
-
})
|
|
37
|
-
})
|