# HG changeset patch # User Olaf Wintermann # Date 1734370691 -3600 # Node ID 5785a693834cf8720e88b1c4e1bfd1b6e8a44306 # Parent bd08116b8af44e4a5445dbbdb1771caa5c00607a prepare for dense queries diff -r bd08116b8af4 -r 5785a693834c dbutils/dbutils/db.h --- a/dbutils/dbutils/db.h Sat Dec 14 17:03:31 2024 +0100 +++ b/dbutils/dbutils/db.h Mon Dec 16 18:38:11 2024 +0100 @@ -111,16 +111,17 @@ DBUObjectBuilder* dbuObjectBuilder(DBUClass *type, DBUQuery *query, const CxAllocator *a); -int dbuObjectBuilderAddSubquery(DBUObjectBuilder *builder, DBUClass *type, DBUQuery *subquery); +void dbuObjectBuilderSetDenseResult(DBUObjectBuilder *builder, bool dense); int dbuObjectBuilderAddAdditionalQuery(DBUObjectBuilder *builder, DBUClass *type, DBUQuery *query); CxList* dbuObjectBuilderGetList(DBUObjectBuilder *builder); CxList* dbuObjectBuilderGetValueList(DBUObjectBuilder *builder); int dbuObjectBuilderGetArray(DBUObjectBuilder *builder, void **array, size_t *size); void dbuObjectBuilderDestroy(DBUObjectBuilder *builder); +// TODO: implement +int dbuObjectBuilderAddSubquery(DBUObjectBuilder *builder, DBUClass *type, DBUQuery *subquery); -// TODO: remove -CxList* dbuQuerySingleType(DBUContext *ctx, DBUQuery *query, const char *type); + #ifdef __cplusplus } diff -r bd08116b8af4 -r 5785a693834c dbutils/object.c --- a/dbutils/object.c Sat Dec 14 17:03:31 2024 +0100 +++ b/dbutils/object.c Mon Dec 16 18:38:11 2024 +0100 @@ -69,6 +69,10 @@ return builder; } +void dbuObjectBuilderSetDenseResult(DBUObjectBuilder *builder, bool dense) { + builder->denseResult = dense; +} + int dbuObjectBuilderAddSubquery(DBUObjectBuilder *builder, DBUClass *type, DBUQuery *subquery) { return cxMapPut(builder->subQueries, type->name, subquery); } @@ -185,14 +189,14 @@ } int dbuObjectExec(DBUObjectBuilder *builder, DBUObjectResult *objresult) { - if(cxListSize(builder->additionalQueries) > 0) { + if(cxListSize(builder->additionalQueries) > 0 || builder->denseResult) { builder->cache = cxHashMapCreateSimple(sizeof(DBUBuilderObjCache)); if(!builder->cache) { return 1; } } - int ret = dbuObjectExecuteQuery(builder, builder->mainQuery, builder->resultType, objresult); + int ret = dbuObjectExecuteQuery(builder, builder->mainQuery, builder->resultType, objresult, builder->denseResult); if(!ret) { CxIterator i = cxListIterator(builder->additionalQueries); cx_foreach(DBUBuilderQuery *, q, i) { @@ -204,7 +208,7 @@ .add = add_to_parent }; - ret = dbuObjectExecuteQuery(builder, q->query, q->type, &result); + ret = dbuObjectExecuteQuery(builder, q->query, q->type, &result, false); if(ret) { break; } @@ -222,7 +226,7 @@ free(elm->cache_key); } -int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass *type, DBUObjectResult *objresult) { +int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass *type, DBUObjectResult *objresult, bool dense) { DBUClass *cls = type; // TODO: execute additional queries @@ -250,6 +254,9 @@ bool is_main = true; DBUClass *field_class = cls; + int main_pk_index = -1; + int end_main_fields = numcols; + for(int i=0;ifieldName(result, i)); DBUField *field = NULL; @@ -287,9 +294,21 @@ mapping.type = result->fieldType(result, i); mapping.is_main = is_main; field_mapping[i] = mapping; + + if(field == cls->primary_key) { + main_pk_index = i; + } + + if(end_main_fields == numcols && field_class != cls) { + end_main_fields = i; + } } } + if(main_pk_index < 0) { + dense = false; + } + const CxAllocator *a = builder->allocator; CxList *fklist = cxArrayListCreateSimple(sizeof(DBUFK), 4); @@ -300,7 +319,28 @@ while(result->hasData(result)) { // create main result obj - void *obj = objresult->create(objresult, cls, a); + bool addobj = true; + void *obj = NULL; + int skip_fields = 0; + if(dense) { + cxstring text = result->getText(result, main_pk_index); + cxmutstr cache_key = cx_asprintf("%.*s::%.*s", + (int)cls->name.length, cls->name.ptr, + (int)text.length, text.ptr); + if(!cache_key.ptr) { + err = 1; + break; + } + DBUBuilderObjCache *cached_obj = cxMapGet(builder->cache, cache_key); + free(cache_key.ptr); + if(cached_obj && cached_obj->class == cls) { + obj = cached_obj->obj; + addobj = false; + skip_fields = end_main_fields; + } + } + + obj = objresult->create(objresult, cls, a); if(!obj) { break; } @@ -312,7 +352,7 @@ void *current_obj = obj; void *child_obj = NULL; DBUClass *current_cls = cls; - for(int i=0;iisNull(result, i); @@ -385,7 +425,9 @@ break; } - objresult->add(objresult, NULL, cls, obj, fklist, a); + if(addobj) { + objresult->add(objresult, NULL, cls, obj, fklist, a); + } cxListClear(fklist); diff -r bd08116b8af4 -r 5785a693834c dbutils/object.h --- a/dbutils/object.h Sat Dec 14 17:03:31 2024 +0100 +++ b/dbutils/object.h Mon Dec 16 18:38:11 2024 +0100 @@ -100,6 +100,12 @@ * */ CxMap *cache; + + /* + * if true, the main result does not contain duplicated entries + * with the same primary key + */ + bool denseResult; }; typedef struct DBUFK { @@ -109,7 +115,7 @@ int dbuObjectExec(DBUObjectBuilder *builder, DBUObjectResult *objresult); -int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass *type, DBUObjectResult *objresult); +int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass *type, DBUObjectResult *objresult, bool dense); #ifdef __cplusplus }