From: Eric Bollengier Date: Thu, 7 Oct 2021 16:25:17 +0000 (+0200) Subject: Enhance JSON output for .jlist command with error, errmsg and type X-Git-Tag: Release-11.3.2~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=845ceba147d307bdefcc93a62c9f60a62fb84b2b;p=thirdparty%2Fbacula.git Enhance JSON output for .jlist command with error, errmsg and type --- diff --git a/bacula/src/cats/bdb.h b/bacula/src/cats/bdb.h index 59fe7edd1..52e277cb1 100644 --- a/bacula/src/cats/bdb.h +++ b/bacula/src/cats/bdb.h @@ -262,7 +262,7 @@ public: void bdb_list_jobmedia_records(JCR *jcr, JobId_t JobId, char *volume, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type); void bdb_list_filemedia_records(JCR *jcr, JobId_t JobId, uint32_t FileIndex, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type); void bdb_list_joblog_records(JCR *jcr, JobId_t JobId, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type); - int bdb_list_sql_query(JCR *jcr, const char *query, DB_LIST_HANDLER *sendit, void *ctx, int verbose, e_list_type type); + int bdb_list_sql_query(JCR *jcr, const char *title, const char *query, DB_LIST_HANDLER *sendit, void *ctx, int verbose, e_list_type type); void bdb_list_client_records(JCR *jcr, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type); void bdb_list_copies_records(JCR *jcr, uint32_t limit, char *jobids, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type); void bdb_list_events_records(JCR *jcr, EVENTS_DBR *rec, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type); diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index 767f8d6a5..c1197188f 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -723,8 +723,10 @@ public: /* Functions exported by sql.c for use within the cats directory. */ +void json_list_begin(void *vctx, const char *title); +void json_list_end(void *vctx, int errcode, const char *errmsg); int list_result(void *vctx, int cols, char **row); -int list_result(JCR *jcr, BDB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type type); +int list_result(JCR *jcr, BDB *mdb, const char *title, DB_LIST_HANDLER *send, void *ctx, e_list_type type); int get_sql_record_max(JCR *jcr, BDB *mdb); void list_dashes(BDB *mdb, DB_LIST_HANDLER *send, void *ctx); diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index f5889e1b6..53e668251 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -81,6 +81,7 @@ BDB *db_init_database(JCR *jcr, const char *db_driver, const char *db_name, if (mdb) mdb->bdb_thread_cleanup() /* sql.c */ +int db_mint64_handler(void *ctx, int num_fields, char **row); int db_int64_handler(void *ctx, int num_fields, char **row); int db_strtime_handler(void *ctx, int num_fields, char **row); int db_list_handler(void *ctx, int num_fields, char **row); @@ -278,8 +279,8 @@ void bdb_free_restoreobject_record(JCR *jcr, ROBJECT_DBR *rr); mdb->bdb_list_filemedia_records(jcr, JobId, FI, sendit, ctx, type) #define db_list_joblog_records(jcr, mdb, JobId, sendit, ctx, type) \ mdb->bdb_list_joblog_records(jcr, JobId, sendit, ctx, type) -#define db_list_sql_query(jcr, mdb, query, sendit, ctx, verbose, type) \ - mdb->bdb_list_sql_query(jcr, query, sendit, ctx, verbose, type) +#define db_list_sql_query(jcr, mdb, title, query, sendit, ctx, verbose, type) \ + mdb->bdb_list_sql_query(jcr, title, query, sendit, ctx, verbose, type) #define db_list_client_records(jcr, mdb, sendit, ctx, type) \ mdb->bdb_list_client_records(jcr, sendit, ctx, type) #define db_list_copies_records(jcr, mdb, limit, jobids, sendit, ctx, type) \ diff --git a/bacula/src/cats/sql.c b/bacula/src/cats/sql.c index 1de5dc184..85bda0ae8 100644 --- a/bacula/src/cats/sql.c +++ b/bacula/src/cats/sql.c @@ -122,7 +122,24 @@ int db_int64_handler(void *ctx, int num_fields, char **row) } return 0; } - + +/* + * Called here to retrieve a 32/64 bit integer from the database. + * The returned integer will be extended to 64 bit. It can + * return multiple values, but the array has to match the number + * of fields to be returned. + */ +int db_mint64_handler(void *ctx, int num_fields, char **row) +{ + int64_t *tab = (int64_t *)ctx; + for (int i = 0; i < num_fields; i++) { + if (row[i]) { + tab[i] = str_to_int64(row[i]); + } + } + return 0; +} + /* * Called here to retrieve a btime from the database. * The returned integer will be extended to 64 bit. @@ -740,7 +757,7 @@ static void last_line_handler(void *vctx, const char *str) LIST_CTX *ctx = (LIST_CTX *)vctx; bstrncat(ctx->line, str, sizeof(ctx->line)); } - + int list_result(void *vctx, int nb_col, char **row) { SQL_FIELD *field; @@ -844,7 +861,6 @@ int list_result(void *vctx, int nb_col, char **row) return 0; vertical_list: - Dmsg1(800, "list_result starts vertical list at %d fields\n", mdb->sql_num_fields()); mdb->sql_field_seek(0); for (i = 0; i < mdb->sql_num_fields(); i++) { @@ -908,27 +924,46 @@ json_list: send(ctx, tmp.c_str()); first = false; } - send(ctx, "}\n"); + send(ctx, "}"); return 0; } - + +/* Use this function to start a new JSON list */ +void json_list_begin(DB_LIST_HANDLER *send, void *ctx, const char *title) +{ + send(ctx, "{\"type\":\""); + send(ctx, title); + send(ctx, "\", \"data\":"); +} + +/* Use this function to end a JSON list */ +void json_list_end(DB_LIST_HANDLER *send, void *ctx, int errcode, const char *errmsg) +{ + send(ctx, ",\"error\":0, \"errmsg\":\"\"}\n"); +} + /* * If full_list is set, we list vertically, otherwise, we * list on one line horizontally. * Return number of rows */ int -list_result(JCR *jcr, BDB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type type) +list_result(JCR *jcr, BDB *mdb, const char *title, DB_LIST_HANDLER *send, void *ctx, e_list_type type) { SQL_FIELD *field; SQL_ROW row; int i, col_len, max_len = 0; char buf[2000], ewc[30]; - + + if (type == JSON_LIST) { + json_list_begin(send, ctx, title); + } + Dmsg0(800, "list_result starts\n"); if (mdb->sql_num_rows() == 0) { if (type == JSON_LIST) { - send(ctx, "[]\n"); + send(ctx, "[]"); + json_list_end(send, ctx, 0, ""); } else { send(ctx, _("No results to list.\n")); } @@ -1090,7 +1125,8 @@ json_list: } send(ctx, "}"); } - send(ctx, "]\n"); + send(ctx, "]"); + json_list_end(send, ctx, 0, ""); return mdb->sql_num_rows(); } diff --git a/bacula/src/cats/sql_list.c b/bacula/src/cats/sql_list.c index e70f485c1..06b8f8d8f 100644 --- a/bacula/src/cats/sql_list.c +++ b/bacula/src/cats/sql_list.c @@ -39,7 +39,7 @@ /* * Submit general SQL query */ -int BDB::bdb_list_sql_query(JCR *jcr, const char *query, DB_LIST_HANDLER *sendit, +int BDB::bdb_list_sql_query(JCR *jcr, const char *title, const char *query, DB_LIST_HANDLER *sendit, void *ctx, int verbose, e_list_type type) { bdb_lock(); @@ -52,7 +52,7 @@ int BDB::bdb_list_sql_query(JCR *jcr, const char *query, DB_LIST_HANDLER *sendit return 0; } - list_result(jcr,this, sendit, ctx, type); + list_result(jcr,this, title, sendit, ctx, type); sql_free_result(); bdb_unlock(); return 1; @@ -100,7 +100,7 @@ void BDB::bdb_list_pool_records(JCR *jcr, POOL_DBR *pdbr, return; } - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "pool", sendit, ctx, type); sql_free_result(); bdb_unlock(); @@ -122,7 +122,7 @@ void BDB::bdb_list_client_records(JCR *jcr, DB_LIST_HANDLER *sendit, void *ctx, return; } - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "client", sendit, ctx, type); sql_free_result(); bdb_unlock(); @@ -144,7 +144,7 @@ void BDB::bdb_list_plugin_object_types(JCR *jcr, DB_LIST_HANDLER *sendit, void * return; } - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "objecttype", sendit, ctx, type); sql_free_result(); bdb_unlock(); @@ -204,7 +204,7 @@ void BDB::bdb_list_plugin_objects(JCR *jcr, OBJECT_DBR *obj_r, DB_LIST_HANDLER * return; } - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "object", sendit, ctx, type); sql_free_result(); bdb_unlock(); @@ -244,7 +244,7 @@ void BDB::bdb_list_plugin_objects_ids(JCR *jcr, char* id_list, DB_LIST_HANDLER * return; } - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "object", sendit, ctx, type); sql_free_result(); bdb_unlock(); @@ -296,7 +296,7 @@ void BDB::bdb_list_restore_objects(JCR *jcr, ROBJECT_DBR *rr, DB_LIST_HANDLER *s return; } - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "restoreobject", sendit, ctx, type); sql_free_result(); bdb_unlock(); @@ -385,7 +385,7 @@ void BDB::bdb_list_media_records(JCR *jcr, MEDIA_DBR *mdbr, return; } - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "media", sendit, ctx, type); sql_free_result(); bdb_unlock(); @@ -442,7 +442,7 @@ void BDB::bdb_list_jobmedia_records(JCR *jcr, uint32_t JobId, char *volume, return; } - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "jobmedia", sendit, ctx, type); sql_free_result(); bdb_unlock(); @@ -479,7 +479,7 @@ void BDB::bdb_list_filemedia_records(JCR *jcr, uint32_t JobId, uint32_t FileInde return; } - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "filemedia", sendit, ctx, type); sql_free_result(); bdb_unlock(); @@ -525,7 +525,7 @@ void BDB::bdb_list_copies_records(JCR *jcr, uint32_t limit, char *JobIds, sendit(ctx, _("The catalog contains copies as follows:\n")); } - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "copy", sendit, ctx, type); } sql_free_result(); @@ -627,7 +627,7 @@ void BDB::bdb_list_events_records(JCR *jcr, EVENTS_DBR *rec, if (!QueryDB(jcr, cmd)) { goto bail_out; } - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "event", sendit, ctx, type); bail_out: bdb_unlock(); @@ -670,7 +670,7 @@ void BDB::bdb_list_joblog_records(JCR *jcr, uint32_t JobId, goto bail_out; } - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "joblog", sendit, ctx, type); sql_free_result(); @@ -818,7 +818,7 @@ alist *BDB::bdb_list_job_records(JCR *jcr, JOB_DBR *jr, DB_LIST_HANDLER *sendit, } } sql_data_seek(0); - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "job", sendit, ctx, type); sql_free_result(); bdb_unlock(); return list; @@ -827,6 +827,7 @@ alist *BDB::bdb_list_job_records(JCR *jcr, JOB_DBR *jr, DB_LIST_HANDLER *sendit, /* * List Job totals * + * TODO: Adapt for JSON */ void BDB::bdb_list_job_totals(JCR *jcr, JOB_DBR *jr, DB_LIST_HANDLER *sendit, void *ctx) { @@ -844,7 +845,7 @@ void BDB::bdb_list_job_totals(JCR *jcr, JOB_DBR *jr, DB_LIST_HANDLER *sendit, vo return; } - list_result(jcr, this, sendit, ctx, HORZ_LIST); + list_result(jcr, this, "jobtotal", sendit, ctx, HORZ_LIST); sql_free_result(); @@ -858,7 +859,7 @@ void BDB::bdb_list_job_totals(JCR *jcr, JOB_DBR *jr, DB_LIST_HANDLER *sendit, vo return; } - list_result(jcr, this, sendit, ctx, HORZ_LIST); + list_result(jcr, this, "jobtotal", sendit, ctx, HORZ_LIST); sql_free_result(); bdb_unlock(); @@ -1055,7 +1056,7 @@ void BDB::bdb_list_snapshot_records(JCR *jcr, SNAPSHOT_DBR *sdbr, goto bail_out; } - list_result(jcr, this, sendit, ctx, type); + list_result(jcr, this, "snapshot", sendit, ctx, type); bail_out: sql_free_result(); @@ -1129,10 +1130,9 @@ void BDB::bdb_list_tag_records(JCR *jcr, TAG_DBR *tag, DB_LIST_HANDLER *result_h } } Dmsg1(DT_SQL|50, "q=%s\n", tmp.c_str()); - bdb_list_sql_query(jcr, tmp.c_str(), result_handler, ctx, 0, type); + bdb_list_sql_query(jcr, "tag", tmp.c_str(), result_handler, ctx, 0, type); } bdb_unlock(); } - #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL */ diff --git a/bacula/src/dird/ua_query.c b/bacula/src/dird/ua_query.c index 522cb10f1..c46d904bc 100644 --- a/bacula/src/dird/ua_query.c +++ b/bacula/src/dird/ua_query.c @@ -141,8 +141,8 @@ int query_cmd(UAContext *ua, const char *cmd) query = substitute_prompts(ua, query, prompt, nprompt); Dmsg1(100, "Query2=%s\n", query); if (query[0] == '!') { - db_list_sql_query(ua->jcr, ua->db, query+1, prtit, ua, 0, VERT_LIST); - } else if (!db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST)) { + db_list_sql_query(ua->jcr, ua->db, "query", query+1, prtit, ua, 0, VERT_LIST); + } else if (!db_list_sql_query(ua->jcr, ua->db, "query", query, prtit, ua, 1, HORZ_LIST)) { ua->send_msg("%s\n", query); } query[0] = 0; @@ -153,8 +153,8 @@ int query_cmd(UAContext *ua, const char *cmd) query = substitute_prompts(ua, query, prompt, nprompt); Dmsg1(100, "Query2=%s\n", query); if (query[0] == '!') { - db_list_sql_query(ua->jcr, ua->db, query+1, prtit, ua, 0, VERT_LIST); - } else if (!db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST)) { + db_list_sql_query(ua->jcr, ua->db, "query", query+1, prtit, ua, 0, VERT_LIST); + } else if (!db_list_sql_query(ua->jcr, ua->db, "query", query, prtit, ua, 1, HORZ_LIST)) { ua->error_msg("%s\n", query); } } @@ -289,7 +289,7 @@ int sqlquery_cmd(UAContext *ua, const char *cmd) if (ua->cmd[len-1] == ';') { ua->cmd[len-1] = 0; /* zap ; */ /* Submit query */ - db_list_sql_query(ua->jcr, ua->db, query.c_str(), prtit, ua, 1, HORZ_LIST); + db_list_sql_query(ua->jcr, ua->db, "query", query.c_str(), prtit, ua, 1, HORZ_LIST); *query.c_str() = 0; /* start new query */ msg = _("Enter SQL query: "); } else { diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index bbf8ccac1..9caab2ee0 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -455,7 +455,7 @@ static void get_and_display_basejobs(UAContext *ua, RESTORE_CTX *rx) POOL_MEM q; Mmsg(q, uar_print_jobs, jobids.list); ua->send_msg(_("The restore will use the following job(s) as Base\n")); - db_list_sql_query(ua->jcr, ua->db, q.c_str(), prtit, ua, 1, HORZ_LIST); + db_list_sql_query(ua->jcr, ua->db, "basejobs", q.c_str(), prtit, ua, 1, HORZ_LIST); } pm_strcpy(rx->BaseJobIds, jobids.list); } @@ -842,7 +842,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) } gui_save = ua->jcr->gui; ua->jcr->gui = true; - db_list_sql_query(ua->jcr, ua->db, uar_list_jobs, prtit, ua, 1, HORZ_LIST); + db_list_sql_query(ua->jcr, ua->db, "job", uar_list_jobs, prtit, ua, 1, HORZ_LIST); ua->jcr->gui = gui_save; done = false; break; @@ -860,7 +860,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) free(fname); gui_save = ua->jcr->gui; ua->jcr->gui = true; - db_list_sql_query(ua->jcr, ua->db, rx->query, prtit, ua, 1, HORZ_LIST); + db_list_sql_query(ua->jcr, ua->db, "job", rx->query, prtit, ua, 1, HORZ_LIST); ua->jcr->gui = gui_save; done = false; break; @@ -880,7 +880,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) } gui_save = ua->jcr->gui; ua->jcr->gui = true; - db_list_sql_query(ua->jcr, ua->db, ua->cmd, prtit, ua, 1, HORZ_LIST); + db_list_sql_query(ua->jcr, ua->db, "job", ua->cmd, prtit, ua, 1, HORZ_LIST); ua->jcr->gui = gui_save; done = false; break; @@ -1104,7 +1104,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) "WHERE Object.ObjectName='%s' AND Object.ObjectCategory='%s' AND Object.ObjectType='%s'", esc.c_str(), esc_cat.c_str(), esc_type.c_str()); - if (!db_list_sql_query(ua->jcr, ua->db, query.c_str(), prtit, ua, 0, HORZ_LIST)) { + if (!db_list_sql_query(ua->jcr, ua->db, "object", query.c_str(), prtit, ua, 0, HORZ_LIST)) { ua->error_msg(_("SQL Query failed: %s\n"), db_strerror(ua->db)); return 0; } @@ -1858,7 +1858,7 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat if (rx->JobIds[0] != 0) { /* Display a list of Jobs selected for this restore */ - db_list_sql_query(ua->jcr, ua->db, uar_list_temp, prtit, ua, 1,HORZ_LIST); + db_list_sql_query(ua->jcr, ua->db, "job", uar_list_temp, prtit, ua, 1,HORZ_LIST); ok = true; } else { ua->warning_msg(_("No jobs found.\n")); diff --git a/bacula/src/dird/ua_update.c b/bacula/src/dird/ua_update.c index 0e338977d..89194b052 100644 --- a/bacula/src/dird/ua_update.c +++ b/bacula/src/dird/ua_update.c @@ -917,7 +917,7 @@ static bool update_pool(UAContext *ua) } query = get_pool_memory(PM_MESSAGE); Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1)); - db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST); + db_list_sql_query(ua->jcr, ua->db, "pool", query, prtit, ua, 1, HORZ_LIST); free_pool_memory(query); ua->info_msg(_("Pool DB record updated from resource.\n")); return true;