From: Olaf Wintermann Date: Wed, 21 Jan 2026 17:26:47 +0000 (+0100) Subject: update dbutils, simplify delete_collection X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;p=note.git update dbutils, simplify delete_collection --- diff --git a/application/store.c b/application/store.c index 3f6525a..5fb6980 100644 --- a/application/store.c +++ b/application/store.c @@ -84,6 +84,7 @@ #define SQL_RESOURCE_DELETE_CHILDREN "delete from resources where parent_id = ? ;" +// unused #define SQL_RESOURCE_DELETE_ALL \ "with recursive cte as ( " \ " select resource_id, parent_id, nodename from resources where resource_id = ? " \ @@ -367,7 +368,7 @@ int note_store_create_default(const char *host, const char *user) { if(!q->exec(q)) { err = dbuResultAsValue(q->getResult(q), ¬ebooks_id); if(!err) { - DBUResult *result = dbuSqlExecParamInt64(connection, NULL, SQL_NOTEBOOK_NEW, notebooks_id); + DBUResult *result = dbuSqlExecQueryParamInt64(connection, NULL, SQL_NOTEBOOK_NEW, notebooks_id); int64_t unused; err = dbuResultAsInt64(result, &unused); } @@ -381,7 +382,7 @@ int note_store_create_default(const char *host, const char *user) { if(!q->exec(q)) { err = dbuResultAsValue(q->getResult(q), &mynotes_id); if(!err) { - DBUResult *result = dbuSqlExecParamInt64(connection, NULL, SQL_NOTEBOOK_NEW, mynotes_id); + DBUResult *result = dbuSqlExecQueryParamInt64(connection, NULL, SQL_NOTEBOOK_NEW, mynotes_id); int64_t unused; err = dbuResultAsInt64(result, &unused); } @@ -1173,7 +1174,7 @@ typedef struct CountJob { } CountJob; static int qthr_collection_get_size(CountJob *job) { - DBUResult *result = dbuSqlExecParamInt64(connection, NULL, SQL_NOTEBOOK_COUNT_CHILDREN, job->id1); + DBUResult *result = dbuSqlExecQueryParamInt64(connection, NULL, SQL_NOTEBOOK_COUNT_CHILDREN, job->id1); if(!result) { job->error = 1; return 0; @@ -1216,17 +1217,10 @@ 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_ALL, job->id1); - if(!result) { + if(dbuSqlExecParamInt64(connection, SQL_RESOURCE_DELETE, job->id1)) { job->error = 3; return 0; } - int ok = dbuResultIsOk(result); - dbuResultFree(result); - if(!ok) { - job->error = 4; - return 0; - } } else { // only delete the resource when there are no children int64_t nchildren = note_store_count_children(job->id1); @@ -1239,14 +1233,8 @@ static int qthr_delete_collection(ExecJob *job) { 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; + if(dbuSqlExecParamInt64(connection, SQL_RESOURCE_DELETE, job->id1)) { + job->error = 3; } } diff --git a/application/store_sqlite.c b/application/store_sqlite.c index 8ecf6ca..7ec45c2 100644 --- a/application/store_sqlite.c +++ b/application/store_sqlite.c @@ -109,7 +109,7 @@ int store_sqlite_init_db(DBUConnection *connection) { int nsql = sizeof(sql) / sizeof(char*); for(int i=0;iname.ptr); field->name = name ? cx_strdup(cx_str(name)) : (cxmutstr){NULL,0}; cxMapPut(cls->obj_fields, foreign_cls->name, field); + cxMapPut(cls->fields, name, field); } diff --git a/dbutils/db.c b/dbutils/db.c index 0dbea99..4d3f7aa 100644 --- a/dbutils/db.c +++ b/dbutils/db.c @@ -29,16 +29,6 @@ #include "db.h" #include "dbutils/db.h" -int dbuConnectionExec(DBUConnection *conn, const char *sql) { - DBUQuery *q = conn->createQuery(conn, NULL); - int err = 1; - if(!dbuQuerySetSQL(q, sql)) { - err = dbuQueryExec(q); - } - dbuQueryFree(q); - return err; -} - int dbuConnectionIsActive(DBUConnection *conn) { return conn->isActive ? conn->isActive(conn) : 1; } @@ -246,7 +236,7 @@ static DBUQuery* execStringParamQuery(DBUConnection *conn, const char *sql, cxst return q; } -DBUResult* dbuSqlExec(DBUConnection *conn, const CxAllocator *a, const char *sql) { +DBUResult* dbuSqlExecQuery(DBUConnection *conn, const CxAllocator *a, const char *sql) { DBUQuery *q = dbuQueryCreate(conn, a, sql); if(!q) { return NULL; @@ -260,7 +250,7 @@ DBUResult* dbuSqlExec(DBUConnection *conn, const CxAllocator *a, const char *sql return result; } -DBUResult* dbuSqlExecParamInt32(DBUConnection *conn, const CxAllocator *a, const char *sql, int32_t param) { +DBUResult* dbuSqlExecQueryParamInt32(DBUConnection *conn, const CxAllocator *a, const char *sql, int32_t param) { DBUQuery *q = execInt64ParamQuery(conn, sql, param); if(!q) return NULL; DBUResult *r = dbuQueryGetResult(q); @@ -268,7 +258,7 @@ DBUResult* dbuSqlExecParamInt32(DBUConnection *conn, const CxAllocator *a, const return r; } -DBUResult* dbuSqlExecParamInt64(DBUConnection *conn, const CxAllocator *a, const char *sql, int64_t param) { +DBUResult* dbuSqlExecQueryParamInt64(DBUConnection *conn, const CxAllocator *a, const char *sql, int64_t param) { DBUQuery *q = execInt64ParamQuery(conn, sql, param); if(!q) return NULL; DBUResult *r = dbuQueryGetResult(q); @@ -276,7 +266,7 @@ DBUResult* dbuSqlExecParamInt64(DBUConnection *conn, const CxAllocator *a, const return r; } -DBUResult* dbuSqlExecParamUInt32(DBUConnection *conn, const CxAllocator *a, const char *sql, uint32_t param) { +DBUResult* dbuSqlExecQueryParamUInt32(DBUConnection *conn, const CxAllocator *a, const char *sql, uint32_t param) { DBUQuery *q = execInt64ParamQuery(conn, sql, param); if(!q) return NULL; DBUResult *r = dbuQueryGetResult(q); @@ -284,7 +274,7 @@ DBUResult* dbuSqlExecParamUInt32(DBUConnection *conn, const CxAllocator *a, cons return r; } -DBUResult* dbuSqlExecParamUInt64(DBUConnection *conn, const CxAllocator *a, const char *sql, uint32_t param) { +DBUResult* dbuSqlExecQueryParamUInt64(DBUConnection *conn, const CxAllocator *a, const char *sql, uint64_t param) { DBUQuery *q = execInt64ParamQuery(conn, sql, param); if(!q) return NULL; DBUResult *r = dbuQueryGetResult(q); @@ -292,7 +282,7 @@ DBUResult* dbuSqlExecParamUInt64(DBUConnection *conn, const CxAllocator *a, cons return r; } -DBUResult* dbuSqlExecParamString(DBUConnection *conn, const CxAllocator *a, const char *sql, const char *param) { +DBUResult* dbuSqlExecQueryParamString(DBUConnection *conn, const CxAllocator *a, const char *sql, const char *param) { DBUQuery *q = execStringParamQuery(conn, sql, cx_str(param)); if(!q) return NULL; DBUResult *r = dbuQueryGetResult(q); @@ -300,7 +290,7 @@ DBUResult* dbuSqlExecParamString(DBUConnection *conn, const CxAllocator *a, cons return r; } -DBUResult* dbuSqlExecParamCxString(DBUConnection *conn, const CxAllocator *a, const char *sql, cxstring param) { +DBUResult* dbuSqlExecQueryParamCxString(DBUConnection *conn, const CxAllocator *a, const char *sql, cxstring param) { DBUQuery *q = execStringParamQuery(conn, sql, param); if(!q) return NULL; DBUResult *r = dbuQueryGetResult(q); @@ -308,7 +298,7 @@ DBUResult* dbuSqlExecParamCxString(DBUConnection *conn, const CxAllocator *a, co return r; } -DBUResult* dbuSqlExecParamCxMutStr(DBUConnection *conn, const CxAllocator *a, const char *sql, cxmutstr param) { +DBUResult* dbuSqlExecQueryParamCxMutStr(DBUConnection *conn, const CxAllocator *a, const char *sql, cxmutstr param) { DBUQuery *q = execStringParamQuery(conn, sql, cx_strcast(param)); if(!q) return NULL; DBUResult *r = dbuQueryGetResult(q); @@ -378,3 +368,83 @@ CxList* dbuSimpleGetListWithStringParam(DBUConnection *conn, const char *sql, cx dbuObjectBuilderDestroy(builder); return list; } + +int dbuSqlExec(DBUConnection *conn, const char *sql) { + DBUResult *result = dbuSqlExecQuery(conn, NULL, sql); + if(!result) { + return 1; + } + int ret = dbuResultIsOk(result); + dbuResultFree(result); + return !ret; +} + +int dbuSqlExecParamInt32(DBUConnection *conn, const char *sql, int32_t param) { + DBUResult *result = dbuSqlExecQueryParam(conn, NULL, sql, param); + if(!result) { + return 1; + } + int ret = dbuResultIsOk(result); + dbuResultFree(result); + return !ret; +} + +int dbuSqlExecParamInt64(DBUConnection *conn, const char *sql, int64_t param) { + DBUResult *result = dbuSqlExecQueryParam(conn, NULL, sql, param); + if(!result) { + return 1; + } + int ret = dbuResultIsOk(result); + dbuResultFree(result); + return !ret; +} + +int dbuSqlExecParamUInt32(DBUConnection *conn, const char *sql, uint32_t param) { + DBUResult *result = dbuSqlExecQueryParam(conn, NULL, sql, param); + if(!result) { + return 1; + } + int ret = dbuResultIsOk(result); + dbuResultFree(result); + return !ret; +} + +int dbuSqlExecParamUInt64(DBUConnection *conn, const char *sql, uint64_t param) { + DBUResult *result = dbuSqlExecQueryParam(conn, NULL, sql, param); + if(!result) { + return 1; + } + int ret = dbuResultIsOk(result); + dbuResultFree(result); + return !ret; +} + +int dbuSqlExecParamString(DBUConnection *conn, const char *sql, const char *param) { + DBUResult *result = dbuSqlExecQueryParam(conn, NULL, sql, param); + if(!result) { + return 1; + } + int ret = dbuResultIsOk(result); + dbuResultFree(result); + return !ret; +} + +int dbuSqlExecParamCxString(DBUConnection *conn, const char *sql, cxstring param) { + DBUResult *result = dbuSqlExecQueryParam(conn, NULL, sql, param); + if(!result) { + return 1; + } + int ret = dbuResultIsOk(result); + dbuResultFree(result); + return !ret; +} + +int dbuSqlExecParamCxMutStr(DBUConnection *conn, const char *sql, cxmutstr param) { + DBUResult *result = dbuSqlExecQueryParam(conn, NULL, sql, param); + if(!result) { + return 1; + } + int ret = dbuResultIsOk(result); + dbuResultFree(result); + return !ret; +} diff --git a/dbutils/dbutils/db.h b/dbutils/dbutils/db.h index 3162704..0074a1f 100644 --- a/dbutils/dbutils/db.h +++ b/dbutils/dbutils/db.h @@ -96,7 +96,6 @@ struct DBUResult { int rowIndex; }; -int dbuConnectionExec(DBUConnection *conn, const char *sql); int dbuConnectionIsActive(DBUConnection *conn); void dbuConnectionFree(DBUConnection *conn); DBUQuery* dbuConnectionQuery(DBUConnection *conn, const CxAllocator *a); @@ -152,27 +151,25 @@ void dbuObjectBuilderDestroy(DBUObjectBuilder *builder); // TODO: implement int dbuObjectBuilderAddSubquery(DBUObjectBuilder *builder, DBUClass *type, DBUQuery *subquery); -#define dbuSqlExecParam(conn, a, sql, param) \ +#define dbuSqlExecQueryParam(conn, a, sql, param) \ _Generic(param, \ - int32_t : dbuSqlExecParamInt32, \ - int64_t : dbuSqlExecParamInt64, \ - uint32_t : dbuSqlExecParamUInt32, \ - uint64_t : dbuSqlExecParamUInt64, \ - char* : dbuSqlExecParamString, \ - const char*: dbuSqlExecParamString, \ - cxstring : dbuSqlExecParamCxString, \ - cxmutstr : dbuSqlExecParamCxMutStr)(conn, a, sql, param) - -DBUResult* dbuSqlExec(DBUConnection *conn, const CxAllocator *a, const char *sql); -DBUResult* dbuSqlExecParamInt32(DBUConnection *conn, const CxAllocator *a, const char *sql, int32_t param); -DBUResult* dbuSqlExecParamInt64(DBUConnection *conn, const CxAllocator *a, const char *sql, int64_t param); -DBUResult* dbuSqlExecParamUInt32(DBUConnection *conn, const CxAllocator *a, const char *sql, uint32_t param); -DBUResult* dbuSqlExecParamUInt64(DBUConnection *conn, const CxAllocator *a, const char *sql, uint32_t param); -DBUResult* dbuSqlExecParamString(DBUConnection *conn, const CxAllocator *a, const char *sql, const char *param); -DBUResult* dbuSqlExecParamCxString(DBUConnection *conn, const CxAllocator *a, const char *sql, cxstring param); -DBUResult* dbuSqlExecParamCxMutStr(DBUConnection *conn, const CxAllocator *a, const char *sql, cxmutstr param); - - + int32_t : dbuSqlExecQueryParamInt32, \ + int64_t : dbuSqlExecQueryParamInt64, \ + uint32_t : dbuSqlExecQueryParamUInt32, \ + uint64_t : dbuSqlExecQueryParamUInt64, \ + char* : dbuSqlExecQueryParamString, \ + const char*: dbuSqlExecQueryParamString, \ + cxstring : dbuSqlExecQueryParamCxString, \ + cxmutstr : dbuSqlExecQueryParamCxMutStr)(conn, a, sql, param) + +DBUResult* dbuSqlExecQuery(DBUConnection *conn, const CxAllocator *a, const char *sql); +DBUResult* dbuSqlExecQueryParamInt32(DBUConnection *conn, const CxAllocator *a, const char *sql, int32_t param); +DBUResult* dbuSqlExecQueryParamInt64(DBUConnection *conn, const CxAllocator *a, const char *sql, int64_t param); +DBUResult* dbuSqlExecQueryParamUInt32(DBUConnection *conn, const CxAllocator *a, const char *sql, uint32_t param); +DBUResult* dbuSqlExecQueryParamUInt64(DBUConnection *conn, const CxAllocator *a, const char *sql, uint64_t param); +DBUResult* dbuSqlExecQueryParamString(DBUConnection *conn, const CxAllocator *a, const char *sql, const char *param); +DBUResult* dbuSqlExecQueryParamCxString(DBUConnection *conn, const CxAllocator *a, const char *sql, cxstring param); +DBUResult* dbuSqlExecQueryParamCxMutStr(DBUConnection *conn, const CxAllocator *a, const char *sql, cxmutstr param); int dbuSimpleGetInt64WithIntParam(DBUConnection *conn, const char *sql, int64_t param, int64_t *result); int dbuSimpleGetInt64WithStringParam(DBUConnection *conn, const char *sql, cxstring param, int64_t *result); @@ -181,6 +178,26 @@ int dbuSimpleGetStringWithStringParam(DBUConnection *conn, const char *sql, cxst CxList* dbuSimpleGetListWithIntParam(DBUConnection *conn, const char *sql, int64_t param, const CxAllocator *a, DBUClass *type); CxList* dbuSimpleGetListWithStringParam(DBUConnection *conn, const char *sql, cxstring param, const CxAllocator *a, DBUClass *type); +#define dbuSqlExecParam(conn, sql, param) \ + _Generic(param, \ + int32_t : dbuSqlExecParamInt32, \ + int64_t : dbuSqlExecParamInt64, \ + uint32_t : dbuSqlExecParamUInt32, \ + uint64_t : dbuSqlExecParamUInt64, \ + char* : dbuSqlExecParamString, \ + const char*: dbuSqlExecParamString, \ + cxstring : dbuSqlExecParamCxString, \ + cxmutstr : dbuSqlExecParamCxMutStr)(conn, sql, param) + +int dbuSqlExec(DBUConnection *conn, const char *sql); +int dbuSqlExecParamInt32(DBUConnection *conn, const char *sql, int32_t param); +int dbuSqlExecParamInt64(DBUConnection *conn, const char *sql, int64_t param); +int dbuSqlExecParamUInt32(DBUConnection *conn, const char *sql, uint32_t param); +int dbuSqlExecParamUInt64(DBUConnection *conn, const char *sql, uint64_t param); +int dbuSqlExecParamString(DBUConnection *conn, const char *sql, const char *param); +int dbuSqlExecParamCxString(DBUConnection *conn, const char *sql, cxstring param); +int dbuSqlExecParamCxMutStr(DBUConnection *conn, const char *sql, cxmutstr param); + #ifdef __cplusplus } #endif diff --git a/dbutils/dbutils/dbutils.h b/dbutils/dbutils/dbutils.h index c757401..12eb671 100644 --- a/dbutils/dbutils/dbutils.h +++ b/dbutils/dbutils/dbutils.h @@ -130,6 +130,7 @@ typedef struct DBUObjectResult DBUObjectResult; struct DBUObjectResult { void *userdata1; void *userdata2; + DBUClass *type; int int1; int int2; DBUObject (*create)(DBUObjectResult *result, DBUClass *type, const CxAllocator *a); diff --git a/dbutils/dbutils/json.h b/dbutils/dbutils/json.h index 0617ef8..46ce0f8 100644 --- a/dbutils/dbutils/json.h +++ b/dbutils/dbutils/json.h @@ -47,6 +47,9 @@ cxmutstr dbuArrayToJsonString(DBUClass *type, void **objArray, size_t size, cons CxJsonValue* dbuObjectToJson2(DBUClass *type, void *obj, const CxAllocator *a, bool setNull, bool forceString); +void* dbuJsonToObject(DBUClass *type, const CxAllocator *a, CxJsonValue *value); +CxList* dbuJsonToList(DBUClass *type, const CxAllocator *a, CxJsonValue *value); + #ifdef __cplusplus } diff --git a/dbutils/field.c b/dbutils/field.c index bebf221..8a5656e 100644 --- a/dbutils/field.c +++ b/dbutils/field.c @@ -1238,7 +1238,7 @@ static DBUObject linkedlist_create_obj(DBUObjectResult *result, DBUClass *type, } 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; + DBUClass *cls = result->type; CxList **list = (CxList**)(parent+field->offset); if(!*list) { *list = cxLinkedListCreate(a, CX_STORE_POINTERS); @@ -1294,13 +1294,14 @@ void dbuClassAddCxLinkedList(DBUClass *cls, const char *name, off_t offset, DBUC memset(field, 0, sizeof(DBUOffsetField)); field->offset = offset; field->def.def = 0; + field->field.builder.type = foreign_cls; field->field.builder.userdata1 = field; field->field.builder.userdata2 = foreign_cls; field->field.builder.create = linkedlist_create_obj; field->field.builder.add = linkedlist_add; field->field.toList = cxlist_tolist; // TODO: can we pass name to dbuClassAddObjField? - dbuClassAddObjField(cls, NULL, (DBUField*)field, foreign_cls); + dbuClassAddObjField(cls, name, (DBUField*)field, foreign_cls); field->field.name = name ? cx_strdup(cx_str(name)) : (cxmutstr){NULL,0}; //dbuClassAddParentObjField(foreign_cls, name, cls, (DBUField*)field); } diff --git a/dbutils/json.c b/dbutils/json.c index 52cdc8a..55339b3 100644 --- a/dbutils/json.c +++ b/dbutils/json.c @@ -26,8 +26,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include + #include "json.h" +/* ---------------- Obj to JSON serialization functions ---------------------*/ + CxJsonValue* dbuObjectToJson(DBUClass *type, void *obj, const CxAllocator *a) { return dbuObjectToJson2(type, obj, a, false, false); } @@ -123,3 +127,186 @@ CxJsonValue* dbuObjectToJson2(DBUClass *type, void *obj, const CxAllocator *a, b return value; } + + +/* --------------- Json to Obj deserialization functions --------------------*/ + +static void* jsonToObj(DBUClass *type, const CxAllocator *a, CxJsonValue *value, int depth, int *error) { + if(!cxJsonIsObject(value)) { + *error = 1; + return NULL; + } + if(depth > DBU_JSON_MAX_DEPTH) { + *error = 2; + return NULL; + } + if(!a) { + a = cxDefaultAllocator; + } + + void *obj = cxMalloc(a, type->obj_size); + if(obj) { + memset(obj, 0, type->obj_size); + } else { + *error = 3; + return NULL; + } + + char buf[64]; + int len = 0; + + CxMapIterator i = cxMapIterator(value->object); + cx_foreach(CxMapEntry *, entry, i) { + DBUField *field = cxMapGet(type->fields, entry->key); + if(!field) { + field = cxMapGet(type->obj_fields, entry->key); + if(!field) { + continue; + } + } + + len = 0; + + CxJsonValue *child = entry->value; + switch(child->type) { + case CX_JSON_LITERAL: { + if(child->literal == CX_JSON_NULL) { + if(field->initObjValue) { + field->initObjValue(field, a, obj, NULL); + } + break; + } else { + int b = child->literal == CX_JSON_TRUE; + if(field->initIntValue) { + field->initIntValue(field, a, obj, b); + continue; + } else { + len = snprintf(buf, 64, "%d", b); + } + } + break; + } + case CX_JSON_INTEGER: { + if(field->initIntValue) { + field->initIntValue(field, a, obj, child->integer); + } else { + len = snprintf(buf, 64, "%" PRId64, child->integer); + } + break; + } + case CX_JSON_NUMBER: { + if(field->initDoubleValue) { + field->initDoubleValue(field, a, obj, child->number); + } else { + len = snprintf(buf, 64, "%f", child->number); + } + break; + } + case CX_JSON_STRING: { + cxmutstr str = child->string; + if(field->initValue(field, a, obj, str.ptr, str.length)) { + *error = 3; + free(obj); // TODO: improve obj cleanup + return NULL; + } + break; + } + case CX_JSON_OBJECT: { + if(field->objType && field->initObjValue) { + void *child_obj = jsonToObj(field->objType, a, child, depth+1, error); + if(child_obj) { + field->initObjValue(field, a, obj, child_obj); + } else { + free(obj); // TODO: improve obj cleanup + return NULL; + } + } + break; + } + case CX_JSON_ARRAY: { + if(field->builder.add) { + for(int i=0;iarray.size;i++) { + CxJsonValue *elm = child->array.data[i]; + void *elm_obj = NULL; + bool add_elm = false; + if(cxJsonIsObject(elm)) { + elm_obj = jsonToObj(field->builder.type, a, elm, depth+1, error); + if(!elm_obj) { + free(obj); // TODO: improve obj cleanup + return NULL; + } + add_elm = true; + + } else if(cxJsonIsLiteral(elm) && elm->literal == CX_JSON_NULL) { + add_elm = true; + } + + if(add_elm) { + if(field->builder.add(&field->builder, obj, field->builder.type, elm_obj, NULL, a)) { + free(obj); // TODO: improve obj cleanup + free(elm_obj); + *error = 3; + return NULL; + } + } + } + } + break; + } + default: break; + } + + if(len > 0) { + if(field->initValue(field, a, obj, buf, len)) { + // TODO: completely cleanup obj + free(obj); + *error = 3; + return NULL; + } + } + } + + *error = 0; + return obj; +} + +void* dbuJsonToObject(DBUClass *type, const CxAllocator *a, CxJsonValue *value) { + int error; + return jsonToObj(type, a, value, 0, &error); +} + +static CxList* jsonToArray(DBUClass *type, const CxAllocator *a, CxJsonValue *value, size_t elmSize, int *error) { + if(!cxJsonIsArray(value)) { + *error = 1; + return NULL; + } + + CxList *list = cxArrayListCreate(a, elmSize, value->array.size); + if(!list) { + *error = 3; + } + + for(size_t i=0;iarray.size;i++) { + CxJsonValue *elm = value->array.data[i]; + void *elm_obj = NULL; + if(cxJsonIsObject(elm)) { + elm_obj = jsonToObj(type, a, elm, 1, error); + if(!elm_obj) { + cxListFree(list); + return NULL; + } + } + if(cxListAdd(list, elm_obj)) { + *error = 3; + cxListFree(list); + return NULL; + } + } + + return list; +} + +CxList* dbuJsonToList(DBUClass *type, const CxAllocator *a, CxJsonValue *value) { + int error; + return jsonToArray(type, a, value, CX_STORE_POINTERS, &error); +} diff --git a/dbutils/json.h b/dbutils/json.h index debdad3..93570c2 100644 --- a/dbutils/json.h +++ b/dbutils/json.h @@ -35,7 +35,7 @@ extern "C" { #endif - +#define DBU_JSON_MAX_DEPTH 512 #ifdef __cplusplus diff --git a/dbutils/object.c b/dbutils/object.c index 6c25e66..6c3a7ad 100644 --- a/dbutils/object.c +++ b/dbutils/object.c @@ -133,7 +133,8 @@ CxList* dbuObjectBuilderGetValueList(DBUObjectBuilder *builder) { } // TODO: the class needs a obj destructor func, because we need to be able // to destroy partialy created lists - DBUObjectResult result = { + DBUObjectResult result = { + .type = builder->resultType, .userdata1 = result_list, .userdata2 = malloc(builder->resultType->obj_size), .int1 = builder->resultType->obj_size, @@ -241,6 +242,10 @@ int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass * DBUClass *cls = type; // execute sql + if(!query) { + return 1; + } + if(query->exec(query)) { query->free(query); return 1; @@ -269,14 +274,13 @@ int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass * // list of all classes returned by the result // used when dense == true, to check, if a new result row contains // the same objects (primary keys haven't changed) - size_t result_types_capacity = 16; - size_t result_types_size = 0; CX_ARRAY(DBUResultType, result_types); cx_array_init(result_types, 16); DBUResultType mainResult = { .cls = cls }; cx_array_add(result_types, mainResult); + // analyse columns: create a column-field mapping for(int i=0;ifieldName(result, i)); DBUField *field = NULL; @@ -303,12 +307,19 @@ int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass * } if(remaining.length > 2) { field = cxMapGet(fcls->fields, cx_strsubs(remaining, 2)); + // make sure the field is a normal field and not an obj/list field + if(!field->initValue) { + field = NULL; + } } field_mapping[i].cls = fcls; field_class = fcls; } } else { field = cxMapGet(field_class->fields, fieldname); + if(field && !field->initValue) { + field = NULL; + } } if(field) { @@ -342,7 +353,7 @@ int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass * CxList *fklist = cxArrayListCreate(NULL, sizeof(DBUFK), 4); fklist->collection.simple_destructor = (cx_destructor_func)dbufkelm_free; - // get result + // get result int err = 0; while(result->hasData(result)) { // create main result obj @@ -351,12 +362,15 @@ int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass * int skip_fields = 0; int cls_index = 0; if(dense) { + // if the primary key in this row is the same as in the previous + // row, we don't create a new obj for this row, but reuse the + // previous obj ptr. cxstring text = result->getText(result, main_pk_index); cxmutstr prev_pk = result_types.data[0].prev_key; - if(prev_pk.ptr && !cx_strcmp(text, cx_strcast(prev_pk))) { + if(prev_pk.ptr && !cx_strcmp(text, prev_pk)) { obj = result_types.data[0].prev_obj; addobj = false; - if(1 < result_types_size) { + if(1 < result_types.size) { skip_fields = result_types.data[1].pk_col; } } @@ -391,12 +405,12 @@ int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass * if(dense) { // check if this object was already added - if(cls_index < result_types_size) { + if(cls_index < result_types.size) { cxstring text = result->getText(result, result_types.data[cls_index].pk_col); cxmutstr prev_pk = result_types.data[cls_index].prev_key; if(prev_pk.ptr && !cx_strcmp(text, cx_strcast(prev_pk))) { //printf("already added -> skip\n"); - if(cls_index+1 < result_types_size) { + if(cls_index+1 < result_types.size) { i = result_types.data[cls_index+1].pk_col-1; // -1 because i++ by loop //printf("next col %d\n", i); continue; @@ -438,7 +452,7 @@ int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass * //printf("list field\n"); DBUField *parent_field = NULL; - for(int c=0;cobj_fields, field.cls->name); if(f && f->builder.create) { @@ -514,7 +528,7 @@ int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass * cxListClear(fklist); if(dense) { - for(int i=0;igetText(result, result_types.data[i].pk_col); free(result_types.data[i].prev_key.ptr); result_types.data[i].prev_key = cx_strdup(text); @@ -528,7 +542,7 @@ int dbuObjectExecuteQuery(DBUObjectBuilder *builder, DBUQuery *query, DBUClass * cxListFree(fklist); - for(int i=0;i