#[cfg(any(test, feature = "sql"))]
use crate::db::predicate::relabel_sql_predicate_field_root;
use crate::{
db::schema::{
AcceptedFieldKind, FieldId, SchemaFieldSlot, SchemaRowLayout, SchemaVersion,
schema_snapshot_index_integrity_detail, schema_snapshot_integrity_detail,
schema_snapshot_relation_integrity_detail,
},
error::InternalError,
model::field::{FieldInsertGeneration, FieldStorageDecode, FieldWriteManagement, LeafCodec},
};
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) struct AcceptedSchemaSnapshot {
snapshot: PersistedSchemaSnapshot,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::db) struct AcceptedSchemaFootprint {
fields: u64,
nested_leaf_facts: u64,
}
impl AcceptedSchemaFootprint {
#[must_use]
const fn new(fields: u64, nested_leaf_facts: u64) -> Self {
Self {
fields,
nested_leaf_facts,
}
}
#[must_use]
pub(in crate::db) const fn fields(self) -> u64 {
self.fields
}
#[must_use]
pub(in crate::db) const fn nested_leaf_facts(self) -> u64 {
self.nested_leaf_facts
}
}
impl AcceptedSchemaSnapshot {
pub(in crate::db) fn try_new(snapshot: PersistedSchemaSnapshot) -> Result<Self, InternalError> {
if schema_snapshot_integrity_detail(
"accepted schema snapshot",
snapshot.version(),
snapshot.primary_key_field_ids(),
snapshot.row_layout(),
snapshot.fields(),
)
.is_some()
{
return Err(InternalError::store_invariant());
}
if schema_snapshot_index_integrity_detail(
"accepted schema snapshot",
snapshot.row_layout(),
snapshot.fields(),
snapshot.indexes(),
)
.is_some()
{
return Err(InternalError::store_invariant());
}
if schema_snapshot_relation_integrity_detail(
"accepted schema snapshot",
snapshot.row_layout(),
snapshot.fields(),
snapshot.relations(),
)
.is_some()
{
return Err(InternalError::store_invariant());
}
Ok(Self { snapshot })
}
#[must_use]
#[cfg(test)]
pub(in crate::db) const fn new(snapshot: PersistedSchemaSnapshot) -> Self {
Self { snapshot }
}
#[must_use]
pub(in crate::db) const fn persisted_snapshot(&self) -> &PersistedSchemaSnapshot {
&self.snapshot
}
#[must_use]
pub(in crate::db) const fn entity_path(&self) -> &str {
self.snapshot.entity_path()
}
#[must_use]
pub(in crate::db) const fn entity_name(&self) -> &str {
self.snapshot.entity_name()
}
#[must_use]
fn primary_key_fields(&self) -> Vec<&PersistedFieldSnapshot> {
self.snapshot
.primary_key_field_ids()
.iter()
.filter_map(|field_id| {
self.snapshot
.fields()
.iter()
.find(|field| field.id() == *field_id)
})
.collect()
}
#[must_use]
pub(in crate::db) fn primary_key_field_names(&self) -> Vec<&str> {
self.primary_key_fields()
.iter()
.map(|field| field.name())
.collect()
}
#[must_use]
pub(in crate::db) fn primary_key_field_kinds(&self) -> Vec<&AcceptedFieldKind> {
self.primary_key_fields()
.iter()
.map(|field| field.kind())
.collect()
}
#[must_use]
#[cfg(test)]
fn field_by_name(&self, name: &str) -> Option<&PersistedFieldSnapshot> {
self.snapshot
.fields()
.iter()
.find(|field| field.name() == name)
}
#[must_use]
#[cfg(test)]
pub(in crate::db) fn field_kind_by_name(&self, name: &str) -> Option<&AcceptedFieldKind> {
self.field_by_name(name).map(PersistedFieldSnapshot::kind)
}
#[must_use]
pub(in crate::db) fn footprint(&self) -> AcceptedSchemaFootprint {
let fields = u64::try_from(self.snapshot.fields().len()).unwrap_or(u64::MAX);
let nested_leaf_facts = self
.snapshot
.fields()
.iter()
.map(|field| u64::try_from(field.nested_leaves().len()).unwrap_or(u64::MAX))
.fold(0u64, u64::saturating_add);
AcceptedSchemaFootprint::new(fields, nested_leaf_facts)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) struct PersistedSchemaSnapshot {
version: SchemaVersion,
entity_path: String,
entity_name: String,
primary_key_field_ids: Vec<FieldId>,
row_layout: SchemaRowLayout,
fields: Vec<PersistedFieldSnapshot>,
indexes: Vec<PersistedIndexSnapshot>,
relations: Vec<PersistedRelationEdgeSnapshot>,
}
pub(in crate::db) trait IntoPrimaryKeyFieldIds {
fn into_primary_key_field_ids(self) -> Vec<FieldId>;
}
impl IntoPrimaryKeyFieldIds for FieldId {
fn into_primary_key_field_ids(self) -> Vec<FieldId> {
vec![self]
}
}
impl IntoPrimaryKeyFieldIds for Vec<FieldId> {
fn into_primary_key_field_ids(self) -> Vec<FieldId> {
self
}
}
impl PersistedSchemaSnapshot {
#[must_use]
#[cfg(test)]
pub(in crate::db) fn new(
version: SchemaVersion,
entity_path: String,
entity_name: String,
primary_key_field_ids: impl IntoPrimaryKeyFieldIds,
row_layout: SchemaRowLayout,
fields: Vec<PersistedFieldSnapshot>,
) -> Self {
Self::new_with_primary_key_fields_and_indexes(
version,
entity_path,
entity_name,
primary_key_field_ids.into_primary_key_field_ids(),
row_layout,
fields,
Vec::new(),
)
}
#[must_use]
#[cfg(test)]
pub(in crate::db) fn new_with_indexes(
version: SchemaVersion,
entity_path: String,
entity_name: String,
primary_key_field_ids: impl IntoPrimaryKeyFieldIds,
row_layout: SchemaRowLayout,
fields: Vec<PersistedFieldSnapshot>,
indexes: Vec<PersistedIndexSnapshot>,
) -> Self {
Self::new_with_primary_key_fields_and_indexes(
version,
entity_path,
entity_name,
primary_key_field_ids.into_primary_key_field_ids(),
row_layout,
fields,
indexes,
)
}
#[must_use]
pub(in crate::db) fn new_with_primary_key_fields_and_indexes(
version: SchemaVersion,
entity_path: String,
entity_name: String,
primary_key_field_ids: impl IntoPrimaryKeyFieldIds,
row_layout: SchemaRowLayout,
fields: Vec<PersistedFieldSnapshot>,
indexes: Vec<PersistedIndexSnapshot>,
) -> Self {
Self {
version,
entity_path,
entity_name,
primary_key_field_ids: primary_key_field_ids.into_primary_key_field_ids(),
row_layout,
fields,
indexes,
relations: Vec::new(),
}
}
#[must_use]
pub(in crate::db) fn with_relations(
mut self,
relations: Vec<PersistedRelationEdgeSnapshot>,
) -> Self {
self.relations = relations;
self
}
#[must_use]
pub(in crate::db) const fn version(&self) -> SchemaVersion {
self.version
}
#[must_use]
pub(in crate::db) const fn entity_path(&self) -> &str {
self.entity_path.as_str()
}
#[must_use]
pub(in crate::db) const fn entity_name(&self) -> &str {
self.entity_name.as_str()
}
#[must_use]
pub(in crate::db) fn first_primary_key_field_id(&self) -> FieldId {
self.primary_key_field_ids[0]
}
#[must_use]
pub(in crate::db) const fn primary_key_field_ids(&self) -> &[FieldId] {
self.primary_key_field_ids.as_slice()
}
#[must_use]
pub(in crate::db) const fn row_layout(&self) -> &SchemaRowLayout {
&self.row_layout
}
#[must_use]
pub(in crate::db) const fn fields(&self) -> &[PersistedFieldSnapshot] {
self.fields.as_slice()
}
#[must_use]
pub(in crate::db) const fn indexes(&self) -> &[PersistedIndexSnapshot] {
self.indexes.as_slice()
}
#[must_use]
pub(in crate::db) const fn relations(&self) -> &[PersistedRelationEdgeSnapshot] {
self.relations.as_slice()
}
#[must_use]
#[cfg(any(test, feature = "sql"))]
pub(in crate::db) fn clone_with_version(&self, version: SchemaVersion) -> Self {
Self::new_with_primary_key_fields_and_indexes(
version,
self.entity_path.clone(),
self.entity_name.clone(),
self.primary_key_field_ids.clone(),
self.row_layout.clone_with_version(version),
self.fields.clone(),
self.indexes.clone(),
)
.with_relations(self.relations.clone())
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) struct PersistedRelationEdgeSnapshot {
name: String,
target_path: String,
local_field_ids: Vec<FieldId>,
}
impl PersistedRelationEdgeSnapshot {
#[must_use]
pub(in crate::db) const fn new(
name: String,
target_path: String,
local_field_ids: Vec<FieldId>,
) -> Self {
Self {
name,
target_path,
local_field_ids,
}
}
#[must_use]
pub(in crate::db) const fn name(&self) -> &str {
self.name.as_str()
}
#[must_use]
pub(in crate::db) const fn target_path(&self) -> &str {
self.target_path.as_str()
}
#[must_use]
pub(in crate::db) const fn local_field_ids(&self) -> &[FieldId] {
self.local_field_ids.as_slice()
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) struct PersistedIndexSnapshot {
ordinal: u16,
name: String,
store: String,
unique: bool,
origin: PersistedIndexOrigin,
key: PersistedIndexKeySnapshot,
predicate_sql: Option<String>,
}
impl PersistedIndexSnapshot {
#[must_use]
pub(in crate::db) const fn new(
ordinal: u16,
name: String,
store: String,
unique: bool,
key: PersistedIndexKeySnapshot,
predicate_sql: Option<String>,
) -> Self {
Self::new_with_origin(
ordinal,
name,
store,
unique,
PersistedIndexOrigin::Generated,
key,
predicate_sql,
)
}
#[must_use]
#[cfg(any(test, feature = "sql"))]
pub(in crate::db) const fn new_sql_ddl(
ordinal: u16,
name: String,
store: String,
unique: bool,
key: PersistedIndexKeySnapshot,
predicate_sql: Option<String>,
) -> Self {
Self::new_with_origin(
ordinal,
name,
store,
unique,
PersistedIndexOrigin::SqlDdl,
key,
predicate_sql,
)
}
#[must_use]
pub(in crate::db) const fn new_with_origin(
ordinal: u16,
name: String,
store: String,
unique: bool,
origin: PersistedIndexOrigin,
key: PersistedIndexKeySnapshot,
predicate_sql: Option<String>,
) -> Self {
Self {
ordinal,
name,
store,
unique,
origin,
key,
predicate_sql,
}
}
#[must_use]
pub(in crate::db) const fn ordinal(&self) -> u16 {
self.ordinal
}
#[must_use]
pub(in crate::db) const fn name(&self) -> &str {
self.name.as_str()
}
#[must_use]
pub(in crate::db) const fn store(&self) -> &str {
self.store.as_str()
}
#[must_use]
pub(in crate::db) const fn unique(&self) -> bool {
self.unique
}
#[must_use]
pub(in crate::db) const fn generated(&self) -> bool {
matches!(self.origin, PersistedIndexOrigin::Generated)
}
#[must_use]
pub(in crate::db) const fn origin(&self) -> PersistedIndexOrigin {
self.origin
}
#[must_use]
pub(in crate::db) const fn key(&self) -> &PersistedIndexKeySnapshot {
&self.key
}
#[must_use]
pub(in crate::db) const fn predicate_sql(&self) -> Option<&str> {
match &self.predicate_sql {
Some(sql) => Some(sql.as_str()),
None => None,
}
}
#[cfg(any(test, feature = "sql"))]
#[must_use]
pub(in crate::db) fn clone_with_renamed_field_path_root(
&self,
field_id: FieldId,
old_name: &str,
new_name: &str,
) -> Self {
Self {
ordinal: self.ordinal,
name: self.name.clone(),
store: self.store.clone(),
unique: self.unique,
origin: self.origin,
key: self
.key
.clone_with_renamed_field_path_root(field_id, new_name),
predicate_sql: self.predicate_sql.as_deref().map(|predicate_sql| {
relabel_sql_predicate_field_root(predicate_sql, old_name, new_name)
.unwrap_or_else(|| predicate_sql.to_string())
}),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::db) enum PersistedIndexOrigin {
Generated,
SqlDdl,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) enum PersistedIndexKeySnapshot {
FieldPath(Vec<PersistedIndexFieldPathSnapshot>),
Items(Vec<PersistedIndexKeyItemSnapshot>),
}
impl PersistedIndexKeySnapshot {
#[must_use]
pub(in crate::db) const fn is_field_path_only(&self) -> bool {
matches!(self, Self::FieldPath(_))
}
#[must_use]
pub(in crate::db) const fn field_paths(&self) -> &[PersistedIndexFieldPathSnapshot] {
match self {
Self::FieldPath(paths) => paths.as_slice(),
Self::Items(_) => &[],
}
}
#[must_use]
pub(in crate::db) fn references_field(&self, field_id: FieldId) -> bool {
match self {
Self::FieldPath(paths) => paths.iter().any(|path| path.field_id() == field_id),
Self::Items(items) => items.iter().any(|item| item.references_field(field_id)),
}
}
#[must_use]
#[cfg(any(test, feature = "sql"))]
pub(in crate::db) fn clone_with_renamed_field_path_root(
&self,
field_id: FieldId,
new_name: &str,
) -> Self {
match self {
Self::FieldPath(paths) => Self::FieldPath(
paths
.iter()
.map(|path| path.clone_with_renamed_root(field_id, new_name))
.collect(),
),
Self::Items(items) => Self::Items(
items
.iter()
.map(|item| item.clone_with_renamed_field_path_root(field_id, new_name))
.collect(),
),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) enum PersistedIndexKeyItemSnapshot {
FieldPath(PersistedIndexFieldPathSnapshot),
Expression(Box<PersistedIndexExpressionSnapshot>),
}
impl PersistedIndexKeyItemSnapshot {
#[must_use]
pub(in crate::db) fn references_field(&self, field_id: FieldId) -> bool {
match self {
Self::FieldPath(path) => path.field_id() == field_id,
Self::Expression(expression) => expression.source().field_id() == field_id,
}
}
#[must_use]
#[cfg(any(test, feature = "sql"))]
pub(in crate::db) fn clone_with_renamed_field_path_root(
&self,
field_id: FieldId,
new_name: &str,
) -> Self {
match self {
Self::FieldPath(path) => {
Self::FieldPath(path.clone_with_renamed_root(field_id, new_name))
}
Self::Expression(expression) => Self::Expression(Box::new(
expression.clone_with_renamed_source_root(field_id, new_name),
)),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) struct PersistedIndexFieldPathSnapshot {
field_id: FieldId,
slot: SchemaFieldSlot,
path: Vec<String>,
kind: AcceptedFieldKind,
nullable: bool,
}
impl PersistedIndexFieldPathSnapshot {
#[must_use]
pub(in crate::db) const fn new(
field_id: FieldId,
slot: SchemaFieldSlot,
path: Vec<String>,
kind: AcceptedFieldKind,
nullable: bool,
) -> Self {
Self {
field_id,
slot,
path,
kind,
nullable,
}
}
#[must_use]
pub(in crate::db) const fn field_id(&self) -> FieldId {
self.field_id
}
#[must_use]
pub(in crate::db) const fn slot(&self) -> SchemaFieldSlot {
self.slot
}
#[must_use]
pub(in crate::db) const fn path(&self) -> &[String] {
self.path.as_slice()
}
#[must_use]
pub(in crate::db) const fn kind(&self) -> &AcceptedFieldKind {
&self.kind
}
#[must_use]
pub(in crate::db) const fn nullable(&self) -> bool {
self.nullable
}
#[must_use]
#[cfg(any(test, feature = "sql"))]
pub(in crate::db) fn clone_with_renamed_root(&self, field_id: FieldId, new_name: &str) -> Self {
let mut path = self.path.clone();
if self.field_id == field_id
&& let Some(root) = path.first_mut()
{
*root = new_name.to_string();
}
Self {
field_id: self.field_id,
slot: self.slot,
path,
kind: self.kind.clone(),
nullable: self.nullable,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) struct PersistedIndexExpressionSnapshot {
op: PersistedIndexExpressionOp,
source: PersistedIndexFieldPathSnapshot,
input_kind: AcceptedFieldKind,
output_kind: AcceptedFieldKind,
canonical_text: String,
}
impl PersistedIndexExpressionSnapshot {
#[must_use]
pub(in crate::db) const fn new(
op: PersistedIndexExpressionOp,
source: PersistedIndexFieldPathSnapshot,
input_kind: AcceptedFieldKind,
output_kind: AcceptedFieldKind,
canonical_text: String,
) -> Self {
Self {
op,
source,
input_kind,
output_kind,
canonical_text,
}
}
#[must_use]
pub(in crate::db) const fn op(&self) -> PersistedIndexExpressionOp {
self.op
}
#[must_use]
pub(in crate::db) const fn source(&self) -> &PersistedIndexFieldPathSnapshot {
&self.source
}
#[must_use]
pub(in crate::db) const fn input_kind(&self) -> &AcceptedFieldKind {
&self.input_kind
}
#[must_use]
pub(in crate::db) const fn output_kind(&self) -> &AcceptedFieldKind {
&self.output_kind
}
#[must_use]
pub(in crate::db) const fn canonical_text(&self) -> &str {
self.canonical_text.as_str()
}
#[must_use]
#[cfg(any(test, feature = "sql"))]
pub(in crate::db) fn clone_with_renamed_source_root(
&self,
field_id: FieldId,
new_name: &str,
) -> Self {
let source = self.source.clone_with_renamed_root(field_id, new_name);
let canonical_text = canonical_expression_text_for_path(self.op, source.path());
Self {
op: self.op,
source,
input_kind: self.input_kind.clone(),
output_kind: self.output_kind.clone(),
canonical_text,
}
}
}
#[cfg(any(test, feature = "sql"))]
fn canonical_expression_text_for_path(op: PersistedIndexExpressionOp, path: &[String]) -> String {
let path = path.join(".");
match op {
PersistedIndexExpressionOp::Lower => format!("expr:v1:LOWER({path})"),
PersistedIndexExpressionOp::Upper => format!("expr:v1:UPPER({path})"),
PersistedIndexExpressionOp::Trim => format!("expr:v1:TRIM({path})"),
PersistedIndexExpressionOp::LowerTrim => format!("expr:v1:LOWER(TRIM({path}))"),
PersistedIndexExpressionOp::Date => format!("expr:v1:DATE({path})"),
PersistedIndexExpressionOp::Year => format!("expr:v1:YEAR({path})"),
PersistedIndexExpressionOp::Month => format!("expr:v1:MONTH({path})"),
PersistedIndexExpressionOp::Day => format!("expr:v1:DAY({path})"),
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::db) enum PersistedIndexExpressionOp {
Lower,
Upper,
Trim,
LowerTrim,
Date,
Year,
Month,
Day,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::db) enum PersistedFieldOrigin {
Generated,
SqlDdl,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) struct PersistedFieldSnapshot {
id: FieldId,
name: String,
slot: SchemaFieldSlot,
kind: AcceptedFieldKind,
nested_leaves: Vec<PersistedNestedLeafSnapshot>,
nullable: bool,
default: SchemaFieldDefault,
write_policy: SchemaFieldWritePolicy,
origin: PersistedFieldOrigin,
storage_decode: FieldStorageDecode,
leaf_codec: LeafCodec,
}
impl PersistedFieldSnapshot {
#[cfg(test)]
#[expect(
clippy::too_many_arguments,
reason = "schema snapshot construction keeps every persisted field contract explicit"
)]
#[must_use]
pub(in crate::db) const fn new(
id: FieldId,
name: String,
slot: SchemaFieldSlot,
kind: AcceptedFieldKind,
nested_leaves: Vec<PersistedNestedLeafSnapshot>,
nullable: bool,
default: SchemaFieldDefault,
storage_decode: FieldStorageDecode,
leaf_codec: LeafCodec,
) -> Self {
Self::new_with_write_policy(
id,
name,
slot,
kind,
nested_leaves,
nullable,
default,
SchemaFieldWritePolicy::none(),
storage_decode,
leaf_codec,
)
}
#[expect(
clippy::too_many_arguments,
reason = "schema snapshot construction keeps every persisted field contract explicit"
)]
#[must_use]
pub(in crate::db) const fn new_with_write_policy(
id: FieldId,
name: String,
slot: SchemaFieldSlot,
kind: AcceptedFieldKind,
nested_leaves: Vec<PersistedNestedLeafSnapshot>,
nullable: bool,
default: SchemaFieldDefault,
write_policy: SchemaFieldWritePolicy,
storage_decode: FieldStorageDecode,
leaf_codec: LeafCodec,
) -> Self {
Self::new_with_write_policy_and_origin(
id,
name,
slot,
kind,
nested_leaves,
nullable,
default,
write_policy,
PersistedFieldOrigin::Generated,
storage_decode,
leaf_codec,
)
}
#[expect(
clippy::too_many_arguments,
reason = "schema snapshot construction keeps every persisted field contract explicit"
)]
#[must_use]
pub(in crate::db) const fn new_with_write_policy_and_origin(
id: FieldId,
name: String,
slot: SchemaFieldSlot,
kind: AcceptedFieldKind,
nested_leaves: Vec<PersistedNestedLeafSnapshot>,
nullable: bool,
default: SchemaFieldDefault,
write_policy: SchemaFieldWritePolicy,
origin: PersistedFieldOrigin,
storage_decode: FieldStorageDecode,
leaf_codec: LeafCodec,
) -> Self {
Self {
id,
name,
slot,
kind,
nested_leaves,
nullable,
default,
write_policy,
origin,
storage_decode,
leaf_codec,
}
}
#[must_use]
pub(in crate::db) const fn id(&self) -> FieldId {
self.id
}
#[must_use]
pub(in crate::db) const fn name(&self) -> &str {
self.name.as_str()
}
#[must_use]
pub(in crate::db) const fn slot(&self) -> SchemaFieldSlot {
self.slot
}
#[must_use]
pub(in crate::db) const fn kind(&self) -> &AcceptedFieldKind {
&self.kind
}
#[must_use]
pub(in crate::db) const fn nested_leaves(&self) -> &[PersistedNestedLeafSnapshot] {
self.nested_leaves.as_slice()
}
#[must_use]
pub(in crate::db) const fn nullable(&self) -> bool {
self.nullable
}
#[must_use]
pub(in crate::db) const fn default(&self) -> &SchemaFieldDefault {
&self.default
}
#[must_use]
#[cfg(any(test, feature = "sql"))]
pub(in crate::db) fn clone_with_default(&self, default: SchemaFieldDefault) -> Self {
Self {
id: self.id,
name: self.name.clone(),
slot: self.slot,
kind: self.kind.clone(),
nested_leaves: self.nested_leaves.clone(),
nullable: self.nullable,
default,
write_policy: self.write_policy,
origin: self.origin,
storage_decode: self.storage_decode,
leaf_codec: self.leaf_codec,
}
}
#[must_use]
#[cfg(any(test, feature = "sql"))]
pub(in crate::db) fn clone_with_nullable(&self, nullable: bool) -> Self {
Self {
id: self.id,
name: self.name.clone(),
slot: self.slot,
kind: self.kind.clone(),
nested_leaves: self.nested_leaves.clone(),
nullable,
default: self.default.clone(),
write_policy: self.write_policy,
origin: self.origin,
storage_decode: self.storage_decode,
leaf_codec: self.leaf_codec,
}
}
#[must_use]
#[cfg(any(test, feature = "sql"))]
pub(in crate::db) fn clone_with_name(&self, name: String) -> Self {
Self {
id: self.id,
name,
slot: self.slot,
kind: self.kind.clone(),
nested_leaves: self.nested_leaves.clone(),
nullable: self.nullable,
default: self.default.clone(),
write_policy: self.write_policy,
origin: self.origin,
storage_decode: self.storage_decode,
leaf_codec: self.leaf_codec,
}
}
#[must_use]
pub(in crate::db) const fn write_policy(&self) -> SchemaFieldWritePolicy {
self.write_policy
}
#[must_use]
pub(in crate::db) const fn origin(&self) -> PersistedFieldOrigin {
self.origin
}
#[must_use]
pub(in crate::db) const fn generated(&self) -> bool {
matches!(self.origin, PersistedFieldOrigin::Generated)
}
#[must_use]
pub(in crate::db) const fn storage_decode(&self) -> FieldStorageDecode {
self.storage_decode
}
#[must_use]
pub(in crate::db) const fn leaf_codec(&self) -> LeafCodec {
self.leaf_codec
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) struct PersistedNestedLeafSnapshot {
path: Vec<String>,
kind: AcceptedFieldKind,
nullable: bool,
storage_decode: FieldStorageDecode,
leaf_codec: LeafCodec,
}
impl PersistedNestedLeafSnapshot {
#[must_use]
pub(in crate::db) const fn new(
path: Vec<String>,
kind: AcceptedFieldKind,
nullable: bool,
storage_decode: FieldStorageDecode,
leaf_codec: LeafCodec,
) -> Self {
Self {
path,
kind,
nullable,
storage_decode,
leaf_codec,
}
}
#[must_use]
pub(in crate::db) const fn path(&self) -> &[String] {
self.path.as_slice()
}
#[must_use]
pub(in crate::db) const fn kind(&self) -> &AcceptedFieldKind {
&self.kind
}
#[must_use]
pub(in crate::db) const fn nullable(&self) -> bool {
self.nullable
}
#[must_use]
pub(in crate::db) const fn storage_decode(&self) -> FieldStorageDecode {
self.storage_decode
}
#[must_use]
pub(in crate::db) const fn leaf_codec(&self) -> LeafCodec {
self.leaf_codec
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(in crate::db) enum SchemaFieldDefault {
None,
SlotPayload(Vec<u8>),
}
impl SchemaFieldDefault {
#[must_use]
pub(in crate::db) const fn is_none(&self) -> bool {
matches!(self, Self::None)
}
#[must_use]
pub(in crate::db) const fn slot_payload(&self) -> Option<&[u8]> {
match self {
Self::None => None,
Self::SlotPayload(bytes) => Some(bytes.as_slice()),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::db) struct SchemaFieldWritePolicy {
insert_generation: Option<FieldInsertGeneration>,
write_management: Option<FieldWriteManagement>,
}
impl SchemaFieldWritePolicy {
#[cfg(test)]
#[must_use]
pub(in crate::db) const fn none() -> Self {
Self {
insert_generation: None,
write_management: None,
}
}
#[must_use]
pub(in crate::db) const fn from_model_policies(
insert_generation: Option<FieldInsertGeneration>,
write_management: Option<FieldWriteManagement>,
) -> Self {
Self {
insert_generation,
write_management,
}
}
#[must_use]
pub(in crate::db) const fn insert_generation(self) -> Option<FieldInsertGeneration> {
self.insert_generation
}
#[must_use]
pub(in crate::db) const fn write_management(self) -> Option<FieldWriteManagement> {
self.write_management
}
}
#[cfg(test)]
mod tests;