ThingsDatabase

Struct ThingsDatabase 

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

SQLx-based database implementation for Things 3 data This provides async, Send + Sync compatible database access

Implementations§

Source§

impl ThingsDatabase

Source

pub async fn new(database_path: &Path) -> ThingsResult<Self>

Create a new database connection pool with default configuration

§Examples
use things3_core::{ThingsDatabase, ThingsError};
use std::path::Path;

// Connect to Things 3 database
let db = ThingsDatabase::new(Path::new("/path/to/things.db")).await?;

// Get inbox tasks
let tasks = db.get_inbox(None).await?;
println!("Found {} tasks in inbox", tasks.len());
§Errors

Returns an error if the database connection fails or if SQLite configuration fails

Source

pub async fn new_with_config( database_path: &Path, config: DatabasePoolConfig, ) -> ThingsResult<Self>

Create a new database connection pool with custom configuration

§Examples
use things3_core::{ThingsDatabase, DatabasePoolConfig, ThingsError};
use std::path::Path;
use std::time::Duration;

// Create custom pool configuration
let config = DatabasePoolConfig {
    max_connections: 10,
    min_connections: 2,
    connect_timeout: Duration::from_secs(5),
    idle_timeout: Duration::from_secs(300),
    max_lifetime: Duration::from_secs(3600),
    test_before_acquire: true,
    sqlite_optimizations: Default::default(),
};

// Connect with custom configuration
let db = ThingsDatabase::new_with_config(
    Path::new("/path/to/things.db"),
    config,
).await?;
§Errors

Returns an error if the database connection fails or if SQLite configuration fails

Source

pub async fn from_connection_string(database_url: &str) -> ThingsResult<Self>

Create a new database connection pool from a connection string with default configuration

§Errors

Returns an error if the database connection fails or if SQLite configuration fails

Source

pub async fn from_connection_string_with_config( database_url: &str, config: DatabasePoolConfig, ) -> ThingsResult<Self>

Create a new database connection pool from a connection string with custom configuration

§Errors

Returns an error if the database connection fails or if SQLite configuration fails

Source

pub fn pool(&self) -> &SqlitePool

Get the underlying connection pool

Source

pub async fn is_connected(&self) -> bool

Check if the database is connected

Source

pub async fn get_pool_health(&self) -> ThingsResult<PoolHealthStatus>

Get connection pool health status

§Errors

Returns an error if the health check fails

Source

pub async fn get_pool_metrics(&self) -> ThingsResult<PoolMetrics>

Get detailed connection pool metrics

§Errors

Returns an error if the metrics collection fails

Source

pub async fn comprehensive_health_check( &self, ) -> ThingsResult<ComprehensiveHealthStatus>

Perform a comprehensive health check including pool and database

§Errors

Returns an error if the health check fails

Source

pub async fn get_stats(&self) -> ThingsResult<DatabaseStats>

Get database statistics

§Errors

Returns an error if the database query fails

Source

pub async fn get_all_tasks(&self) -> ThingsResult<Vec<Task>>

Get all tasks from the database

§Examples
use things3_core::{ThingsDatabase, ThingsError};
use std::path::Path;

let db = ThingsDatabase::new(Path::new("/path/to/things.db")).await?;

// Get all tasks
let tasks = db.get_all_tasks().await?;
println!("Found {} total tasks", tasks.len());

// Filter tasks by status
let incomplete: Vec<_> = tasks.iter()
    .filter(|t| t.status == things3_core::TaskStatus::Incomplete)
    .collect();
println!("Found {} incomplete tasks", incomplete.len());
§Errors

Returns an error if the database query fails or if task data is invalid

Source

pub async fn get_all_projects(&self) -> ThingsResult<Vec<Project>>

Get all projects (from TMTask table where type = 1)

§Errors

Returns an error if the database query fails or if project data is invalid

Source

pub async fn get_all_areas(&self) -> ThingsResult<Vec<Area>>

Get all areas

§Errors

Returns an error if the database query fails or if area data is invalid

Source

pub async fn get_tasks_by_status( &self, status: TaskStatus, ) -> ThingsResult<Vec<Task>>

Get tasks by status

§Errors

Returns an error if the database query fails or if task data is invalid

Source

pub async fn search_tasks(&self, query: &str) -> ThingsResult<Vec<Task>>

Search tasks by title or notes

§Errors

Returns an error if the database query fails or if task data is invalid

Source

pub async fn search_logbook( &self, search_text: Option<String>, from_date: Option<NaiveDate>, to_date: Option<NaiveDate>, project_uuid: Option<Uuid>, area_uuid: Option<Uuid>, tags: Option<Vec<String>>, limit: Option<u32>, ) -> ThingsResult<Vec<Task>>

Search completed tasks in the logbook

Returns completed tasks matching the provided filters. All filters are optional and can be combined.

§Parameters
  • search_text: Search in task titles and notes (case-insensitive)
  • from_date: Start date for completion date range
  • to_date: End date for completion date range
  • project_uuid: Filter by project UUID
  • area_uuid: Filter by area UUID
  • tags: Filter by tags (all tags must match)
  • limit: Maximum number of results (default: 50)
§Errors

Returns an error if the database query fails or if task data is invalid

Source

pub async fn get_inbox(&self, limit: Option<usize>) -> ThingsResult<Vec<Task>>

Get inbox tasks (incomplete tasks without project)

§Errors

Returns an error if the database query fails or if task data is invalid

Source

pub async fn get_today(&self, limit: Option<usize>) -> ThingsResult<Vec<Task>>

Get today’s tasks (incomplete tasks due today or started today)

§Errors

Returns an error if the database query fails or if task data is invalid

§Panics

Panics if the current date cannot be converted to a valid time with hours, minutes, and seconds

Source

pub async fn get_projects( &self, limit: Option<usize>, ) -> ThingsResult<Vec<Project>>

Get all projects (alias for get_all_projects for compatibility)

§Errors

Returns an error if the database query fails or if project data is invalid

Source

pub async fn get_areas(&self) -> ThingsResult<Vec<Area>>

Get all areas (alias for get_all_areas for compatibility)

§Errors

Returns an error if the database query fails or if area data is invalid

Source

pub async fn create_task( &self, request: CreateTaskRequest, ) -> ThingsResult<Uuid>

Create a new task in the database

Validates:

  • Project UUID exists if provided
  • Area UUID exists if provided
  • Parent task UUID exists if provided
  • Date range (deadline >= start_date)

Returns the UUID of the created task

§Examples
use things3_core::{ThingsDatabase, CreateTaskRequest, ThingsError};
use std::path::Path;
use chrono::NaiveDate;

let db = ThingsDatabase::new(Path::new("/path/to/things.db")).await?;

// Create a simple task
let request = CreateTaskRequest {
    title: "Buy groceries".to_string(),
    notes: Some("Milk, eggs, bread".to_string()),
    deadline: Some(NaiveDate::from_ymd_opt(2024, 12, 31).unwrap()),
    start_date: None,
    project_uuid: None,
    area_uuid: None,
    parent_uuid: None,
    tags: None,
    task_type: None,
    status: None,
};

let task_uuid = db.create_task(request).await?;
println!("Created task with UUID: {}", task_uuid);
§Errors

Returns an error if validation fails or if the database insert fails

Source

pub async fn create_project( &self, request: CreateProjectRequest, ) -> ThingsResult<Uuid>

Create a new project

Projects are tasks with type = 1 in the TMTask table

§Errors

Returns an error if validation fails or the database insert fails

Source

pub async fn update_task(&self, request: UpdateTaskRequest) -> ThingsResult<()>

Update an existing task

Only updates fields that are provided (Some(_)) Validates existence of referenced entities

§Errors

Returns an error if the task doesn’t exist, validation fails, or the database update fails

Source

pub async fn get_project_by_uuid( &self, uuid: &Uuid, ) -> ThingsResult<Option<Project>>

Get a single project by UUID

Returns None if the project doesn’t exist or is trashed

§Errors

Returns an error if the database query fails

Source

pub async fn update_project( &self, request: UpdateProjectRequest, ) -> ThingsResult<()>

Update an existing project

Only updates fields that are provided (Some(_)) Validates existence and that the entity is a project (type = 1)

§Errors

Returns an error if the project doesn’t exist, validation fails, or the database update fails

Source

pub async fn get_task_by_uuid(&self, uuid: &Uuid) -> ThingsResult<Option<Task>>

Get a task by its UUID

§Errors

Returns an error if the task does not exist or if the database query fails

Source

pub async fn complete_task(&self, uuid: &Uuid) -> ThingsResult<()>

Mark a task as completed

§Errors

Returns an error if the task does not exist or if the database update fails

Source

pub async fn uncomplete_task(&self, uuid: &Uuid) -> ThingsResult<()>

Mark a completed task as incomplete

§Errors

Returns an error if the task does not exist or if the database update fails

Source

pub async fn complete_project( &self, uuid: &Uuid, child_handling: ProjectChildHandling, ) -> ThingsResult<()>

Complete a project and optionally handle its child tasks

§Errors

Returns an error if the project doesn’t exist or if the database update fails

Source

pub async fn delete_task( &self, uuid: &Uuid, child_handling: DeleteChildHandling, ) -> ThingsResult<()>

Soft delete a task (set trashed flag)

§Errors

Returns an error if the task does not exist, if child handling fails, or if the database update fails

Source

pub async fn delete_project( &self, uuid: &Uuid, child_handling: ProjectChildHandling, ) -> ThingsResult<()>

Soft delete a project and handle its child tasks

§Errors

Returns an error if the project doesn’t exist, if child handling fails, or if the database update fails

Source

pub async fn create_area( &self, request: CreateAreaRequest, ) -> ThingsResult<Uuid>

Create a new area

§Errors

Returns an error if the database insert fails

Source

pub async fn update_area(&self, request: UpdateAreaRequest) -> ThingsResult<()>

Update an existing area

§Errors

Returns an error if the area doesn’t exist or if the database update fails

Source

pub async fn delete_area(&self, uuid: &Uuid) -> ThingsResult<()>

Delete an area

Hard delete (areas don’t have a trashed field) Orphans all projects in the area by setting their area to NULL

§Errors

Returns an error if the area doesn’t exist or if the database delete fails

Source

pub async fn find_tag_by_normalized_title( &self, normalized: &str, ) -> ThingsResult<Option<Tag>>

Find a tag by normalized title (exact match, case-insensitive)

§Errors

Returns an error if the database query fails

Source

pub async fn find_similar_tags( &self, title: &str, min_similarity: f32, ) -> ThingsResult<Vec<TagMatch>>

Find tags similar to the given title using fuzzy matching

Returns tags sorted by similarity score (highest first)

§Errors

Returns an error if the database query fails

Source

pub async fn search_tags(&self, query: &str) -> ThingsResult<Vec<Tag>>

Search tags by partial title match

§Errors

Returns an error if the database query fails

Source

pub async fn get_all_tags(&self) -> ThingsResult<Vec<Tag>>

Get all tags ordered by title

§Errors

Returns an error if the database query fails

Get most frequently used tags

§Errors

Returns an error if the database query fails

Source

pub async fn get_recent_tags(&self, limit: usize) -> ThingsResult<Vec<Tag>>

Get recently used tags

§Errors

Returns an error if the database query fails

Source

pub async fn create_tag_smart( &self, request: CreateTagRequest, ) -> ThingsResult<TagCreationResult>

Create a tag with smart duplicate detection

Returns:

  • Created: New tag was created
  • Existing: Exact match found (case-insensitive)
  • SimilarFound: Similar tags found (user decision needed)
§Errors

Returns an error if the database operation fails

Source

pub async fn create_tag_force( &self, request: CreateTagRequest, ) -> ThingsResult<Uuid>

Create tag forcefully (skip duplicate check)

§Errors

Returns an error if the database operation fails

Source

pub async fn update_tag(&self, request: UpdateTagRequest) -> ThingsResult<()>

Update a tag

§Errors

Returns an error if the tag doesn’t exist or database operation fails

Source

pub async fn delete_tag( &self, uuid: &Uuid, remove_from_tasks: bool, ) -> ThingsResult<()>

Delete a tag

§Arguments
  • uuid - UUID of the tag to delete
  • remove_from_tasks - If true, removes tag from all tasks’ cachedTags
§Errors

Returns an error if the database operation fails

Source

pub async fn merge_tags( &self, source_uuid: &Uuid, target_uuid: &Uuid, ) -> ThingsResult<()>

Merge two tags (combine source into target)

§Arguments
  • source_uuid - UUID of tag to merge from (will be deleted)
  • target_uuid - UUID of tag to merge into (will remain)
§Errors

Returns an error if either tag doesn’t exist or database operation fails

Source

pub async fn add_tag_to_task( &self, task_uuid: &Uuid, tag_title: &str, ) -> ThingsResult<TagAssignmentResult>

Add a tag to a task (with duplicate prevention)

Returns:

  • Assigned: Tag was successfully assigned
  • Suggestions: Similar tags found (user decision needed)
§Errors

Returns an error if the task doesn’t exist or database operation fails

Source

pub async fn remove_tag_from_task( &self, task_uuid: &Uuid, tag_title: &str, ) -> ThingsResult<()>

Remove a tag from a task

§Errors

Returns an error if the task doesn’t exist or database operation fails

Source

pub async fn set_task_tags( &self, task_uuid: &Uuid, tag_titles: Vec<String>, ) -> ThingsResult<Vec<TagMatch>>

Replace all tags on a task (with duplicate prevention)

Returns any tag titles that had similar matches for user confirmation

§Errors

Returns an error if the task doesn’t exist or database operation fails

Source

pub async fn get_tag_completions( &self, partial_input: &str, limit: usize, ) -> ThingsResult<Vec<TagCompletion>>

Get tag completions for partial input

Returns tags sorted by:

  1. Exact prefix matches (prioritized)
  2. Contains matches
  3. Fuzzy matches Within each category, sorted by usage frequency
§Errors

Returns an error if the database query fails

Source

pub async fn get_tag_statistics( &self, uuid: &Uuid, ) -> ThingsResult<TagStatistics>

Get detailed statistics for a tag

§Errors

Returns an error if the tag doesn’t exist or database query fails

Source

pub async fn find_duplicate_tags( &self, min_similarity: f32, ) -> ThingsResult<Vec<TagPair>>

Find duplicate or highly similar tags

Returns pairs of tags that are similar above the threshold

§Errors

Returns an error if the database query fails

Source

pub async fn bulk_move( &self, request: BulkMoveRequest, ) -> ThingsResult<BulkOperationResult>

Move multiple tasks to a project or area (transactional)

All tasks must exist and be valid, or the entire operation will be rolled back.

§Errors

Returns an error if:

  • Task UUIDs array is empty
  • Neither project_uuid nor area_uuid is specified
  • Target project or area doesn’t exist
  • Any task UUID is invalid or doesn’t exist
  • Database operation fails
Source

pub async fn bulk_update_dates( &self, request: BulkUpdateDatesRequest, ) -> ThingsResult<BulkOperationResult>

Update dates for multiple tasks with validation (transactional)

All tasks must exist and dates must be valid, or the entire operation will be rolled back. Validates that deadline >= start_date for each task after merging with existing dates.

§Errors

Returns an error if:

  • Task UUIDs array is empty
  • Any task UUID is invalid or doesn’t exist
  • Date range validation fails (deadline before start_date)
  • Database operation fails
Source

pub async fn bulk_complete( &self, request: BulkCompleteRequest, ) -> ThingsResult<BulkOperationResult>

Complete multiple tasks (transactional)

All tasks must exist, or the entire operation will be rolled back.

§Errors

Returns an error if:

  • Task UUIDs array is empty
  • Any task UUID is invalid or doesn’t exist
  • Database operation fails
Source

pub async fn bulk_delete( &self, request: BulkDeleteRequest, ) -> ThingsResult<BulkOperationResult>

Delete multiple tasks (soft delete, transactional)

All tasks must exist, or the entire operation will be rolled back.

§Errors

Returns an error if:

  • Task UUIDs array is empty
  • Any task UUID is invalid or doesn’t exist
  • Database operation fails

Trait Implementations§

Source§

impl Clone for ThingsDatabase

Source§

fn clone(&self) -> ThingsDatabase

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for ThingsDatabase

Source§

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

Formats the value using the given formatter. 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> 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> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

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

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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
Source§

impl<T> ErasedDestructor for T
where T: 'static,