#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 = ? ;"
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;
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;
"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( " \
"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) {
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;
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);
}