datanotes 3.3.0 → 3.4.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/SECURITY.md +5 -3
- package/dist/api/extensions.cjs +1345 -21
- package/dist/api/extensions.js +1345 -21
- package/dist/api/index.cjs +1345 -21
- package/dist/api/index.js +1345 -21
- package/dist/api/mcp.cjs +1345 -21
- package/dist/api/mcp.js +1345 -21
- package/dist/datanotes.cjs +2927 -609
- package/dist/docs/administration/extensions.md +2 -2
- package/dist/docs/api/operations/add_column.md +1 -0
- package/dist/docs/api/operations/alter_table.md +4 -3
- package/dist/docs/api/operations/check_table.md +1 -0
- package/dist/docs/api/operations/create_table.md +1 -0
- package/dist/docs/api/operations/describe_database.md +2 -0
- package/dist/docs/api/operations/describe_history.md +1 -0
- package/dist/docs/api/operations/describe_semantic_index.md +1 -0
- package/dist/docs/api/operations/describe_table.md +1 -0
- package/dist/docs/api/operations/graph_neighbors.md +1 -0
- package/dist/docs/api/operations/graph_path.md +1 -0
- package/dist/docs/api/operations/graph_traverse.md +1 -0
- package/dist/docs/api/operations/infer_table.md +1 -0
- package/dist/docs/api/operations/list_changes.md +1 -0
- package/dist/docs/api/operations/list_folder.md +1 -0
- package/dist/docs/api/operations/list_link_targets.md +1 -0
- package/dist/docs/api/operations/list_migrations.md +1 -0
- package/dist/docs/api/operations/list_tables.md +2 -0
- package/dist/docs/api/operations/list_webhooks.md +1 -0
- package/dist/docs/api/operations/read_note.md +1 -0
- package/dist/docs/api/operations/search.md +39 -0
- package/dist/docs/api/operations/search_notes.md +1 -0
- package/dist/docs/api/operations/select_rows.md +1 -0
- package/dist/docs/api/operations/semantic_search.md +1 -0
- package/dist/docs/api/operations/table_changes.md +1 -0
- package/dist/docs/api/operations/tags/queries.md +1 -0
- package/dist/docs/api/operations/tags/tokens.md +1 -1
- package/dist/docs/api/operations/tokens_create.md +1 -0
- package/dist/docs/api/operations/tokens_update.md +2 -1
- package/dist/docs/api.md +5 -4
- package/dist/docs/develop/build-an-app.md +2 -1
- package/dist/docs/develop/change-feed-and-webhooks.md +1 -1
- package/dist/docs/develop/http-api.md +1 -1
- package/dist/docs/guides/data-quality/check-constraints.md +10 -10
- package/dist/docs/guides/data-quality/hand-edits.md +8 -8
- package/dist/docs/guides/database-objects/bases.md +11 -11
- package/dist/docs/guides/database-objects/catalogs-and-schemas.md +30 -10
- package/dist/docs/guides/database-objects/columns.md +243 -40
- package/dist/docs/guides/database-objects/relations.md +28 -28
- package/dist/docs/guides/database-objects/tables.md +167 -43
- package/dist/docs/guides/database-objects/views.md +44 -44
- package/dist/docs/guides/history/change-data-feed.md +34 -34
- package/dist/docs/guides/history/journal-and-undo.md +12 -12
- package/dist/docs/guides/history/restore.md +20 -20
- package/dist/docs/guides/history/table-history.md +31 -31
- package/dist/docs/guides/read-and-write/automatic-links.md +15 -15
- package/dist/docs/guides/read-and-write/import-notes.md +20 -20
- package/dist/docs/guides/read-and-write/joins-and-aggregates.md +7 -7
- package/dist/docs/guides/read-and-write/read-and-filter.md +10 -10
- package/dist/docs/guides/read-and-write/write-rows.md +10 -10
- package/dist/docs/guides/search/hybrid.md +162 -0
- package/dist/docs/guides/search/text.md +1 -1
- package/dist/docs/guides/security/security-model.md +5 -3
- package/dist/docs/guides/security/tokens.md +121 -8
- package/dist/docs/reference/cli.md +1 -1
- package/dist/docs/reference/glossary.md +1 -1
- package/dist/docs/reference/operations/auxiliary.md +3 -3
- package/dist/docs/reference/operations/queries.md +16 -0
- package/dist/docs/reference/operations/rows.md +1 -1
- package/dist/docs/reference/operations/schema.md +5 -5
- package/dist/docs/reference/operations.md +6 -5
- package/dist/docs/release-notes.md +59 -0
- package/dist/docs/start/connect-agents.md +10 -3
- package/package.json +1 -1
|
@@ -35,7 +35,7 @@ Answer:
|
|
|
35
35
|
"op": "add_column",
|
|
36
36
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
37
37
|
"commits": [{ "table": "main.public.film", "version": 3, "operation": "ADD COLUMNS" }],
|
|
38
|
-
"migration_id": "
|
|
38
|
+
"migration_id": "20261024T063903-add_column-add-column-minutes-to-film"
|
|
39
39
|
}
|
|
40
40
|
```
|
|
41
41
|
|
|
@@ -118,7 +118,7 @@ Answer:
|
|
|
118
118
|
],
|
|
119
119
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
120
120
|
"commits": [{ "table": "main.public.film", "version": 5, "operation": "ADD COLUMNS" }],
|
|
121
|
-
"migration_id": "
|
|
121
|
+
"migration_id": "20261024T063903-add_column-add-column-favourite-to-film"
|
|
122
122
|
}
|
|
123
123
|
```
|
|
124
124
|
|
|
@@ -176,7 +176,7 @@ Answer:
|
|
|
176
176
|
"op": "add_column",
|
|
177
177
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
178
178
|
"commits": [{ "table": "main.public.film", "version": 6, "operation": "ADD COLUMNS" }],
|
|
179
|
-
"migration_id": "
|
|
179
|
+
"migration_id": "20261024T063903-add_column-add-column-status-to-film"
|
|
180
180
|
}
|
|
181
181
|
```
|
|
182
182
|
|
|
@@ -283,7 +283,7 @@ Answer:
|
|
|
283
283
|
],
|
|
284
284
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
285
285
|
"commits": [{ "table": "main.public.film", "version": 9, "operation": "UPDATE" }],
|
|
286
|
-
"migration_id": "
|
|
286
|
+
"migration_id": "20261024T063903-rename_value-rename-film-status-value-seen-"
|
|
287
287
|
}
|
|
288
288
|
```
|
|
289
289
|
|
|
@@ -338,7 +338,7 @@ Answer:
|
|
|
338
338
|
"commits": [
|
|
339
339
|
{ "table": "main.public.film", "version": 10, "operation": "CHANGE COLUMN" }
|
|
340
340
|
],
|
|
341
|
-
"migration_id": "
|
|
341
|
+
"migration_id": "20261024T063903-alter_column-alter-column-status-in-film"
|
|
342
342
|
}
|
|
343
343
|
```
|
|
344
344
|
|
|
@@ -402,7 +402,7 @@ Answer:
|
|
|
402
402
|
"commits": [
|
|
403
403
|
{ "table": "main.public.film", "version": 11, "operation": "CHANGE COLUMN" }
|
|
404
404
|
],
|
|
405
|
-
"migration_id": "
|
|
405
|
+
"migration_id": "20261024T063903-alter_column-alter-column-minutes-in-film"
|
|
406
406
|
}
|
|
407
407
|
```
|
|
408
408
|
|
|
@@ -424,7 +424,7 @@ Answer:
|
|
|
424
424
|
"commits": [
|
|
425
425
|
{ "table": "main.public.film", "version": 12, "operation": "CHANGE COLUMN" }
|
|
426
426
|
],
|
|
427
|
-
"migration_id": "
|
|
427
|
+
"migration_id": "20261024T063903-alter_column-alter-column-minutes-in-film-2"
|
|
428
428
|
}
|
|
429
429
|
```
|
|
430
430
|
|
|
@@ -454,7 +454,7 @@ Answer:
|
|
|
454
454
|
"commits": [
|
|
455
455
|
{ "table": "main.public.film", "version": 13, "operation": "CHANGE COLUMN" }
|
|
456
456
|
],
|
|
457
|
-
"migration_id": "
|
|
457
|
+
"migration_id": "20261024T063903-alter_column-alter-column-minutes-in-film-3"
|
|
458
458
|
}
|
|
459
459
|
```
|
|
460
460
|
|
|
@@ -463,7 +463,7 @@ Answer:
|
|
|
463
463
|
```markdown
|
|
464
464
|
---
|
|
465
465
|
table: main.public.film
|
|
466
|
-
id:
|
|
466
|
+
id: 01a16ca2-622e-77f6-96b8-9b911fafe9fb
|
|
467
467
|
title: Nosferatu
|
|
468
468
|
year: 1922
|
|
469
469
|
favourite: false
|
|
@@ -490,7 +490,7 @@ Answer:
|
|
|
490
490
|
"commits": [
|
|
491
491
|
{ "table": "main.public.film", "version": 14, "operation": "CHANGE COLUMN" }
|
|
492
492
|
],
|
|
493
|
-
"migration_id": "
|
|
493
|
+
"migration_id": "20261024T063903-alter_column-alter-column-minutes-in-film-4"
|
|
494
494
|
}
|
|
495
495
|
```
|
|
496
496
|
|
|
@@ -499,7 +499,7 @@ Answer:
|
|
|
499
499
|
```markdown
|
|
500
500
|
---
|
|
501
501
|
table: main.public.film
|
|
502
|
-
id:
|
|
502
|
+
id: 01a16ca2-622e-77f6-96b8-9b911fafe9fb
|
|
503
503
|
title: Nosferatu
|
|
504
504
|
year: 1922
|
|
505
505
|
favourite: false
|
|
@@ -541,7 +541,7 @@ Answer:
|
|
|
541
541
|
"commits": [
|
|
542
542
|
{ "table": "main.public.film", "version": 15, "operation": "RENAME COLUMN" }
|
|
543
543
|
],
|
|
544
|
-
"migration_id": "
|
|
544
|
+
"migration_id": "20261024T063903-rename_column-rename-column-favourite-to-lov"
|
|
545
545
|
}
|
|
546
546
|
```
|
|
547
547
|
|
|
@@ -603,14 +603,14 @@ Answer:
|
|
|
603
603
|
],
|
|
604
604
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
605
605
|
"commits": [{ "table": "main.public.film", "version": 16, "operation": "DROP COLUMNS" }],
|
|
606
|
-
"migration_id": "
|
|
606
|
+
"migration_id": "20261024T063903-drop_column-drop-column-loved_it-from-film"
|
|
607
607
|
}
|
|
608
608
|
```
|
|
609
609
|
|
|
610
610
|
**`undo_migration`**
|
|
611
611
|
|
|
612
612
|
```json
|
|
613
|
-
{ "migration_id": "
|
|
613
|
+
{ "migration_id": "20261024T063903-drop_column-drop-column-loved_it-from-film" }
|
|
614
614
|
```
|
|
615
615
|
|
|
616
616
|
Answer:
|
|
@@ -619,8 +619,8 @@ Answer:
|
|
|
619
619
|
{
|
|
620
620
|
"ok": true,
|
|
621
621
|
"op": "undo_migration",
|
|
622
|
-
"undoes": "
|
|
623
|
-
"migration_id": "
|
|
622
|
+
"undoes": "20261024T063903-drop_column-drop-column-loved_it-from-film",
|
|
623
|
+
"migration_id": "20261024T063903-undo_migration-undo-20261024t063903-drop_colu",
|
|
624
624
|
"conflicts": [],
|
|
625
625
|
"failed": []
|
|
626
626
|
}
|
|
@@ -681,7 +681,7 @@ Answer:
|
|
|
681
681
|
"op": "add_column",
|
|
682
682
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
683
683
|
"commits": [{ "table": "main.public.film", "version": 18, "operation": "ADD COLUMNS" }],
|
|
684
|
-
"migration_id": "
|
|
684
|
+
"migration_id": "20261024T063903-add_column-add-column-added-to-film"
|
|
685
685
|
}
|
|
686
686
|
```
|
|
687
687
|
|
|
@@ -714,7 +714,7 @@ Answer:
|
|
|
714
714
|
"files_created": 1,
|
|
715
715
|
"planned_creates": ["datanotes/main/public/film/Sherlock Jr..md"],
|
|
716
716
|
"commits": [{ "table": "main.public.film", "version": 20, "operation": "WRITE" }],
|
|
717
|
-
"migration_id": "
|
|
717
|
+
"migration_id": "20261024T063903-insert_row-insert-into-film-3"
|
|
718
718
|
}
|
|
719
719
|
```
|
|
720
720
|
|
|
@@ -723,12 +723,12 @@ Answer:
|
|
|
723
723
|
```markdown
|
|
724
724
|
---
|
|
725
725
|
table: main.public.film
|
|
726
|
-
id:
|
|
726
|
+
id: 01a16ca2-62f5-7e75-b2e7-e4aab44a8a93
|
|
727
727
|
loved_it: false
|
|
728
728
|
title: Sherlock Jr.
|
|
729
729
|
year: 1924
|
|
730
|
-
added: 2026-10-
|
|
731
|
-
added_at: 2026-10-
|
|
730
|
+
added: 2026-10-24
|
|
731
|
+
added_at: 2026-10-24T06:39:03Z
|
|
732
732
|
---
|
|
733
733
|
```
|
|
734
734
|
|
|
@@ -759,7 +759,7 @@ Answer:
|
|
|
759
759
|
"op": "add_column",
|
|
760
760
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
761
761
|
"commits": [{ "table": "main.public.film", "version": 21, "operation": "ADD COLUMNS" }],
|
|
762
|
-
"migration_id": "
|
|
762
|
+
"migration_id": "20261024T063903-add_column-add-column-seen_at-to-film"
|
|
763
763
|
}
|
|
764
764
|
```
|
|
765
765
|
|
|
@@ -784,7 +784,7 @@ Answer:
|
|
|
784
784
|
"op": "add_column",
|
|
785
785
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
786
786
|
"commits": [{ "table": "main.public.film", "version": 22, "operation": "ADD COLUMNS" }],
|
|
787
|
-
"migration_id": "
|
|
787
|
+
"migration_id": "20261024T063903-add_column-add-column-viewings-to-film"
|
|
788
788
|
}
|
|
789
789
|
```
|
|
790
790
|
|
|
@@ -833,7 +833,7 @@ Answer:
|
|
|
833
833
|
}
|
|
834
834
|
],
|
|
835
835
|
"commits": [{ "table": "main.public.film", "version": 23, "operation": "UPDATE" }],
|
|
836
|
-
"migration_id": "
|
|
836
|
+
"migration_id": "20261024T063903-update_row-update-film-4"
|
|
837
837
|
}
|
|
838
838
|
```
|
|
839
839
|
|
|
@@ -842,7 +842,7 @@ Answer:
|
|
|
842
842
|
```markdown
|
|
843
843
|
---
|
|
844
844
|
table: main.public.film
|
|
845
|
-
id:
|
|
845
|
+
id: 01a16ca2-622e-77f6-96b8-9b911fafe9fb
|
|
846
846
|
title: Nosferatu
|
|
847
847
|
year: 1922
|
|
848
848
|
loved_it: false
|
|
@@ -884,13 +884,14 @@ Docs: https://datanotes.dev/guides/database-objects/columns.md#describe-what-eac
|
|
|
884
884
|
|
|
885
885
|
## Compute a column from other columns
|
|
886
886
|
|
|
887
|
-
The engine computes a `generated` column from other columns on every write, and you can’t set it yourself. The expression takes one of
|
|
887
|
+
The engine computes a `generated` column from other columns on every write, and you can’t set it yourself. The expression takes one of four forms:
|
|
888
888
|
|
|
889
889
|
* **A column name**: the value of that column
|
|
890
890
|
* **`date(col)`**: the date of `col`, with an optional day shift
|
|
891
891
|
* **A template**: text with `{col}` and `{col:FORMAT}` placeholders
|
|
892
|
+
* **An aggregate**: a count or a total of the items of a `json` list, shown in the next section
|
|
892
893
|
|
|
893
|
-
`min(…)`, `max(…)` and `coalesce(…)` pick among several columns.
|
|
894
|
+
In a template, `min(…)`, `max(…)` and `coalesce(…)` pick among several columns.
|
|
894
895
|
|
|
895
896
|
**`create_table`**
|
|
896
897
|
|
|
@@ -942,7 +943,7 @@ Answer:
|
|
|
942
943
|
"op": "create_table",
|
|
943
944
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
944
945
|
"commits": [{ "table": "main.public.watch", "version": 0, "operation": "CREATE TABLE" }],
|
|
945
|
-
"migration_id": "
|
|
946
|
+
"migration_id": "20261024T063903-create_table-create-table-main-public-watch"
|
|
946
947
|
}
|
|
947
948
|
```
|
|
948
949
|
|
|
@@ -968,7 +969,7 @@ Answer:
|
|
|
968
969
|
"files_created": 1,
|
|
969
970
|
"planned_creates": ["datanotes/main/public/watch/2026-10-03T2130.md"],
|
|
970
971
|
"commits": [{ "table": "main.public.watch", "version": 1, "operation": "WRITE" }],
|
|
971
|
-
"migration_id": "
|
|
972
|
+
"migration_id": "20261024T063903-insert_row-insert-into-watch"
|
|
972
973
|
}
|
|
973
974
|
```
|
|
974
975
|
|
|
@@ -977,7 +978,7 @@ Answer:
|
|
|
977
978
|
```markdown
|
|
978
979
|
---
|
|
979
980
|
table: main.public.watch
|
|
980
|
-
id:
|
|
981
|
+
id: 01a16ca2-6327-778b-85f9-d586c0c733a8
|
|
981
982
|
film: His Girl Friday
|
|
982
983
|
occurred_at: 2026-10-03T21:30
|
|
983
984
|
where: home
|
|
@@ -1011,6 +1012,168 @@ Docs: https://datanotes.dev/guides/database-objects/columns.md#compute-a-column-
|
|
|
1011
1012
|
|
|
1012
1013
|
`time_column` names each row’s file after that date-time: here, the time the viewing started. The name follows the database’s `filename` format, `YYYY-MM-DD[T]HHmm` by default.
|
|
1013
1014
|
|
|
1015
|
+
## Count and total the items of a json list
|
|
1016
|
+
|
|
1017
|
+
A `generated` column can count the items of a `json` list of objects. It can also total one field of them. The engine recomputes it on every write of the row, so a total never falls behind its list. These functions read the list:
|
|
1018
|
+
|
|
1019
|
+
* **`count(films)`**: the number of items
|
|
1020
|
+
* **`count(films.minutes)`**: the items that have a `minutes` value
|
|
1021
|
+
* **`sum(films.minutes)`**: the total of the field
|
|
1022
|
+
* **`avg(…)`, `min(…)`, `max(…)`**: the average, the smallest and the largest value
|
|
1023
|
+
|
|
1024
|
+
A filter after a comma keeps only some items: `count(films, rewatch = true)`. It compares one field with `"text"`, a number, `true` or `false`. It uses `=`, `!=`, `<`, `<=`, `>` or `>=`, and the four orderings compare numbers. `!=` keeps every item that `=` leaves out, items without the field included.
|
|
1025
|
+
|
|
1026
|
+
**`create_table`**
|
|
1027
|
+
|
|
1028
|
+
```json
|
|
1029
|
+
{
|
|
1030
|
+
"name": "marathon",
|
|
1031
|
+
"description": "Nights when I watch several films in a row",
|
|
1032
|
+
"columns": [
|
|
1033
|
+
{
|
|
1034
|
+
"name": "night",
|
|
1035
|
+
"type": "date",
|
|
1036
|
+
"required": true,
|
|
1037
|
+
"description": "The night of the marathon"
|
|
1038
|
+
},
|
|
1039
|
+
{
|
|
1040
|
+
"name": "films",
|
|
1041
|
+
"type": "json",
|
|
1042
|
+
"description": "The films of the night: title, minutes and rewatch"
|
|
1043
|
+
},
|
|
1044
|
+
{
|
|
1045
|
+
"name": "film_count",
|
|
1046
|
+
"type": "integer",
|
|
1047
|
+
"generated": "count(films)",
|
|
1048
|
+
"description": "How many films I watched"
|
|
1049
|
+
},
|
|
1050
|
+
{
|
|
1051
|
+
"name": "rewatches",
|
|
1052
|
+
"type": "integer",
|
|
1053
|
+
"generated": "count(films, rewatch = true)",
|
|
1054
|
+
"description": "Films I had seen before"
|
|
1055
|
+
},
|
|
1056
|
+
{
|
|
1057
|
+
"name": "total_min",
|
|
1058
|
+
"type": "integer",
|
|
1059
|
+
"generated": "sum(films.minutes)",
|
|
1060
|
+
"description": "Minutes of film in the night"
|
|
1061
|
+
},
|
|
1062
|
+
{
|
|
1063
|
+
"name": "longest_min",
|
|
1064
|
+
"type": "integer",
|
|
1065
|
+
"generated": "max(films.minutes)",
|
|
1066
|
+
"description": "Running time of the longest film"
|
|
1067
|
+
},
|
|
1068
|
+
{
|
|
1069
|
+
"name": "avg_min",
|
|
1070
|
+
"type": "number",
|
|
1071
|
+
"generated": "avg(films.minutes, rewatch != true)",
|
|
1072
|
+
"description": "Average running time of the new films"
|
|
1073
|
+
}
|
|
1074
|
+
],
|
|
1075
|
+
"filename": "{night}"
|
|
1076
|
+
}
|
|
1077
|
+
```
|
|
1078
|
+
|
|
1079
|
+
Answer:
|
|
1080
|
+
|
|
1081
|
+
```json
|
|
1082
|
+
{
|
|
1083
|
+
"ok": true,
|
|
1084
|
+
"op": "create_table",
|
|
1085
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
1086
|
+
"commits": [
|
|
1087
|
+
{ "table": "main.public.marathon", "version": 0, "operation": "CREATE TABLE" }
|
|
1088
|
+
],
|
|
1089
|
+
"migration_id": "20261024T063903-create_table-create-table-main-public-marat"
|
|
1090
|
+
}
|
|
1091
|
+
```
|
|
1092
|
+
|
|
1093
|
+
**`insert_row`**
|
|
1094
|
+
|
|
1095
|
+
```json
|
|
1096
|
+
{
|
|
1097
|
+
"table": "marathon",
|
|
1098
|
+
"values": {
|
|
1099
|
+
"night": "2026-10-31",
|
|
1100
|
+
"films": [
|
|
1101
|
+
{ "title": "Nosferatu", "minutes": 94, "rewatch": true },
|
|
1102
|
+
{ "title": "Vampyr", "minutes": 73 },
|
|
1103
|
+
{ "title": "Frankenstein", "minutes": 70 }
|
|
1104
|
+
]
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
```
|
|
1108
|
+
|
|
1109
|
+
Answer:
|
|
1110
|
+
|
|
1111
|
+
```json
|
|
1112
|
+
{
|
|
1113
|
+
"ok": true,
|
|
1114
|
+
"op": "insert_row",
|
|
1115
|
+
"files_created": 1,
|
|
1116
|
+
"planned_creates": ["datanotes/main/public/marathon/2026-10-31.md"],
|
|
1117
|
+
"commits": [{ "table": "main.public.marathon", "version": 1, "operation": "WRITE" }],
|
|
1118
|
+
"migration_id": "20261024T063903-insert_row-insert-into-marathon"
|
|
1119
|
+
}
|
|
1120
|
+
```
|
|
1121
|
+
|
|
1122
|
+
`datanotes/main/public/marathon/2026-10-31.md` now reads:
|
|
1123
|
+
|
|
1124
|
+
```markdown
|
|
1125
|
+
---
|
|
1126
|
+
table: main.public.marathon
|
|
1127
|
+
id: 01a16ca2-633b-782d-afde-11976841ccee
|
|
1128
|
+
night: 2026-10-31
|
|
1129
|
+
films:
|
|
1130
|
+
- title: Nosferatu
|
|
1131
|
+
minutes: 94
|
|
1132
|
+
rewatch: true
|
|
1133
|
+
- title: Vampyr
|
|
1134
|
+
minutes: 73
|
|
1135
|
+
- title: Frankenstein
|
|
1136
|
+
minutes: 70
|
|
1137
|
+
film_count: 3
|
|
1138
|
+
rewatches: 1
|
|
1139
|
+
total_min: 237
|
|
1140
|
+
longest_min: 94
|
|
1141
|
+
avg_min: 71.5
|
|
1142
|
+
---
|
|
1143
|
+
```
|
|
1144
|
+
|
|
1145
|
+
The type of the column must fit the result. `count` makes a whole number, and `avg` needs a `number` column. An aggregate of a column that isn’t `json` is refused too:
|
|
1146
|
+
|
|
1147
|
+
**`add_column`**
|
|
1148
|
+
|
|
1149
|
+
```json
|
|
1150
|
+
{
|
|
1151
|
+
"table": "marathon",
|
|
1152
|
+
"column": {
|
|
1153
|
+
"name": "nights",
|
|
1154
|
+
"type": "integer",
|
|
1155
|
+
"generated": "count(night)",
|
|
1156
|
+
"description": "Not a list"
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
```
|
|
1160
|
+
|
|
1161
|
+
Refused:
|
|
1162
|
+
|
|
1163
|
+
```text
|
|
1164
|
+
columns[8]: "generated" aggregates "night", which is not a json column
|
|
1165
|
+
Hint: count() reads a json column (type json, or a list of json) holding a list of objects, such as [{side: left, min: 12}]; "night" has type date. describe_table shows the type of each column.
|
|
1166
|
+
Docs: https://datanotes.dev/guides/database-objects/columns.md#count-and-total-the-items-of-a-json-list (offline: read_docs("guides/database-objects/columns#count-and-total-the-items-of-a-json-list"))
|
|
1167
|
+
```
|
|
1168
|
+
|
|
1169
|
+
Values the engine can’t total leave the column empty instead of storing a wrong number:
|
|
1170
|
+
|
|
1171
|
+
* **No list, or an empty one**: `count` and `sum` are 0, and `avg`, `min` and `max` are empty
|
|
1172
|
+
* **An item without the field**: the engine leaves it out
|
|
1173
|
+
* **A field that isn’t a number**: the total is empty, as when the column isn’t a list
|
|
1174
|
+
|
|
1175
|
+
An `integer` column refuses a write whose total isn’t whole. After a hand edit of the list, `check_table` reports the stale totals and `recompute_columns` fixes them.
|
|
1176
|
+
|
|
1014
1177
|
## Let the engine fill identity columns
|
|
1015
1178
|
|
|
1016
1179
|
The engine fills an `identity` column on its own. `filename` keeps the note’s file name, and `created` records when the engine created the row and never changes. Every table also has `id`, the identity column that holds the row’s universally unique identifier (UUID). The meaning of `id` and `created` never changes, so the engine writes their descriptions too.
|
|
@@ -1037,7 +1200,7 @@ Answer:
|
|
|
1037
1200
|
"op": "add_column",
|
|
1038
1201
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
1039
1202
|
"commits": [{ "table": "main.public.film", "version": 24, "operation": "ADD COLUMNS" }],
|
|
1040
|
-
"migration_id": "
|
|
1203
|
+
"migration_id": "20261024T063904-add_column-add-column-note_name-to-film"
|
|
1041
1204
|
}
|
|
1042
1205
|
```
|
|
1043
1206
|
|
|
@@ -1058,7 +1221,7 @@ Answer:
|
|
|
1058
1221
|
"op": "add_column",
|
|
1059
1222
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
1060
1223
|
"commits": [{ "table": "main.public.film", "version": 25, "operation": "ADD COLUMNS" }],
|
|
1061
|
-
"migration_id": "
|
|
1224
|
+
"migration_id": "20261024T063904-add_column-add-column-created-to-film"
|
|
1062
1225
|
}
|
|
1063
1226
|
```
|
|
1064
1227
|
|
|
@@ -1077,7 +1240,7 @@ Answer:
|
|
|
1077
1240
|
"files_created": 1,
|
|
1078
1241
|
"planned_creates": ["datanotes/main/public/film/Charade.md"],
|
|
1079
1242
|
"commits": [{ "table": "main.public.film", "version": 26, "operation": "WRITE" }],
|
|
1080
|
-
"migration_id": "
|
|
1243
|
+
"migration_id": "20261024T063904-insert_row-insert-into-film"
|
|
1081
1244
|
}
|
|
1082
1245
|
```
|
|
1083
1246
|
|
|
@@ -1086,14 +1249,14 @@ Answer:
|
|
|
1086
1249
|
```markdown
|
|
1087
1250
|
---
|
|
1088
1251
|
table: main.public.film
|
|
1089
|
-
id:
|
|
1252
|
+
id: 01a16ca2-636a-7001-a23b-b75df0897156
|
|
1090
1253
|
loved_it: false
|
|
1091
1254
|
title: Charade
|
|
1092
1255
|
year: 1963
|
|
1093
|
-
added: 2026-10-
|
|
1094
|
-
added_at: 2026-10-
|
|
1256
|
+
added: 2026-10-24
|
|
1257
|
+
added_at: 2026-10-24T06:39:04Z
|
|
1095
1258
|
note_name: Charade
|
|
1096
|
-
created: 2026-10-
|
|
1259
|
+
created: 2026-10-24T06:39:04Z
|
|
1097
1260
|
---
|
|
1098
1261
|
```
|
|
1099
1262
|
|
|
@@ -1134,7 +1297,7 @@ Answer:
|
|
|
1134
1297
|
"op": "create_table",
|
|
1135
1298
|
"planned_texts": ["datanotes/metastore.yaml"],
|
|
1136
1299
|
"commits": [{ "table": "main.public.actor", "version": 0, "operation": "CREATE TABLE" }],
|
|
1137
|
-
"migration_id": "
|
|
1300
|
+
"migration_id": "20261024T063905-create_table-create-table-main-public-actor"
|
|
1138
1301
|
}
|
|
1139
1302
|
```
|
|
1140
1303
|
|
|
@@ -1153,7 +1316,7 @@ Answer:
|
|
|
1153
1316
|
"files_created": 1,
|
|
1154
1317
|
"planned_creates": ["datanotes/main/public/actor/1904/Cary Grant.md"],
|
|
1155
1318
|
"commits": [{ "table": "main.public.actor", "version": 1, "operation": "WRITE" }],
|
|
1156
|
-
"migration_id": "
|
|
1319
|
+
"migration_id": "20261024T063905-insert_row-insert-into-actor"
|
|
1157
1320
|
}
|
|
1158
1321
|
```
|
|
1159
1322
|
|
|
@@ -1190,7 +1353,7 @@ The engine wrote this file with the columns from this page, in the operations’
|
|
|
1190
1353
|
|
|
1191
1354
|
```yaml
|
|
1192
1355
|
# Metastore (Datanotes): catalogs, schemas, tables, columns, views.
|
|
1193
|
-
id:
|
|
1356
|
+
id: 01a16ca2-6220-75b7-ab5a-a37b8500206f
|
|
1194
1357
|
config:
|
|
1195
1358
|
history: true
|
|
1196
1359
|
|
|
@@ -1307,6 +1470,46 @@ catalogs:
|
|
|
1307
1470
|
type: string
|
|
1308
1471
|
description: A one-line summary of the viewing, for lists
|
|
1309
1472
|
generated: "{film} ({occurred_at:DD/MM HH:mm}, {where})"
|
|
1473
|
+
marathon:
|
|
1474
|
+
description: Nights when I watch several films in a row
|
|
1475
|
+
options:
|
|
1476
|
+
filename: "{night}"
|
|
1477
|
+
archive: _archive
|
|
1478
|
+
columns:
|
|
1479
|
+
- name: id
|
|
1480
|
+
type: string
|
|
1481
|
+
required: true
|
|
1482
|
+
description: "Unique id of the row (UUIDv7): set when the row is created, never changes"
|
|
1483
|
+
unique: true
|
|
1484
|
+
identity: uuid
|
|
1485
|
+
dense: true
|
|
1486
|
+
- name: night
|
|
1487
|
+
type: date
|
|
1488
|
+
required: true
|
|
1489
|
+
description: The night of the marathon
|
|
1490
|
+
- name: films
|
|
1491
|
+
type: json
|
|
1492
|
+
description: "The films of the night: title, minutes and rewatch"
|
|
1493
|
+
- name: film_count
|
|
1494
|
+
type: integer
|
|
1495
|
+
description: How many films I watched
|
|
1496
|
+
generated: count(films)
|
|
1497
|
+
- name: rewatches
|
|
1498
|
+
type: integer
|
|
1499
|
+
description: Films I had seen before
|
|
1500
|
+
generated: count(films, rewatch = true)
|
|
1501
|
+
- name: total_min
|
|
1502
|
+
type: integer
|
|
1503
|
+
description: Minutes of film in the night
|
|
1504
|
+
generated: sum(films.minutes)
|
|
1505
|
+
- name: longest_min
|
|
1506
|
+
type: integer
|
|
1507
|
+
description: Running time of the longest film
|
|
1508
|
+
generated: max(films.minutes)
|
|
1509
|
+
- name: avg_min
|
|
1510
|
+
type: number
|
|
1511
|
+
description: Average running time of the new films
|
|
1512
|
+
generated: avg(films.minutes, rewatch != true)
|
|
1310
1513
|
actor:
|
|
1311
1514
|
description: Actors of the films I watch
|
|
1312
1515
|
options:
|