#ifndef DB_UTILS_H #define DB_UTILS_H #include "r.h" #include "utils.h" #include <json-c/json.h> #include <sqlite3.h> json_object *db_execute(const char *query); char *db_file_expanded() { char *expanded = expand_home_directory(DB_FILE); static char result[4096]; result[0] = 0; strcpy(result, expanded); free(expanded); return result; } void db_initialize(); json_object *db_set(const char *key, const char *value); json_object *db_get(const char *key); json_object *db_query(const char *query); void db_initialize() { sqlite3 *db; int rc = sqlite3_open(db_file_expanded(), &db); if (rc != SQLITE_OK) { return; } db_execute("CREATE TABLE IF NOT EXISTS kv_store (key TEXT PRIMARY KEY, value TEXT);"); db_execute("CREATE TABLE IF NOT EXISTS file_version_history ( id INTEGER PRIMARY KEY AUTOINCREMENT," "path TEXT NOT NULL," "content TEXT," "date DATETIME DEFAULT CURRENT_TIMESTAMP" ");"); sqlite3_close(db); } json_object *db_set(const char *key, const char *value) { sqlite3 *db; char *err_msg = 0; int rc = sqlite3_open(db_file_expanded(), &db); if (rc != SQLITE_OK) { return NULL; } char *sql = sqlite3_mprintf("INSERT INTO kv_store (key, value) VALUES (%Q, %Q) ON " "CONFLICT(key) DO UPDATE SET value = %Q WHERE key = %Q", key, value, value, key); rc = sqlite3_exec(db, sql, 0, 0, &err_msg); sqlite3_free(sql); if (rc != SQLITE_OK) { sqlite3_free(err_msg); sqlite3_close(db); return NULL; } sqlite3_close(db); return json_object_new_string("Success"); } json_object *db_get(const char *key) { sqlite3 *db; sqlite3_stmt *stmt; json_object *result = json_object_new_object(); const char *value = NULL; int rc = sqlite3_open(db_file_expanded(), &db); if (rc != SQLITE_OK) { return NULL; } const char *sql = "SELECT value FROM kv_store WHERE key = ?"; sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC); if (sqlite3_step(stmt) == SQLITE_ROW) { value = (const char *)sqlite3_column_text(stmt, 0); } if (value) { json_object_object_add(result, "value", json_object_new_string(value)); } else { json_object_object_add(result, "error", json_object_new_string("Key not found")); } sqlite3_finalize(stmt); sqlite3_close(db); return result; } json_object *db_query(const char *query) { sqlite3 *db; sqlite3_stmt *stmt; if (strncmp(query, "SELECT", 6)) { return db_execute(query); } json_object *result = json_object_new_array(); int rc = sqlite3_open(db_file_expanded(), &db); if (rc != SQLITE_OK) { return NULL; } sqlite3_prepare_v2(db, query, -1, &stmt, NULL); while (sqlite3_step(stmt) == SQLITE_ROW) { json_object *row = json_object_new_object(); for (int i = 0; i < sqlite3_column_count(stmt); i++) { const char *col_name = sqlite3_column_name(stmt, i); switch (sqlite3_column_type(stmt, i)) { case SQLITE_INTEGER: json_object_object_add( row, col_name, json_object_new_int64(sqlite3_column_int64(stmt, i))); break; case SQLITE_FLOAT: json_object_object_add( row, col_name, json_object_new_double(sqlite3_column_double(stmt, i))); break; case SQLITE_TEXT: json_object_object_add( row, col_name, json_object_new_string((const char *)sqlite3_column_text(stmt, i))); break; case SQLITE_BLOB: json_object_object_add(row, col_name, json_object_new_string_len( (const char *)sqlite3_column_blob(stmt, i), sqlite3_column_bytes(stmt, i))); break; case SQLITE_NULL: default: json_object_object_add(row, col_name, json_object_new_string("NULL")); break; } } json_object_array_add(result, row); } sqlite3_finalize(stmt); sqlite3_close(db); return result; } json_object *db_execute(const char *query) { sqlite3 *db; char *err_msg = 0; int rc = sqlite3_open(db_file_expanded(), &db); json_object *result = json_object_new_object(); if (rc != SQLITE_OK) { json_object_object_add(result, "error", json_object_new_string("Cannot open database")); return result; } rc = sqlite3_exec(db, query, 0, 0, &err_msg); if (rc != SQLITE_OK) { json_object_object_add(result, "error", json_object_new_string(err_msg)); sqlite3_free(err_msg); } else { json_object_object_add( result, "success", json_object_new_string("Query executed successfully")); } sqlite3_close(db); return result; } void db_store_file_version(const char * path) { char * expanded = expand_home_directory(path); char * content = read_file(expanded); if(!content) { return; } fprintf(stderr, "Creating backup:: %s\n", expanded); char * formatted = sqlite3_mprintf("INSERT INTO file_version_history (path, content) VALUES (%Q, %Q)", expanded, content); db_execute(formatted); sqlite3_free(formatted); free(content); } char *db_get_schema() { json_object *tables = db_query("SELECT * FROM sqlite_master WHERE type='table'"); char *result = strdup(json_object_get_string(tables)); json_object_put(tables); return result; } #endif