]> uap-core.de Git - note.git/commitdiff
implement sub-tree deletion in note_store_delete_collection_async main
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Tue, 20 Jan 2026 19:48:14 +0000 (20:48 +0100)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Tue, 20 Jan 2026 19:48:14 +0000 (20:48 +0100)
application/store.c
application/store_sqlite.c
application/tests/test-store.c

index e7f677379983c03778054bc6d6292aa64111e30d..3f6525af758a54bb17a6cfee7be730dd3cbdb296 100644 (file)
 
 #define SQL_RESOURCE_DELETE_CHILDREN "delete from resources where parent_id = ? ;"
 
+#define SQL_RESOURCE_DELETE_ALL \
+    "with recursive cte as ( " \
+    "    select resource_id, parent_id, nodename from resources where resource_id = ? " \
+    "    union all " \
+    "    select r.resource_id, r.parent_id, r.nodename from resources r join cte on r.parent_id = cte.resource_id " \
+    ") " \
+    "delete from resources where resource_id in (select resource_id from cte);"
+
 #define SQL_RESOURCE_UPDATE_PARENT "update resources set parent_id = ? where parent_id = ? ;"
 
 #define SQL_RESOURCE_COUNT_CHILDREN "select count(*) from resources where parent_id = ? ;"
@@ -1208,7 +1216,7 @@ static void uithr_execjob_finished(UiEvent *event, ExecJob *job) {
 
 static int qthr_delete_collection(ExecJob *job) {
     if(job->flag == NOTESTORE_COLLECTION_DELETE_ALL) {
-        DBUResult *result = dbuSqlExecParamInt64(connection, NULL, SQL_RESOURCE_DELETE_CHILDREN, job->id1);
+        DBUResult *result = dbuSqlExecParamInt64(connection, NULL, SQL_RESOURCE_DELETE_ALL, job->id1);
         if(!result) {
             job->error = 3;
             return 0;
@@ -1230,16 +1238,16 @@ static int qthr_delete_collection(ExecJob *job) {
             job->error = 2; // db error
             return 0;
         } 
-    }
-    
-    DBUResult *result = dbuSqlExecParamInt64(connection, NULL, SQL_RESOURCE_DELETE, job->id1);
-    if(!result) {
-        job->error = 5;
-    }
-    int ok = dbuResultIsOk(result);
-    dbuResultFree(result);
-    if(!ok) {
-        job->error = 6;
+        
+        DBUResult *result = dbuSqlExecParamInt64(connection, NULL, SQL_RESOURCE_DELETE, job->id1);
+        if(!result) {
+            job->error = 5;
+        }
+        int ok = dbuResultIsOk(result);
+        dbuResultFree(result);
+        if(!ok) {
+            job->error = 6;
+        }
     }
     
     return 0;
index 79c8d867fecaeb38402e39fccd6c61a49289d39b..8ecf6ca483597810724f923650ebb18f798a0f40 100644 (file)
@@ -67,7 +67,7 @@
     "creationdate            integer, " \
     "etag                    text, " \
     "content                 blob, " \
-    "foreign key (parent_id) references resources(resource_id), " \
+    "foreign key (parent_id) references resources(resource_id) on delete cascade, " \
     "unique (parent_id, nodename) " \
     ");"
 #define SQL_CREATE_TABLE_NOTES "create table notes( " \
@@ -92,8 +92,8 @@
     "attachment_resource_id  integer, " \
     "parent_resource_id      integer, " \
     "type                    integer , " \
-    "foreign key (attachment_resource_id) references resources(resource_id), " \
-    "foreign key (parent_resource_id) references resources(resource_id) " \
+    "foreign key (attachment_resource_id) references resources(resource_id) on delete cascade, " \
+    "foreign key (parent_resource_id) references resources(resource_id) on delete cascade" \
     ");"
 
 int store_sqlite_init_db(DBUConnection *connection) {
index c5486216b13cd3213794724e998fb1868c422f6d..665507c3f414be1bf39a31f7a687167f92a17bd5 100644 (file)
@@ -558,10 +558,32 @@ CX_TEST(test_note_store_delete_collection_async) {
         ui_exec_buffered_mainthread_calls_wait(3);
         
         CX_TEST_ASSERT(error == 0);
-        CX_TEST_ASSERT(res1->resource_id != 0);
+        CX_TEST_ASSERT(res1_child->resource_id != 0);
+        
+        Resource *res1_child_collection = cxZalloc(store->mp->allocator, sizeof(Resource));
+        res1_child_collection->parent_id = res1->resource_id;
+        res1_child_collection->nodename = cx_strdup_a(store->mp->allocator, "child2_collection").ptr;
+        
+        error = -1;
+        note_store_save_notebook_async(obj, res1_child_collection, 0, test_save_notebook_result, &error);
+        ui_exec_buffered_mainthread_calls_wait(3);
+        
+        CX_TEST_ASSERT(error == 0);
+        CX_TEST_ASSERT(res1_child_collection->resource_id != 0);
+        
+        Resource *res1_sub_child = cxZalloc(store->mp->allocator, sizeof(Resource));
+        res1_sub_child->parent_id = res1_child_collection->resource_id;
+        res1_sub_child->nodename = cx_strdup_a(store->mp->allocator, "subchild1").ptr;
+        
+        error = -1;
+        note_store_save_notebook_async(obj, res1_sub_child, 0, test_save_notebook_result, &error);
+        ui_exec_buffered_mainthread_calls_wait(3);
+        
+        CX_TEST_ASSERT(error == 0);
+        CX_TEST_ASSERT(res1_sub_child->resource_id != 0);
         
         int64_t res1_id = res1->resource_id;
-        int64_t res1_child_id = res1_child->resource_id;
+        int64_t res1_child_collection_id = res1_child_collection->resource_id;
         
         // test delete
         int result = -1;
@@ -581,6 +603,9 @@ CX_TEST(test_note_store_delete_collection_async) {
         int64_t nchildren = note_store_count_children(res1_id);
         CX_TEST_ASSERT(nchildren == 0);
         
+        int64_t nsubchildren = note_store_count_children(res1_child_collection_id);
+        CX_TEST_ASSERT(nsubchildren == 0);
+        
         // cleanup
         ui_close(obj);
     }