json-fs-query 2.2.1 → 2.3.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 +114 -6
- package/browser/jsonFsQuery.js +907 -456
- package/browser/jsonFsQuery.min.js +1 -1
- package/dist/data/queries/joinEntity.d.ts +1 -1
- package/dist/data/queries/joinEntity.js +5 -2
- package/dist/data/queries/joinEntity.min.js +1 -1
- package/dist/data/queries/where.d.ts +38 -7
- package/dist/data/queries/where.js +119 -13
- package/dist/data/queries/where.min.js +1 -1
- package/dist/data/utilities/conditionEntities.d.ts +20 -0
- package/dist/data/utilities/conditionEntities.js +85 -0
- package/dist/data/utilities/conditionEntities.min.js +1 -0
- package/dist/data/utilities/conditionTree.d.ts +36 -0
- package/dist/data/utilities/conditionTree.js +62 -0
- package/dist/data/utilities/conditionTree.min.js +1 -0
- package/dist/data/utilities/getConditionIndexedList.d.ts +10 -7
- package/dist/data/utilities/getConditionIndexedList.js +108 -32
- package/dist/data/utilities/getConditionIndexedList.min.js +1 -1
- package/dist/data/utilities/parsers/findConditions.d.ts +7 -5
- package/dist/data/utilities/parsers/findConditions.js +163 -35
- package/dist/data/utilities/parsers/findConditions.min.js +1 -1
- package/dist/data/utilities/parsers/parseQuery.d.ts +2 -2
- package/dist/data/utilities/parsers/parseQuery.js +1 -1
- package/dist/data/utilities/parsers/parseQuery.min.js +1 -1
- package/dist/data/utilities/runQuery.js +12 -23
- package/dist/data/utilities/runQuery.min.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,6 +64,10 @@ const [workouts, exercises] = await query("read workouts where date = '2024-06-0
|
|
|
64
64
|
|
|
65
65
|
The `;` after the last (or only) query is optional. A `;` inside a string, a comment or brackets doesn't end a query.
|
|
66
66
|
|
|
67
|
+
Write the commands `read`, `insert`, `update` and `delete`, and the sort directions `asc` and `desc`, in lowercase:
|
|
68
|
+
`READ t` is an error, and `sort a ASC` sorts descending. Other keywords (`where`, `and`, `sort`, `limit`, `create`,
|
|
69
|
+
`show records`...) and comparators can be written in any case.
|
|
70
|
+
|
|
67
71
|
### Strings
|
|
68
72
|
|
|
69
73
|
Strings use single or double quotes. A string closes only with the quote it opened with, so the other quote is just
|
|
@@ -137,16 +141,39 @@ string are just text.
|
|
|
137
141
|
read workouts where date = '2024-06-02' /* the Sunday */;
|
|
138
142
|
```
|
|
139
143
|
|
|
140
|
-
###
|
|
144
|
+
### Where clauses: `and`, `or`, `not` and brackets
|
|
141
145
|
|
|
142
|
-
|
|
146
|
+
A `where` clause is one condition, or several joined with `and` / `or`, each of which can be negated with `not`.
|
|
147
|
+
Brackets group them, nested to any depth:
|
|
143
148
|
|
|
144
149
|
```sql
|
|
145
|
-
read workouts where
|
|
150
|
+
read workouts where date = '2024-06-02' and (exercise_id = 1 or exercise_id = 3)
|
|
151
|
+
read exercises where not (name like 'bench%' or name like 'squat%')
|
|
146
152
|
```
|
|
147
153
|
|
|
148
|
-
`
|
|
149
|
-
|
|
154
|
+
`not` binds tightest, then `and`, then `or`, as in SQL. So `a or b and c` means `a or (b and c)`. Use brackets
|
|
155
|
+
for anything else:
|
|
156
|
+
|
|
157
|
+
| Where clause | Means |
|
|
158
|
+
|---|---|
|
|
159
|
+
| `where a = 1 or b = 2 and c = 3` | `a = 1 or (b = 2 and c = 3)` |
|
|
160
|
+
| `where (a = 1 or b = 2) and c = 3` | as written |
|
|
161
|
+
| `where not a = 1 and b = 2` | `(not a = 1) and b = 2` |
|
|
162
|
+
| `where not (a = 1 or b = 2)` | neither |
|
|
163
|
+
|
|
164
|
+
The comparators are `=`, `!=` (or `<>`), `>`, `>=`, `<`, `<=`, `in [...]`, `between [low, high]` and `like` (`%`
|
|
165
|
+
matches any text, `_` one character, ignoring case). `is null`, `is not null`, `exists` and `does not exist` test
|
|
166
|
+
for null and missing fields (see below). In a where clause, the keywords (`where`, `and`, `or`, `not`, `is null`...) and comparators (`IN`, `LIKE`) can be
|
|
167
|
+
written in any case (see the casing note under Writing queries).
|
|
168
|
+
|
|
169
|
+
The older form, a `where` per condition (`where a = 1 and where b = 2`, `or where`), still works and means the same.
|
|
170
|
+
|
|
171
|
+
Mistakes are errors that point at the place: an unclosed or unexpected bracket, an operator with nothing after it
|
|
172
|
+
(`where a = 1 and`), empty brackets, or two conditions with nothing between them (`where a = 1 b = 2`).
|
|
173
|
+
|
|
174
|
+
Indexes make a where clause faster but never change its result. An indexed condition only narrows which rows are
|
|
175
|
+
read, and the whole clause is then checked on each of them. That works through `and` and through an `or` whose
|
|
176
|
+
every branch is indexed. A `not` reads every row.
|
|
150
177
|
|
|
151
178
|
### Comparing by the field's type
|
|
152
179
|
|
|
@@ -174,6 +201,75 @@ then `null`, then the values (`asc`; `desc` is the reverse).
|
|
|
174
201
|
|
|
175
202
|
In 2.0 and earlier, a `null` acted as `0` in comparisons and sorting (`where n < 5` matched it), and `= null` matched it.
|
|
176
203
|
|
|
204
|
+
Inside `and` / `or` / `not`, a comparison on a null or missing field is **unknown**: neither true nor false, as in
|
|
205
|
+
SQL. A row is returned only when the whole clause is true:
|
|
206
|
+
|
|
207
|
+
| | result |
|
|
208
|
+
|---|---|
|
|
209
|
+
| `not unknown` | unknown |
|
|
210
|
+
| `false and unknown` | false |
|
|
211
|
+
| `true and unknown` | unknown |
|
|
212
|
+
| `true or unknown` | true |
|
|
213
|
+
| `false or unknown` | unknown |
|
|
214
|
+
|
|
215
|
+
So `where not (n = 5)` returns the same rows as `where n != 5`: neither returns a row where `n` is null or missing.
|
|
216
|
+
To include them, ask for them: `where n != 5 or n is null`. The same goes for `in` with a `null` in the list:
|
|
217
|
+
`n in [5, null]` is `n = 5 or n = null`, so a row it doesn't match is unknown and `not (n in [5, null])` returns
|
|
218
|
+
nothing.
|
|
219
|
+
|
|
220
|
+
### Joins: `on` and `merge`
|
|
221
|
+
|
|
222
|
+
`read workouts.exercises` reads workouts and attaches the matching exercises to each one as a list, using `on` (add
|
|
223
|
+
more with `and on` to go through linking records):
|
|
224
|
+
|
|
225
|
+
```sql
|
|
226
|
+
read workouts.exercises on workouts.exercise_id = exercises._id
|
|
227
|
+
read workouts.muscles on workouts.exercise_id = exercises._id
|
|
228
|
+
and on exercises._id = exercise_muscle.exercise_id
|
|
229
|
+
and on exercise_muscle.muscle_id = muscles._id
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
`merge` copies one matching record's fields onto each row instead, named `entity.field`:
|
|
233
|
+
|
|
234
|
+
```sql
|
|
235
|
+
read workouts merge workouts.exercise_id with exercises._id
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
A condition can use the fields of the record being read, the joined record and merged records, written
|
|
239
|
+
`entity.field`:
|
|
240
|
+
|
|
241
|
+
```sql
|
|
242
|
+
read workouts.exercises on workouts.exercise_id = exercises._id
|
|
243
|
+
where date = '2024-06-05' and exercises.name like 'b%'
|
|
244
|
+
read workouts merge workouts.exercise_id with exercises._id where exercises.name = 'Squat'
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
A condition on the joined record's fields works like SQL's inner join. The clause is checked for each pair of a row
|
|
248
|
+
and one of its joined rows. Each row keeps only the joined rows the clause is true for, and a row left with none
|
|
249
|
+
isn't returned. That includes a row with no joined rows at all, even when an `or` matches its own fields.
|
|
250
|
+
`read exercises.workouts on exercises._id = workouts.exercise_id where workouts.date = '2024-06-02'` returns each
|
|
251
|
+
exercise with only that day's workouts.
|
|
252
|
+
|
|
253
|
+
These are errors:
|
|
254
|
+
- a condition on a record that only links the join (`exercise_muscle` above)
|
|
255
|
+
- a condition on a record that isn't in the query
|
|
256
|
+
- in `update` and `delete`, any condition on another record's fields. They only change the record they name, and
|
|
257
|
+
check its own fields before any join runs.
|
|
258
|
+
|
|
259
|
+
### Clause order
|
|
260
|
+
|
|
261
|
+
Clauses can come in any order after the record name, but the SQL order reads best and is recommended (a fixed order
|
|
262
|
+
may become required in a later version):
|
|
263
|
+
|
|
264
|
+
```sql
|
|
265
|
+
read workouts.exercises select date, reps
|
|
266
|
+
on workouts.exercise_id = exercises._id
|
|
267
|
+
where reps > 8 and (exercises.name = 'Squat' or exercises.name = 'Deadlift')
|
|
268
|
+
group by date
|
|
269
|
+
sort date desc
|
|
270
|
+
limit 10 offset 0
|
|
271
|
+
```
|
|
272
|
+
|
|
177
273
|
### Creating a record: `create`
|
|
178
274
|
|
|
179
275
|
The query form of `create()`. Inside the brackets: the fields, then the keys, separated by commas. Everything is
|
|
@@ -256,12 +352,24 @@ queryStatus('read notes;') // { complete: true, waitingFor: ''
|
|
|
256
352
|
- `null` is only accepted by fields with `nullable: true`, and is stored as a real `null`. Before, a `string` field
|
|
257
353
|
stored the text `"null"` and an `int` field stored `0`.
|
|
258
354
|
- `create()` throws for a default that doesn't fit its field's type, and for a nullable primary key field.
|
|
259
|
-
- `or where`
|
|
355
|
+
- `or where` means `or` (2.3). In 1.x it was read as `and where`, returning the wrong rows, and in 2.0 to 2.2 it was an
|
|
356
|
+
error.
|
|
260
357
|
- A select alias needs `as`: `select name as n`. Before, the first field took the next word as its alias, so
|
|
261
358
|
`select name where a = 1` failed and `select name limit 1` lost its limit; `select name n` is now an error.
|
|
262
359
|
- Sort fields need a comma between them: `sort a, b desc`. Before, the list ran on into the next clause, so
|
|
263
360
|
`sort a limit 1` sorted by `a`, `limit` and `1` and lost the limit; `sort a b` is now an error.
|
|
264
361
|
|
|
362
|
+
### Upgrading to 2.3
|
|
363
|
+
|
|
364
|
+
- `and`, `or`, `not` and brackets in a where clause (above). `or where` works again, now as `or`.
|
|
365
|
+
- A condition on a joined record's field works, as an inner join. Before, an unindexed one matched nothing, and an
|
|
366
|
+
indexed one (`exercises._id = 1`) returned every row, most of them with an empty list of joined rows. Only rows
|
|
367
|
+
with a matching joined row are returned now.
|
|
368
|
+
- A condition on the read record's own field written with its name (`workouts.date`) works. It matched nothing before.
|
|
369
|
+
- A condition on a record that isn't in the query, or only links a join, is an error. Before, it matched nothing or
|
|
370
|
+
failed to read the record.
|
|
371
|
+
- Comparators are case-insensitive (`IN`, `LIKE`). Before, only lowercase ones matched anything.
|
|
372
|
+
|
|
265
373
|
## Configuration
|
|
266
374
|
|
|
267
375
|
`configure()` sets where this package's data lives and how strictly it enforces foreign keys - call it once,
|