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ยง

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