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,1404 @@
|
|
|
1
|
+
# Tables
|
|
2
|
+
|
|
3
|
+
> Create a table, find and describe it, set its folders, file names, template and tags, rename, copy and drop it.
|
|
4
|
+
|
|
5
|
+
A table lives in `datanotes/metastore.yaml`, and each of its rows is a Markdown note whose front matter key `table` names the table. Each column is a key of that front matter. You create and change tables only through operations, which validate each change, journal it and can undo it.
|
|
6
|
+
|
|
7
|
+
The examples start from an empty vault and build a small diary of classic films in the public domain. Later examples organize the tables of a second diary, kept in the catalog `diary`.
|
|
8
|
+
|
|
9
|
+
## Create a table with typed columns
|
|
10
|
+
|
|
11
|
+
`create_table` takes the table’s columns and their types. The table and each column need a `description`: what a row records, and what each column holds. An agent matches your words against the descriptions and the `aliases` to find the table. `filename` names each row’s note after one of its columns.
|
|
12
|
+
|
|
13
|
+
**`create_table`**
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"name": "film",
|
|
18
|
+
"description": "Classic films I watched or want to watch",
|
|
19
|
+
"columns": [
|
|
20
|
+
{
|
|
21
|
+
"name": "title",
|
|
22
|
+
"type": "string",
|
|
23
|
+
"required": true,
|
|
24
|
+
"unique": true,
|
|
25
|
+
"description": "The film's title, as on its poster"
|
|
26
|
+
},
|
|
27
|
+
{ "name": "year", "type": "integer", "description": "Year the film first came out" },
|
|
28
|
+
{
|
|
29
|
+
"name": "minutes",
|
|
30
|
+
"type": "integer",
|
|
31
|
+
"min": 1,
|
|
32
|
+
"description": "Running time in minutes"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "status",
|
|
36
|
+
"type": "enum",
|
|
37
|
+
"values": ["to watch", "watched"],
|
|
38
|
+
"ordered": true,
|
|
39
|
+
"default": "to watch",
|
|
40
|
+
"description": "Where the film is on my list"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "rating",
|
|
44
|
+
"type": "integer",
|
|
45
|
+
"min": 1,
|
|
46
|
+
"max": 5,
|
|
47
|
+
"description": "My rating, from 1 (poor) to 5 (a masterpiece)"
|
|
48
|
+
},
|
|
49
|
+
{ "name": "watched_on", "type": "date", "description": "The day I last watched it" }
|
|
50
|
+
],
|
|
51
|
+
"filename": "{title}",
|
|
52
|
+
"aliases": ["films", "movies", "watchlist"]
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Answer:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"ok": true,
|
|
61
|
+
"migration_id": "20261012T071946-create_table-create-table-main-public-film",
|
|
62
|
+
"summary": null
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`datanotes/metastore.yaml` now reads:
|
|
67
|
+
|
|
68
|
+
```yaml
|
|
69
|
+
# Metastore (Datanotes): catalogs, schemas, tables, columns, views.
|
|
70
|
+
id: 01a12efb-589d-722c-bc9b-81ec34e480a4
|
|
71
|
+
config:
|
|
72
|
+
history: true
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
catalogs:
|
|
76
|
+
main:
|
|
77
|
+
schemas:
|
|
78
|
+
public:
|
|
79
|
+
tables:
|
|
80
|
+
film:
|
|
81
|
+
description: Classic films I watched or want to watch
|
|
82
|
+
aliases:
|
|
83
|
+
- films
|
|
84
|
+
- movies
|
|
85
|
+
- watchlist
|
|
86
|
+
options:
|
|
87
|
+
filename: "{title}"
|
|
88
|
+
archive: _archive
|
|
89
|
+
columns:
|
|
90
|
+
- name: id
|
|
91
|
+
type: string
|
|
92
|
+
required: true
|
|
93
|
+
description: "Unique id of the row (UUIDv7): set when the row is created, never changes"
|
|
94
|
+
unique: true
|
|
95
|
+
identity: uuid
|
|
96
|
+
dense: true
|
|
97
|
+
- name: title
|
|
98
|
+
type: string
|
|
99
|
+
required: true
|
|
100
|
+
description: The film's title, as on its poster
|
|
101
|
+
unique: true
|
|
102
|
+
- name: year
|
|
103
|
+
type: integer
|
|
104
|
+
description: Year the film first came out
|
|
105
|
+
- name: minutes
|
|
106
|
+
type: integer
|
|
107
|
+
min: 1
|
|
108
|
+
description: Running time in minutes
|
|
109
|
+
- name: status
|
|
110
|
+
type: enum
|
|
111
|
+
default: to watch
|
|
112
|
+
values:
|
|
113
|
+
- to watch
|
|
114
|
+
- watched
|
|
115
|
+
description: Where the film is on my list
|
|
116
|
+
ordered: true
|
|
117
|
+
- name: rating
|
|
118
|
+
type: integer
|
|
119
|
+
min: 1
|
|
120
|
+
max: 5
|
|
121
|
+
description: My rating, from 1 (poor) to 5 (a masterpiece)
|
|
122
|
+
- name: watched_on
|
|
123
|
+
type: date
|
|
124
|
+
description: The day I last watched it
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The engine writes the definition in YAML Ain’t Markup Language (YAML), and you can read the file like any other note. Change it only through the operations (`add_column`, `alter_table`, …): they validate the change against the rows, journal it and make it undoable. A hand edit does none of that.
|
|
128
|
+
|
|
129
|
+
The file uses the operations’ words: a column is `required`, a table or a column has a `description`, and `fields` keeps the fixed front matter keys. The table’s `partition`, `filename`, `archive` and `exclude` go under `options`.
|
|
130
|
+
|
|
131
|
+
The file also holds two things the engine adds on its own. One is the `id` column every table has, with its description. The other is `archive`, the folder for archived rows. `archive` is `_archive` unless `configure_database` sets another folder.
|
|
132
|
+
|
|
133
|
+
## Describe every table and column
|
|
134
|
+
|
|
135
|
+
Agents and people understand the schema through its descriptions. The engine refuses a table or a column without one. The refusal lists every missing description at once, with the shape that fixes it. Write each one for a reader who never saw your notes.
|
|
136
|
+
|
|
137
|
+
**`create_table`**
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"name": "screening",
|
|
142
|
+
"description": "Films shown in my town",
|
|
143
|
+
"columns": [
|
|
144
|
+
{ "name": "film", "type": "string", "required": true },
|
|
145
|
+
{ "name": "venue", "type": "string" },
|
|
146
|
+
{
|
|
147
|
+
"name": "starts_at",
|
|
148
|
+
"type": "datetime",
|
|
149
|
+
"description": "When the screening begins"
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
"filename": "{starts_at:YYYY-MM-DD} {film}"
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Refused:
|
|
157
|
+
|
|
158
|
+
```text
|
|
159
|
+
descriptions are required: main.public.screening has none for columns film, venue
|
|
160
|
+
Hint: Say what a row records in "description" and what each column holds in its own "description": {"name": "screening", "description": "<what a row of screening records>", "columns": [{"name": "film", "type": "string", "description": "<what film holds>"}, …]}. Agents and people understand the schema through them.
|
|
161
|
+
Docs: https://datanotes.dev/guides/database-objects/tables.md#describe-every-table-and-column (offline: read_docs("guides/database-objects/tables#describe-every-table-and-column"))
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
A description can change, but it never goes. `alter_column` and `alter_table` refuse `null` or an empty text:
|
|
165
|
+
|
|
166
|
+
**`alter_column`**
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{ "table": "film", "column": "year", "changes": { "description": null } }
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Refused:
|
|
173
|
+
|
|
174
|
+
```text
|
|
175
|
+
the description of column year of main.public.film cannot be removed (null or empty): every column needs one
|
|
176
|
+
Hint: Pass the new text, as in {"table": "main.public.film", "column": "year", "changes": {"description": "<what year holds>"}}, or leave "description" out to keep the one it has.
|
|
177
|
+
Docs: https://datanotes.dev/guides/database-objects/tables.md#describe-every-table-and-column (offline: read_docs("guides/database-objects/tables#describe-every-table-and-column"))
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
You don’t write every description yourself. The engine writes those of the columns it sets itself: `id`, and `identity` columns of kind `uuid` or `created`.
|
|
181
|
+
|
|
182
|
+
A table created before descriptions were required may lack some, and it stays valid. `describe_table` and `describe_database` name what it lacks in `missing_descriptions`, such as `{"table": false, "columns": ["year"]}`. Fill each one with `alter_table` or `alter_column`. An `infer_table` proposal leaves its descriptions `null` for you to write, as [Infer a table from notes](https://datanotes.dev/guides/read-and-write/import-notes/#infer-a-table-from-notes) shows.
|
|
183
|
+
|
|
184
|
+
## Find the table that matches a request
|
|
185
|
+
|
|
186
|
+
`list_tables` returns every table with its description and aliases. An agent matches your words against them, so “add this to my watchlist” leads to the `film` table.
|
|
187
|
+
|
|
188
|
+
**`list_tables`** (no arguments)
|
|
189
|
+
|
|
190
|
+
Answer:
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"tables": [
|
|
195
|
+
{
|
|
196
|
+
"name": "film",
|
|
197
|
+
"catalog": "main",
|
|
198
|
+
"schema": "public",
|
|
199
|
+
"qualified": "main.public.film",
|
|
200
|
+
"description": "Classic films I watched or want to watch",
|
|
201
|
+
"aliases": ["films", "movies", "watchlist"]
|
|
202
|
+
}
|
|
203
|
+
],
|
|
204
|
+
"views": []
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Describe a table before writing to it
|
|
209
|
+
|
|
210
|
+
`describe_table` lists the columns with their types and constraints, and the table’s row count. Read it before you write: it tells you which values the table accepts.
|
|
211
|
+
|
|
212
|
+
**`describe_table`**
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{ "table": "film" }
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Answer (83 lines)
|
|
219
|
+
|
|
220
|
+
```json
|
|
221
|
+
{
|
|
222
|
+
"qualified": "main.public.film",
|
|
223
|
+
"name": "film",
|
|
224
|
+
"catalog": "main",
|
|
225
|
+
"schema": "public",
|
|
226
|
+
"description": "Classic films I watched or want to watch",
|
|
227
|
+
"aliases": ["films", "movies", "watchlist"],
|
|
228
|
+
"layout": {
|
|
229
|
+
"folder": "datanotes/main/public/film",
|
|
230
|
+
"row_folder": "datanotes/main/public/film",
|
|
231
|
+
"archive": "datanotes/main/public/film/_archive"
|
|
232
|
+
},
|
|
233
|
+
"options": { "filename": "{title}", "archive": "_archive" },
|
|
234
|
+
"columns": [
|
|
235
|
+
{
|
|
236
|
+
"name": "id",
|
|
237
|
+
"type": "string",
|
|
238
|
+
"required": true,
|
|
239
|
+
"aliases": [],
|
|
240
|
+
"unique": true,
|
|
241
|
+
"description": "Unique id of the row (UUIDv7): set when the row is created, never changes",
|
|
242
|
+
"identity": "uuid",
|
|
243
|
+
"dense": true
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
"name": "title",
|
|
247
|
+
"type": "string",
|
|
248
|
+
"required": true,
|
|
249
|
+
"aliases": [],
|
|
250
|
+
"unique": true,
|
|
251
|
+
"description": "The film's title, as on its poster",
|
|
252
|
+
"dense": false
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"name": "year",
|
|
256
|
+
"type": "integer",
|
|
257
|
+
"required": false,
|
|
258
|
+
"aliases": [],
|
|
259
|
+
"description": "Year the film first came out",
|
|
260
|
+
"dense": false
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"name": "minutes",
|
|
264
|
+
"type": "integer",
|
|
265
|
+
"required": false,
|
|
266
|
+
"min": 1,
|
|
267
|
+
"aliases": [],
|
|
268
|
+
"description": "Running time in minutes",
|
|
269
|
+
"dense": false
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"name": "status",
|
|
273
|
+
"type": "enum",
|
|
274
|
+
"required": false,
|
|
275
|
+
"values": ["to watch", "watched"],
|
|
276
|
+
"aliases": [],
|
|
277
|
+
"ordered": true,
|
|
278
|
+
"description": "Where the film is on my list",
|
|
279
|
+
"default": "to watch",
|
|
280
|
+
"dense": false
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
"name": "rating",
|
|
284
|
+
"type": "integer",
|
|
285
|
+
"required": false,
|
|
286
|
+
"min": 1,
|
|
287
|
+
"max": 5,
|
|
288
|
+
"aliases": [],
|
|
289
|
+
"description": "My rating, from 1 (poor) to 5 (a masterpiece)",
|
|
290
|
+
"dense": false
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"name": "watched_on",
|
|
294
|
+
"type": "date",
|
|
295
|
+
"required": false,
|
|
296
|
+
"aliases": [],
|
|
297
|
+
"description": "The day I last watched it",
|
|
298
|
+
"dense": false
|
|
299
|
+
}
|
|
300
|
+
],
|
|
301
|
+
"untyped_fields": ["table"],
|
|
302
|
+
"row_count": 0
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Add fixed front matter keys, a note template and tags
|
|
307
|
+
|
|
308
|
+
`create_table` takes three more arguments:
|
|
309
|
+
|
|
310
|
+
* **`fields`**: front matter keys every new row gets with a fixed value and no checks, such as `cssclasses`, which styles the notes in Obsidian
|
|
311
|
+
* **`row_template`**: the text of every new row’s note, with `{column}` placeholders
|
|
312
|
+
* **`tags`**: key/value labels for the table, which `list_tables` and `describe_table` return
|
|
313
|
+
|
|
314
|
+
**`create_table`**
|
|
315
|
+
|
|
316
|
+
```json
|
|
317
|
+
{
|
|
318
|
+
"name": "watch",
|
|
319
|
+
"description": "Each time I watch a film",
|
|
320
|
+
"columns": [
|
|
321
|
+
{
|
|
322
|
+
"name": "film",
|
|
323
|
+
"type": "string",
|
|
324
|
+
"required": true,
|
|
325
|
+
"description": "The film I watched"
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"name": "where",
|
|
329
|
+
"type": "enum",
|
|
330
|
+
"values": ["cinema", "home", "outdoor screening"],
|
|
331
|
+
"required": true,
|
|
332
|
+
"description": "The kind of place I watched it in"
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
"name": "place",
|
|
336
|
+
"type": "string",
|
|
337
|
+
"description": "The cinema, park or room, in my words"
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"name": "occurred_at",
|
|
341
|
+
"type": "datetime",
|
|
342
|
+
"default": "{now}",
|
|
343
|
+
"description": "When the film started"
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
"name": "price",
|
|
347
|
+
"type": "number",
|
|
348
|
+
"min": 0,
|
|
349
|
+
"step": 0.01,
|
|
350
|
+
"description": "What the ticket cost, if anything"
|
|
351
|
+
}
|
|
352
|
+
],
|
|
353
|
+
"filename": "{occurred_at:YYYY-MM-DD} {film}",
|
|
354
|
+
"fields": { "cssclasses": ["watch"] },
|
|
355
|
+
"row_template": "Watched {film} ({where}).\n\n## Thoughts\n",
|
|
356
|
+
"tags": { "area": "films" }
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
**`insert_row`**
|
|
361
|
+
|
|
362
|
+
```json
|
|
363
|
+
{
|
|
364
|
+
"table": "watch",
|
|
365
|
+
"values": {
|
|
366
|
+
"film": "Nosferatu",
|
|
367
|
+
"where": "outdoor screening",
|
|
368
|
+
"place": "the park by the river"
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
Answer:
|
|
374
|
+
|
|
375
|
+
```json
|
|
376
|
+
{
|
|
377
|
+
"ok": true,
|
|
378
|
+
"op": "insert_row",
|
|
379
|
+
"files_created": 1,
|
|
380
|
+
"planned_creates": ["datanotes/main/public/watch/2026-10-12 Nosferatu.md"],
|
|
381
|
+
"commits": [{ "table": "main.public.watch", "version": 1, "operation": "WRITE" }],
|
|
382
|
+
"migration_id": "20261012T071946-insert_row-insert-into-watch"
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
`datanotes/main/public/watch/2026-10-12 Nosferatu.md` now reads:
|
|
387
|
+
|
|
388
|
+
```markdown
|
|
389
|
+
---
|
|
390
|
+
table: main.public.watch
|
|
391
|
+
cssclasses:
|
|
392
|
+
- watch
|
|
393
|
+
id: 01a12efb-596f-7f8d-a613-98700dbd6bde
|
|
394
|
+
film: Nosferatu
|
|
395
|
+
where: outdoor screening
|
|
396
|
+
place: the park by the river
|
|
397
|
+
occurred_at: 2026-10-12T07:19:46Z
|
|
398
|
+
---
|
|
399
|
+
Watched Nosferatu (outdoor screening).
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
## Thoughts
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## Set a table’s options when you create it
|
|
406
|
+
|
|
407
|
+
`create_table` also takes the options that `alter_table` changes later. Two of them:
|
|
408
|
+
|
|
409
|
+
* **`exclude`**: folders whose notes never become rows, such as an editor’s templates
|
|
410
|
+
* **`history`**: `true` keeps every version of the table, whatever the database’s setting
|
|
411
|
+
|
|
412
|
+
**`create_table`**
|
|
413
|
+
|
|
414
|
+
```json
|
|
415
|
+
{
|
|
416
|
+
"name": "review",
|
|
417
|
+
"description": "What I wrote about a film after watching it",
|
|
418
|
+
"columns": [
|
|
419
|
+
{
|
|
420
|
+
"name": "film",
|
|
421
|
+
"type": "string",
|
|
422
|
+
"required": true,
|
|
423
|
+
"unique": true,
|
|
424
|
+
"description": "The film the review is about"
|
|
425
|
+
},
|
|
426
|
+
{ "name": "verdict", "type": "string", "description": "The review in one sentence" }
|
|
427
|
+
],
|
|
428
|
+
"filename": "{film}",
|
|
429
|
+
"exclude": ["datanotes/main/public/review/Templates"],
|
|
430
|
+
"history": true
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
Answer:
|
|
435
|
+
|
|
436
|
+
```json
|
|
437
|
+
{ "ok": true, "summary": null }
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
[Keep a folder’s notes out of the table](https://datanotes.dev/guides/read-and-write/import-notes/#keep-a-folders-notes-out-of-the-table-with-exclude) and [Table history and time travel](https://datanotes.dev/guides/history/table-history/) show both at work.
|
|
441
|
+
|
|
442
|
+
## Rename or move a table
|
|
443
|
+
|
|
444
|
+
`alter_table` renames a table with `name`, or moves it to another `catalog` or `schema`. Here `actors` becomes `actor`, singular like the other tables. The rows’ folder and their front matter key `table` follow, and the engine rewrites the links to them. `dry_run` lists the notes that would move.
|
|
445
|
+
|
|
446
|
+
**`alter_table`**
|
|
447
|
+
|
|
448
|
+
```json
|
|
449
|
+
{ "table": "classics.actors", "name": "actor", "dry_run": true }
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
Answer:
|
|
453
|
+
|
|
454
|
+
```json
|
|
455
|
+
{
|
|
456
|
+
"ok": true,
|
|
457
|
+
"op": "alter_table",
|
|
458
|
+
"dry_run": true,
|
|
459
|
+
"planned_edits": [
|
|
460
|
+
{
|
|
461
|
+
"path": "datanotes/diary/classics/actors/Max Schreck.md",
|
|
462
|
+
"set": { "table": "diary.classics.actor" },
|
|
463
|
+
"remove": []
|
|
464
|
+
}
|
|
465
|
+
],
|
|
466
|
+
"planned_moves": [
|
|
467
|
+
{
|
|
468
|
+
"from": "store:transaction_log/diary.classics.actors/00000000000000000000.json",
|
|
469
|
+
"to": "store:transaction_log/diary.classics.actor/00000000000000000000.json"
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
"from": "store:transaction_log/diary.classics.actors/00000000000000000001.json",
|
|
473
|
+
"to": "store:transaction_log/diary.classics.actor/00000000000000000001.json"
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
"from": "store:transaction_log/diary.classics.actors/00000000000000000002.json",
|
|
477
|
+
"to": "store:transaction_log/diary.classics.actor/00000000000000000002.json"
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
"from": "store:transaction_log/diary.classics.actors/00000000000000000003.json",
|
|
481
|
+
"to": "store:transaction_log/diary.classics.actor/00000000000000000003.json"
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
"from": "store:transaction_log/diary.classics.actors/00000000000000000004.json",
|
|
485
|
+
"to": "store:transaction_log/diary.classics.actor/00000000000000000004.json"
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
"from": "store:transaction_log/diary.classics.actors/00000000000000000005.json",
|
|
489
|
+
"to": "store:transaction_log/diary.classics.actor/00000000000000000005.json"
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
"from": "datanotes/diary/classics/actors/Max Schreck.md",
|
|
493
|
+
"to": "datanotes/diary/classics/actor/Max Schreck.md"
|
|
494
|
+
}
|
|
495
|
+
],
|
|
496
|
+
"planned_texts": ["datanotes/metastore.yaml"]
|
|
497
|
+
}
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
**`alter_table`**
|
|
501
|
+
|
|
502
|
+
```json
|
|
503
|
+
{ "table": "classics.actors", "name": "actor" }
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
Answer (48 lines)
|
|
507
|
+
|
|
508
|
+
```json
|
|
509
|
+
{
|
|
510
|
+
"ok": true,
|
|
511
|
+
"op": "alter_table",
|
|
512
|
+
"notes_changed": 1,
|
|
513
|
+
"files_moved": 7,
|
|
514
|
+
"planned_edits": [
|
|
515
|
+
{
|
|
516
|
+
"path": "datanotes/diary/classics/actors/Max Schreck.md",
|
|
517
|
+
"set": { "table": "diary.classics.actor" },
|
|
518
|
+
"remove": []
|
|
519
|
+
}
|
|
520
|
+
],
|
|
521
|
+
"planned_moves": [
|
|
522
|
+
{
|
|
523
|
+
"from": "store:transaction_log/diary.classics.actors/00000000000000000000.json",
|
|
524
|
+
"to": "store:transaction_log/diary.classics.actor/00000000000000000000.json"
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
"from": "store:transaction_log/diary.classics.actors/00000000000000000001.json",
|
|
528
|
+
"to": "store:transaction_log/diary.classics.actor/00000000000000000001.json"
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
"from": "store:transaction_log/diary.classics.actors/00000000000000000002.json",
|
|
532
|
+
"to": "store:transaction_log/diary.classics.actor/00000000000000000002.json"
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
"from": "store:transaction_log/diary.classics.actors/00000000000000000003.json",
|
|
536
|
+
"to": "store:transaction_log/diary.classics.actor/00000000000000000003.json"
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
"from": "store:transaction_log/diary.classics.actors/00000000000000000004.json",
|
|
540
|
+
"to": "store:transaction_log/diary.classics.actor/00000000000000000004.json"
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
"from": "store:transaction_log/diary.classics.actors/00000000000000000005.json",
|
|
544
|
+
"to": "store:transaction_log/diary.classics.actor/00000000000000000005.json"
|
|
545
|
+
},
|
|
546
|
+
{
|
|
547
|
+
"from": "datanotes/diary/classics/actors/Max Schreck.md",
|
|
548
|
+
"to": "datanotes/diary/classics/actor/Max Schreck.md"
|
|
549
|
+
}
|
|
550
|
+
],
|
|
551
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
552
|
+
"commits": [
|
|
553
|
+
{ "table": "diary.classics.actor", "version": 6, "operation": "ALTER TABLE" }
|
|
554
|
+
],
|
|
555
|
+
"migration_id": "20261012T072004-alter_table-move-table-diary-classics-acto"
|
|
556
|
+
}
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
Then move it to a schema of its own:
|
|
560
|
+
|
|
561
|
+
**`alter_table`**
|
|
562
|
+
|
|
563
|
+
```json
|
|
564
|
+
{ "table": "classics.actor", "catalog": "diary", "schema": "credits" }
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
Answer (52 lines)
|
|
568
|
+
|
|
569
|
+
```json
|
|
570
|
+
{
|
|
571
|
+
"ok": true,
|
|
572
|
+
"op": "alter_table",
|
|
573
|
+
"notes_changed": 1,
|
|
574
|
+
"files_moved": 8,
|
|
575
|
+
"planned_edits": [
|
|
576
|
+
{
|
|
577
|
+
"path": "datanotes/diary/classics/actor/Max Schreck.md",
|
|
578
|
+
"set": { "table": "diary.credits.actor" },
|
|
579
|
+
"remove": []
|
|
580
|
+
}
|
|
581
|
+
],
|
|
582
|
+
"planned_moves": [
|
|
583
|
+
{
|
|
584
|
+
"from": "store:transaction_log/diary.classics.actor/00000000000000000000.json",
|
|
585
|
+
"to": "store:transaction_log/diary.credits.actor/00000000000000000000.json"
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
"from": "store:transaction_log/diary.classics.actor/00000000000000000001.json",
|
|
589
|
+
"to": "store:transaction_log/diary.credits.actor/00000000000000000001.json"
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
"from": "store:transaction_log/diary.classics.actor/00000000000000000002.json",
|
|
593
|
+
"to": "store:transaction_log/diary.credits.actor/00000000000000000002.json"
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
"from": "store:transaction_log/diary.classics.actor/00000000000000000003.json",
|
|
597
|
+
"to": "store:transaction_log/diary.credits.actor/00000000000000000003.json"
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
"from": "store:transaction_log/diary.classics.actor/00000000000000000004.json",
|
|
601
|
+
"to": "store:transaction_log/diary.credits.actor/00000000000000000004.json"
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
"from": "store:transaction_log/diary.classics.actor/00000000000000000005.json",
|
|
605
|
+
"to": "store:transaction_log/diary.credits.actor/00000000000000000005.json"
|
|
606
|
+
},
|
|
607
|
+
{
|
|
608
|
+
"from": "store:transaction_log/diary.classics.actor/00000000000000000006.json",
|
|
609
|
+
"to": "store:transaction_log/diary.credits.actor/00000000000000000006.json"
|
|
610
|
+
},
|
|
611
|
+
{
|
|
612
|
+
"from": "datanotes/diary/classics/actor/Max Schreck.md",
|
|
613
|
+
"to": "datanotes/diary/credits/actor/Max Schreck.md"
|
|
614
|
+
}
|
|
615
|
+
],
|
|
616
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
617
|
+
"commits": [
|
|
618
|
+
{ "table": "diary.credits.actor", "version": 7, "operation": "ALTER TABLE" }
|
|
619
|
+
],
|
|
620
|
+
"migration_id": "20261012T072004-alter_table-move-table-diary-classics-acto-2"
|
|
621
|
+
}
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
**`list_folder`**
|
|
625
|
+
|
|
626
|
+
```json
|
|
627
|
+
{ "folder": "datanotes/diary/credits/actor" }
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
Answer:
|
|
631
|
+
|
|
632
|
+
```json
|
|
633
|
+
{
|
|
634
|
+
"folder": "datanotes/diary/credits/actor",
|
|
635
|
+
"folders": [],
|
|
636
|
+
"files": ["datanotes/diary/credits/actor/Max Schreck.md"]
|
|
637
|
+
}
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
## Change sub-folders and file names
|
|
641
|
+
|
|
642
|
+
`alter_table` also changes `partition`, the sub-folders, and `filename`, the name pattern. The engine renames every row to fit, and refuses the change when a row can’t fill the pattern.
|
|
643
|
+
|
|
644
|
+
**`insert_row`**
|
|
645
|
+
|
|
646
|
+
```json
|
|
647
|
+
{
|
|
648
|
+
"table": "film",
|
|
649
|
+
"values": { "title": "Metropolis", "year": 1927, "minutes": 153, "status": "to watch" }
|
|
650
|
+
}
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
**`alter_table`**
|
|
654
|
+
|
|
655
|
+
```json
|
|
656
|
+
{ "table": "film", "partition": "{year}" }
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
Answer:
|
|
660
|
+
|
|
661
|
+
```json
|
|
662
|
+
{
|
|
663
|
+
"ok": true,
|
|
664
|
+
"op": "alter_table",
|
|
665
|
+
"files_moved": 3,
|
|
666
|
+
"planned_moves": [
|
|
667
|
+
{
|
|
668
|
+
"from": "datanotes/diary/classics/film/His Girl Friday.md",
|
|
669
|
+
"to": "datanotes/diary/classics/film/1940/His Girl Friday.md"
|
|
670
|
+
},
|
|
671
|
+
{
|
|
672
|
+
"from": "datanotes/diary/classics/film/Metropolis.md",
|
|
673
|
+
"to": "datanotes/diary/classics/film/1927/Metropolis.md"
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
"from": "datanotes/diary/classics/film/Nosferatu.md",
|
|
677
|
+
"to": "datanotes/diary/classics/film/1922/Nosferatu.md"
|
|
678
|
+
}
|
|
679
|
+
],
|
|
680
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
681
|
+
"commits": [
|
|
682
|
+
{ "table": "diary.classics.film", "version": 13, "operation": "ALTER TABLE" }
|
|
683
|
+
],
|
|
684
|
+
"migration_id": "20261012T072004-alter_table-alter-table-diary-classics-fil"
|
|
685
|
+
}
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
Metropolis has no `rating` yet, so the engine refuses a name with `{rating}`:
|
|
689
|
+
|
|
690
|
+
**`alter_table`**
|
|
691
|
+
|
|
692
|
+
```json
|
|
693
|
+
{ "table": "film", "filename": "{title} ({rating} stars)" }
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
Refused:
|
|
697
|
+
|
|
698
|
+
```text
|
|
699
|
+
alter_table refused — nothing was written:
|
|
700
|
+
conflict datanotes/diary/classics/film/1927/Metropolis.md: cannot compute the new path: path placeholder {rating} has no value
|
|
701
|
+
Hint: Resolve what the message names, then call alter_table again; dry_run: true checks without writing.
|
|
702
|
+
Docs: https://datanotes.dev/guides/agents/reading-errors.md (offline: read_docs("guides/agents/reading-errors"))
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
**`alter_table`**
|
|
706
|
+
|
|
707
|
+
```json
|
|
708
|
+
{ "table": "film", "filename": "{title} ({year})" }
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
Answer:
|
|
712
|
+
|
|
713
|
+
```json
|
|
714
|
+
{
|
|
715
|
+
"ok": true,
|
|
716
|
+
"op": "alter_table",
|
|
717
|
+
"files_moved": 3,
|
|
718
|
+
"planned_moves": [
|
|
719
|
+
{
|
|
720
|
+
"from": "datanotes/diary/classics/film/1922/Nosferatu.md",
|
|
721
|
+
"to": "datanotes/diary/classics/film/1922/Nosferatu (1922).md"
|
|
722
|
+
},
|
|
723
|
+
{
|
|
724
|
+
"from": "datanotes/diary/classics/film/1927/Metropolis.md",
|
|
725
|
+
"to": "datanotes/diary/classics/film/1927/Metropolis (1927).md"
|
|
726
|
+
},
|
|
727
|
+
{
|
|
728
|
+
"from": "datanotes/diary/classics/film/1940/His Girl Friday.md",
|
|
729
|
+
"to": "datanotes/diary/classics/film/1940/His Girl Friday (1940).md"
|
|
730
|
+
}
|
|
731
|
+
],
|
|
732
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
733
|
+
"commits": [
|
|
734
|
+
{ "table": "diary.classics.film", "version": 14, "operation": "ALTER TABLE" }
|
|
735
|
+
],
|
|
736
|
+
"migration_id": "20261012T072004-alter_table-alter-table-diary-classics-fil-2"
|
|
737
|
+
}
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
**`list_folder`**
|
|
741
|
+
|
|
742
|
+
```json
|
|
743
|
+
{ "folder": "datanotes/diary/classics/film/1940" }
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
Answer:
|
|
747
|
+
|
|
748
|
+
```json
|
|
749
|
+
{
|
|
750
|
+
"folder": "datanotes/diary/classics/film/1940",
|
|
751
|
+
"folders": [],
|
|
752
|
+
"files": ["datanotes/diary/classics/film/1940/His Girl Friday (1940).md"]
|
|
753
|
+
}
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
## Set the archive folder and untyped fields
|
|
757
|
+
|
|
758
|
+
`archive` names the folder, inside the table’s folder, that archived rows go to, and rows already archived move with it. `archive: ""` goes back to the database’s `archive_folder`. `fields` sets untyped fields that every new row gets, as names and values like in `create_table`, and a `null` value removes one.
|
|
759
|
+
|
|
760
|
+
A change that touches only metadata, meaning fields, tags, description, history or the template, rewrites the definition alone and moves no row.
|
|
761
|
+
|
|
762
|
+
**`alter_table`**
|
|
763
|
+
|
|
764
|
+
```json
|
|
765
|
+
{ "table": "film", "archive": "_done" }
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
Answer:
|
|
769
|
+
|
|
770
|
+
```json
|
|
771
|
+
{
|
|
772
|
+
"ok": true,
|
|
773
|
+
"op": "alter_table",
|
|
774
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
775
|
+
"commits": [
|
|
776
|
+
{ "table": "diary.classics.film", "version": 15, "operation": "ALTER TABLE" }
|
|
777
|
+
],
|
|
778
|
+
"migration_id": "20261012T072004-alter_table-alter-table-diary-classics-fil-3"
|
|
779
|
+
}
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
**`alter_table`**
|
|
783
|
+
|
|
784
|
+
```json
|
|
785
|
+
{ "table": "film", "fields": { "cut": "restored", "subtitles": "off" } }
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
Answer:
|
|
789
|
+
|
|
790
|
+
```json
|
|
791
|
+
{
|
|
792
|
+
"ok": true,
|
|
793
|
+
"op": "alter_table",
|
|
794
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
795
|
+
"commits": [
|
|
796
|
+
{ "table": "diary.classics.film", "version": 16, "operation": "ALTER TABLE" }
|
|
797
|
+
],
|
|
798
|
+
"migration_id": "20261012T072004-alter_table-alter-table-diary-classics-fil-4"
|
|
799
|
+
}
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
**`alter_table`**
|
|
803
|
+
|
|
804
|
+
```json
|
|
805
|
+
{ "table": "film", "fields": { "subtitles": null } }
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
Answer:
|
|
809
|
+
|
|
810
|
+
```json
|
|
811
|
+
{
|
|
812
|
+
"ok": true,
|
|
813
|
+
"op": "alter_table",
|
|
814
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
815
|
+
"commits": [
|
|
816
|
+
{ "table": "diary.classics.film", "version": 17, "operation": "ALTER TABLE" }
|
|
817
|
+
],
|
|
818
|
+
"migration_id": "20261012T072004-alter_table-alter-table-diary-classics-fil-5"
|
|
819
|
+
}
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
**`insert_row`**
|
|
823
|
+
|
|
824
|
+
```json
|
|
825
|
+
{
|
|
826
|
+
"table": "film",
|
|
827
|
+
"values": {
|
|
828
|
+
"title": "Battleship Potemkin",
|
|
829
|
+
"year": 1925,
|
|
830
|
+
"minutes": 75,
|
|
831
|
+
"status": "to watch"
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
Answer:
|
|
837
|
+
|
|
838
|
+
```json
|
|
839
|
+
{
|
|
840
|
+
"ok": true,
|
|
841
|
+
"op": "insert_row",
|
|
842
|
+
"files_created": 1,
|
|
843
|
+
"planned_creates": ["datanotes/diary/classics/film/1925/Battleship Potemkin (1925).md"],
|
|
844
|
+
"commits": [{ "table": "diary.classics.film", "version": 18, "operation": "WRITE" }],
|
|
845
|
+
"migration_id": "20261012T072004-insert_row-insert-into-film-3"
|
|
846
|
+
}
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
`datanotes/diary/classics/film/1925/Battleship Potemkin (1925).md` now reads:
|
|
850
|
+
|
|
851
|
+
```markdown
|
|
852
|
+
---
|
|
853
|
+
table: diary.classics.film
|
|
854
|
+
cut: restored
|
|
855
|
+
id: 01a12efb-9da0-70b8-9f73-bb00b210e05f
|
|
856
|
+
title: Battleship Potemkin
|
|
857
|
+
year: 1925
|
|
858
|
+
minutes: 75
|
|
859
|
+
status: to watch
|
|
860
|
+
---
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
## Give new notes a template
|
|
864
|
+
|
|
865
|
+
`row_template`, in `create_table` and `alter_table`, is the text of every new row’s note, with `{column}` placeholders. Notes you create by hand in the table’s folder get it too.
|
|
866
|
+
|
|
867
|
+
**`alter_table`**
|
|
868
|
+
|
|
869
|
+
```json
|
|
870
|
+
{
|
|
871
|
+
"table": "film",
|
|
872
|
+
"row_template": "# {title} ({year})\n\n## What I liked\n\n## Who I watched it with\n"
|
|
873
|
+
}
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
Answer:
|
|
877
|
+
|
|
878
|
+
```json
|
|
879
|
+
{
|
|
880
|
+
"ok": true,
|
|
881
|
+
"op": "alter_table",
|
|
882
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
883
|
+
"commits": [
|
|
884
|
+
{ "table": "diary.classics.film", "version": 19, "operation": "ALTER TABLE" }
|
|
885
|
+
],
|
|
886
|
+
"migration_id": "20261012T072004-alter_table-alter-table-diary-classics-fil-6"
|
|
887
|
+
}
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
**`insert_row`**
|
|
891
|
+
|
|
892
|
+
```json
|
|
893
|
+
{
|
|
894
|
+
"table": "film",
|
|
895
|
+
"values": { "title": "Sherlock Jr.", "year": 1924, "minutes": 45, "status": "to watch" }
|
|
896
|
+
}
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
Answer:
|
|
900
|
+
|
|
901
|
+
```json
|
|
902
|
+
{
|
|
903
|
+
"ok": true,
|
|
904
|
+
"op": "insert_row",
|
|
905
|
+
"files_created": 1,
|
|
906
|
+
"planned_creates": ["datanotes/diary/classics/film/1924/Sherlock Jr. (1924).md"],
|
|
907
|
+
"commits": [{ "table": "diary.classics.film", "version": 20, "operation": "WRITE" }],
|
|
908
|
+
"migration_id": "20261012T072004-insert_row-insert-into-film-4"
|
|
909
|
+
}
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
`datanotes/diary/classics/film/1924/Sherlock Jr. (1924).md` now reads:
|
|
913
|
+
|
|
914
|
+
```markdown
|
|
915
|
+
---
|
|
916
|
+
table: diary.classics.film
|
|
917
|
+
cut: restored
|
|
918
|
+
id: 01a12efb-9dba-741f-a279-de88358083ce
|
|
919
|
+
title: Sherlock Jr.
|
|
920
|
+
year: 1924
|
|
921
|
+
minutes: 45
|
|
922
|
+
status: to watch
|
|
923
|
+
---
|
|
924
|
+
# Sherlock Jr. (1924)
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
## What I liked
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
## Who I watched it with
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
`row_template: ""` removes the template, and notes already written keep their text:
|
|
934
|
+
|
|
935
|
+
**`alter_table`**
|
|
936
|
+
|
|
937
|
+
```json
|
|
938
|
+
{ "table": "film", "row_template": "" }
|
|
939
|
+
```
|
|
940
|
+
|
|
941
|
+
Answer:
|
|
942
|
+
|
|
943
|
+
```json
|
|
944
|
+
{
|
|
945
|
+
"ok": true,
|
|
946
|
+
"op": "alter_table",
|
|
947
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
948
|
+
"commits": [
|
|
949
|
+
{ "table": "diary.classics.film", "version": 21, "operation": "ALTER TABLE" }
|
|
950
|
+
],
|
|
951
|
+
"migration_id": "20261012T072004-alter_table-alter-table-diary-classics-fil-7"
|
|
952
|
+
}
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
## Set defaults for new tables
|
|
956
|
+
|
|
957
|
+
The other settings shape the tables you create next:
|
|
958
|
+
|
|
959
|
+
* **`default_schema`**, with `default_catalog`: places a table given only a name
|
|
960
|
+
* **`default_partition`**: the sub-folders of a table with a `time_column`, as a date format
|
|
961
|
+
* **`default_filename`**: the file names of a table with a `time_column`, as a date format
|
|
962
|
+
* **`archive_folder`**: the name of a new table’s archive folder
|
|
963
|
+
|
|
964
|
+
Existing tables keep their settings.
|
|
965
|
+
|
|
966
|
+
**`configure_database`**
|
|
967
|
+
|
|
968
|
+
```json
|
|
969
|
+
{
|
|
970
|
+
"default_schema": "log",
|
|
971
|
+
"default_partition": "YYYY/MM",
|
|
972
|
+
"default_filename": "YYYY-MM-DD HHmm",
|
|
973
|
+
"archive_folder": "_old"
|
|
974
|
+
}
|
|
975
|
+
```
|
|
976
|
+
|
|
977
|
+
Answer:
|
|
978
|
+
|
|
979
|
+
```json
|
|
980
|
+
{
|
|
981
|
+
"default_catalog": "diary",
|
|
982
|
+
"default_schema": "log",
|
|
983
|
+
"default_partition": "YYYY/MM",
|
|
984
|
+
"default_filename": "YYYY-MM-DD HHmm",
|
|
985
|
+
"archive_folder": "_old",
|
|
986
|
+
"timezone": "Europe/Rome",
|
|
987
|
+
"history": true,
|
|
988
|
+
"autolink": true
|
|
989
|
+
}
|
|
990
|
+
```
|
|
991
|
+
|
|
992
|
+
**`create_table`**
|
|
993
|
+
|
|
994
|
+
```json
|
|
995
|
+
{
|
|
996
|
+
"name": "watch",
|
|
997
|
+
"description": "Each time I watch a film",
|
|
998
|
+
"columns": [
|
|
999
|
+
{
|
|
1000
|
+
"name": "film",
|
|
1001
|
+
"type": "link",
|
|
1002
|
+
"ref": "diary.classics.film",
|
|
1003
|
+
"required": true,
|
|
1004
|
+
"description": "The film I watched"
|
|
1005
|
+
},
|
|
1006
|
+
{
|
|
1007
|
+
"name": "occurred_at",
|
|
1008
|
+
"type": "datetime",
|
|
1009
|
+
"required": true,
|
|
1010
|
+
"description": "When the film started"
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
"name": "where",
|
|
1014
|
+
"type": "enum",
|
|
1015
|
+
"values": ["cinema", "home", "outdoor screening"],
|
|
1016
|
+
"description": "The kind of place I watched it in"
|
|
1017
|
+
},
|
|
1018
|
+
{
|
|
1019
|
+
"name": "place",
|
|
1020
|
+
"type": "string",
|
|
1021
|
+
"description": "The cinema, park or room, in my words"
|
|
1022
|
+
}
|
|
1023
|
+
],
|
|
1024
|
+
"time_column": "occurred_at"
|
|
1025
|
+
}
|
|
1026
|
+
```
|
|
1027
|
+
|
|
1028
|
+
Answer:
|
|
1029
|
+
|
|
1030
|
+
```json
|
|
1031
|
+
{
|
|
1032
|
+
"ok": true,
|
|
1033
|
+
"migration_id": "20261012T072004-create_table-create-table-diary-log-watch"
|
|
1034
|
+
}
|
|
1035
|
+
```
|
|
1036
|
+
|
|
1037
|
+
The new table is `diary.log.watch`, and its rows go in sub-folders by year and month. A date-time without an offset gets Rome’s offset:
|
|
1038
|
+
|
|
1039
|
+
**`insert_row`**
|
|
1040
|
+
|
|
1041
|
+
```json
|
|
1042
|
+
{
|
|
1043
|
+
"table": "watch",
|
|
1044
|
+
"values": {
|
|
1045
|
+
"film": "[[Nosferatu (1922)]]",
|
|
1046
|
+
"occurred_at": "2026-10-06T21:30",
|
|
1047
|
+
"where": "outdoor screening",
|
|
1048
|
+
"place": "the park by the river"
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
```
|
|
1052
|
+
|
|
1053
|
+
Answer:
|
|
1054
|
+
|
|
1055
|
+
```json
|
|
1056
|
+
{
|
|
1057
|
+
"ok": true,
|
|
1058
|
+
"op": "insert_row",
|
|
1059
|
+
"files_created": 1,
|
|
1060
|
+
"planned_creates": ["datanotes/diary/log/watch/2026/10/2026-10-06 2130.md"],
|
|
1061
|
+
"commits": [{ "table": "diary.log.watch", "version": 1, "operation": "WRITE" }],
|
|
1062
|
+
"migration_id": "20261012T072004-insert_row-insert-into-watch"
|
|
1063
|
+
}
|
|
1064
|
+
```
|
|
1065
|
+
|
|
1066
|
+
`datanotes/diary/log/watch/2026/10/2026-10-06 2130.md` now reads:
|
|
1067
|
+
|
|
1068
|
+
```markdown
|
|
1069
|
+
---
|
|
1070
|
+
table: diary.log.watch
|
|
1071
|
+
id: 01a12efb-9e05-7ed2-95c8-870d481fea29
|
|
1072
|
+
film: "[[Nosferatu (1922)]]"
|
|
1073
|
+
occurred_at: 2026-10-06T21:30:00+02:00
|
|
1074
|
+
where: outdoor screening
|
|
1075
|
+
place: the park by the river
|
|
1076
|
+
---
|
|
1077
|
+
```
|
|
1078
|
+
|
|
1079
|
+
## Copy a table to try changes
|
|
1080
|
+
|
|
1081
|
+
`clone_table` copies a table’s definition and rows under a new name, as independent copies. It can also copy the table as it was at an earlier version, as [Copy a table as it was](https://datanotes.dev/guides/history/table-history/#copy-a-table-as-it-was) shows. With `copy_rows: false`, it copies only the definition. Use a copy to try something without touching the original.
|
|
1082
|
+
|
|
1083
|
+
**`clone_table`**
|
|
1084
|
+
|
|
1085
|
+
```json
|
|
1086
|
+
{ "source": "diary.classics.film", "target": "sandbox.classics.film_copy" }
|
|
1087
|
+
```
|
|
1088
|
+
|
|
1089
|
+
Answer:
|
|
1090
|
+
|
|
1091
|
+
```json
|
|
1092
|
+
{
|
|
1093
|
+
"ok": true,
|
|
1094
|
+
"op": "clone_table",
|
|
1095
|
+
"files_created": 5,
|
|
1096
|
+
"planned_creates": [
|
|
1097
|
+
"datanotes/sandbox/classics/film_copy/1922/Nosferatu (1922).md",
|
|
1098
|
+
"datanotes/sandbox/classics/film_copy/1924/Sherlock Jr. (1924).md",
|
|
1099
|
+
"datanotes/sandbox/classics/film_copy/1925/Battleship Potemkin (1925).md",
|
|
1100
|
+
"datanotes/sandbox/classics/film_copy/1927/Metropolis (1927).md",
|
|
1101
|
+
"datanotes/sandbox/classics/film_copy/1940/His Girl Friday (1940).md"
|
|
1102
|
+
],
|
|
1103
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
1104
|
+
"commits": [
|
|
1105
|
+
{ "table": "sandbox.classics.film_copy", "version": 0, "operation": "CLONE" }
|
|
1106
|
+
],
|
|
1107
|
+
"migration_id": "20261012T072004-clone_table-clone-diary-classics-film-to-s"
|
|
1108
|
+
}
|
|
1109
|
+
```
|
|
1110
|
+
|
|
1111
|
+
**`select_rows`**
|
|
1112
|
+
|
|
1113
|
+
```json
|
|
1114
|
+
{ "table": "sandbox.classics.film_copy", "columns": ["title", "year"] }
|
|
1115
|
+
```
|
|
1116
|
+
|
|
1117
|
+
Answer:
|
|
1118
|
+
|
|
1119
|
+
```json
|
|
1120
|
+
{
|
|
1121
|
+
"table": "sandbox.classics.film_copy",
|
|
1122
|
+
"total": 5,
|
|
1123
|
+
"rows": [
|
|
1124
|
+
{
|
|
1125
|
+
"path": "datanotes/sandbox/classics/film_copy/1922/Nosferatu (1922).md",
|
|
1126
|
+
"title": "Nosferatu",
|
|
1127
|
+
"year": 1922
|
|
1128
|
+
},
|
|
1129
|
+
{
|
|
1130
|
+
"path": "datanotes/sandbox/classics/film_copy/1924/Sherlock Jr. (1924).md",
|
|
1131
|
+
"title": "Sherlock Jr.",
|
|
1132
|
+
"year": 1924
|
|
1133
|
+
},
|
|
1134
|
+
{
|
|
1135
|
+
"path": "datanotes/sandbox/classics/film_copy/1925/Battleship Potemkin (1925).md",
|
|
1136
|
+
"title": "Battleship Potemkin",
|
|
1137
|
+
"year": 1925
|
|
1138
|
+
},
|
|
1139
|
+
{
|
|
1140
|
+
"path": "datanotes/sandbox/classics/film_copy/1927/Metropolis (1927).md",
|
|
1141
|
+
"title": "Metropolis",
|
|
1142
|
+
"year": 1927
|
|
1143
|
+
},
|
|
1144
|
+
{
|
|
1145
|
+
"path": "datanotes/sandbox/classics/film_copy/1940/His Girl Friday (1940).md",
|
|
1146
|
+
"title": "His Girl Friday",
|
|
1147
|
+
"year": 1940
|
|
1148
|
+
}
|
|
1149
|
+
]
|
|
1150
|
+
}
|
|
1151
|
+
```
|
|
1152
|
+
|
|
1153
|
+
**`clone_table`**
|
|
1154
|
+
|
|
1155
|
+
```json
|
|
1156
|
+
{
|
|
1157
|
+
"source": "diary.classics.film",
|
|
1158
|
+
"target": "sandbox.classics.film_empty",
|
|
1159
|
+
"copy_rows": false
|
|
1160
|
+
}
|
|
1161
|
+
```
|
|
1162
|
+
|
|
1163
|
+
Answer:
|
|
1164
|
+
|
|
1165
|
+
```json
|
|
1166
|
+
{
|
|
1167
|
+
"ok": true,
|
|
1168
|
+
"op": "clone_table",
|
|
1169
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
1170
|
+
"commits": [
|
|
1171
|
+
{ "table": "sandbox.classics.film_empty", "version": 0, "operation": "CLONE" }
|
|
1172
|
+
],
|
|
1173
|
+
"migration_id": "20261012T072004-clone_table-clone-diary-classics-film-to-s-2"
|
|
1174
|
+
}
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
**`describe_table`**
|
|
1178
|
+
|
|
1179
|
+
```json
|
|
1180
|
+
{ "table": "film_empty" }
|
|
1181
|
+
```
|
|
1182
|
+
|
|
1183
|
+
Answer:
|
|
1184
|
+
|
|
1185
|
+
```json
|
|
1186
|
+
{
|
|
1187
|
+
"name": "film_empty",
|
|
1188
|
+
"catalog": "sandbox",
|
|
1189
|
+
"schema": "classics",
|
|
1190
|
+
"rows": 0,
|
|
1191
|
+
"columns": ["id", "added_on", "title", "year", "minutes", "status", "rating"]
|
|
1192
|
+
}
|
|
1193
|
+
```
|
|
1194
|
+
|
|
1195
|
+
## Drop a table and archive its rows
|
|
1196
|
+
|
|
1197
|
+
`drop_table` refuses a table that still has rows. With `mode: "archive"`, it removes the definition and moves the rows to the table’s archive folder. The engine deletes nothing, and you can undo the operation.
|
|
1198
|
+
|
|
1199
|
+
You choose that folder with `archive` when you create the table. It’s a vault path, as here, or a folder name inside the table’s folder (`_archive` by default).
|
|
1200
|
+
|
|
1201
|
+
**`create_table`**
|
|
1202
|
+
|
|
1203
|
+
```json
|
|
1204
|
+
{
|
|
1205
|
+
"name": "scratch",
|
|
1206
|
+
"description": "Throwaway notes for trying things out",
|
|
1207
|
+
"columns": [{ "name": "note", "type": "string", "description": "The note's text" }],
|
|
1208
|
+
"filename": "{note}",
|
|
1209
|
+
"archive": "Archive/scratch"
|
|
1210
|
+
}
|
|
1211
|
+
```
|
|
1212
|
+
|
|
1213
|
+
**`insert_row`**
|
|
1214
|
+
|
|
1215
|
+
```json
|
|
1216
|
+
{ "table": "scratch", "values": { "note": "temporary" } }
|
|
1217
|
+
```
|
|
1218
|
+
|
|
1219
|
+
**`drop_table`**
|
|
1220
|
+
|
|
1221
|
+
```json
|
|
1222
|
+
{ "table": "scratch" }
|
|
1223
|
+
```
|
|
1224
|
+
|
|
1225
|
+
Refused:
|
|
1226
|
+
|
|
1227
|
+
```text
|
|
1228
|
+
drop_table refused — nothing was written:
|
|
1229
|
+
conflict datanotes/metastore.yaml: table has 1 rows; pass mode: "archive" to archive them with the table
|
|
1230
|
+
Hint: Pass mode: "archive" to archive the rows with the table, or delete them first (delete_rows).
|
|
1231
|
+
Docs: https://datanotes.dev/guides/database-objects/tables.md#drop-a-table-and-archive-its-rows (offline: read_docs("guides/database-objects/tables#drop-a-table-and-archive-its-rows"))
|
|
1232
|
+
```
|
|
1233
|
+
|
|
1234
|
+
**`drop_table`**
|
|
1235
|
+
|
|
1236
|
+
```json
|
|
1237
|
+
{ "table": "scratch", "mode": "archive" }
|
|
1238
|
+
```
|
|
1239
|
+
|
|
1240
|
+
Answer:
|
|
1241
|
+
|
|
1242
|
+
```json
|
|
1243
|
+
{
|
|
1244
|
+
"ok": true,
|
|
1245
|
+
"op": "drop_table",
|
|
1246
|
+
"files_moved": 1,
|
|
1247
|
+
"planned_moves": [
|
|
1248
|
+
{
|
|
1249
|
+
"from": "datanotes/main/public/scratch/temporary.md",
|
|
1250
|
+
"to": "Archive/scratch/temporary.md"
|
|
1251
|
+
}
|
|
1252
|
+
],
|
|
1253
|
+
"planned_texts": ["datanotes/metastore.yaml"],
|
|
1254
|
+
"commits": [{ "table": "main.public.scratch", "version": 2, "operation": "DROP TABLE" }],
|
|
1255
|
+
"migration_id": "20261012T071946-drop_table-drop-table-scratch"
|
|
1256
|
+
}
|
|
1257
|
+
```
|
|
1258
|
+
|
|
1259
|
+
**`list_folder`**
|
|
1260
|
+
|
|
1261
|
+
```json
|
|
1262
|
+
{ "folder": "Archive/scratch" }
|
|
1263
|
+
```
|
|
1264
|
+
|
|
1265
|
+
Answer:
|
|
1266
|
+
|
|
1267
|
+
```json
|
|
1268
|
+
{ "folder": "Archive/scratch", "folders": [], "files": ["Archive/scratch/temporary.md"] }
|
|
1269
|
+
```
|
|
1270
|
+
|
|
1271
|
+
## See the tables in `metastore.yaml`
|
|
1272
|
+
|
|
1273
|
+
The engine wrote this file in its own words. It holds `film`, `watch` and `review`, and `scratch` is gone because you dropped it.
|
|
1274
|
+
|
|
1275
|
+
`datanotes/metastore.yaml` now reads:
|
|
1276
|
+
|
|
1277
|
+
```yaml
|
|
1278
|
+
# Metastore (Datanotes): catalogs, schemas, tables, columns, views.
|
|
1279
|
+
id: 01a12efb-589d-722c-bc9b-81ec34e480a4
|
|
1280
|
+
config:
|
|
1281
|
+
history: true
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
catalogs:
|
|
1285
|
+
main:
|
|
1286
|
+
schemas:
|
|
1287
|
+
public:
|
|
1288
|
+
tables:
|
|
1289
|
+
film:
|
|
1290
|
+
description: Classic films I watched or want to watch
|
|
1291
|
+
aliases:
|
|
1292
|
+
- films
|
|
1293
|
+
- movies
|
|
1294
|
+
- watchlist
|
|
1295
|
+
options:
|
|
1296
|
+
filename: "{title}"
|
|
1297
|
+
archive: _archive
|
|
1298
|
+
columns:
|
|
1299
|
+
- name: id
|
|
1300
|
+
type: string
|
|
1301
|
+
required: true
|
|
1302
|
+
description: "Unique id of the row (UUIDv7): set when the row is created, never changes"
|
|
1303
|
+
unique: true
|
|
1304
|
+
identity: uuid
|
|
1305
|
+
dense: true
|
|
1306
|
+
- name: title
|
|
1307
|
+
type: string
|
|
1308
|
+
required: true
|
|
1309
|
+
description: The film's title, as on its poster
|
|
1310
|
+
unique: true
|
|
1311
|
+
- name: year
|
|
1312
|
+
type: integer
|
|
1313
|
+
description: Year the film first came out
|
|
1314
|
+
- name: minutes
|
|
1315
|
+
type: integer
|
|
1316
|
+
min: 1
|
|
1317
|
+
description: Running time in minutes
|
|
1318
|
+
- name: status
|
|
1319
|
+
type: enum
|
|
1320
|
+
default: to watch
|
|
1321
|
+
values:
|
|
1322
|
+
- to watch
|
|
1323
|
+
- watched
|
|
1324
|
+
description: Where the film is on my list
|
|
1325
|
+
ordered: true
|
|
1326
|
+
- name: rating
|
|
1327
|
+
type: integer
|
|
1328
|
+
min: 1
|
|
1329
|
+
max: 5
|
|
1330
|
+
description: My rating, from 1 (poor) to 5 (a masterpiece)
|
|
1331
|
+
- name: watched_on
|
|
1332
|
+
type: date
|
|
1333
|
+
description: The day I last watched it
|
|
1334
|
+
watch:
|
|
1335
|
+
description: Each time I watch a film
|
|
1336
|
+
tags:
|
|
1337
|
+
area: films
|
|
1338
|
+
options:
|
|
1339
|
+
filename: "{occurred_at:YYYY-MM-DD} {film}"
|
|
1340
|
+
archive: _archive
|
|
1341
|
+
fields:
|
|
1342
|
+
cssclasses:
|
|
1343
|
+
- watch
|
|
1344
|
+
columns:
|
|
1345
|
+
- name: id
|
|
1346
|
+
type: string
|
|
1347
|
+
required: true
|
|
1348
|
+
description: "Unique id of the row (UUIDv7): set when the row is created, never changes"
|
|
1349
|
+
unique: true
|
|
1350
|
+
identity: uuid
|
|
1351
|
+
dense: true
|
|
1352
|
+
- name: film
|
|
1353
|
+
type: string
|
|
1354
|
+
required: true
|
|
1355
|
+
description: The film I watched
|
|
1356
|
+
- name: where
|
|
1357
|
+
type: enum
|
|
1358
|
+
required: true
|
|
1359
|
+
values:
|
|
1360
|
+
- cinema
|
|
1361
|
+
- home
|
|
1362
|
+
- outdoor screening
|
|
1363
|
+
description: The kind of place I watched it in
|
|
1364
|
+
- name: place
|
|
1365
|
+
type: string
|
|
1366
|
+
description: The cinema, park or room, in my words
|
|
1367
|
+
- name: occurred_at
|
|
1368
|
+
type: datetime
|
|
1369
|
+
default: "{now}"
|
|
1370
|
+
description: When the film started
|
|
1371
|
+
- name: price
|
|
1372
|
+
type: number
|
|
1373
|
+
min: 0
|
|
1374
|
+
step: 0.01
|
|
1375
|
+
description: What the ticket cost, if anything
|
|
1376
|
+
row_template: |
|
|
1377
|
+
Watched {film} ({where}).
|
|
1378
|
+
|
|
1379
|
+
|
|
1380
|
+
## Thoughts
|
|
1381
|
+
review:
|
|
1382
|
+
description: What I wrote about a film after watching it
|
|
1383
|
+
options:
|
|
1384
|
+
filename: "{film}"
|
|
1385
|
+
archive: _archive
|
|
1386
|
+
exclude: datanotes/main/public/review/Templates
|
|
1387
|
+
history: true
|
|
1388
|
+
columns:
|
|
1389
|
+
- name: id
|
|
1390
|
+
type: string
|
|
1391
|
+
required: true
|
|
1392
|
+
description: "Unique id of the row (UUIDv7): set when the row is created, never changes"
|
|
1393
|
+
unique: true
|
|
1394
|
+
identity: uuid
|
|
1395
|
+
dense: true
|
|
1396
|
+
- name: film
|
|
1397
|
+
type: string
|
|
1398
|
+
required: true
|
|
1399
|
+
description: The film the review is about
|
|
1400
|
+
unique: true
|
|
1401
|
+
- name: verdict
|
|
1402
|
+
type: string
|
|
1403
|
+
description: The review in one sentence
|
|
1404
|
+
```
|