Fossil SCM

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

Keyboard Shortcuts

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