schema_core/config/index_mapping.rs
1use serde::Serialize;
2
3use crate::common::{FieldName, IndexName};
4
5use super::{ContentHash, Mapping};
6
7/// A fully-resolved mapping for one index: every field typed and ready for a
8/// sink to translate into its native mapping format.
9///
10/// A source produces this from the [`IndexSchema`](super::IndexSchema) — using
11/// each field's explicit [`Mapping`] where one is given, and the database's own
12/// column types where it is not. The result has a
13/// concrete type for every field, which is what a sink needs to create the
14/// index up front rather than leaving the destination to guess.
15#[derive(Debug, Clone, Serialize)]
16pub struct IndexMapping {
17 /// The logical index name (the config key) — the pipeline's stable identity.
18 pub index: IndexName,
19 /// Hash of the parsed index schema. A sink that owns a physical index folds
20 /// this into the index's name (e.g. `users_3f2a1b9c`), so a structural
21 /// schema change yields a new name — a fresh index that is re-seeded rather
22 /// than written into the old shape.
23 pub hash: ContentHash,
24 pub fields: Vec<ResolvedField>,
25}
26
27/// One field within an [`IndexMapping`]: the document key it lands under, its
28/// resolved [`Mapping`] (the `mapping_type` is always present), whether the
29/// value can be null, and the fields nested under it for `object` / `nested`
30/// types.
31#[derive(Debug, Clone, Serialize)]
32pub struct ResolvedField {
33 pub name: FieldName,
34 pub mapping: Mapping,
35 /// Whether this field's value can be null in the document. Derived by the
36 /// source while resolving the mapping — the config does not state it, but the
37 /// source knows (a column's `NOT NULL`, a primary key, a `default`, the
38 /// arity of a relation, an aggregate's zero-row behavior). A sink ignores it;
39 /// it exists for consumers that turn the mapping into typed bindings, where
40 /// `nullable` is the difference between `T` and `Option<T>`.
41 pub nullable: bool,
42 #[serde(skip_serializing_if = "Vec::is_empty")]
43 pub children: Vec<ResolvedField>,
44}