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: ConnectionDirect 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
impl Tasks
Sourcepub fn new() -> Result<Self>
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
Sourcepub fn insert(&mut self, task: &Task) -> Result<&mut Self>
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
Sourcepub fn update_id(&mut self) -> Result<&mut Self>
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
Sourcepub fn get(&mut self) -> Result<Vec<Task>>
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
Sourcepub fn fetch(&mut self, filter: TaskFilter) -> Result<Vec<Task>>
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
Sourcepub fn delete(&mut self, id: i32) -> Result<usize>
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
Sourcepub fn delete_many(&mut self, ids: &[i32]) -> Result<usize>
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
Sourcepub fn exists(&mut self, id: i32) -> Result<bool>
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.
Sourcepub fn update(&mut self, task: &Task) -> Result<()>
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
Sourcepub fn get_by_id(&mut self, id: i32) -> Result<Option<Task>>
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.