Skip to main content

Tasks

Struct Tasks 

Source
pub struct Tasks {
    pub conn: Connection,
    pub id: Option<i32>,
}
Expand description

Database interface for comprehensive task management operations.

The Tasks struct provides a high-level API for all task-related database operations, managing connections, transactions, and result processing. It maintains state for the most recently inserted task ID to support method chaining and immediate post-creation operations.

§Architecture

  • Connection Management: Direct SQLite connection for optimal performance
  • State Tracking: Maintains last insertion ID for operation chaining
  • Error Handling: Comprehensive error propagation and message generation
  • Transaction Support: Implicit transaction handling for data consistency

§Performance Considerations

  • Prepared statements are used for frequently executed queries
  • Bulk operations are optimized for large dataset manipulation
  • Index-aware query construction for efficient filtering
  • Tag integration is lazy-loaded to minimize overhead

Fields§

§conn: Connection

Direct SQLite database connection for task operations.

Provides transactional access to the tasks table and related structures. Connection is managed internally and provides optimal performance for task-specific operations.

§id: Option<i32>

Identifier of the most recently inserted task.

Maintained automatically by insertion operations to support method chaining and immediate post-creation tasks like tag association or hierarchical relationship establishment.

Implementations§

Source§

impl Tasks

Source

pub fn new() -> Result<Self>

Creates a new Tasks manager and initializes the database schema.

This constructor establishes a database connection, ensures the tasks table schema is properly initialized, and prepares the manager for task operations. Schema creation is idempotent and safe for repeated calls.

§Returns

Returns a new Tasks instance ready for task management operations, or an error if database initialization fails.

§Example
use kasl::db::tasks::Tasks;

let mut tasks = Tasks::new()?;
// Ready for task operations
§Errors

Returns an error if:

  • Database connection cannot be established
  • Schema creation fails due to permissions or corruption
  • Migration system encounters errors during table setup
Source

pub fn insert(&mut self, task: &Task) -> Result<&mut Self>

Inserts a new task into the database and returns a mutable reference for chaining.

Creates a new task record with automatic ID assignment and timestamp generation. The task’s completion status, parent relationships, and search visibility are all properly configured during insertion. The assigned ID is stored internally for subsequent operations.

§Automatic Field Handling
  • ID Assignment: Database automatically assigns unique primary key
  • Timestamp: Current local time is set as creation timestamp
  • Validation: Required fields are validated before insertion
  • Defaults: Missing optional fields receive appropriate default values
§Arguments
  • task - Task object containing the properties to insert
§Returns

Returns a mutable reference to self for method chaining, allowing immediate follow-up operations like tag association or updates.

§Example
use kasl::db::tasks::Tasks;
use kasl::libs::task::Task;

let mut tasks = Tasks::new()?;
let task = Task::new("Code review", "Review PR #123", Some(50));
tasks.insert(&task)?
     .update_id()?; // Method chaining
§Database Effects
  • Creates new record in tasks table
  • Triggers any associated database triggers
  • Updates internal state with new task ID
  • Maintains referential integrity with tag system
Source

pub fn update_id(&mut self) -> Result<&mut Self>

Updates the parent task relationship for the most recently inserted task.

This method sets the task_id field to establish hierarchical relationships between tasks. It operates on the task ID stored from the most recent insertion, making it ideal for immediate post-creation relationship setup.

§Hierarchical Task Support
  • Parent-Child Relationships: Link tasks in hierarchical structures
  • Project Organization: Group related tasks under parent tasks
  • Dependency Tracking: Establish task dependencies and workflows
  • Nested Task Management: Support for multi-level task hierarchies
§Returns

Returns a mutable reference to self for continued method chaining, or an error if no recent insertion ID is available.

§Example
use kasl::libs::task::Task;

let mut tasks = Tasks::new()?;
let subtask = Task::new("Subtask", "Part of larger task", Some(0));
tasks.insert(&subtask)?
     .update_id()?; // Set task_id to reference itself or parent
§Errors

Returns an error if:

  • No recent insertion ID is available (call after insert)
  • Database update operation fails
  • Referential integrity constraints are violated
Source

pub fn get(&mut self) -> Result<Vec<Task>>

Retrieves the most recently inserted task as a vector.

This convenience method fetches the complete task record for the most recently inserted task, including all associated tags and relationships. Useful for immediate verification of insertion results.

§Returns

Returns a vector containing the single most recent task, or an error if no recent insertion ID is available or the task cannot be found.

§Example
use kasl::libs::task::Task;

let mut tasks = Tasks::new()?;
let task = Task::new("New task", "Description", Some(100));
let inserted_tasks = tasks.insert(&task)?
                         .get()?; // Retrieve the inserted task
§Error Conditions
  • No recent insertion ID available
  • Task was deleted after insertion
  • Database access failures
Source

pub fn fetch(&mut self, filter: TaskFilter) -> Result<Vec<Task>>

Fetches tasks based on sophisticated filtering criteria.

This is the primary query method that supports all task filtering scenarios through a unified interface. It dynamically constructs SQL queries based on the provided filter, executes them efficiently, and enriches results with associated tag information.

§Supported Filters
  • All: Retrieves every task in the database without restrictions
  • Date: Tasks created on a specific date (local timezone)
  • Incomplete: Tasks with progress < 100% from recent periods
  • ByIds: Direct lookup of tasks by their unique identifiers
  • ByTag: Tasks associated with a specific tag name
  • ByTags: Tasks associated with any of multiple tag names
§Query Optimization

The method uses prepared statements and parameterized queries for security and performance. Complex filters like “Incomplete” use sophisticated SQL to efficiently identify the latest completion status for each task.

§Tag Integration

All returned tasks are automatically enriched with their associated tag information through a secondary query. This provides complete task context without requiring separate tag lookups.

§Arguments
  • filter - The filtering criteria to apply when retrieving tasks
§Returns

Returns a vector of tasks matching the filter criteria, with complete tag information included. Empty vector if no tasks match the filter.

§Example
use kasl::db::tasks::Tasks;
use kasl::libs::task::TaskFilter;
use chrono::Local;

let mut tasks = Tasks::new()?;

// Get all tasks
let all_tasks = tasks.fetch(TaskFilter::All)?;

// Get today's tasks
let today = tasks.fetch(TaskFilter::Date(Local::now().date_naive()))?;

// Get tasks tagged as "urgent"
let urgent = tasks.fetch(TaskFilter::ByTag("urgent".to_string()))?;

// Get incomplete tasks
let incomplete = tasks.fetch(TaskFilter::Incomplete)?;
§Performance Notes
  • Uses prepared statements for optimal query performance
  • Complex filters like Incomplete may be slower on large datasets
  • Tag information is loaded separately and may add overhead
  • Results are loaded entirely into memory
Source

pub fn delete(&mut self, id: i32) -> Result<usize>

Deletes a single task by its unique identifier.

Permanently removes a task record from the database along with all associated relationships such as tag assignments. The operation is atomic and cannot be undone without database backups.

§Cascade Effects

Due to foreign key constraints, deleting a task will also:

  • Remove all task-tag associations
  • Update any child tasks that reference this task as parent
  • Trigger any associated database cleanup procedures
§Arguments
  • id - Unique identifier of the task to delete
§Returns

Returns the number of records affected (0 or 1), or an error if the database operation fails.

§Example
let mut tasks = Tasks::new()?;
let task_id = 1;
let deleted_count = tasks.delete(task_id)?;
if deleted_count > 0 {
    println!("Task deleted successfully");
}
§Safety Considerations
  • Deletion is immediate and permanent
  • No confirmation prompts at this level
  • Callers should implement appropriate confirmation flows
  • Consider soft deletion for recoverable scenarios
Source

pub fn delete_many(&mut self, ids: &[i32]) -> Result<usize>

Efficiently deletes multiple tasks in a single database transaction.

Performs bulk deletion of tasks specified by their IDs, providing better performance than individual delete operations and ensuring atomicity. All specified tasks and their relationships are removed in a single transaction.

§Performance Benefits
  • Single SQL statement execution reduces database round trips
  • Transaction-based operation ensures consistency
  • More efficient than individual deletion loops
  • Reduced lock contention on high-concurrency scenarios
§Transaction Behavior

The operation is atomic - either all specified tasks are deleted or none are deleted if any error occurs. This prevents partial deletion states that could lead to data inconsistency.

§Arguments
  • ids - Slice of task IDs to delete
§Returns

Returns the total number of tasks actually deleted, or an error if the database operation fails. Count may be less than input length if some IDs don’t exist.

§Example
let mut tasks = Tasks::new()?;
let ids_to_delete = vec![101, 102, 103];
let deleted_count = tasks.delete_many(&ids_to_delete)?;
println!("Deleted {} tasks", deleted_count);
§Edge Cases
  • Empty input slice returns 0 without database interaction
  • Non-existent IDs are silently ignored in the count
  • Very large ID lists may hit database query limits
Source

pub fn exists(&mut self, id: i32) -> Result<bool>

Checks if a task with the specified ID exists in the database.

Efficiently determines task existence without retrieving the full task data. This method is useful for validation before performing operations that require existing tasks.

§Arguments
  • id - Unique identifier of the task to check
§Returns

Returns true if the task exists, false otherwise, or an error if the database query fails.

§Example
let mut tasks = Tasks::new()?;
let task_id = 1;
if tasks.exists(task_id)? {
    println!("Task exists and can be updated");
} else {
    println!("Task not found");
}
§Performance

This method uses COUNT(*) which is optimized for existence checking and is more efficient than retrieving full task records when only existence verification is needed.

Source

pub fn update(&mut self, task: &Task) -> Result<()>

Updates an existing task’s properties in the database.

Modifies the core properties of an existing task (name, comment, completion) while preserving the task’s ID, timestamp, and relationships. The task must have a valid ID from a previous database operation.

§Update Scope

This method updates the following fields:

  • name: Task title/description
  • comment: Detailed description or notes
  • completeness: Progress percentage (0-100)

The following fields are not modified:

  • id: Primary key remains unchanged
  • timestamp: Creation time is preserved
  • task_id: Parent relationships require separate operations
  • excluded_from_search: Search visibility requires separate handling
§Arguments
  • task - Task object with updated properties and valid ID
§Returns

Returns Ok(()) if the update succeeds, or an error if the operation fails or the task doesn’t exist.

§Example
let mut tasks = Tasks::new()?;
let task_id = 1;
let mut task = tasks.get_by_id(task_id)?.unwrap();
task.name = "Updated task name".to_string();
task.completeness = Some(75);
tasks.update(&task)?;
§Errors

Returns an error if:

  • Task doesn’t have a valid ID (not saved to database)
  • No task exists with the specified ID
  • Database constraints are violated
  • Connection or transaction failures occur
Source

pub fn get_by_id(&mut self, id: i32) -> Result<Option<Task>>

Retrieves a single task by its unique identifier.

This convenience method fetches a complete task record including all associated tags and properties. It’s a specialized version of the fetch method optimized for single-task retrieval.

§Arguments
  • id - Unique identifier of the task to retrieve
§Returns

Returns Some(Task) if found, None if the task doesn’t exist, or an error if the database query fails.

§Example
let mut tasks = Tasks::new()?;
if let Some(task) = tasks.get_by_id(42)? {
    println!("Found task: {}", task.name);
} else {
    println!("Task with ID 42 not found");
}
§Performance

This method internally uses the fetch mechanism with ID filtering, so it includes full tag loading and relationship resolution. For simple existence checking, use the exists method instead.

Trait Implementations§

Source§

impl Debug for Tasks

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl !Freeze for Tasks

§

impl !RefUnwindSafe for Tasks

§

impl !Sync for Tasks

§

impl !UnwindSafe for Tasks

§

impl Send for Tasks

§

impl Unpin for Tasks

§

impl UnsafeUnpin for Tasks

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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> 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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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 = 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<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

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