datanotes 2.0.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +9 -0
- package/README.md +207 -28
- package/SECURITY.md +92 -45
- package/dist/THIRD-PARTY-NOTICES.txt +682 -0
- package/dist/api/catalog.d.cts +69 -0
- package/dist/api/catalog.d.ts +50 -2
- package/dist/api/cli-options.d.cts +39 -0
- package/dist/api/cli-options.d.ts +39 -0
- package/dist/api/client.d.cts +89 -0
- package/dist/api/client.d.ts +19 -30
- package/dist/api/docs.d.cts +211 -0
- package/dist/api/docs.d.ts +211 -0
- package/dist/api/guidance.d.cts +81 -0
- package/dist/api/guidance.d.ts +81 -0
- package/dist/api/index.cjs +6610 -2247
- package/dist/api/index.d.cts +13 -0
- package/dist/api/index.d.ts +10 -7
- package/dist/api/index.js +6610 -2247
- package/dist/api/local.cjs +118 -6
- package/dist/api/local.d.cts +95 -0
- package/dist/api/local.d.ts +70 -6
- package/dist/api/local.js +104 -6
- package/dist/api/mcp.cjs +17384 -0
- package/dist/api/mcp.d.cts +108 -0
- package/dist/api/mcp.d.ts +108 -0
- package/dist/api/mcp.js +17334 -0
- package/dist/api/otlp.d.cts +65 -0
- package/dist/api/redact.d.cts +17 -0
- package/dist/api/redact.d.ts +17 -0
- package/dist/api/requests.d.cts +26 -0
- package/dist/api/requests.d.ts +14 -16
- package/dist/api/results.d.cts +16 -0
- package/dist/api/results.d.ts +2 -1
- package/dist/api/tokens.d.cts +7 -0
- package/dist/datanotes.cjs +62511 -28069
- package/dist/docs/administration/configuration.md +59 -0
- package/dist/docs/administration/docker.md +80 -0
- package/dist/docs/administration/git-sync.md +71 -0
- package/dist/docs/administration/limits.md +69 -0
- package/dist/docs/administration/run-the-service.md +219 -0
- package/dist/docs/administration/status.md +61 -0
- package/dist/docs/administration/use-with-obsidian.md +75 -0
- package/dist/docs/api/operations/add_column.md +49 -0
- package/dist/docs/api/operations/add_constraint.md +55 -0
- package/dist/docs/api/operations/adopt_rows.md +50 -0
- package/dist/docs/api/operations/align_relations.md +41 -0
- package/dist/docs/api/operations/alter_column.md +46 -0
- package/dist/docs/api/operations/alter_table.md +67 -0
- package/dist/docs/api/operations/batch.md +48 -0
- package/dist/docs/api/operations/changes_stream.md +28 -0
- package/dist/docs/api/operations/check_table.md +29 -0
- package/dist/docs/api/operations/clone_table.md +48 -0
- package/dist/docs/api/operations/comment_on.md +42 -0
- package/dist/docs/api/operations/configure_database.md +52 -0
- package/dist/docs/api/operations/create_table.md +78 -0
- package/dist/docs/api/operations/create_view.md +54 -0
- package/dist/docs/api/operations/create_webhook.md +37 -0
- package/dist/docs/api/operations/define_base.md +52 -0
- package/dist/docs/api/operations/delete_rows.md +43 -0
- package/dist/docs/api/operations/delete_webhook.md +31 -0
- package/dist/docs/api/operations/describe_database.md +30 -0
- package/dist/docs/api/operations/describe_history.md +40 -0
- package/dist/docs/api/operations/describe_semantic_index.md +24 -0
- package/dist/docs/api/operations/describe_table.md +38 -0
- package/dist/docs/api/operations/docs.md +13 -0
- package/dist/docs/api/operations/drop_column.md +41 -0
- package/dist/docs/api/operations/drop_constraint.md +39 -0
- package/dist/docs/api/operations/drop_table.md +43 -0
- package/dist/docs/api/operations/drop_view.md +38 -0
- package/dist/docs/api/operations/engine_status.md +23 -0
- package/dist/docs/api/operations/graph_neighbors.md +32 -0
- package/dist/docs/api/operations/graph_path.md +32 -0
- package/dist/docs/api/operations/graph_traverse.md +43 -0
- package/dist/docs/api/operations/identify_session.md +24 -0
- package/dist/docs/api/operations/infer_table.md +43 -0
- package/dist/docs/api/operations/insert_row.md +48 -0
- package/dist/docs/api/operations/list_changes.md +35 -0
- package/dist/docs/api/operations/list_folder.md +28 -0
- package/dist/docs/api/operations/list_link_targets.md +44 -0
- package/dist/docs/api/operations/list_migrations.md +35 -0
- package/dist/docs/api/operations/list_tables.md +32 -0
- package/dist/docs/api/operations/list_webhooks.md +23 -0
- package/dist/docs/api/operations/manual_index.md +14 -0
- package/dist/docs/api/operations/manual_page.md +22 -0
- package/dist/docs/api/operations/merge_rows.md +44 -0
- package/dist/docs/api/operations/move_rows.md +52 -0
- package/dist/docs/api/operations/openapi.md +13 -0
- package/dist/docs/api/operations/openapi_post.md +20 -0
- package/dist/docs/api/operations/read_note.md +29 -0
- package/dist/docs/api/operations/recompute_columns.md +44 -0
- package/dist/docs/api/operations/record_tool_call.md +36 -0
- package/dist/docs/api/operations/rename_column.md +44 -0
- package/dist/docs/api/operations/rename_value.md +45 -0
- package/dist/docs/api/operations/restore_database.md +51 -0
- package/dist/docs/api/operations/restore_table.md +46 -0
- package/dist/docs/api/operations/search_notes.md +28 -0
- package/dist/docs/api/operations/select_rows.md +61 -0
- package/dist/docs/api/operations/semantic_search.md +34 -0
- package/dist/docs/api/operations/semantic_search_docs.md +26 -0
- package/dist/docs/api/operations/set_table_bases.md +44 -0
- package/dist/docs/api/operations/status.md +13 -0
- package/dist/docs/api/operations/stop_engine.md +23 -0
- package/dist/docs/api/operations/sync_semantic_index.md +33 -0
- package/dist/docs/api/operations/table_changes.md +31 -0
- package/dist/docs/api/operations/tags/auxiliary.md +14 -0
- package/dist/docs/api/operations/tags/change-feed.md +8 -0
- package/dist/docs/api/operations/tags/history.md +17 -0
- package/dist/docs/api/operations/tags/queries.md +15 -0
- package/dist/docs/api/operations/tags/rows-dml.md +16 -0
- package/dist/docs/api/operations/tags/schema-ddl.md +22 -0
- package/dist/docs/api/operations/tags/service.md +15 -0
- package/dist/docs/api/operations/tags/tokens.md +13 -0
- package/dist/docs/api/operations/tokens_create.md +34 -0
- package/dist/docs/api/operations/tokens_delete.md +29 -0
- package/dist/docs/api/operations/tokens_list.md +21 -0
- package/dist/docs/api/operations/tokens_me.md +20 -0
- package/dist/docs/api/operations/tokens_rotate.md +29 -0
- package/dist/docs/api/operations/tokens_update.md +34 -0
- package/dist/docs/api/operations/undo_migration.md +46 -0
- package/dist/docs/api/operations/update_row.md +60 -0
- package/dist/docs/api/operations/update_rows.md +46 -0
- package/dist/docs/api/operations/vacuum_table.md +37 -0
- package/dist/docs/api.md +135 -0
- package/dist/docs/develop/build-an-app.md +320 -0
- package/dist/docs/develop/build-on-datanotes.md +138 -0
- package/dist/docs/develop/change-feed-and-webhooks.md +70 -0
- package/dist/docs/develop/client.md +116 -0
- package/dist/docs/develop/concurrency.md +153 -0
- package/dist/docs/develop/http-api.md +79 -0
- package/dist/docs/develop/telemetry.md +86 -0
- package/dist/docs/guides/agents/docs-offline.md +99 -0
- package/dist/docs/guides/agents/how-agents-use-datanotes.md +124 -0
- package/dist/docs/guides/agents/prompts.md +495 -0
- package/dist/docs/guides/agents/reading-errors.md +112 -0
- package/dist/docs/guides/data-quality/check-constraints.md +379 -0
- package/dist/docs/guides/data-quality/check-table.md +63 -0
- package/dist/docs/guides/data-quality/hand-edits.md +507 -0
- package/dist/docs/guides/data-quality/sync-between-devices.md +51 -0
- package/dist/docs/guides/data-quality/validation.md +90 -0
- package/dist/docs/guides/database-objects/bases.md +480 -0
- package/dist/docs/guides/database-objects/catalogs-and-schemas.md +897 -0
- package/dist/docs/guides/database-objects/columns.md +1332 -0
- package/dist/docs/guides/database-objects/relations.md +1454 -0
- package/dist/docs/guides/database-objects/tables.md +1404 -0
- package/dist/docs/guides/database-objects/views.md +1003 -0
- package/dist/docs/guides/history/back-up.md +195 -0
- package/dist/docs/guides/history/change-data-feed.md +247 -0
- package/dist/docs/guides/history/journal-and-undo.md +262 -0
- package/dist/docs/guides/history/restore.md +341 -0
- package/dist/docs/guides/history/table-history.md +657 -0
- package/dist/docs/guides/history/vacuum.md +35 -0
- package/dist/docs/guides/read-and-write/automatic-links.md +768 -0
- package/dist/docs/guides/read-and-write/batch.md +139 -0
- package/dist/docs/guides/read-and-write/import-notes.md +896 -0
- package/dist/docs/guides/read-and-write/joins-and-aggregates.md +251 -0
- package/dist/docs/guides/read-and-write/read-and-filter.md +536 -0
- package/dist/docs/guides/read-and-write/write-rows.md +573 -0
- package/dist/docs/guides/search/link-graph.md +146 -0
- package/dist/docs/guides/search/semantic.md +133 -0
- package/dist/docs/guides/search/text.md +142 -0
- package/dist/docs/guides/security/security-model.md +110 -0
- package/dist/docs/guides/security/tokens.md +60 -0
- package/dist/docs/guides/security/who-did-what.md +42 -0
- package/dist/docs/index.md +113 -0
- package/dist/docs/llms.txt +33 -0
- package/dist/docs/reference/cli.md +136 -0
- package/dist/docs/reference/compatibility.md +63 -0
- package/dist/docs/reference/errors.md +72 -0
- package/dist/docs/reference/glossary.md +161 -0
- package/dist/docs/reference/operations/auxiliary.md +116 -0
- package/dist/docs/reference/operations/history.md +168 -0
- package/dist/docs/reference/operations/queries.md +169 -0
- package/dist/docs/reference/operations/rows.md +185 -0
- package/dist/docs/reference/operations/schema.md +316 -0
- package/dist/docs/reference/operations.md +96 -0
- package/dist/docs/reference/settings.md +31 -0
- package/dist/docs/release-notes.md +67 -0
- package/dist/docs/start/connect-agents.md +204 -0
- package/dist/docs/start/how-it-works.md +317 -0
- package/dist/docs/start/quick-start.md +126 -0
- package/package.json +58 -14
|
@@ -0,0 +1,657 @@
|
|
|
1
|
+
# Table history and time travel
|
|
2
|
+
|
|
3
|
+
> Turn history on, list a table’s versions, read a table as it was, compare two versions and find hand edits.
|
|
4
|
+
|
|
5
|
+
With history on, every write to a table becomes a numbered version in a transaction log, including edits made by hand. The engine keeps the log in its store, outside the vault.
|
|
6
|
+
|
|
7
|
+
History is on in a database the engine creates: its `metastore.yaml` says `history: true` under `config`. A database whose `metastore.yaml` lacks the key, such as one from a version before 3.0.0, has it off. Turn it on for the whole database with `configure_database`, or per table with `alter_table` or `create_table` (`history: true`).
|
|
8
|
+
|
|
9
|
+
History costs disk space. Each version keeps the full text of every note it writes, so a note saved ten times is stored about ten times. Trim old versions with [`vacuum_table`](https://datanotes.dev/guides/history/vacuum/), and turn history off with `history: false` for a table that doesn’t need it.
|
|
10
|
+
|
|
11
|
+
## Turn history on for a table
|
|
12
|
+
|
|
13
|
+
A table’s own `history` wins over the database’s setting. With `history: true`, the engine records every write to the table, even in a database with history off.
|
|
14
|
+
|
|
15
|
+
**`alter_table`**
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{ "table": "film", "history": true }
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Answer:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"ok": true,
|
|
26
|
+
"op": "alter_table",
|
|
27
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
28
|
+
"commits": [{ "table": "main.public.film", "version": 1, "operation": "ALTER TABLE" }],
|
|
29
|
+
"migration_id": "20261012T072004-alter_table-alter-table-main-public-film"
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**`insert_row`**
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{ "table": "film", "values": { "title": "Nosferatu" } }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**`insert_row`**
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{ "table": "film", "values": { "title": "Metropolis" } }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**`update_row`**
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"table": "film",
|
|
50
|
+
"path": "datanotes/main/public/film/Nosferatu.md",
|
|
51
|
+
"set": { "status": "watched", "rating": 4, "watched_on": "2026-10-03" }
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**`update_row`**
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"table": "film",
|
|
60
|
+
"path": "datanotes/main/public/film/Metropolis.md",
|
|
61
|
+
"set": { "status": "watched" }
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**`delete_rows`**
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{ "table": "film", "where": { "title": "Metropolis" } }
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The calls after `alter_table` add two films, rate Nosferatu, mark Metropolis watched by mistake and then remove it.
|
|
72
|
+
|
|
73
|
+
## List the versions of a table
|
|
74
|
+
|
|
75
|
+
`describe_history` lists the versions, newest first, each with its operation and metrics. Each version has the `migration_id` that `undo_migration` takes.
|
|
76
|
+
|
|
77
|
+
**`describe_history`**
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{ "table": "film" }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Answer (110 lines)
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"table": "main.public.film",
|
|
88
|
+
"history": [
|
|
89
|
+
{
|
|
90
|
+
"version": 6,
|
|
91
|
+
"timestamp": "2026-10-12T07:20:04.648Z",
|
|
92
|
+
"operation": "DELETE",
|
|
93
|
+
"operation_parameters": { "summary": "archive 1 rows of film" },
|
|
94
|
+
"migration_id": "20261012T072004-delete_rows-archive-1-rows-of-film",
|
|
95
|
+
"operation_metrics": {
|
|
96
|
+
"num_added_files": 0,
|
|
97
|
+
"num_removed_files": 1,
|
|
98
|
+
"metadata_changed": false
|
|
99
|
+
},
|
|
100
|
+
"engine_info": "datanotes",
|
|
101
|
+
"user_name": "docs-example",
|
|
102
|
+
"actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"version": 5,
|
|
106
|
+
"timestamp": "2026-10-12T07:20:04.642Z",
|
|
107
|
+
"operation": "UPDATE",
|
|
108
|
+
"operation_parameters": { "summary": "update film" },
|
|
109
|
+
"migration_id": "20261012T072004-update_row-update-film-2",
|
|
110
|
+
"operation_metrics": {
|
|
111
|
+
"num_added_files": 1,
|
|
112
|
+
"num_removed_files": 1,
|
|
113
|
+
"metadata_changed": false
|
|
114
|
+
},
|
|
115
|
+
"engine_info": "datanotes",
|
|
116
|
+
"user_name": "docs-example",
|
|
117
|
+
"actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"version": 4,
|
|
121
|
+
"timestamp": "2026-10-12T07:20:04.636Z",
|
|
122
|
+
"operation": "UPDATE",
|
|
123
|
+
"operation_parameters": { "summary": "update film" },
|
|
124
|
+
"migration_id": "20261012T072004-update_row-update-film",
|
|
125
|
+
"operation_metrics": {
|
|
126
|
+
"num_added_files": 1,
|
|
127
|
+
"num_removed_files": 1,
|
|
128
|
+
"metadata_changed": false
|
|
129
|
+
},
|
|
130
|
+
"engine_info": "datanotes",
|
|
131
|
+
"user_name": "docs-example",
|
|
132
|
+
"actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"version": 3,
|
|
136
|
+
"timestamp": "2026-10-12T07:20:04.630Z",
|
|
137
|
+
"operation": "WRITE",
|
|
138
|
+
"operation_parameters": { "summary": "insert into film" },
|
|
139
|
+
"migration_id": "20261012T072004-insert_row-insert-into-film-2",
|
|
140
|
+
"operation_metrics": {
|
|
141
|
+
"num_added_files": 1,
|
|
142
|
+
"num_removed_files": 0,
|
|
143
|
+
"metadata_changed": false
|
|
144
|
+
},
|
|
145
|
+
"engine_info": "datanotes",
|
|
146
|
+
"user_name": "docs-example",
|
|
147
|
+
"actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"version": 2,
|
|
151
|
+
"timestamp": "2026-10-12T07:20:04.624Z",
|
|
152
|
+
"operation": "WRITE",
|
|
153
|
+
"operation_parameters": { "summary": "insert into film" },
|
|
154
|
+
"migration_id": "20261012T072004-insert_row-insert-into-film",
|
|
155
|
+
"operation_metrics": {
|
|
156
|
+
"num_added_files": 1,
|
|
157
|
+
"num_removed_files": 0,
|
|
158
|
+
"metadata_changed": false
|
|
159
|
+
},
|
|
160
|
+
"engine_info": "datanotes",
|
|
161
|
+
"user_name": "docs-example",
|
|
162
|
+
"actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"version": 1,
|
|
166
|
+
"timestamp": "2026-10-12T07:20:04.617Z",
|
|
167
|
+
"operation": "ALTER TABLE",
|
|
168
|
+
"operation_parameters": { "summary": "alter table main.public.film" },
|
|
169
|
+
"migration_id": "20261012T072004-alter_table-alter-table-main-public-film",
|
|
170
|
+
"operation_metrics": {
|
|
171
|
+
"num_added_files": 0,
|
|
172
|
+
"num_removed_files": 0,
|
|
173
|
+
"metadata_changed": true
|
|
174
|
+
},
|
|
175
|
+
"engine_info": "datanotes",
|
|
176
|
+
"user_name": "docs-example",
|
|
177
|
+
"actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"version": 0,
|
|
181
|
+
"timestamp": "2026-10-12T07:20:04.609Z",
|
|
182
|
+
"operation": "CREATE TABLE",
|
|
183
|
+
"operation_parameters": { "summary": "create table main.public.film" },
|
|
184
|
+
"migration_id": "20261012T072004-create_table-create-table-main-public-film",
|
|
185
|
+
"operation_metrics": {
|
|
186
|
+
"num_added_files": 0,
|
|
187
|
+
"num_removed_files": 0,
|
|
188
|
+
"metadata_changed": true
|
|
189
|
+
},
|
|
190
|
+
"engine_info": "datanotes",
|
|
191
|
+
"user_name": "docs-example",
|
|
192
|
+
"actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
|
|
193
|
+
}
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Read a table as it was
|
|
199
|
+
|
|
200
|
+
`select_rows` with `version` or `timestamp` reads the table as it was at that point, a technique called time travel. Metropolis, which you removed since, is still there.
|
|
201
|
+
|
|
202
|
+
**`select_rows`**
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{ "table": "film", "columns": ["title", "status", "rating"], "version": 5 }
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Answer:
|
|
209
|
+
|
|
210
|
+
```json
|
|
211
|
+
{
|
|
212
|
+
"table": "main.public.film",
|
|
213
|
+
"total": 2,
|
|
214
|
+
"rows": [
|
|
215
|
+
{
|
|
216
|
+
"path": "datanotes/main/public/film/Metropolis.md",
|
|
217
|
+
"title": "Metropolis",
|
|
218
|
+
"status": "watched",
|
|
219
|
+
"rating": null
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"path": "datanotes/main/public/film/Nosferatu.md",
|
|
223
|
+
"title": "Nosferatu",
|
|
224
|
+
"status": "watched",
|
|
225
|
+
"rating": 4
|
|
226
|
+
}
|
|
227
|
+
],
|
|
228
|
+
"version": 5,
|
|
229
|
+
"timestamp": "2026-10-12T07:20:04.642Z"
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Copy a table as it was
|
|
234
|
+
|
|
235
|
+
`clone_table` with `version`, or with `timestamp` as a date-time, copies the table as it was then into a new table. The copy gets the definition and the rows as independent notes, and the source stays untouched.
|
|
236
|
+
|
|
237
|
+
**`clone_table`**
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{ "source": "film", "target": "film_before", "version": 5 }
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Answer:
|
|
244
|
+
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"ok": true,
|
|
248
|
+
"op": "clone_table",
|
|
249
|
+
"files_created": 2,
|
|
250
|
+
"planned_creates": [
|
|
251
|
+
"datanotes/main/public/film_before/Metropolis.md",
|
|
252
|
+
"datanotes/main/public/film_before/Nosferatu.md"
|
|
253
|
+
],
|
|
254
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
255
|
+
"commits": [{ "table": "main.public.film_before", "version": 0, "operation": "CLONE" }],
|
|
256
|
+
"migration_id": "20261012T072004-clone_table-clone-main-public-film-to-main"
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**`select_rows`**
|
|
261
|
+
|
|
262
|
+
```json
|
|
263
|
+
{ "table": "film_before", "columns": ["title", "status", "rating"] }
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Answer:
|
|
267
|
+
|
|
268
|
+
```json
|
|
269
|
+
{
|
|
270
|
+
"table": "main.public.film_before",
|
|
271
|
+
"total": 2,
|
|
272
|
+
"rows": [
|
|
273
|
+
{
|
|
274
|
+
"path": "datanotes/main/public/film_before/Metropolis.md",
|
|
275
|
+
"title": "Metropolis",
|
|
276
|
+
"status": "watched",
|
|
277
|
+
"rating": null
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"path": "datanotes/main/public/film_before/Nosferatu.md",
|
|
281
|
+
"title": "Nosferatu",
|
|
282
|
+
"status": "watched",
|
|
283
|
+
"rating": 4
|
|
284
|
+
}
|
|
285
|
+
]
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
This call names the same moment by its time, taken from the history read above:
|
|
290
|
+
|
|
291
|
+
**`clone_table`**
|
|
292
|
+
|
|
293
|
+
```json
|
|
294
|
+
{
|
|
295
|
+
"source": "film",
|
|
296
|
+
"target": "film_at",
|
|
297
|
+
"timestamp": "2026-10-12T07:20:04.642Z",
|
|
298
|
+
"copy_rows": false
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## See what changed between two versions
|
|
303
|
+
|
|
304
|
+
`table_changes` returns one entry per row change between two versions. It lists inserts, deletes, and updates, each update as a pre-image and a post-image of the row.
|
|
305
|
+
|
|
306
|
+
**`table_changes`**
|
|
307
|
+
|
|
308
|
+
```json
|
|
309
|
+
{ "table": "film", "start_version": 5 }
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Answer:
|
|
313
|
+
|
|
314
|
+
```json
|
|
315
|
+
{
|
|
316
|
+
"table": "main.public.film",
|
|
317
|
+
"changes": [
|
|
318
|
+
{
|
|
319
|
+
"id": "01a12efb-9f12-7afd-8545-4fec074ff1fb",
|
|
320
|
+
"title": "Metropolis",
|
|
321
|
+
"status": "to watch",
|
|
322
|
+
"path": "datanotes/main/public/film/Metropolis.md",
|
|
323
|
+
"_change_type": "update_preimage",
|
|
324
|
+
"_commit_version": 5,
|
|
325
|
+
"_commit_timestamp": "2026-10-12T07:20:04.642Z",
|
|
326
|
+
"_operation": "UPDATE"
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
"id": "01a12efb-9f12-7afd-8545-4fec074ff1fb",
|
|
330
|
+
"title": "Metropolis",
|
|
331
|
+
"status": "watched",
|
|
332
|
+
"path": "datanotes/main/public/film/Metropolis.md",
|
|
333
|
+
"_change_type": "update_postimage",
|
|
334
|
+
"_commit_version": 5,
|
|
335
|
+
"_commit_timestamp": "2026-10-12T07:20:04.642Z",
|
|
336
|
+
"_operation": "UPDATE"
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
"id": "01a12efb-9f12-7afd-8545-4fec074ff1fb",
|
|
340
|
+
"title": "Metropolis",
|
|
341
|
+
"status": "watched",
|
|
342
|
+
"path": "datanotes/main/public/film/Metropolis.md",
|
|
343
|
+
"_change_type": "delete",
|
|
344
|
+
"_commit_version": 6,
|
|
345
|
+
"_commit_timestamp": "2026-10-12T07:20:04.648Z",
|
|
346
|
+
"_operation": "DELETE"
|
|
347
|
+
}
|
|
348
|
+
]
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Find hand edits in the history
|
|
353
|
+
|
|
354
|
+
When a note changes outside the engine, in an editor, through git or through a sync, the engine records an `EXTERNAL_EDIT` version a moment later.
|
|
355
|
+
|
|
356
|
+
You edit `datanotes/main/public/film/Nosferatu.md` by hand, outside the engine. The note now reads:
|
|
357
|
+
|
|
358
|
+
```markdown
|
|
359
|
+
---
|
|
360
|
+
table: main.public.film
|
|
361
|
+
id: 01a12efb-9f0c-7795-aacb-6e9601757026
|
|
362
|
+
title: Nosferatu
|
|
363
|
+
status: watched
|
|
364
|
+
rating: 5
|
|
365
|
+
watched_on: 2026-10-03
|
|
366
|
+
---
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
**`describe_history`**
|
|
370
|
+
|
|
371
|
+
```json
|
|
372
|
+
{ "table": "film", "limit": 2 }
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
Answer:
|
|
376
|
+
|
|
377
|
+
```json
|
|
378
|
+
{
|
|
379
|
+
"table": "main.public.film",
|
|
380
|
+
"history": [
|
|
381
|
+
{
|
|
382
|
+
"version": 8,
|
|
383
|
+
"timestamp": "2026-10-12T07:20:07.804Z",
|
|
384
|
+
"operation": "EXTERNAL_EDIT",
|
|
385
|
+
"operation_metrics": {
|
|
386
|
+
"num_added_files": 1,
|
|
387
|
+
"num_removed_files": 1,
|
|
388
|
+
"metadata_changed": false,
|
|
389
|
+
"violations": 0
|
|
390
|
+
},
|
|
391
|
+
"engine_info": "datanotes"
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
"version": 7,
|
|
395
|
+
"timestamp": "2026-10-12T07:20:04.709Z",
|
|
396
|
+
"operation": "RESTORE",
|
|
397
|
+
"operation_parameters": { "summary": "restore main.public.film to version 5" },
|
|
398
|
+
"migration_id": "20261012T072004-restore_table-restore-main-public-film-to-ve",
|
|
399
|
+
"operation_metrics": {
|
|
400
|
+
"num_added_files": 1,
|
|
401
|
+
"num_removed_files": 0,
|
|
402
|
+
"metadata_changed": false
|
|
403
|
+
},
|
|
404
|
+
"engine_info": "datanotes",
|
|
405
|
+
"user_name": "docs-example",
|
|
406
|
+
"actor": { "session": "history", "harness": "docs-example", "auth": "owner" }
|
|
407
|
+
}
|
|
408
|
+
]
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## Turn history on for every table
|
|
413
|
+
|
|
414
|
+
`configure_database` with `history: true` turns history on for every table that doesn’t say otherwise. A database the engine creates has it on already. One whose `metastore.yaml` lacks the setting, such as one from a version before 3.0.0, has it off. A table’s own `history`, `true` or `false` with `alter_table`, wins, and `"default"` makes it follow the database again. The journal doesn’t record settings, so an agent changes it only when you ask.
|
|
415
|
+
|
|
416
|
+
**`configure_database`**
|
|
417
|
+
|
|
418
|
+
```json
|
|
419
|
+
{ "history": true }
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Answer:
|
|
423
|
+
|
|
424
|
+
```json
|
|
425
|
+
{
|
|
426
|
+
"default_catalog": "main",
|
|
427
|
+
"default_schema": "public",
|
|
428
|
+
"default_partition": "",
|
|
429
|
+
"default_filename": "YYYY-MM-DD[T]HHmm",
|
|
430
|
+
"archive_folder": "_archive",
|
|
431
|
+
"timezone": "",
|
|
432
|
+
"history": true,
|
|
433
|
+
"autolink": true
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
**`create_table`**
|
|
438
|
+
|
|
439
|
+
```json
|
|
440
|
+
{
|
|
441
|
+
"name": "actor",
|
|
442
|
+
"description": "Actors of the films I watch",
|
|
443
|
+
"columns": [
|
|
444
|
+
{
|
|
445
|
+
"name": "name",
|
|
446
|
+
"type": "string",
|
|
447
|
+
"required": true,
|
|
448
|
+
"description": "The actor's name, as credited"
|
|
449
|
+
},
|
|
450
|
+
{ "name": "born", "type": "date", "description": "The actor's date of birth" }
|
|
451
|
+
],
|
|
452
|
+
"filename": "{name}"
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
**`insert_row`**
|
|
457
|
+
|
|
458
|
+
```json
|
|
459
|
+
{ "table": "actor", "values": { "name": "Rosalind Russell", "born": "1907-06-04" } }
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
The new table has versions from its creation:
|
|
463
|
+
|
|
464
|
+
**`describe_history`**
|
|
465
|
+
|
|
466
|
+
```json
|
|
467
|
+
{ "table": "actor" }
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Answer:
|
|
471
|
+
|
|
472
|
+
```json
|
|
473
|
+
[{ "version": 1, "operation": "WRITE" }, { "version": 0, "operation": "CREATE TABLE" }]
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
A table’s own setting wins: `false` keeps the copy `film_before` without history, and `"default"` makes `film_at` follow the database again:
|
|
477
|
+
|
|
478
|
+
**`alter_table`**
|
|
479
|
+
|
|
480
|
+
```json
|
|
481
|
+
{ "table": "film_before", "history": false }
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
Answer:
|
|
485
|
+
|
|
486
|
+
```json
|
|
487
|
+
{
|
|
488
|
+
"ok": true,
|
|
489
|
+
"op": "alter_table",
|
|
490
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
491
|
+
"migration_id": "20261012T072013-alter_table-alter-table-main-public-film_b"
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
**`alter_table`**
|
|
496
|
+
|
|
497
|
+
```json
|
|
498
|
+
{ "table": "film_at", "history": "default" }
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Answer:
|
|
502
|
+
|
|
503
|
+
```json
|
|
504
|
+
{
|
|
505
|
+
"ok": true,
|
|
506
|
+
"op": "alter_table",
|
|
507
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
508
|
+
"commits": [
|
|
509
|
+
{ "table": "main.public.film_at", "version": 1, "operation": "ALTER TABLE" }
|
|
510
|
+
],
|
|
511
|
+
"migration_id": "20261012T072013-alter_table-alter-table-main-public-film_a"
|
|
512
|
+
}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
## See the history settings in `metastore.yaml`
|
|
516
|
+
|
|
517
|
+
History is a setting of the definition. `alter_table` writes `history: true` under the table’s `options`, `false` writes `false`, and `"default"` removes the key. For the whole database, the setting is under `config`. The copies made on this page are tables of their own.
|
|
518
|
+
|
|
519
|
+
`datanotes/metastore.yaml` now reads:
|
|
520
|
+
|
|
521
|
+
```yaml
|
|
522
|
+
# Metastore (Datanotes): catalogs, schemas, tables, columns, views.
|
|
523
|
+
id: 01a12efb-9ef8-7ceb-9b54-14318eb9becb
|
|
524
|
+
config:
|
|
525
|
+
history: true
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
catalogs:
|
|
529
|
+
main:
|
|
530
|
+
schemas:
|
|
531
|
+
public:
|
|
532
|
+
tables:
|
|
533
|
+
film:
|
|
534
|
+
description: Classic films I watched or want to watch
|
|
535
|
+
options:
|
|
536
|
+
filename: "{title}"
|
|
537
|
+
archive: _archive
|
|
538
|
+
history: true
|
|
539
|
+
columns:
|
|
540
|
+
- name: id
|
|
541
|
+
type: string
|
|
542
|
+
unique: true
|
|
543
|
+
identity: uuid
|
|
544
|
+
required: true
|
|
545
|
+
dense: true
|
|
546
|
+
description: "Unique id of the row (UUIDv7): set when the row is created, never changes"
|
|
547
|
+
- name: title
|
|
548
|
+
type: string
|
|
549
|
+
required: true
|
|
550
|
+
description: The film's title, as on its poster
|
|
551
|
+
unique: true
|
|
552
|
+
- name: status
|
|
553
|
+
type: enum
|
|
554
|
+
default: to watch
|
|
555
|
+
values:
|
|
556
|
+
- to watch
|
|
557
|
+
- watched
|
|
558
|
+
description: Where the film is on my list
|
|
559
|
+
ordered: true
|
|
560
|
+
- name: rating
|
|
561
|
+
type: integer
|
|
562
|
+
min: 1
|
|
563
|
+
max: 5
|
|
564
|
+
description: My rating, from 1 (poor) to 5 (a masterpiece)
|
|
565
|
+
- name: watched_on
|
|
566
|
+
type: date
|
|
567
|
+
description: The day I last watched it
|
|
568
|
+
film_before:
|
|
569
|
+
description: Classic films I watched or want to watch
|
|
570
|
+
options:
|
|
571
|
+
filename: "{title}"
|
|
572
|
+
archive: _archive
|
|
573
|
+
history: false
|
|
574
|
+
columns:
|
|
575
|
+
- name: id
|
|
576
|
+
type: string
|
|
577
|
+
unique: true
|
|
578
|
+
identity: uuid
|
|
579
|
+
required: true
|
|
580
|
+
dense: true
|
|
581
|
+
description: "Unique id of the row (UUIDv7): set when the row is created, never changes"
|
|
582
|
+
- name: title
|
|
583
|
+
type: string
|
|
584
|
+
required: true
|
|
585
|
+
description: The film's title, as on its poster
|
|
586
|
+
unique: true
|
|
587
|
+
- name: status
|
|
588
|
+
type: enum
|
|
589
|
+
default: to watch
|
|
590
|
+
values:
|
|
591
|
+
- to watch
|
|
592
|
+
- watched
|
|
593
|
+
description: Where the film is on my list
|
|
594
|
+
ordered: true
|
|
595
|
+
- name: rating
|
|
596
|
+
type: integer
|
|
597
|
+
min: 1
|
|
598
|
+
max: 5
|
|
599
|
+
description: My rating, from 1 (poor) to 5 (a masterpiece)
|
|
600
|
+
- name: watched_on
|
|
601
|
+
type: date
|
|
602
|
+
description: The day I last watched it
|
|
603
|
+
film_at:
|
|
604
|
+
description: Classic films I watched or want to watch
|
|
605
|
+
options:
|
|
606
|
+
filename: "{title}"
|
|
607
|
+
archive: _archive
|
|
608
|
+
columns:
|
|
609
|
+
- name: id
|
|
610
|
+
type: string
|
|
611
|
+
unique: true
|
|
612
|
+
identity: uuid
|
|
613
|
+
required: true
|
|
614
|
+
dense: true
|
|
615
|
+
description: "Unique id of the row (UUIDv7): set when the row is created, never changes"
|
|
616
|
+
- name: title
|
|
617
|
+
type: string
|
|
618
|
+
required: true
|
|
619
|
+
description: The film's title, as on its poster
|
|
620
|
+
unique: true
|
|
621
|
+
- name: status
|
|
622
|
+
type: enum
|
|
623
|
+
default: to watch
|
|
624
|
+
values:
|
|
625
|
+
- to watch
|
|
626
|
+
- watched
|
|
627
|
+
description: Where the film is on my list
|
|
628
|
+
ordered: true
|
|
629
|
+
- name: rating
|
|
630
|
+
type: integer
|
|
631
|
+
min: 1
|
|
632
|
+
max: 5
|
|
633
|
+
description: My rating, from 1 (poor) to 5 (a masterpiece)
|
|
634
|
+
- name: watched_on
|
|
635
|
+
type: date
|
|
636
|
+
description: The day I last watched it
|
|
637
|
+
actor:
|
|
638
|
+
description: Actors of the films I watch
|
|
639
|
+
options:
|
|
640
|
+
filename: "{name}"
|
|
641
|
+
archive: _archive
|
|
642
|
+
columns:
|
|
643
|
+
- name: id
|
|
644
|
+
type: string
|
|
645
|
+
required: true
|
|
646
|
+
description: "Unique id of the row (UUIDv7): set when the row is created, never changes"
|
|
647
|
+
unique: true
|
|
648
|
+
identity: uuid
|
|
649
|
+
dense: true
|
|
650
|
+
- name: name
|
|
651
|
+
type: string
|
|
652
|
+
required: true
|
|
653
|
+
description: The actor's name, as credited
|
|
654
|
+
- name: born
|
|
655
|
+
type: date
|
|
656
|
+
description: The actor's date of birth
|
|
657
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Vacuum old history
|
|
2
|
+
|
|
3
|
+
> Trim a table’s old versions with vacuum_table to keep its transaction log small.
|
|
4
|
+
|
|
5
|
+
A table’s transaction log grows with what you write. `vacuum_table` deletes the history older than `retain_from_version`, by default every version but the latest, so time travel and restores reach back only that far. The rows stay as they are. It isn’t journaled and can’t be undone, so its `dry_run` is on by default: it lists the log files that would go.
|
|
6
|
+
|
|
7
|
+
## Trim old history with `vacuum_table`
|
|
8
|
+
|
|
9
|
+
`vacuum_table` deletes log history older than a version. You can no longer time travel to an earlier version, and the rows stay untouched. It’s a dry run unless you pass `dry_run: false`, and an agent runs it only when you ask.
|
|
10
|
+
|
|
11
|
+
**`vacuum_table`**
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{ "table": "film" }
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Answer:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"table": "main.public.film",
|
|
22
|
+
"retained_from": 8,
|
|
23
|
+
"deleted": [
|
|
24
|
+
"store:transaction_log/main.public.film/00000000000000000000.json",
|
|
25
|
+
"store:transaction_log/main.public.film/00000000000000000001.json",
|
|
26
|
+
"store:transaction_log/main.public.film/00000000000000000002.json",
|
|
27
|
+
"store:transaction_log/main.public.film/00000000000000000003.json",
|
|
28
|
+
"store:transaction_log/main.public.film/00000000000000000004.json",
|
|
29
|
+
"store:transaction_log/main.public.film/00000000000000000005.json",
|
|
30
|
+
"store:transaction_log/main.public.film/00000000000000000006.json",
|
|
31
|
+
"store:transaction_log/main.public.film/00000000000000000007.json"
|
|
32
|
+
],
|
|
33
|
+
"dry_run": true
|
|
34
|
+
}
|
|
35
|
+
```
|