summaryrefslogtreecommitdiff
path: root/src/json_report.c
diff options
context:
space:
mode:
authorcashmere <cashmere@autistici.org>2026-09-04 09:05:24 +0200
committercashmere <cashmere@autistici.org>2026-09-04 09:05:24 +0200
commit4f49b16079b27d7ce633619e4cddfdf2bffbc952 (patch)
treec296c1e7f3c3e2f6859c6d3a1b1b208779b89679 /src/json_report.c
downloadrelic-master.tar.gz
initial commitHEADmaster
Diffstat (limited to 'src/json_report.c')
-rw-r--r--src/json_report.c263
1 files changed, 263 insertions, 0 deletions
diff --git a/src/json_report.c b/src/json_report.c
new file mode 100644
index 0000000..e3fb8ad
--- /dev/null
+++ b/src/json_report.c
@@ -0,0 +1,263 @@
+#ifdef FOSSIL_ENABLE_JSON
+/*
+** Copyright (c) 2011 D. Richard Hipp
+**
+** This program is free software; you can redistribute it and/or
+** modify it under the terms of the Simplified BSD License (also
+** known as the "2-Clause License" or "FreeBSD License".)
+**
+** This program is distributed in the hope that it will be useful,
+** but without any warranty; without even the implied warranty of
+** merchantability or fitness for a particular purpose.
+**
+** Author contact information:
+** drh@hwaci.com
+** http://www.hwaci.com/drh/
+**
+*/
+
+#include "config.h"
+#include "json_report.h"
+
+#if INTERFACE
+#include "json_detail.h"
+#endif
+
+
+static cson_value * json_report_create(void);
+static cson_value * json_report_get(void);
+static cson_value * json_report_list(void);
+static cson_value * json_report_run(void);
+static cson_value * json_report_save(void);
+
+/*
+** Mapping of /json/report/XXX commands/paths to callbacks.
+*/
+static const JsonPageDef JsonPageDefs_Report[] = {
+{"create", json_report_create, 0},
+{"get", json_report_get, 0},
+{"list", json_report_list, 0},
+{"run", json_report_run, 0},
+{"save", json_report_save, 0},
+/* Last entry MUST have a NULL name. */
+{NULL,NULL,0}
+};
+/*
+** Implementation of the /json/report page.
+**
+**
+*/
+cson_value * json_page_report(void){
+ if(!g.perm.RdTkt && !g.perm.NewTkt ){
+ json_set_err(FSL_JSON_E_DENIED,
+ "Requires 'r' or 'n' permissions.");
+ return NULL;
+ }
+ return json_page_dispatch_helper(JsonPageDefs_Report);
+}
+
+/*
+** Searches the environment for a "report" parameter
+** (CLI: -report/-r #).
+**
+** If one is not found and argPos is >0 then json_command_arg()
+** is checked.
+**
+** Returns >0 (the report number) on success .
+*/
+static int json_report_get_number(int argPos){
+ int nReport = json_find_option_int("report",NULL,"r",-1);
+ if( (nReport<=0) && cson_value_is_integer(g.json.reqPayload.v)){
+ nReport = cson_value_get_integer(g.json.reqPayload.v);
+ }
+ if( (nReport <= 0) && (argPos>0) ){
+ char const * arg = json_command_arg(argPos);
+ if(arg && fossil_isdigit(*arg)) {
+ nReport = atoi(arg);
+ }
+ }
+ return nReport;
+}
+
+static cson_value * json_report_create(void){
+ json_set_err(FSL_JSON_E_NYI, NULL);
+ return NULL;
+}
+
+static cson_value * json_report_get(void){
+ int nReport;
+ Stmt q = empty_Stmt;
+ cson_value * pay = NULL;
+
+ if(!g.perm.TktFmt){
+ json_set_err(FSL_JSON_E_DENIED,
+ "Requires 't' privileges.");
+ return NULL;
+ }
+ nReport = json_report_get_number(3);
+ if(nReport <=0){
+ json_set_err(FSL_JSON_E_MISSING_ARGS,
+ "Missing or invalid 'report' (-r) parameter.");
+ return NULL;
+ }
+
+ db_prepare(&q,"SELECT rn AS report,"
+ " owner AS owner,"
+ " title AS title,"
+ " cast(strftime('%%s',mtime) as int) as timestamp,"
+ " cols as columns,"
+ " sqlcode as sqlCode"
+ " FROM reportfmt"
+ " WHERE rn=%d",
+ nReport);
+ if( SQLITE_ROW != db_step(&q) ){
+ db_finalize(&q);
+ json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
+ "Report #%d not found.", nReport);
+ return NULL;
+ }
+ pay = cson_sqlite3_row_to_object(q.pStmt);
+ db_finalize(&q);
+ return pay;
+}
+
+/*
+** Impl of /json/report/list.
+*/
+static cson_value * json_report_list(void){
+ Blob sql = empty_blob;
+ cson_value * pay = NULL;
+ if(!g.perm.RdTkt){
+ json_set_err(FSL_JSON_E_DENIED,
+ "Requires 'r' privileges.");
+ return NULL;
+ }
+ blob_append(&sql, "SELECT"
+ " rn AS report,"
+ " title as title,"
+ " owner as owner"
+ " FROM reportfmt"
+ " WHERE 1"
+ " ORDER BY title",
+ -1);
+ pay = json_sql_to_array_of_obj(&sql, NULL, 1);
+ if(!pay){
+ json_set_err(FSL_JSON_E_UNKNOWN,
+ "Quite unexpected: no ticket reports found.");
+ }
+ return pay;
+}
+
+/*
+** Impl for /json/report/run
+**
+** Options/arguments:
+**
+** report=int (CLI: -report # or -r #) is the report number to run.
+**
+** limit=int (CLI: -limit # or -n #) -n is for compat. with other commands.
+**
+** format=a|o Specifies result format: a=each row is an array, o=each
+** row is an object. Default=o.
+*/
+static cson_value * json_report_run(void){
+ int nReport;
+ Stmt q = empty_Stmt;
+ cson_object * pay = NULL;
+ cson_array * tktList = NULL;
+ char const * zFmt;
+ char * zTitle = NULL;
+ Blob sql = empty_blob;
+ int limit = 0;
+ cson_value * colNames = NULL;
+ int i;
+
+ if(!g.perm.RdTkt){
+ json_set_err(FSL_JSON_E_DENIED,
+ "Requires 'r' privileges.");
+ return NULL;
+ }
+ nReport = json_report_get_number(3);
+ if(nReport <=0){
+ json_set_err(FSL_JSON_E_MISSING_ARGS,
+ "Missing or invalid 'number' (-n) parameter.");
+ goto error;
+ }
+ zFmt = json_find_option_cstr2("format",NULL,"f",3);
+ if(!zFmt) zFmt = "o";
+ db_prepare(&q,
+ "SELECT sqlcode, "
+ " title"
+ " FROM reportfmt"
+ " WHERE rn=%d",
+ nReport);
+ if(SQLITE_ROW != db_step(&q)){
+ json_set_err(FSL_JSON_E_INVALID_ARGS,
+ "Report number %d not found.",
+ nReport);
+ db_finalize(&q);
+ goto error;
+ }
+
+ limit = json_find_option_int("limit",NULL,"n",-1);
+
+
+ /* Copy over report's SQL...*/
+ blob_append(&sql, db_column_text(&q,0), -1);
+ zTitle = fossil_strdup(db_column_text(&q,1));
+ db_finalize(&q);
+ db_prepare(&q, "%s", blob_sql_text(&sql));
+
+ /** Build the response... */
+ pay = cson_new_object();
+
+ cson_object_set(pay, "report", json_new_int(nReport));
+ cson_object_set(pay, "title", json_new_string(zTitle));
+ if(limit>0){
+ cson_object_set(pay, "limit", json_new_int((limit<0) ? 0 : limit));
+ }
+ free(zTitle);
+ zTitle = NULL;
+
+ if(g.perm.TktFmt){
+ cson_object_set(pay, "sqlcode",
+ cson_value_new_string(blob_str(&sql),
+ (unsigned int)blob_size(&sql)));
+ }
+ blob_reset(&sql);
+
+ colNames = cson_sqlite3_column_names(q.pStmt);
+ cson_object_set( pay, "columnNames", colNames);
+ for( i = 0 ; ((limit>0) ?(i < limit) : 1)
+ && (SQLITE_ROW == db_step(&q));
+ ++i){
+ cson_value * row = ('a'==*zFmt)
+ ? cson_sqlite3_row_to_array(q.pStmt)
+ : cson_sqlite3_row_to_object2(q.pStmt,
+ cson_value_get_array(colNames));
+ ;
+ if(row && !tktList){
+ tktList = cson_new_array();
+ }
+ cson_array_append(tktList, row);
+ }
+ db_finalize(&q);
+ cson_object_set(pay, "tickets",
+ tktList ? cson_array_value(tktList) : cson_value_null());
+
+ goto end;
+
+ error:
+ assert(0 != g.json.resultCode);
+ cson_value_free( cson_object_value(pay) );
+ pay = NULL;
+ end:
+
+ return pay ? cson_object_value(pay) : NULL;
+
+}
+
+static cson_value * json_report_save(void){
+ return NULL;
+}
+#endif /* FOSSIL_ENABLE_JSON */