add object cache

Wed, 11 Dec 2024 21:53:31 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 11 Dec 2024 21:53:31 +0100
changeset 6
d6981b56ab30
parent 5
f0c66b2139ea
child 7
c98ff52cd806

add object cache

dbutils/object.c file | annotate | diff | comparison | revisions
dbutils/object.h file | annotate | diff | comparison | revisions
--- a/dbutils/object.c	Wed Dec 11 20:57:19 2024 +0100
+++ b/dbutils/object.c	Wed Dec 11 21:53:31 2024 +0100
@@ -33,6 +33,7 @@
 #include <cx/array_list.h>
 #include <cx/linked_list.h>
 #include <cx/hash_map.h>
+#include <cx/printf.h>
 
 #include "object.h"
 
@@ -110,7 +111,7 @@
         .create = list_result_create,
         .add = list_result_add
     };
-    if(dbuObjectBuilderGet(builder, &result)) {
+    if(dbuObjectExec(builder, &result)) {
         cxListDestroy(result_list);
         return NULL;
     }
@@ -136,10 +137,10 @@
         cxListDestroy(result_list);
         return NULL;
     }
-    if(dbuObjectBuilderGet(builder, &result)) {
+    if(dbuObjectExec(builder, &result)) {
         cxListDestroy(result_list);
         return NULL;
-    }
+    }  
     return result_list;
 }
 
@@ -155,13 +156,50 @@
 
 /* ------------------------- Object Builder -----------------------------*/
 
-int dbuObjectBuilderGet(DBUObjectBuilder *builder, DBUObjectBuilderResult *objresult) {
-    DBUClass *cls = builder->resultType; // TODO: rename var
+static int result_add_noop(DBUObjectBuilderResult *result, void *obj) {
+    return 0;
+}
+
+int dbuObjectExec(DBUObjectBuilder *builder, DBUObjectBuilderResult *objresult) {
+    if(cxListSize(builder->additionalQueries) > 0) {
+        builder->cache = cxHashMapCreateSimple(sizeof(DBUBuilderObjCache));
+        if(!builder->cache) {
+            return 1;
+        }
+    }
+    
+    int ret = dbuObjectExecuteQuery(builder, builder->mainQuery, builder->resultType, objresult);
+    if(!ret) {
+        CxIterator i = cxListIterator(builder->additionalQueries);
+        cx_foreach(DBUBuilderQuery *, a, i) {
+            DBUObjectBuilderResult result = { 
+                .userdata1 = NULL,
+                .userdata2 = NULL,
+                .int1 = CX_STORE_POINTERS,
+                .create = list_result_create,
+                .add = result_add_noop
+            };
+            
+            ret = dbuObjectExecuteQuery(builder, a->query, a->type, &result);
+            if(ret) {
+                break;
+            }
+        }
+    }
+    
+    if(builder->cache) {
+        cxMapDestroy(builder->cache);
+    }
+    builder->cache = NULL;
+    return ret;
+}
+
+int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass *type, DBUObjectBuilderResult *objresult) {
+    DBUClass *cls = type;
     
     // TODO: execute additional queries
     
     // execute sql
-    DBUQuery *query = builder->mainQuery;
     if(query->exec(query)) {
         query->free(query);
         return 1;
@@ -276,6 +314,24 @@
                 } else {
                     cxstring text = result->getText(result, i);
                     field.field->initValue(field.field, a, current_obj, text.ptr, text.length);
+                    
+                    // if obj caching is enabled and the current field contains
+                    // the primary key, add this object to the cache
+                    if(builder->cache && field.field == current_cls->primary_key) {
+                        cxmutstr cache_key = cx_asprintf("%.*s::%.*s",
+                                (int)current_cls->name.length, current_cls->name.ptr,
+                                (int)text.length, text.ptr);
+                        if(!cache_key.ptr) {
+                            err = 1;
+                            break;
+                        }
+                        int r = cxMapPut(builder->cache, cache_key, current_obj);
+                        free(cache_key.ptr);
+                        if(r) {
+                            err = 1;
+                            break;
+                        }
+                    }
                 }
             }
         }
--- a/dbutils/object.h	Wed Dec 11 20:57:19 2024 +0100
+++ b/dbutils/object.h	Wed Dec 11 21:53:31 2024 +0100
@@ -60,6 +60,11 @@
     void (*free)(DBUObjectBuilderResult *result);
 };
 
+typedef struct DBUBuilderObjCache {
+    DBUClass *class;
+    void *obj;
+} DBUBuilderObjCache;
+
 struct DBUObjectBuilder {
     const CxAllocator *allocator;
     
@@ -88,8 +93,8 @@
     /*
      * value: DBUBuilderQuery
      * 
-     * Additional queries are executed before the main query and the result
-     * objects are cached and later added as children to the main result.
+     * Additional queries are executed after the main query and the result
+     * objects are added to the previous queried objects
      */
     CxList *additionalQueries;
     
@@ -97,9 +102,20 @@
      * result builder
      */
     DBUObjectBuilderResult *result;
+    
+    /*
+     * object cache
+     * 
+     * key: <tablename> + <primary key>
+     * value: DBUBuilderObjCache
+     * 
+     */
+    CxMap *cache;
 };
 
-int dbuObjectBuilderGet(DBUObjectBuilder *builder, DBUObjectBuilderResult *objresult);
+int dbuObjectExec(DBUObjectBuilder *builder, DBUObjectBuilderResult *objresult);
+
+int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass *type, DBUObjectBuilderResult *objresult);
 
 #ifdef __cplusplus
 }

mercurial