From 522298cf50e67d92b0aa85a85177ed7c16b00e08 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 29 Sep 2019 15:45:14 +0200 Subject: Provided a generic way to update DB values. --- src/analysis/db/collection.c | 142 ++++++------------------------------------- src/common/sqlite.c | 131 +++++++++++++++++++++++++++++++++++---- src/common/sqlite.h | 3 + 3 files changed, 142 insertions(+), 134 deletions(-) diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c index 9ae7b9c..7b2082a 100644 --- a/src/analysis/db/collection.c +++ b/src/analysis/db/collection.c @@ -1219,147 +1219,43 @@ static bool g_db_collection_store_updated_item(const GDbCollection *collec, cons bool result; /* Conclusion à faire remonter */ bound_value *values; /* Champs de table à inclure */ size_t count; /* Nombre de ces champs */ - char *sql; /* Requête SQL à construire */ - bool first; /* Première valeur ? */ + bound_value *updates; /* Champs à mettre à jour */ + size_t ucount; /* Nombre de ces champs */ + bound_value *conds; /* Champs de condition */ + size_t ccount; /* Nombre de ces champs */ + const bound_value *flags_ptr; /* Emplacement des fanions */ size_t i; /* Boucle de parcours */ - sqlite3_stmt *stmt; /* Déclaration mise en place */ - int ret; /* Bilan d'un appel à SQLite */ - int index; /* Indice de valeur attachée */ - const bound_value *timestamp; /* Valeur de l'horodatage */ result = false; if (!g_db_item_store(item, &values, &count)) - goto gdcsui_building_values; + goto building_values; - /* Préparation de la requête */ + updates = malloc(1 * sizeof(bound_value)); + ucount = 0; - sql = strdup("UPDATE "); - sql = stradd(sql, collec->name); + conds = malloc((count - 1) * sizeof(bound_value)); + ccount = 0; - sql = stradd(sql, " SET timestamp = ? "); - - sql = stradd(sql, "WHERE "); - - first = true; + flags_ptr = find_bound_value(values, count, "flags"); for (i = 0; i < count; i++) { - if (strcmp(values[i].name, "timestamp") == 0) - continue; - - if (first) - first = false; - else - sql = stradd(sql, " AND "); - - sql = stradd(sql, values[i].name); - - if (values[i].type == SQLITE_NULL) - sql = stradd(sql, " IS "); - else - sql = stradd(sql, " = "); - - if (values[i].type == SQLITE_RAW) - sql = stradd(sql, values[i].cstring); - else - sql = stradd(sql, "?"); - - } - - sql = stradd(sql, ";"); - - ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); - if (ret != SQLITE_OK) - { - fprintf(stderr, "Can't prepare UPDATE statment '%s' (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db)); - goto gdcsui_exit; - } - - /* Attribution des valeurs */ - - index = 1; - - timestamp = find_bound_value(values, count, "timestamp"); - assert(timestamp->type == SQLITE_INT64); - - ret = sqlite3_bind_int64(stmt, index, timestamp->integer64); - index++; - - if (ret != SQLITE_OK) - { - fprintf(stderr, "Can't bind value for parameter nb %d in '%s' (ret=%d): %s\n", - index - 1, sql, ret, sqlite3_errmsg(db)); - goto gdcsui_exit; - } - - for (i = 0; i < count; i++) - { - if (strcmp(values[i].name, "timestamp") == 0) - continue; - - switch (values[i].type) + if (&values[i] == flags_ptr) { - case SQLITE_BOOLEAN: - ret = sqlite3_bind_int(stmt, index, values[i].boolean); - index++; - break; - - case SQLITE_INTEGER: - ret = sqlite3_bind_int(stmt, index, values[i].integer); - index++; - break; - - case SQLITE_INT64: - ret = sqlite3_bind_int64(stmt, index, values[i].integer64); - index++; - break; - - case SQLITE_TEXT: - ret = sqlite3_bind_text(stmt, index, values[i].string, -1, values[i].delete); - index++; - break; - - case SQLITE_NULL: - ret = sqlite3_bind_null(stmt, index); - index++; - break; - - default: - assert(false); - ret = SQLITE_ERROR; - break; - + assert(ucount < 1); + memcpy(&updates[ucount++], &values[i], sizeof(bound_value)); } - - if (ret != SQLITE_OK) + else { - fprintf(stderr, "Can't bind value for parameter nb %d in '%s' (ret=%d): %s\n", - index - 1, sql, ret, sqlite3_errmsg(db)); - goto gdcsui_exit; + assert(ccount < (count - 1)); + memcpy(&conds[ccount++], &values[i], sizeof(bound_value)); } - - } - - /* Exécution finale */ - - ret = sqlite3_step(stmt); - - if (ret != SQLITE_DONE) - { - fprintf(stderr, "UPDATE statement '%s' didn't return DONE (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db)); - goto gdcsui_exit; } - sqlite3_finalize(stmt); - - result = true; - - gdcsui_exit: - - free(sql); + result = update_db_values(db, collec->name, updates, ucount, conds, ccount); - gdcsui_building_values: + building_values: free_all_bound_values(values, count); diff --git a/src/common/sqlite.c b/src/common/sqlite.c index d497c81..3a94623 100644 --- a/src/common/sqlite.c +++ b/src/common/sqlite.c @@ -34,7 +34,7 @@ /* Attribue une définition aux valeurs paramétrées. */ -static bool bind_bound_values(sqlite3 *, sqlite3_stmt *, const char *, const bound_value *, size_t, bool, int *); +static bool bind_bound_values(sqlite3 *, sqlite3_stmt *, const char *, const bound_value *, size_t, int *); @@ -106,12 +106,11 @@ const bound_value *find_bound_value(const bound_value *values, size_t count, con /****************************************************************************** * * * Paramètres : db = base de données à consulter. * -* stmt = requête SQL en préparation à faire évoluer. * -* sql = définition brute de cette requête SQL. * -* values = tableau d'éléments à consulter. * -* count = nombre de descriptions renseignées. * -* has_value = fitre sur la définition des valeurs. * -* index = indice évolutif des valeurs paramétrées. [OUT] * +* stmt = requête SQL en préparation à faire évoluer. * +* sql = définition brute de cette requête SQL. * +* values = tableau d'éléments à consulter. * +* count = nombre de descriptions renseignées. * +* index = indice évolutif des valeurs paramétrées. [OUT] * * * * Description : Attribue une définition aux valeurs paramétrées. * * * @@ -121,7 +120,7 @@ const bound_value *find_bound_value(const bound_value *values, size_t count, con * * ******************************************************************************/ -static bool bind_bound_values(sqlite3 *db, sqlite3_stmt *stmt, const char *sql, const bound_value *values, size_t count, bool has_value, int *index) +static bool bind_bound_values(sqlite3 *db, sqlite3_stmt *stmt, const char *sql, const bound_value *values, size_t count, int *index) { bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ @@ -131,7 +130,7 @@ static bool bind_bound_values(sqlite3 *db, sqlite3_stmt *stmt, const char *sql, for (i = 0; i < count && result; i++) { - if (values[i].has_value != has_value) + if (!values[i].has_value) continue; switch (values[i].type) @@ -269,7 +268,7 @@ bool load_db_values(sqlite3 *db, const char *table, bound_value *values, size_t index = 1; - if (!bind_bound_values(db, stmt, sql, values, count, true, &index)) + if (!bind_bound_values(db, stmt, sql, values, count, &index)) goto bind_error; /* Chargement des valeurs existantes */ @@ -446,7 +445,7 @@ bool store_db_values(sqlite3 *db, const char *table, const bound_value *values, index = 1; - if (!bind_bound_values(db, stmt, sql, values, count, true, &index)) + if (!bind_bound_values(db, stmt, sql, values, count, &index)) goto bind_error; /* Exécution finale */ @@ -474,3 +473,113 @@ bool store_db_values(sqlite3 *db, const char *table, const bound_value *values, return result; } + + +/****************************************************************************** +* * +* Paramètres : db = base de données à mettre à jour. * +* table = nom de la table concernée. * +* values = champs avec leur valeur nouvelle. * +* vcount = quantité de ces champs. * +* values = champs avec leur valeur de condition. * +* ccount = quantité de ces champs. * +* * +* Description : Met à jour une série de valeurs dans une base de données. * +* * +* Retour : Bilan de l'exécution de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool update_db_values(sqlite3 *db, const char *table, const bound_value *values, size_t vcount, const bound_value *conds, size_t ccount) +{ + bool result; /* Conclusion à faire remonter */ + char *sql; /* Requête SQL à construire */ + size_t i; /* Boucle de parcours */ + sqlite3_stmt *stmt; /* Déclaration mise en place */ + int ret; /* Bilan d'un appel à SQLite */ + int index; /* Indice de valeur attachée */ + + result = false; + + /* Préparation de la requête */ + + sql = strdup("UPDATE "); + sql = stradd(sql, table); + sql = stradd(sql, " SET"); + + for (i = 0; i < vcount; i++) + { + assert(values[i].has_value); + + if (i > 0) sql = stradd(sql, " ,"); + + sql = stradd(sql, " "); + sql = stradd(sql, values[i].name); + + sql = stradd(sql, " = ?"); + + } + + if (ccount > 0) + { + sql = stradd(sql, " WHERE"); + + for (i = 0; i < ccount; i++) + { + if (i > 0) sql = stradd(sql, " AND"); + + sql = stradd(sql, " "); + sql = stradd(sql, conds[i].name); + + sql = stradd(sql, " = ?"); + + } + + } + + sql = stradd(sql, ";"); + + ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); + if (ret != SQLITE_OK) + { + fprintf(stderr, "Can't prepare UPDATE statment '%s' (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db)); + goto prepare_error; + } + + /* Attribution des valeurs */ + + index = 1; + + if (!bind_bound_values(db, stmt, sql, values, vcount, &index)) + goto bind_error; + + if (!bind_bound_values(db, stmt, sql, conds, ccount, &index)) + goto bind_error; + + /* Exécution finale */ + + ret = sqlite3_step(stmt); + + if (ret != SQLITE_DONE) + { + fprintf(stderr, "UPDATE statement '%s' didn't return DONE (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db)); + goto update_error; + } + + result = true; + + update_error: + + bind_error: + + sqlite3_finalize(stmt); + + prepare_error: + + free(sql); + + return result; + +} diff --git a/src/common/sqlite.h b/src/common/sqlite.h index 291eec8..99de12d 100644 --- a/src/common/sqlite.h +++ b/src/common/sqlite.h @@ -84,6 +84,9 @@ bool load_db_values(sqlite3 *, const char *, bound_value *, size_t, db_load_cb, /* Enregistre une série de valeurs dans une base de données. */ bool store_db_values(sqlite3 *, const char *, const bound_value *, size_t); +/* Met à jour une série de valeurs dans une base de données. */ +bool update_db_values(sqlite3 *, const char *, const bound_value *, size_t, const bound_value *, size_t); + #endif /* _COMMON_SQLITE_H */ -- cgit v0.11.2-87-g4458