Skip to main content

SchemaRegistry

Struct SchemaRegistry 

Source
pub struct SchemaRegistry { /* private fields */ }
Expand description

Thread-safe, in-memory schema registry.

Tracks the schema for every measurement. Schemas are created automatically on first write and evolve additively (new tags/fields added, type conflicts rejected).

§Schema Evolution

The registry follows a schema-on-write model:

OperationSupportedMechanism
Add tag/fieldYesAutomatic on write
Type conflictRejectedSchemaError
Remove columnNoN/A (append-only)
Rename columnNoN/A
Change column typeNoWrite new field

Durability is the catalog manifest’s job: the database persists every action this registry returns before it writes the data that needs it.

Implementations§

Source§

impl SchemaRegistry

Source

pub fn new() -> Self

Create an empty schema registry.

Source

pub fn register_batch( &self, points: &[&Point], ) -> Result<Vec<SchemaAction>, SchemaError>

Register every point of a batch, or none of them.

Validates the whole batch against the current schemas and against the columns earlier points of the same batch introduce, and only then applies the additions. A type conflict anywhere in the batch rejects it with the registry untouched — which is the property that lets the caller persist every returned action unconditionally. Registering point by point left the columns of the first points behind when a later point was refused, and nothing ever persisted them.

Returns the actions the batch caused, in application order. Empty when the batch fits the existing schemas, which is the common case and takes no lock.

§Errors

Returns SchemaError::TypeConflict if any field’s type conflicts with the schema, or with the type another point of the batch gives the same field.

Source

pub fn normalize_decimals( &self, points: &[&Point], ) -> Result<Option<Vec<Point>>, SchemaError>

Rescale every decimal field of points to its column’s scale.

A decimal column stores one number of fractional digits, and this is where a value that arrived with fewer is widened to it — 1.5 into a scale-4 column becomes 1.5000. Without it the memtable, the WAL and two segments of the same column could each hold a different scale, and a scan across them could not produce one Arrow schema.

Returns None when nothing needed changing, which is the common case and copies nothing: a batch with no decimal fields never allocates. Otherwise returns the whole batch, with the affected points rewritten.

Call after register_batch, so the columns the batch introduces already exist.

§Errors

SchemaError::DecimalScaleConflict if a value carries more fractional digits than its column stores. register_batch refuses the same batch for the same reason, so reaching this is a sign the two were called out of order.

Source

pub fn declare_field( &self, measurement: &str, field: &str, column_type: ColumnType, ) -> Result<Vec<SchemaAction>, SchemaError>

Declare a field column before anything is written to it.

The reason this exists is decimals: a decimal column’s scale is fixed by whatever creates the column, and letting the first meter reading decide how many fractional digits a settlement register keeps is a coin toss. Declaring Decimal { scale: 4 } up front makes it a decision.

Returns the actions to persist — empty when the column already existed with exactly this type.

§Errors

SchemaError::TypeConflict if the column exists with a different type, a different decimal scale, or as a tag.

Source

pub fn register_point( &self, point: &Point, ) -> Result<Vec<SchemaAction>, SchemaError>

Register a single point — register_batch for one point.

§Errors

Returns SchemaError::TypeConflict if a field’s type doesn’t match the existing schema.

Source

pub fn lookup(&self, measurement: &str) -> Option<Arc<MeasurementSchema>>

Look up the schema for a measurement.

Returns Arc<MeasurementSchema> for an O(1) clone.

Source

pub fn register_schema(&self, name: &str, schema: MeasurementSchema)

Register a pre-built schema directly (e.g. during catalog replay on startup). If the measurement already has a schema, the existing one is kept unchanged.

Source

pub fn register_measurement(&self, ms: MeasurementSchema)

Register a measurement from a MeasurementSchema (WAL replay).

Idempotent: if the measurement already exists the call is a no-op.

Source

pub fn apply_add_column(&self, measurement: &str, column: ColumnDef)

Apply an AddColumn action from WAL replay.

Idempotent: if the column already exists it is not duplicated. Checks for role conflicts (e.g., tag vs field with same name).

Source

pub fn measurement_count(&self) -> usize

Returns the number of registered measurements.

Source

pub fn measurement_names(&self) -> Vec<String>

Returns all registered measurement names.

Source

pub fn remove(&self, measurement: &str) -> Option<Arc<MeasurementSchema>>

Remove a measurement schema. Returns the removed schema if it existed.

Trait Implementations§

Source§

impl Clone for SchemaRegistry

Source§

fn clone(&self) -> SchemaRegistry

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SchemaRegistry

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for SchemaRegistry

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more