836 lines
18 KiB
C
836 lines
18 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include "sqlite3.h"
|
|
#include "x_string.h"
|
|
#include "x_curses.h"
|
|
#include "x_ctypes.h"
|
|
#include "dodo.h"
|
|
|
|
//TODO: check that only one row is modified with sqlite3_change()
|
|
|
|
// FOR DEBUG
|
|
int callback(void *NotUsed, int argc, char **argv, char **azColName){
|
|
int i;
|
|
for(i=0; i<argc; i++){
|
|
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
|
|
}
|
|
printf("\n");
|
|
return 0;
|
|
}
|
|
|
|
// FOR DEBUG
|
|
int view_all(sqlite3 *db){
|
|
int rc = 0;
|
|
char* errmsg;
|
|
|
|
//rc = sqlite3_exec(db, "SELECT * FROM all_info;", print_select, 0, &errmsg);
|
|
rc = sqlite3_exec(db, "SELECT * FROM tasks;", callback, 0, &errmsg);
|
|
//rc = sqlite3_exec(db, "SELECT * FROM entries;", print_select, 0, &errmsg);
|
|
checksqlerr(rc, errmsg);
|
|
return rc;
|
|
}
|
|
|
|
int get_today(date *d){
|
|
struct tm *local;
|
|
time_t rawtime;
|
|
|
|
time(&rawtime);
|
|
|
|
local = localtime(&rawtime);
|
|
|
|
d->year = local->tm_year + 1900;
|
|
d->month = local->tm_mon + 1;
|
|
d->day = local->tm_mday;
|
|
d->dow = local->tm_wday;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int get_day_of_week(date *d, int target_day_of_week){
|
|
struct tm *local;
|
|
time_t rawtime;
|
|
int days_to_add = 0;
|
|
|
|
time(&rawtime);
|
|
local = localtime(&rawtime);
|
|
|
|
days_to_add = ( target_day_of_week - local->tm_wday + 7 ) % 7;
|
|
|
|
if ( days_to_add == 0 ){
|
|
days_to_add = 7;
|
|
}
|
|
|
|
local->tm_mday += days_to_add;
|
|
|
|
mktime(local);
|
|
|
|
d->year = local->tm_year + 1900;
|
|
d->month = local->tm_mon + 1;
|
|
d->day = local->tm_mday;
|
|
d->dow = local->tm_wday;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_due_date(filtered_tasks *task, char* passed_date){
|
|
int day_of_week = 0; // Sunday = 0 Monday = 1 .. Saterday = 6
|
|
date *d = malloc(sizeof(date));
|
|
|
|
if ( x_strcmp(passed_date, "today") == 0 ){
|
|
get_today(d);
|
|
}
|
|
else if ( x_strcmp(passed_date, "tomorrow") == 0 ) {
|
|
get_today(d);
|
|
get_day_of_week(d, d->dow + 1);
|
|
}
|
|
else if ( x_strcmp(passed_date, "sun") == 0 ){
|
|
day_of_week = 0;
|
|
get_day_of_week(d, day_of_week);
|
|
}
|
|
else if ( x_strcmp(passed_date, "mon") == 0 ){
|
|
day_of_week = 1;
|
|
get_day_of_week(d, day_of_week);
|
|
}
|
|
else if ( x_strcmp(passed_date, "tues") == 0 ){
|
|
day_of_week = 2;
|
|
get_day_of_week(d, day_of_week);
|
|
}
|
|
else if ( x_strcmp(passed_date, "wed") == 0 ){
|
|
day_of_week = 3;
|
|
get_day_of_week(d, day_of_week);
|
|
}
|
|
else if ( x_strcmp(passed_date, "thurs") == 0 ){
|
|
day_of_week = 4;
|
|
get_day_of_week(d, day_of_week);
|
|
}
|
|
else if ( x_strcmp(passed_date, "fri") == 0 ){
|
|
day_of_week = 5;
|
|
get_day_of_week(d, day_of_week);
|
|
}
|
|
else if ( x_strcmp(passed_date, "sat") == 0 ){
|
|
day_of_week = 6;
|
|
get_day_of_week(d, day_of_week);
|
|
}
|
|
else{
|
|
task->due_date = passed_date;
|
|
return 0;
|
|
}
|
|
|
|
task->due_date = malloc(ARG_MAX * sizeof(char));
|
|
snprintf(task->due_date, ARG_MAX, "%04d-%02d-%02d", d->year, d->month, d->day);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void init_filtered_tasks(filtered_tasks* task){
|
|
task->selected_columns = NULL;
|
|
task->title = NULL;
|
|
task->new_title = NULL;
|
|
task->active_id = -1;
|
|
task->status = NULL;
|
|
task->project_tag = NULL;
|
|
task->due_date = NULL;
|
|
}
|
|
|
|
|
|
// TODO: prob should use realloc woops!
|
|
char* concat_with_mem_cleanup(char* str1, char* str2){
|
|
char *temp;
|
|
|
|
if ( str1 == NULL || str2 == NULL ){
|
|
return NULL;
|
|
}
|
|
|
|
temp = str1;
|
|
str1 = x_strconcat(str1, str2);
|
|
free(temp);
|
|
|
|
return str1;
|
|
}
|
|
|
|
|
|
int prepare_sql_update_stmt(sqlite3 *db, sqlite3_stmt** out_stmt, filtered_tasks* task){
|
|
char *sql_query;
|
|
int rc = 0;
|
|
int num_params = 0;
|
|
|
|
sql_query = malloc(SQLQUERY_MAX * sizeof(char));
|
|
|
|
x_strcpy(sql_query,"UPDATE tasks SET ", SQLQUERY_MAX);
|
|
|
|
if ( task->new_title ){
|
|
sql_query = concat_with_mem_cleanup(sql_query, "title=?");
|
|
num_params++;
|
|
}
|
|
|
|
if ( task->due_date ){
|
|
if ( num_params > 0 ){
|
|
sql_query = concat_with_mem_cleanup(sql_query, ",");
|
|
}
|
|
sql_query = concat_with_mem_cleanup(sql_query, "due_date=?");
|
|
num_params++;
|
|
}
|
|
|
|
if ( task->status ){
|
|
if ( num_params > 0 ){
|
|
sql_query = concat_with_mem_cleanup(sql_query, ",");
|
|
}
|
|
sql_query = concat_with_mem_cleanup(sql_query, "status=?");
|
|
num_params++;
|
|
|
|
if ( !(x_strcmp(task->status, "complete")) ){
|
|
sql_query = concat_with_mem_cleanup(sql_query, ",");
|
|
sql_query = concat_with_mem_cleanup(sql_query, "active_id='NULL'");
|
|
}
|
|
}
|
|
|
|
sql_query = concat_with_mem_cleanup(sql_query, " WHERE ");
|
|
|
|
if ( task->title ){
|
|
sql_query = concat_with_mem_cleanup(sql_query, "title=?");
|
|
num_params++;
|
|
}
|
|
else if ( task->active_id != -1 ){
|
|
sql_query = concat_with_mem_cleanup(sql_query, "active_id=?");
|
|
num_params++;
|
|
}
|
|
else {
|
|
free(sql_query);
|
|
return -1;
|
|
|
|
}
|
|
|
|
rc = sqlite3_prepare_v2(db, sql_query, -1, out_stmt, NULL);
|
|
free(sql_query);
|
|
|
|
if (checksqlerr(rc, "prepare broken in gen_sql_insert_stmt")){
|
|
return -1;
|
|
}
|
|
|
|
return num_params;
|
|
}
|
|
|
|
int bind_sql_update_stmt(filtered_tasks* task, int num_params, sqlite3_stmt* out_stmt){
|
|
int max_param = 0;
|
|
int param_pos = 0;
|
|
int rc = 0;
|
|
|
|
max_param = num_params;
|
|
|
|
if ( task->new_title ){
|
|
param_pos = max_param - num_params + 1;
|
|
rc = sqlite3_bind_text(out_stmt, param_pos, task->new_title, -1, SQLITE_STATIC);
|
|
num_params--;
|
|
}
|
|
|
|
if (checksqlerr(rc, "prepare broken in bind_sql_update_stmt")){
|
|
return -1;
|
|
}
|
|
|
|
if ( task->due_date ){
|
|
param_pos = max_param - num_params + 1;
|
|
rc = sqlite3_bind_text(out_stmt, param_pos, task->due_date, -1, SQLITE_STATIC);
|
|
num_params--;
|
|
}
|
|
|
|
if (checksqlerr(rc, "prepare broken in bind_sql_update_stmt")){
|
|
return -1;
|
|
}
|
|
|
|
if ( task->status ){
|
|
param_pos = max_param - num_params + 1;
|
|
rc = sqlite3_bind_text(out_stmt, param_pos, task->status, -1, SQLITE_STATIC);
|
|
num_params--;
|
|
}
|
|
|
|
if ( task->title ){
|
|
param_pos = max_param - num_params + 1;
|
|
rc = sqlite3_bind_text(out_stmt, param_pos, task->title, -1, SQLITE_STATIC);
|
|
num_params--;
|
|
}
|
|
else if ( task->active_id != -1 ){
|
|
param_pos = max_param - num_params + 1;
|
|
rc = sqlite3_bind_int(out_stmt, param_pos, task->active_id);
|
|
num_params--;
|
|
}
|
|
else{
|
|
return -1;
|
|
}
|
|
|
|
if (checksqlerr(rc, "prepare broken in bind_sql_update_stmt")){
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int prepare_sql_delete_stmt(sqlite3 *db, sqlite3_stmt** out_stmt, filtered_tasks* task){
|
|
char *sql_query;
|
|
int rc = 0;
|
|
|
|
sql_query = malloc(SQLQUERY_MAX * sizeof(char));
|
|
|
|
x_strcpy(sql_query,"DELETE FROM tasks WHERE ", SQLQUERY_MAX);
|
|
|
|
if ( task->title ){
|
|
sql_query = concat_with_mem_cleanup(sql_query, "title=? AND active_id IS NOT NULL");
|
|
}
|
|
else if ( task->active_id != -1 ){
|
|
sql_query = concat_with_mem_cleanup(sql_query, "active_id=?");
|
|
}
|
|
else{
|
|
free(sql_query);
|
|
return -1;
|
|
}
|
|
|
|
rc = sqlite3_prepare_v2(db, sql_query, -1, out_stmt, NULL);
|
|
free(sql_query);
|
|
|
|
if (checksqlerr(rc, "prepare broken in gen_sql_insert_stmt")){
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int bind_sql_delete_stmt(filtered_tasks* task, sqlite3_stmt* out_stmt){
|
|
int rc = 0;
|
|
const int param_pos = 1;
|
|
|
|
if ( task->title ){
|
|
rc = sqlite3_bind_text(out_stmt, param_pos, task->title, -1, SQLITE_STATIC);
|
|
}
|
|
else if ( task->active_id != -1 ){
|
|
rc = sqlite3_bind_int(out_stmt, param_pos, task->active_id);
|
|
}
|
|
else{
|
|
return -1;
|
|
}
|
|
|
|
if (checksqlerr(rc, "prepare broken in gen_sql_insert_stmt")){
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int prepare_sql_insert_stmt(sqlite3 *db, sqlite3_stmt** out_stmt, filtered_tasks* task, char* values){
|
|
char sql_query[SQLQUERY_MAX];
|
|
int rc = 0;
|
|
|
|
snprintf(sql_query, SQLQUERY_MAX, "INSERT INTO tasks %s VALUES %s", task->selected_columns, values);
|
|
rc = sqlite3_prepare_v2(db, sql_query, -1, out_stmt, NULL);
|
|
|
|
if (checksqlerr(rc, "prepare broken in gen_sql_insert_stmt")){
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int bind_sql_insert_stmt(filtered_tasks* task, sqlite3_stmt* out_stmt){
|
|
int rc = 0;
|
|
int param_pos = 1;
|
|
|
|
if ( task->title ){
|
|
rc = sqlite3_bind_text(out_stmt, param_pos, task->title, -1, SQLITE_STATIC);
|
|
}
|
|
|
|
if (checksqlerr(rc, "prepare broken in gen_sql_insert_stmt")){
|
|
return -1;
|
|
}
|
|
|
|
if ( task->due_date ){
|
|
param_pos = 2;
|
|
rc = sqlite3_bind_text(out_stmt, param_pos, task->due_date, -1, SQLITE_STATIC);
|
|
}
|
|
|
|
if (checksqlerr(rc, "prepare broken in gen_sql_insert_stmt")){
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
// Generate the sql statement by giving the columns, table, and current task list wanted
|
|
int prepare_sql_select_stmt(sqlite3 *db, sqlite3_stmt** out_stmt, filtered_tasks* task){
|
|
char sql_query[SQLQUERY_MAX];
|
|
int rc = 0;
|
|
|
|
snprintf(sql_query, SQLQUERY_MAX, "SELECT %s FROM tasks WHERE status=? AND active_id!='NULL' ORDER BY due_date NULLS LAST", task->selected_columns);
|
|
|
|
rc = sqlite3_prepare_v2(db, sql_query, -1, out_stmt, NULL);
|
|
|
|
if (checksqlerr(rc, "prepare broken in gen_sql_select_stmt")){
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int bind_sql_select_stmt(filtered_tasks* task, sqlite3_stmt* out_stmt){
|
|
int rc = 0;
|
|
const int param_pos = 1;
|
|
|
|
if ( task->status ){
|
|
rc = sqlite3_bind_text(out_stmt, param_pos, task->status, -1, SQLITE_STATIC);
|
|
}
|
|
|
|
if (checksqlerr(rc, "prepare broken in gen_sql_insert_stmt")){
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
// TODO: I think this needs a bit of a refactor not sure how
|
|
int checksqlerr(int rc, char *errmsg){
|
|
if( rc!=SQLITE_OK ){
|
|
fprintf(stderr, "rc = %d\n", rc);
|
|
fprintf(stderr, "SQL error: %s\n", errmsg);
|
|
//sqlite3_free(errmsg);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int opendb(sqlite3 **db, char* filename){
|
|
int rc = 0;
|
|
|
|
rc = sqlite3_open(filename, db);
|
|
|
|
if ( rc != 0 ){
|
|
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(*db));
|
|
sqlite3_close(*db);
|
|
return(rc);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
void display_task_list_heading(char* heading){
|
|
int width = (FIXED_ID_WIDTH + FIXED_TITLE_WIDTH + FIXED_DATE_WIDTH + x_strlen(heading) );
|
|
int width_div_2 = width / 2;
|
|
printf("%s%*s", X_BOLD, width_div_2, heading);
|
|
printf("%*s", width_div_2 - x_strlen(heading), "");
|
|
printf(" ");
|
|
}
|
|
|
|
void display_column_heading(const char* str){
|
|
int width = 0;
|
|
|
|
if ( x_strcmp(str, "id") == 0 ){
|
|
width = FIXED_ID_WIDTH;
|
|
}
|
|
else if ( x_strcmp(str, "title") == 0 ){
|
|
width = FIXED_TITLE_WIDTH;
|
|
}
|
|
else if ( x_strcmp(str, "due_date") == 0 ){
|
|
width = FIXED_DATE_WIDTH;
|
|
}
|
|
else{
|
|
width = FIXED_MAX_WIDTH;
|
|
}
|
|
|
|
printf("%s%s%-*.*s%s", X_BOLD, X_UNDL, width, width, str, X_RST);
|
|
}
|
|
|
|
void display_column_headings_for_all_task_lists(){
|
|
int i = 0;
|
|
char* str;
|
|
for ( i = 0; i < NUM_TASK_LISTS; i++){
|
|
str = "id";
|
|
display_column_heading(str);
|
|
str = "title";
|
|
display_column_heading(str);
|
|
str = "due_date";
|
|
display_column_heading(str);
|
|
printf(" ");
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
|
|
// pass in the args and return the title and due date
|
|
// due date passed as NULL if for delete
|
|
// TODO input validation for strings implement in strings!
|
|
// TODO maybe a Abstract Sytnax Tree for parsing
|
|
int parse_args(int argc, char** argv, filtered_tasks* task){
|
|
|
|
if ( argc > 2 ){
|
|
if ( x_isnumber(argv[2]) ){
|
|
task->active_id = atoi(argv[2]);
|
|
}
|
|
else {
|
|
task->title = argv[2];
|
|
}
|
|
}
|
|
|
|
if ( argc > 3 ){
|
|
if ( x_strcmp(argv[1], "update") ){
|
|
get_due_date(task, argv[3]);
|
|
return 0;
|
|
}
|
|
else{
|
|
task->new_title = argv[3];
|
|
}
|
|
}
|
|
|
|
if ( argc > 4 ){
|
|
get_due_date(task, argv[4]);
|
|
}
|
|
|
|
if ( argc > 5 ){
|
|
task->project_tag = argv[5];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Get number of tasks from tasks table give status
|
|
int get_num_rows(sqlite3 *db, char* table, char* status){
|
|
filtered_tasks* task = malloc(sizeof(filtered_tasks));
|
|
task->status = status;
|
|
task->selected_columns = "COUNT(*)";
|
|
sqlite3_stmt *out_stmt;
|
|
int rc = 0;
|
|
|
|
if ( prepare_sql_select_stmt(db, &out_stmt, task) == 1 ){
|
|
return -1;
|
|
}
|
|
|
|
if ( ( rc = bind_sql_select_stmt(task, out_stmt) ) ){
|
|
return -1;
|
|
}
|
|
|
|
free(task);
|
|
|
|
while ( rc = sqlite3_step(out_stmt) == SQLITE_ROW ){
|
|
return sqlite3_column_int(out_stmt, 0);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
// Print with FIXED_WIDTH
|
|
int print_fixed_width(const unsigned char* str, int width){
|
|
if (str){
|
|
printf("%-*.*s", width, width - FIXED_WHITESPACE, str);
|
|
}else{
|
|
printf("%-*.*s", width, width, "");
|
|
}
|
|
}
|
|
|
|
// Print Heading
|
|
void display_heading(){
|
|
char * str;
|
|
|
|
printf("\n");
|
|
str = "Today";
|
|
display_task_list_heading(str);
|
|
str = "Backlog";
|
|
display_task_list_heading(str);
|
|
str = "Blocked";
|
|
display_task_list_heading(str);
|
|
printf("\n");
|
|
|
|
display_column_headings_for_all_task_lists();
|
|
}
|
|
|
|
int display_task_list(int start_col, sqlite3 *db, filtered_tasks* task){
|
|
static int max_rows = -1;
|
|
int rc = 0;
|
|
int i = 0;
|
|
int num_rows = -1;
|
|
int num_cols = 0;
|
|
int fixed_width = 0;
|
|
char* errmsg;
|
|
const unsigned char* col_val;
|
|
const unsigned char* col_name;
|
|
sqlite3_stmt* out_stmt;
|
|
char* table = "tasks";
|
|
|
|
// Get the number of rows in current task list
|
|
num_rows = get_num_rows(db, table, task->status);
|
|
// Then keep track of the furthest down we go
|
|
if (num_rows > max_rows){
|
|
max_rows = num_rows;
|
|
}
|
|
|
|
// Generate the sql statement by giving the columns, table, and current task list wanted
|
|
if ( prepare_sql_select_stmt(db, &out_stmt, task) ){
|
|
return -1;
|
|
}
|
|
|
|
if ( bind_sql_select_stmt(task, out_stmt) ){
|
|
return -1;
|
|
}
|
|
|
|
// TODO: prob should be a func begin
|
|
// Start col for the current task list
|
|
X_goright(start_col);
|
|
|
|
// while there is still rows available
|
|
while ( rc = sqlite3_step(out_stmt) == SQLITE_ROW ){
|
|
// for each column print the column
|
|
num_cols = sqlite3_column_count(out_stmt);
|
|
for (i = 0; i < num_cols; i++){
|
|
col_val = sqlite3_column_text(out_stmt, i);
|
|
col_name = sqlite3_column_name(out_stmt, i);
|
|
if ( x_strcmp(col_name, "title") == 0 ){
|
|
fixed_width = FIXED_TITLE_WIDTH;
|
|
}
|
|
else if ( x_strcmp(col_name, "active_id") == 0 ){
|
|
fixed_width = FIXED_ID_WIDTH;
|
|
}
|
|
else if ( x_strcmp(col_name, "due_date") == 0 ){
|
|
fixed_width = FIXED_DATE_WIDTH;
|
|
}
|
|
print_fixed_width(col_val, fixed_width);
|
|
}
|
|
// end
|
|
|
|
// move down one and over to the start of the current task column
|
|
printf("\n");
|
|
X_goright(start_col);
|
|
}
|
|
|
|
// reset to the beginning of the line
|
|
printf("\r");
|
|
|
|
// if while loop broke and rc returned an error
|
|
if ( rc == SQLITE_ERROR ){
|
|
X_godown(max_rows);
|
|
checksqlerr(rc, "step broken in display_task_list");
|
|
return -1;
|
|
}
|
|
|
|
// Once the task list is completely printed
|
|
// reset to the top of the task lists
|
|
if (num_rows > 0){
|
|
X_goup(num_rows);
|
|
}
|
|
|
|
// if it is the last task list move down one past the longest list
|
|
if ( x_strcmp(task->status, "blocked") == 0){
|
|
X_godown(max_rows);
|
|
printf("\n");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Print kanban table
|
|
// All lists with task name and due date
|
|
int view_tasks(sqlite3 *db){
|
|
|
|
// Set the table and cols to be printed
|
|
filtered_tasks* tasks = malloc(sizeof(filtered_tasks));
|
|
// TODO check that malloc is ok
|
|
|
|
init_filtered_tasks(tasks);
|
|
tasks->selected_columns = "active_id, title, due_date";
|
|
|
|
// Print Heading
|
|
display_heading();
|
|
|
|
// Print "today" tasks
|
|
tasks->status = "today";
|
|
if ( display_task_list(TODAY_COL_START, db, tasks) ){
|
|
free(tasks);
|
|
return -1;
|
|
}
|
|
|
|
// Print "backlog" tasks
|
|
tasks->status = "backlog";
|
|
if ( display_task_list(BACKLOG_COL_START, db, tasks) ){
|
|
free(tasks);
|
|
return -1;
|
|
}
|
|
|
|
// Print "blocked" tasks
|
|
tasks->status = "blocked";
|
|
if ( display_task_list(BLOCKED_COL_START, db, tasks) ){
|
|
free(tasks);
|
|
return -1;
|
|
}
|
|
|
|
free(tasks);
|
|
return 0;
|
|
}
|
|
|
|
int add_new_task(sqlite3 *db, int argc, char** argv){
|
|
int rc = 0;
|
|
char values[ARG_MAX];
|
|
sqlite3_stmt* out_stmt;
|
|
|
|
filtered_tasks* task = malloc(sizeof(filtered_tasks));
|
|
|
|
init_filtered_tasks(task);
|
|
|
|
parse_args(argc, argv, task);
|
|
|
|
if ( task->title != NULL ){
|
|
if ( task->due_date != NULL ){
|
|
task->selected_columns = "(title, due_date)";
|
|
snprintf(values, ARG_MAX, "(?, ?)");
|
|
}
|
|
else{
|
|
task->selected_columns = "(title)";
|
|
snprintf(values, ARG_MAX, "(?)");
|
|
}
|
|
}
|
|
else{
|
|
return -1;
|
|
}
|
|
|
|
if ( ( rc = prepare_sql_insert_stmt(db, &out_stmt, task, values) ) ){
|
|
return -1;
|
|
}
|
|
|
|
if ( ( rc = bind_sql_insert_stmt(task, out_stmt) ) ){
|
|
return -1;
|
|
}
|
|
|
|
if ( ( rc = sqlite3_step(out_stmt) ) == SQLITE_DONE){
|
|
return 0;
|
|
}
|
|
|
|
checksqlerr(rc, "broken in add_new_task");
|
|
return -1;
|
|
}
|
|
|
|
|
|
int update_task_status(sqlite3 *db, int argc, char** argv){
|
|
int rc = 0;
|
|
int num_params = 0;
|
|
sqlite3_stmt* out_stmt;
|
|
filtered_tasks* task = malloc(sizeof(filtered_tasks));
|
|
|
|
init_filtered_tasks(task);
|
|
|
|
parse_args(argc, argv, task);
|
|
|
|
task->status = argv[1];
|
|
|
|
if ( ( num_params = prepare_sql_update_stmt(db, &out_stmt, task) ) == -1 ){
|
|
free(task);
|
|
return -1;
|
|
}
|
|
|
|
if ( ( rc = bind_sql_update_stmt(task, num_params, out_stmt) ) ){
|
|
free(task);
|
|
return -1;
|
|
}
|
|
|
|
if ( ( rc = sqlite3_step(out_stmt) ) == SQLITE_DONE){
|
|
free(task);
|
|
return 0;
|
|
}
|
|
|
|
checksqlerr(rc, "broken in update_task_status");
|
|
|
|
free(task);
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
int complete_task(sqlite3 *db, int argc, char** argv){
|
|
int rc = 0;
|
|
int num_params = 0;
|
|
sqlite3_stmt* out_stmt;
|
|
filtered_tasks* task = malloc(sizeof(filtered_tasks));
|
|
|
|
init_filtered_tasks(task);
|
|
|
|
task->status = "complete";
|
|
|
|
parse_args(argc, argv, task);
|
|
if ( ( num_params = prepare_sql_update_stmt(db, &out_stmt, task) ) == -1 ){
|
|
free(task);
|
|
return -1;
|
|
}
|
|
|
|
if ( ( rc = bind_sql_update_stmt(task, num_params, out_stmt) ) ){
|
|
free(task);
|
|
return -1;
|
|
}
|
|
|
|
if ( ( rc = sqlite3_step(out_stmt) ) == SQLITE_DONE){
|
|
free(task);
|
|
return 0;
|
|
}
|
|
|
|
checksqlerr(rc, "broken in complete_task");
|
|
|
|
free(task);
|
|
return -1;
|
|
}
|
|
|
|
int update_task(sqlite3 *db, int argc, char** argv){
|
|
int rc = 0;
|
|
int num_params = 0;
|
|
sqlite3_stmt* out_stmt;
|
|
filtered_tasks* task = malloc(sizeof(filtered_tasks));
|
|
|
|
init_filtered_tasks(task);
|
|
|
|
|
|
parse_args(argc, argv, task);
|
|
|
|
if ( ( num_params = prepare_sql_update_stmt(db, &out_stmt, task) ) == -1 ){
|
|
free(task);
|
|
return -1;
|
|
}
|
|
|
|
if ( ( rc = bind_sql_update_stmt(task, num_params, out_stmt) ) ){
|
|
free(task);
|
|
return -1;
|
|
}
|
|
|
|
if ( ( rc = sqlite3_step(out_stmt) ) == SQLITE_DONE){
|
|
free(task);
|
|
return 0;
|
|
}
|
|
|
|
checksqlerr(rc, "broken in update_task");
|
|
|
|
free(task);
|
|
return -1;
|
|
}
|
|
|
|
|
|
int del_task(sqlite3 *db, int argc, char** argv){
|
|
int rc = 0;
|
|
sqlite3_stmt* out_stmt;
|
|
filtered_tasks* task = malloc(sizeof(filtered_tasks));
|
|
|
|
init_filtered_tasks(task);
|
|
|
|
|
|
parse_args(argc, argv, task);
|
|
if ( prepare_sql_delete_stmt(db, &out_stmt, task) ){
|
|
free(task);
|
|
return -1;
|
|
}
|
|
|
|
if ( ( rc = bind_sql_delete_stmt(task, out_stmt) ) ){
|
|
free(task);
|
|
return -1;
|
|
}
|
|
|
|
if ( ( rc = sqlite3_step(out_stmt) ) == SQLITE_DONE){
|
|
free(task);
|
|
return 0;
|
|
}
|
|
|
|
checksqlerr(rc, "broken in del_task");
|
|
|
|
free(task);
|
|
return -1;
|
|
}
|