diff --git a/crates/db/migrations/0004_field_definition.sql b/crates/db/migrations/0004_field_definition.sql new file mode 100644 index 0000000..eee46d2 --- /dev/null +++ b/crates/db/migrations/0004_field_definition.sql @@ -0,0 +1,23 @@ +-- Registry of flexible field definitions (the "schema of schemas"). +CREATE TABLE field_definition ( + id UUID PRIMARY KEY, + key TEXT NOT NULL UNIQUE CHECK (key <> ''), + data_type TEXT NOT NULL CHECK (data_type IN + ('text', 'localized_text', 'integer', 'date', 'boolean', 'term', 'authority')), + vocabulary_id UUID REFERENCES vocabulary (id) ON DELETE RESTRICT, + authority_kind TEXT CHECK (authority_kind IN ('person', 'organisation', 'place')), + required BOOLEAN NOT NULL DEFAULT false, + group_key TEXT CHECK (group_key <> ''), + -- A term field must name a vocabulary; any other type must not. + CONSTRAINT term_has_vocabulary CHECK ((data_type = 'term') = (vocabulary_id IS NOT NULL)), + -- authority_kind is only meaningful for authority fields. + CONSTRAINT authority_kind_only_for_authority + CHECK (authority_kind IS NULL OR data_type = 'authority') +); + +CREATE TABLE field_definition_label ( + field_definition_id UUID NOT NULL REFERENCES field_definition (id) ON DELETE CASCADE, + lang TEXT NOT NULL CHECK (lang <> ''), + label TEXT NOT NULL CHECK (label <> ''), + PRIMARY KEY (field_definition_id, lang) +); diff --git a/crates/db/tests/migrate.rs b/crates/db/tests/migrate.rs index 5588e37..680e992 100644 --- a/crates/db/tests/migrate.rs +++ b/crates/db/tests/migrate.rs @@ -53,3 +53,21 @@ async fn migrate_creates_vocabulary_and_authority_tables(pool: PgPool) { ); } } + +#[sqlx::test] +async fn migrate_creates_field_definition_tables(pool: PgPool) { + let db = Db::from_pool(pool); + + for table in ["field_definition", "field_definition_label"] { + let regclass: Option = + sqlx::query_scalar(&format!("SELECT to_regclass('public.{table}')::text")) + .fetch_one(db.pool()) + .await + .unwrap(); + assert_eq!( + regclass.as_deref(), + Some(table), + "table {table} should exist" + ); + } +}