Sat, 14 Dec 2024 17:03:31 +0100
add support for list members to the object builder
| dbutils/class.c | file | annotate | diff | comparison | revisions | |
| dbutils/dbutils/dbutils.h | file | annotate | diff | comparison | revisions | |
| dbutils/field.c | file | annotate | diff | comparison | revisions | |
| dbutils/object.c | file | annotate | diff | comparison | revisions | |
| dbutils/object.h | file | annotate | diff | comparison | revisions | |
| test/main.c | file | annotate | diff | comparison | revisions |
--- a/dbutils/class.c Fri Dec 13 11:24:55 2024 +0100 +++ b/dbutils/class.c Sat Dec 14 17:03:31 2024 +0100 @@ -74,6 +74,7 @@ val.cls = fkcls; field->foreignKeyClass = fkcls; cxMapPut(cls->foreign_keys, name, &val); + dbuClassAddField(cls, name, field); } void dbuClassAddObjField(DBUClass *cls, const char *name, DBUField *field, DBUClass *foreign_cls) {
--- a/dbutils/dbutils/dbutils.h Fri Dec 13 11:24:55 2024 +0100 +++ b/dbutils/dbutils/dbutils.h Sat Dec 14 17:03:31 2024 +0100 @@ -127,7 +127,7 @@ int int1; int int2; DBUObject (*create)(DBUObjectResult *result, DBUClass *type, const CxAllocator *a); - int (*add)(DBUObjectResult *result, DBUObject parent, void *obj, CxList *fk, const CxAllocator *a); + int (*add)(DBUObjectResult *result, DBUObject parent, DBUClass *tye, void *obj, CxList *fk, const CxAllocator *a); void (*free)(DBUObjectResult *result); };
--- a/dbutils/field.c Fri Dec 13 11:24:55 2024 +0100 +++ b/dbutils/field.c Sat Dec 14 17:03:31 2024 +0100 @@ -1089,11 +1089,11 @@ } return obj; } -static int linkedlist_add(DBUObjectResult *result, DBUObject parent, void *obj, CxList *fk, const CxAllocator *a) { +static int linkedlist_add(DBUObjectResult *result, DBUObject parent, DBUClass *type, void *obj, CxList *fk, const CxAllocator *a) { DBUOffsetField *field = result->userdata1; DBUClass *cls = result->userdata2; CxList **list = (CxList**)(parent+field->offset); - if(*list) { + if(!*list) { *list = cxLinkedListCreate(a, NULL, CX_STORE_POINTERS); if(!(*list)) { return 1;
--- a/dbutils/object.c Fri Dec 13 11:24:55 2024 +0100 +++ b/dbutils/object.c Sat Dec 14 17:03:31 2024 +0100 @@ -96,7 +96,7 @@ return result->userdata2; } -static int list_result_add(DBUObjectResult *result, DBUObject parent, void *obj, CxList *fk, const CxAllocator *a) { +static int list_result_add(DBUObjectResult *result, DBUObject parent, DBUClass *type, void *obj, CxList *fk, const CxAllocator *a) { return cxListAdd(result->userdata1, obj); } @@ -159,9 +159,27 @@ /* ------------------------- Object Builder -----------------------------*/ -static int add_to_parent(DBUObjectResult *result, DBUObject parent, void *obj, CxList *fk, const CxAllocator *a) { +static int add_to_parent(DBUObjectResult *result, DBUObject parent, DBUClass *type, void *obj, CxList *fklist, const CxAllocator *a) { DBUBuilderQuery *query = result->userdata1; - + DBUObjectBuilder *builder = result->userdata2; + CxIterator i = cxListIterator(fklist); + cx_foreach(DBUFK*, fk, i) { + // check if the elm can be added + DBUField *field = cxMapGet(fk->cls->obj_fields, type->name); + if(!field) { + continue; + } + + // find cached object for all foreign keys + DBUBuilderObjCache *parent_cached = cxMapGet(builder->cache, fk->cache_key); + if(!parent_cached) { + continue; + } + + if(field->builder.add) { + field->builder.add(&field->builder, parent_cached->obj, type, obj, NULL, a); + } + } return 0; } @@ -180,7 +198,7 @@ cx_foreach(DBUBuilderQuery *, q, i) { DBUObjectResult result = { .userdata1 = q, - .userdata2 = NULL, + .userdata2 = builder, .int1 = CX_STORE_POINTERS, .create = result_create_obj, .add = add_to_parent @@ -200,6 +218,10 @@ return ret; } +void dbufkelm_free(DBUFK *elm) { + free(elm->cache_key); +} + int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass *type, DBUObjectResult *objresult) { DBUClass *cls = type; @@ -270,12 +292,13 @@ const CxAllocator *a = builder->allocator; - CxList *fklist = cxArrayListCreateSimple(CX_STORE_POINTERS, 4); - fklist->collection.simple_destructor = free; + CxList *fklist = cxArrayListCreateSimple(sizeof(DBUFK), 4); + fklist->collection.simple_destructor = (cx_destructor_func)dbufkelm_free; // get result int err = 0; while(result->hasData(result)) { + // create main result obj void *obj = objresult->create(objresult, cls, a); if(!obj) { @@ -326,7 +349,7 @@ // 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) { + if(builder->cache) { if(field.field == current_cls->primary_key) { cxmutstr cache_key = cx_asprintf("%.*s::%.*s", (int)current_cls->name.length, current_cls->name.ptr, @@ -335,7 +358,10 @@ err = 1; break; } - int r = cxMapPut(builder->cache, cache_key, current_obj); + DBUBuilderObjCache cache_elm; + cache_elm.class = current_cls; + cache_elm.obj = current_obj; + int r = cxMapPut(builder->cache, cache_key, &cache_elm); free(cache_key.ptr); if(r) { err = 1; @@ -343,9 +369,12 @@ } } else if(field.field->foreignKeyClass) { cxmutstr fkey = cx_asprintf("%.*s::%.*s", - (int)field.field->foreignKeyClass->name.length, current_cls->name.ptr, + (int)field.field->foreignKeyClass->name.length, field.field->foreignKeyClass->name.ptr, (int)text.length, text.ptr); - cxListAdd(fklist, fkey.ptr); + DBUFK fkelm; + fkelm.cache_key = fkey.ptr; + fkelm.cls = field.field->foreignKeyClass; + cxListAdd(fklist, &fkelm); } } } @@ -356,7 +385,7 @@ break; } - objresult->add(objresult, NULL, obj, fklist, a); + objresult->add(objresult, NULL, cls, obj, fklist, a); cxListClear(fklist);
--- a/dbutils/object.h Fri Dec 13 11:24:55 2024 +0100 +++ b/dbutils/object.h Sat Dec 14 17:03:31 2024 +0100 @@ -102,6 +102,11 @@ CxMap *cache; }; +typedef struct DBUFK { + char *cache_key; + DBUClass *cls; +} DBUFK; + int dbuObjectExec(DBUObjectBuilder *builder, DBUObjectResult *objresult); int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass *type, DBUObjectResult *objresult);
--- a/test/main.c Fri Dec 13 11:24:55 2024 +0100 +++ b/test/main.c Sat Dec 14 17:03:31 2024 +0100 @@ -33,6 +33,9 @@ #include <dbutils/sqlite.h> #include <dbutils/db.h> +#include <cx/buffer.h> +#include <cx/printf.h> + const char *sql_create_table_person = "create table if not exists Person (" "person_id integer primary key autoincrement, " @@ -161,8 +164,23 @@ if(persons) { CxIterator i = cxListIterator(persons); cx_foreach(Person *, p, i) { - printf("{ person_id = %" PRId64 ", name = \"%s\", email = \"%s\", age = %d, iscustomer = %s, hash = %" PRIu64 " }\n", - p->person_id, p->name.ptr, p->email.ptr, p->age, p->iscustomer ? "true" : "false", p->hash); + CxBuffer rolebuffer; + cxBufferInit(&rolebuffer, NULL, 256, 0, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); + cxBufferPut(&rolebuffer, '['); + if(p->roles) { + CxIterator r = cxListIterator(p->roles); + char *addseparator = ""; + cx_foreach(Role *, role, r) { + cx_bprintf(&rolebuffer, "%s{ role_id = %d, name = \"%s\"}", addseparator, role->role_id, role->name.ptr); + addseparator = ", "; + } + } + cxBufferPut(&rolebuffer, ']'); + cxBufferPut(&rolebuffer, 0); + printf("{ person_id = %" PRId64 ", name = \"%s\", email = \"%s\", age = %d, iscustomer = %s, hash = %" PRIu64 " roles = %s }\n", + p->person_id, p->name.ptr, p->email.ptr, p->age, p->iscustomer ? "true" : "false", p->hash, rolebuffer.space); + + cxBufferDestroy(&rolebuffer); } } else { fprintf(stderr, "Error\n");