2024-09-18 19:59:25 +00:00
The website schema needs to be discoverable. The `sqlite_schema` table (or the `table_list` pragma) and the `table_info` pragma are essential.
The following facts need to be discoverable:
- The name of each node type.
- The fields in each node type.
- The type of each field in a node.
- The subfields in each field type.
- The type of each subfield in a field.
- Whether a field or subfield is repeated, optional, or single.
- Whether a field has an application-primitive, but non-sqlite-primitive, type, such as datetime.
- Discriminated union fields.
Field types need to be acyclic. *Do they really?*
Field values need to be deleted when the node that contains them is deleted.
If field types are namespaced to a node type, then SQLite schema object naming will get harder.
Maybe just let them be shared.
```
(node blogpost)
(composite-field car)
(node "car review")
(field cars)
(field car)
node:blogpost
field:
(: road-review node)
(: car composite-field)
-- Entity names must be qualified by their type/kind, or there can't be e.g. a node type and field type that share a name.
-- I think qualification is best, because then SQLite will prevent duplicates by the requirement that table names be unique.
(list (: car composite-field))
create table "car:composite-field" (
id integer primary key,
"Make" text not null,
"Model" text not null,
"Year" text not null,
"Test distance" int not null,
"Test date:date" text not null,
);
create table "road review.cars:(list-field (road review:node))" (
"Road review:node" int primary key references "road review:node",
"Car:composite-field" int primary key references "car:composite-field",
);
create table "Road review:node" (
id integer primary key,
"Title" text not null,
"Cars:(list car)"
);
(field car)
(node review)
(list (field car) (node review)) -- If we parameterize each list relation by both the listed field and the containing node or field, then we've basically monomorphized it.
-- However, that won't cut it if a node or field contains multiple lists of the same type. We also need to parameterize list relations by the field name in the containing node or field.
```
```
primitive-field-type := int | text | date |
record-field-type := (record < field-type-name > ((< field-name > < field-type > ) ...))
variant-field-type := (variant < field-type-name > ((< field-name > < field-type > ) ...))
field-type := (field < field-type-name > )
node-type := (node < node-type-name > )
parent-object-type := < field-type > | < node-type >
list := (list < element-type > < parent-object-type > < field-name > )
```
```
(record car)
(id integer)
(make text)
(model text)
(year text)
(test-distance integer)
(test-date date)
(list car)
(node road-review)
(car car)
(node road-review)
(id integer)
(title text)
(cars (list car))
```
```
(node < node-type-name > )
id integer primary key
(< composite-type-name > < field-name > ) < db-type > ...
(list < composite-type-name > )
id
(list-item < composite-type-name > )
list-id references (list < composite-type-name > ) primary key
sequence-number primary key
item-id references (composite-value < composite-type-name > )
(composite-value < composite-type-name > )
id
-- This indirection is so that SQLite will prevent duplicate field type names in table names.
< record | variant > -value-id references (< record | variant > -value < composite-type-name > )
(record-value < composite-type-name > )
id integer primary key
2024-11-01 22:32:02 +00:00
(< composite-type-name > < field-name > ) integer references (composite-value < composite-type-name > ) ...
(primitive < primitive-type-name > < field-name > ) < primitive-type-impl-name > ...
2024-09-18 19:59:25 +00:00
(variant-value < composite-type-name > )
id integer primary key
2024-11-01 22:32:02 +00:00
(< composite-type-name > < field-name > ) integer references (composite-value < composite-type-name > ) ...
(primitive < primitive-type-name > < field-name > ) < primitive-type-impl-name > ...
2024-09-18 19:59:25 +00:00
```