Fossil SCM

fossil-scm / src / json_report.c
Source Blame History 263 lines
796dcfe… drh 1 #ifdef FOSSIL_ENABLE_JSON
796dcfe… drh 2 /*
c19f34c… drh 3 ** Copyright (c) 2011 D. Richard Hipp
796dcfe… drh 4 **
796dcfe… drh 5 ** This program is free software; you can redistribute it and/or
796dcfe… drh 6 ** modify it under the terms of the Simplified BSD License (also
796dcfe… drh 7 ** known as the "2-Clause License" or "FreeBSD License".)
796dcfe… drh 8 **
796dcfe… drh 9 ** This program is distributed in the hope that it will be useful,
796dcfe… drh 10 ** but without any warranty; without even the implied warranty of
796dcfe… drh 11 ** merchantability or fitness for a particular purpose.
796dcfe… drh 12 **
796dcfe… drh 13 ** Author contact information:
796dcfe… drh 14 ** [email protected]
796dcfe… drh 15 ** http://www.hwaci.com/drh/
796dcfe… drh 16 **
796dcfe… drh 17 */
796dcfe… drh 18
796dcfe… drh 19 #include "config.h"
796dcfe… drh 20 #include "json_report.h"
796dcfe… drh 21
796dcfe… drh 22 #if INTERFACE
796dcfe… drh 23 #include "json_detail.h"
796dcfe… drh 24 #endif
796dcfe… drh 25
796dcfe… drh 26
a80f274… stephan 27 static cson_value * json_report_create(void);
a80f274… stephan 28 static cson_value * json_report_get(void);
a80f274… stephan 29 static cson_value * json_report_list(void);
a80f274… stephan 30 static cson_value * json_report_run(void);
a80f274… stephan 31 static cson_value * json_report_save(void);
796dcfe… drh 32
796dcfe… drh 33 /*
796dcfe… drh 34 ** Mapping of /json/report/XXX commands/paths to callbacks.
796dcfe… drh 35 */
796dcfe… drh 36 static const JsonPageDef JsonPageDefs_Report[] = {
796dcfe… drh 37 {"create", json_report_create, 0},
796dcfe… drh 38 {"get", json_report_get, 0},
796dcfe… drh 39 {"list", json_report_list, 0},
796dcfe… drh 40 {"run", json_report_run, 0},
796dcfe… drh 41 {"save", json_report_save, 0},
796dcfe… drh 42 /* Last entry MUST have a NULL name. */
796dcfe… drh 43 {NULL,NULL,0}
796dcfe… drh 44 };
796dcfe… drh 45 /*
796dcfe… drh 46 ** Implementation of the /json/report page.
796dcfe… drh 47 **
796dcfe… drh 48 **
796dcfe… drh 49 */
a80f274… stephan 50 cson_value * json_page_report(void){
796dcfe… drh 51 if(!g.perm.RdTkt && !g.perm.NewTkt ){
796dcfe… drh 52 json_set_err(FSL_JSON_E_DENIED,
796dcfe… drh 53 "Requires 'r' or 'n' permissions.");
796dcfe… drh 54 return NULL;
796dcfe… drh 55 }
055dfb1… stephan 56 return json_page_dispatch_helper(JsonPageDefs_Report);
796dcfe… drh 57 }
796dcfe… drh 58
796dcfe… drh 59 /*
796dcfe… drh 60 ** Searches the environment for a "report" parameter
796dcfe… drh 61 ** (CLI: -report/-r #).
796dcfe… drh 62 **
796dcfe… drh 63 ** If one is not found and argPos is >0 then json_command_arg()
796dcfe… drh 64 ** is checked.
bf9669f… andygoth 65 **
796dcfe… drh 66 ** Returns >0 (the report number) on success .
796dcfe… drh 67 */
796dcfe… drh 68 static int json_report_get_number(int argPos){
796dcfe… drh 69 int nReport = json_find_option_int("report",NULL,"r",-1);
796dcfe… drh 70 if( (nReport<=0) && cson_value_is_integer(g.json.reqPayload.v)){
796dcfe… drh 71 nReport = cson_value_get_integer(g.json.reqPayload.v);
796dcfe… drh 72 }
796dcfe… drh 73 if( (nReport <= 0) && (argPos>0) ){
796dcfe… drh 74 char const * arg = json_command_arg(argPos);
796dcfe… drh 75 if(arg && fossil_isdigit(*arg)) {
796dcfe… drh 76 nReport = atoi(arg);
796dcfe… drh 77 }
796dcfe… drh 78 }
796dcfe… drh 79 return nReport;
796dcfe… drh 80 }
796dcfe… drh 81
a80f274… stephan 82 static cson_value * json_report_create(void){
bbcc8fe… stephan 83 json_set_err(FSL_JSON_E_NYI, NULL);
796dcfe… drh 84 return NULL;
796dcfe… drh 85 }
796dcfe… drh 86
a80f274… stephan 87 static cson_value * json_report_get(void){
796dcfe… drh 88 int nReport;
796dcfe… drh 89 Stmt q = empty_Stmt;
796dcfe… drh 90 cson_value * pay = NULL;
796dcfe… drh 91
796dcfe… drh 92 if(!g.perm.TktFmt){
796dcfe… drh 93 json_set_err(FSL_JSON_E_DENIED,
796dcfe… drh 94 "Requires 't' privileges.");
796dcfe… drh 95 return NULL;
796dcfe… drh 96 }
796dcfe… drh 97 nReport = json_report_get_number(3);
796dcfe… drh 98 if(nReport <=0){
796dcfe… drh 99 json_set_err(FSL_JSON_E_MISSING_ARGS,
53ba1f2… stephan 100 "Missing or invalid 'report' (-r) parameter.");
796dcfe… drh 101 return NULL;
796dcfe… drh 102 }
796dcfe… drh 103
796dcfe… drh 104 db_prepare(&q,"SELECT rn AS report,"
796dcfe… drh 105 " owner AS owner,"
796dcfe… drh 106 " title AS title,"
070b755… stephan 107 " cast(strftime('%%s',mtime) as int) as timestamp,"
796dcfe… drh 108 " cols as columns,"
796dcfe… drh 109 " sqlcode as sqlCode"
796dcfe… drh 110 " FROM reportfmt"
796dcfe… drh 111 " WHERE rn=%d",
796dcfe… drh 112 nReport);
796dcfe… drh 113 if( SQLITE_ROW != db_step(&q) ){
796dcfe… drh 114 db_finalize(&q);
796dcfe… drh 115 json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
796dcfe… drh 116 "Report #%d not found.", nReport);
796dcfe… drh 117 return NULL;
796dcfe… drh 118 }
796dcfe… drh 119 pay = cson_sqlite3_row_to_object(q.pStmt);
796dcfe… drh 120 db_finalize(&q);
796dcfe… drh 121 return pay;
796dcfe… drh 122 }
796dcfe… drh 123
796dcfe… drh 124 /*
796dcfe… drh 125 ** Impl of /json/report/list.
796dcfe… drh 126 */
a80f274… stephan 127 static cson_value * json_report_list(void){
796dcfe… drh 128 Blob sql = empty_blob;
796dcfe… drh 129 cson_value * pay = NULL;
796dcfe… drh 130 if(!g.perm.RdTkt){
796dcfe… drh 131 json_set_err(FSL_JSON_E_DENIED,
796dcfe… drh 132 "Requires 'r' privileges.");
796dcfe… drh 133 return NULL;
796dcfe… drh 134 }
796dcfe… drh 135 blob_append(&sql, "SELECT"
796dcfe… drh 136 " rn AS report,"
796dcfe… drh 137 " title as title,"
796dcfe… drh 138 " owner as owner"
796dcfe… drh 139 " FROM reportfmt"
796dcfe… drh 140 " WHERE 1"
796dcfe… drh 141 " ORDER BY title",
796dcfe… drh 142 -1);
796dcfe… drh 143 pay = json_sql_to_array_of_obj(&sql, NULL, 1);
796dcfe… drh 144 if(!pay){
796dcfe… drh 145 json_set_err(FSL_JSON_E_UNKNOWN,
796dcfe… drh 146 "Quite unexpected: no ticket reports found.");
796dcfe… drh 147 }
796dcfe… drh 148 return pay;
796dcfe… drh 149 }
796dcfe… drh 150
796dcfe… drh 151 /*
796dcfe… drh 152 ** Impl for /json/report/run
796dcfe… drh 153 **
796dcfe… drh 154 ** Options/arguments:
796dcfe… drh 155 **
796dcfe… drh 156 ** report=int (CLI: -report # or -r #) is the report number to run.
796dcfe… drh 157 **
796dcfe… drh 158 ** limit=int (CLI: -limit # or -n #) -n is for compat. with other commands.
796dcfe… drh 159 **
e2bdc10… danield 160 ** format=a|o Specifies result format: a=each row is an array, o=each
796dcfe… drh 161 ** row is an object. Default=o.
796dcfe… drh 162 */
a80f274… stephan 163 static cson_value * json_report_run(void){
796dcfe… drh 164 int nReport;
796dcfe… drh 165 Stmt q = empty_Stmt;
796dcfe… drh 166 cson_object * pay = NULL;
796dcfe… drh 167 cson_array * tktList = NULL;
796dcfe… drh 168 char const * zFmt;
796dcfe… drh 169 char * zTitle = NULL;
796dcfe… drh 170 Blob sql = empty_blob;
796dcfe… drh 171 int limit = 0;
796dcfe… drh 172 cson_value * colNames = NULL;
796dcfe… drh 173 int i;
796dcfe… drh 174
796dcfe… drh 175 if(!g.perm.RdTkt){
796dcfe… drh 176 json_set_err(FSL_JSON_E_DENIED,
796dcfe… drh 177 "Requires 'r' privileges.");
796dcfe… drh 178 return NULL;
796dcfe… drh 179 }
796dcfe… drh 180 nReport = json_report_get_number(3);
796dcfe… drh 181 if(nReport <=0){
796dcfe… drh 182 json_set_err(FSL_JSON_E_MISSING_ARGS,
796dcfe… drh 183 "Missing or invalid 'number' (-n) parameter.");
796dcfe… drh 184 goto error;
796dcfe… drh 185 }
796dcfe… drh 186 zFmt = json_find_option_cstr2("format",NULL,"f",3);
796dcfe… drh 187 if(!zFmt) zFmt = "o";
796dcfe… drh 188 db_prepare(&q,
796dcfe… drh 189 "SELECT sqlcode, "
796dcfe… drh 190 " title"
796dcfe… drh 191 " FROM reportfmt"
796dcfe… drh 192 " WHERE rn=%d",
796dcfe… drh 193 nReport);
796dcfe… drh 194 if(SQLITE_ROW != db_step(&q)){
796dcfe… drh 195 json_set_err(FSL_JSON_E_INVALID_ARGS,
796dcfe… drh 196 "Report number %d not found.",
796dcfe… drh 197 nReport);
796dcfe… drh 198 db_finalize(&q);
796dcfe… drh 199 goto error;
796dcfe… drh 200 }
796dcfe… drh 201
796dcfe… drh 202 limit = json_find_option_int("limit",NULL,"n",-1);
796dcfe… drh 203
bf9669f… andygoth 204
796dcfe… drh 205 /* Copy over report's SQL...*/
796dcfe… drh 206 blob_append(&sql, db_column_text(&q,0), -1);
4c3e172… danield 207 zTitle = fossil_strdup(db_column_text(&q,1));
796dcfe… drh 208 db_finalize(&q);
49b0ff1… drh 209 db_prepare(&q, "%s", blob_sql_text(&sql));
796dcfe… drh 210
796dcfe… drh 211 /** Build the response... */
796dcfe… drh 212 pay = cson_new_object();
796dcfe… drh 213
796dcfe… drh 214 cson_object_set(pay, "report", json_new_int(nReport));
796dcfe… drh 215 cson_object_set(pay, "title", json_new_string(zTitle));
796dcfe… drh 216 if(limit>0){
796dcfe… drh 217 cson_object_set(pay, "limit", json_new_int((limit<0) ? 0 : limit));
796dcfe… drh 218 }
796dcfe… drh 219 free(zTitle);
796dcfe… drh 220 zTitle = NULL;
796dcfe… drh 221
796dcfe… drh 222 if(g.perm.TktFmt){
796dcfe… drh 223 cson_object_set(pay, "sqlcode",
796dcfe… drh 224 cson_value_new_string(blob_str(&sql),
796dcfe… drh 225 (unsigned int)blob_size(&sql)));
796dcfe… drh 226 }
796dcfe… drh 227 blob_reset(&sql);
796dcfe… drh 228
796dcfe… drh 229 colNames = cson_sqlite3_column_names(q.pStmt);
796dcfe… drh 230 cson_object_set( pay, "columnNames", colNames);
796dcfe… drh 231 for( i = 0 ; ((limit>0) ?(i < limit) : 1)
796dcfe… drh 232 && (SQLITE_ROW == db_step(&q));
796dcfe… drh 233 ++i){
796dcfe… drh 234 cson_value * row = ('a'==*zFmt)
796dcfe… drh 235 ? cson_sqlite3_row_to_array(q.pStmt)
796dcfe… drh 236 : cson_sqlite3_row_to_object2(q.pStmt,
796dcfe… drh 237 cson_value_get_array(colNames));
796dcfe… drh 238 ;
796dcfe… drh 239 if(row && !tktList){
796dcfe… drh 240 tktList = cson_new_array();
796dcfe… drh 241 }
796dcfe… drh 242 cson_array_append(tktList, row);
796dcfe… drh 243 }
796dcfe… drh 244 db_finalize(&q);
796dcfe… drh 245 cson_object_set(pay, "tickets",
796dcfe… drh 246 tktList ? cson_array_value(tktList) : cson_value_null());
796dcfe… drh 247
796dcfe… drh 248 goto end;
796dcfe… drh 249
796dcfe… drh 250 error:
796dcfe… drh 251 assert(0 != g.json.resultCode);
796dcfe… drh 252 cson_value_free( cson_object_value(pay) );
796dcfe… drh 253 pay = NULL;
055dfb1… stephan 254 end:
796dcfe… drh 255
796dcfe… drh 256 return pay ? cson_object_value(pay) : NULL;
796dcfe… drh 257
796dcfe… drh 258 }
796dcfe… drh 259
a80f274… stephan 260 static cson_value * json_report_save(void){
796dcfe… drh 261 return NULL;
796dcfe… drh 262 }
796dcfe… drh 263 #endif /* FOSSIL_ENABLE_JSON */

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button