Skip to main content

SqlNoteStore

Struct SqlNoteStore 

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

A NoteStore backed by SQLite. Namespace is the caller’s responsibility.

UUID is globally unique — get/delete by ID alone. Query/count use the namespace parameter as passed. Read routing is always pool-backed; the constructor’s legacy file-backed flag is retained for API compatibility.

Implementations§

Source§

impl SqlNoteStore

Source

pub fn new(pool: Arc<ConnectionPool>, _is_file_backed: bool) -> Self

Create a new store.

Trait Implementations§

Source§

impl NoteStore for SqlNoteStore

Source§

fn get_live_notes_by_key<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, namespace: &'life1 str, key: &'life2 str, kind: Option<&'life3 str>, ) -> Pin<Box<dyn Future<Output = StorageResult<Vec<Note>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Source§

fn query_keyed_notes<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, namespace: &'life1 str, filter: &'life2 NoteFilter, prefix: &'life3 str, after: Option<&'life4 NoteKeyCursor>, page: PageRequest, ) -> Pin<Box<dyn Future<Output = StorageResult<(Vec<Note>, Option<NoteKeyCursor>)>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait,

Source§

fn upsert_note<'life0, 'async_trait>( &'life0 self, note: Note, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Insert or update a single note. Updates preserve the stored immutable key.
Source§

fn insert_note_if_absent<'life0, 'async_trait>( &'life0 self, note: Note, ) -> Pin<Box<dyn Future<Output = Result<bool, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Insert a note only if no row already holds its id, reporting whether this call is the one that inserted it. Read more
Source§

fn replace_note_if_unchanged<'life0, 'async_trait>( &'life0 self, note: Note, expected_updated_at: i64, expected_deleted_at: Option<i64>, ) -> Pin<Box<dyn Future<Output = Result<bool, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Replace a note only when the persisted row still matches the caller’s read snapshot. Read more
Source§

fn update_note_properties<'life0, 'async_trait>( &'life0 self, id: Uuid, properties: Option<Value>, updated_at: i64, ) -> Pin<Box<dyn Future<Output = Result<bool, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Patch properties/updated_at on an existing note in place via a real UPDATE, leaving every other column (including the row’s rowid) untouched. Read more
Source§

fn set_note_property<'life0, 'life1, 'async_trait>( &'life0 self, id: Uuid, key: &'life1 str, value: Value, updated_at: i64, ) -> Pin<Box<dyn Future<Output = Result<bool, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Atomically set one top-level key in a note’s JSON properties object. Read more
Source§

fn try_patch_note_property<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, id: Uuid, namespace: &'life1 str, filter: &'life2 NoteFilter, json_path: &'life3 str, value: Value, updated_at: i64, ) -> Pin<Box<dyn Future<Output = Result<bool, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Atomically patch a single properties JSON key on a note, but only when the row’s current state (re-evaluated inside this same statement, not a snapshot the caller fetched earlier) still satisfies filter’s namespace/kind/property_filters. Read more
Source§

fn patch_note_property_atomic<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, ids: Vec<Uuid>, namespace: &'life1 str, filter: &'life2 NoteFilter, json_path: &'life3 str, value: Value, updated_at: i64, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Atomically patch one JSON property on every supplied note. Read more
Source§

fn try_insert_note<'life0, 'async_trait>( &'life0 self, note: Note, ) -> Pin<Box<dyn Future<Output = Result<bool, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Attempt to insert a note without overwriting an existing row. Read more
Source§

fn upsert_notes<'life0, 'async_trait>( &'life0 self, notes: Vec<Note>, ) -> Pin<Box<dyn Future<Output = Result<BatchWriteSummary, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Insert or update a batch of notes. Updates preserve each stored immutable key.
Source§

fn get_note<'life0, 'async_trait>( &'life0 self, id: Uuid, ) -> Pin<Box<dyn Future<Output = Result<Option<Note>, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Fetch a note by UUID, returning None if absent.
Source§

fn get_note_including_deleted<'life0, 'async_trait>( &'life0 self, id: Uuid, ) -> Pin<Box<dyn Future<Output = Result<Option<Note>, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Fetch a note by UUID regardless of soft-deletion state. Read more
Source§

fn note_sequence<'life0, 'async_trait>( &'life0 self, id: Uuid, ) -> Pin<Box<dyn Future<Output = Result<Option<i64>, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Resolve a note id to its immutable insertion sequence.
Source§

fn get_notes_batch<'life0, 'life1, 'async_trait>( &'life0 self, ids: &'life1 [Uuid], ) -> Pin<Box<dyn Future<Output = Result<Vec<Note>, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Fetch multiple notes by UUID in a single call.
Source§

fn delete_note<'life0, 'async_trait>( &'life0 self, id: Uuid, mode: DeleteMode, ) -> Pin<Box<dyn Future<Output = Result<bool, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Delete a note by UUID using the specified delete mode.
Source§

fn query_notes<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, namespace: &'life1 str, kind: Option<&'life2 str>, page: PageRequest, ) -> Pin<Box<dyn Future<Output = Result<Page<Note>, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Query notes by namespace and optional kind with pagination. The returned total and page items must come from one consistent backend snapshot.
Source§

fn query_notes_count_free<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, namespace: &'life1 str, kind: Option<&'life2 str>, page: PageRequest, ) -> Pin<Box<dyn Future<Output = Result<Page<Note>, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Query notes by namespace and optional kind without computing an exact total. Read more
Source§

fn query_notes_filtered<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, namespace: &'life1 str, filter: &'life2 NoteFilter, page: PageRequest, ) -> Pin<Box<dyn Future<Output = Result<Page<Note>, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Query notes with property-based filtering and custom sort. The returned total and page items must come from one consistent backend snapshot.
Source§

fn query_notes_filtered_count_free<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, namespace: &'life1 str, filter: &'life2 NoteFilter, page: PageRequest, ) -> Pin<Box<dyn Future<Output = Result<Page<Note>, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Query a filtered note page without computing an exact total. Read more
Source§

fn count_notes_filtered_in_snapshot<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, namespace: &'life1 str, filters: &'life2 [NoteFilter], ) -> Pin<Box<dyn Future<Output = Result<Vec<u64>, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Count several filtered note populations in one consistent backend snapshot. Backends that cannot provide that guarantee must return crate::StorageError::Unsupported rather than composing independent queries or treating an absent page total as zero. SQL backends should override this operation so callers can retain separate index-friendly predicates without racing between their counts.
Source§

fn count_notes_filtered_bounded_in_snapshot<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, namespace: &'life1 str, filters: &'life2 [NoteFilter], cap: u32, ) -> Pin<Box<dyn Future<Output = Result<Vec<BoundedCount>, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Count several filtered note populations in one backend snapshot, with each count bounded by cap. Read more
Source§

fn query_notes_filtered_after<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, namespace: &'life1 str, filter: &'life2 NoteFilter, after: Option<SeekCursor>, limit: u32, ) -> Pin<Box<dyn Future<Output = Result<SeekPage<Note>, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Query an immutable insertion-sequence keyset page with the same predicates as Self::query_notes_filtered.
Source§

fn query_notes_filtered_bounded<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, namespace: &'life1 str, filter: &'life2 NoteFilter, max_rows: u32, ) -> Pin<Box<dyn Future<Output = Result<Vec<Note>, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Fetch up to max_rows + 1 notes matching filter in a single deterministically-ordered SQL statement, with no separate COUNT(*) and no pagination loop. Read more
Source§

fn count_notes<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, namespace: &'life1 str, kind: Option<&'life2 str>, ) -> Pin<Box<dyn Future<Output = Result<u64, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Count notes in a namespace, optionally filtered by kind.
Source§

fn count_notes_in_namespaces<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, namespaces: &'life1 [String], kind: Option<&'life2 str>, ) -> Pin<Box<dyn Future<Output = Result<u64, StorageError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Count notes across the given namespaces, optionally filtered by kind. The default preserves compatibility by summing the existing single-namespace operation; SQL backends should override this with one IN aggregate.

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> 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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

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

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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