Fossil SCM
Added /json/tag/find.
Commit
9d27ade314cabed175c5af1c799751290f7c6fbf
Parent
0b685fcc0f2ef09…
2 files changed
+34
-11
+120
-1
+34
-11
| --- src/json.c | ||
| +++ src/json.c | ||
| @@ -821,11 +821,11 @@ | ||
| 821 | 821 | ** |
| 822 | 822 | ** FIXME: if msg is NULL then use a standard string for |
| 823 | 823 | ** the given code. If !*msg then elide the "text" property, |
| 824 | 824 | ** for consistency with how json_err() works. |
| 825 | 825 | */ |
| 826 | -void json_warn( int code, char const * msg ){ | |
| 826 | +void json_warn( int code, char const * fmt, ... ){ | |
| 827 | 827 | cson_value * objV = NULL; |
| 828 | 828 | cson_object * obj = NULL; |
| 829 | 829 | assert( (code>FSL_JSON_W_START) |
| 830 | 830 | && (code<FSL_JSON_W_END) |
| 831 | 831 | && "Invalid warning code."); |
| @@ -838,15 +838,20 @@ | ||
| 838 | 838 | objV = cson_value_new_object(); |
| 839 | 839 | assert((NULL != objV) && "Alloc error."); |
| 840 | 840 | cson_array_append(g.json.warnings.a, objV); |
| 841 | 841 | obj = cson_value_get_object(objV); |
| 842 | 842 | cson_object_set(obj,"code",cson_value_new_integer(code)); |
| 843 | - if(msg && *msg){ | |
| 844 | - /* FIXME: treat NULL msg as standard warning message for | |
| 843 | + if(fmt && *fmt){ | |
| 844 | + /* FIXME: treat NULL fmt as standard warning message for | |
| 845 | 845 | the code, but we don't have those yet. |
| 846 | 846 | */ |
| 847 | - cson_object_set(obj,"text",cson_value_new_string(msg,strlen(msg))); | |
| 847 | + va_list vargs; | |
| 848 | + va_start(vargs,fmt); | |
| 849 | + char * msg = vmprintf(fmt,vargs); | |
| 850 | + va_end(vargs); | |
| 851 | + cson_object_set(obj,"text", cson_value_new_string(msg,strlen(msg))); | |
| 852 | + free(msg); | |
| 848 | 853 | } |
| 849 | 854 | } |
| 850 | 855 | |
| 851 | 856 | /* |
| 852 | 857 | ** Splits zStr (which must not be NULL) into tokens separated by the |
| @@ -1261,11 +1266,11 @@ | ||
| 1261 | 1266 | ** Epoch timestamp. Requires the db, so this cannot be used before the |
| 1262 | 1267 | ** repo is opened (will trigger a fatal error in db_xxx()). |
| 1263 | 1268 | */ |
| 1264 | 1269 | cson_value * json_julian_to_timestamp(double j){ |
| 1265 | 1270 | return cson_value_new_integer((cson_int_t) |
| 1266 | - db_int64(0,"SELECT strftime('%%s',%lf)",j) | |
| 1271 | + db_int64(0,"SELECT cast(strftime('%%s',%lf) as int)",j) | |
| 1267 | 1272 | ); |
| 1268 | 1273 | } |
| 1269 | 1274 | |
| 1270 | 1275 | /* |
| 1271 | 1276 | ** Returns a timestamp value. |
| @@ -1525,25 +1530,43 @@ | ||
| 1525 | 1530 | ** Iterates through a prepared SELECT statement and converts each row |
| 1526 | 1531 | ** to a JSON object. If pTgt is not NULL then it must be-a Array |
| 1527 | 1532 | ** object and this function will return pTgt. If pTgt is NULL then a |
| 1528 | 1533 | ** new Array object is created and returned (owned by the |
| 1529 | 1534 | ** caller). Each row of pStmt is converted to an Object and appended |
| 1530 | -** to the array. | |
| 1535 | +** to the array. If the result set has no rows AND pTgt is NULL then | |
| 1536 | +** NULL is returned. | |
| 1531 | 1537 | */ |
| 1532 | 1538 | cson_value * json_stmt_to_array_of_obj(Stmt *pStmt, |
| 1533 | 1539 | cson_value * pTgt){ |
| 1534 | - cson_value * v = pTgt ? pTgt : cson_value_new_array(); | |
| 1535 | - cson_array * a = cson_value_get_array(pTgt ? pTgt : v); | |
| 1540 | + cson_value * v = pTgt; | |
| 1541 | + cson_array * a = NULL; | |
| 1536 | 1542 | char const * warnMsg = NULL; |
| 1537 | - assert( NULL != a ); | |
| 1543 | + if(v && !cson_value_is_array(v)){ | |
| 1544 | + return NULL; | |
| 1545 | + } | |
| 1538 | 1546 | while( (SQLITE_ROW==db_step(pStmt)) ){ |
| 1539 | - cson_value * row = cson_sqlite3_row_to_object(pStmt->pStmt); | |
| 1547 | + cson_value * row = NULL; | |
| 1548 | + if(!a){ | |
| 1549 | + if(!v){ | |
| 1550 | + v = cson_value_new_array(); | |
| 1551 | + } | |
| 1552 | + a = cson_value_get_array(v); | |
| 1553 | + assert(NULL!=a); | |
| 1554 | + } | |
| 1555 | + row = cson_sqlite3_row_to_object(pStmt->pStmt); | |
| 1540 | 1556 | if(!row && !warnMsg){ |
| 1541 | 1557 | warnMsg = "Could not convert at least one result row to JSON."; |
| 1542 | 1558 | continue; |
| 1543 | 1559 | } |
| 1544 | - cson_array_append(a, row); | |
| 1560 | + if( 0 != cson_array_append(a, row) ){ | |
| 1561 | + cson_value_free(row); | |
| 1562 | + assert( 0 && "Alloc error."); | |
| 1563 | + if(pTgt != v) { | |
| 1564 | + cson_value_free(v); | |
| 1565 | + } | |
| 1566 | + return NULL; | |
| 1567 | + } | |
| 1545 | 1568 | } |
| 1546 | 1569 | if(warnMsg){ |
| 1547 | 1570 | json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED, warnMsg ); |
| 1548 | 1571 | } |
| 1549 | 1572 | return v; |
| 1550 | 1573 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -821,11 +821,11 @@ | |
| 821 | ** |
| 822 | ** FIXME: if msg is NULL then use a standard string for |
| 823 | ** the given code. If !*msg then elide the "text" property, |
| 824 | ** for consistency with how json_err() works. |
| 825 | */ |
| 826 | void json_warn( int code, char const * msg ){ |
| 827 | cson_value * objV = NULL; |
| 828 | cson_object * obj = NULL; |
| 829 | assert( (code>FSL_JSON_W_START) |
| 830 | && (code<FSL_JSON_W_END) |
| 831 | && "Invalid warning code."); |
| @@ -838,15 +838,20 @@ | |
| 838 | objV = cson_value_new_object(); |
| 839 | assert((NULL != objV) && "Alloc error."); |
| 840 | cson_array_append(g.json.warnings.a, objV); |
| 841 | obj = cson_value_get_object(objV); |
| 842 | cson_object_set(obj,"code",cson_value_new_integer(code)); |
| 843 | if(msg && *msg){ |
| 844 | /* FIXME: treat NULL msg as standard warning message for |
| 845 | the code, but we don't have those yet. |
| 846 | */ |
| 847 | cson_object_set(obj,"text",cson_value_new_string(msg,strlen(msg))); |
| 848 | } |
| 849 | } |
| 850 | |
| 851 | /* |
| 852 | ** Splits zStr (which must not be NULL) into tokens separated by the |
| @@ -1261,11 +1266,11 @@ | |
| 1261 | ** Epoch timestamp. Requires the db, so this cannot be used before the |
| 1262 | ** repo is opened (will trigger a fatal error in db_xxx()). |
| 1263 | */ |
| 1264 | cson_value * json_julian_to_timestamp(double j){ |
| 1265 | return cson_value_new_integer((cson_int_t) |
| 1266 | db_int64(0,"SELECT strftime('%%s',%lf)",j) |
| 1267 | ); |
| 1268 | } |
| 1269 | |
| 1270 | /* |
| 1271 | ** Returns a timestamp value. |
| @@ -1525,25 +1530,43 @@ | |
| 1525 | ** Iterates through a prepared SELECT statement and converts each row |
| 1526 | ** to a JSON object. If pTgt is not NULL then it must be-a Array |
| 1527 | ** object and this function will return pTgt. If pTgt is NULL then a |
| 1528 | ** new Array object is created and returned (owned by the |
| 1529 | ** caller). Each row of pStmt is converted to an Object and appended |
| 1530 | ** to the array. |
| 1531 | */ |
| 1532 | cson_value * json_stmt_to_array_of_obj(Stmt *pStmt, |
| 1533 | cson_value * pTgt){ |
| 1534 | cson_value * v = pTgt ? pTgt : cson_value_new_array(); |
| 1535 | cson_array * a = cson_value_get_array(pTgt ? pTgt : v); |
| 1536 | char const * warnMsg = NULL; |
| 1537 | assert( NULL != a ); |
| 1538 | while( (SQLITE_ROW==db_step(pStmt)) ){ |
| 1539 | cson_value * row = cson_sqlite3_row_to_object(pStmt->pStmt); |
| 1540 | if(!row && !warnMsg){ |
| 1541 | warnMsg = "Could not convert at least one result row to JSON."; |
| 1542 | continue; |
| 1543 | } |
| 1544 | cson_array_append(a, row); |
| 1545 | } |
| 1546 | if(warnMsg){ |
| 1547 | json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED, warnMsg ); |
| 1548 | } |
| 1549 | return v; |
| 1550 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -821,11 +821,11 @@ | |
| 821 | ** |
| 822 | ** FIXME: if msg is NULL then use a standard string for |
| 823 | ** the given code. If !*msg then elide the "text" property, |
| 824 | ** for consistency with how json_err() works. |
| 825 | */ |
| 826 | void json_warn( int code, char const * fmt, ... ){ |
| 827 | cson_value * objV = NULL; |
| 828 | cson_object * obj = NULL; |
| 829 | assert( (code>FSL_JSON_W_START) |
| 830 | && (code<FSL_JSON_W_END) |
| 831 | && "Invalid warning code."); |
| @@ -838,15 +838,20 @@ | |
| 838 | objV = cson_value_new_object(); |
| 839 | assert((NULL != objV) && "Alloc error."); |
| 840 | cson_array_append(g.json.warnings.a, objV); |
| 841 | obj = cson_value_get_object(objV); |
| 842 | cson_object_set(obj,"code",cson_value_new_integer(code)); |
| 843 | if(fmt && *fmt){ |
| 844 | /* FIXME: treat NULL fmt as standard warning message for |
| 845 | the code, but we don't have those yet. |
| 846 | */ |
| 847 | va_list vargs; |
| 848 | va_start(vargs,fmt); |
| 849 | char * msg = vmprintf(fmt,vargs); |
| 850 | va_end(vargs); |
| 851 | cson_object_set(obj,"text", cson_value_new_string(msg,strlen(msg))); |
| 852 | free(msg); |
| 853 | } |
| 854 | } |
| 855 | |
| 856 | /* |
| 857 | ** Splits zStr (which must not be NULL) into tokens separated by the |
| @@ -1261,11 +1266,11 @@ | |
| 1266 | ** Epoch timestamp. Requires the db, so this cannot be used before the |
| 1267 | ** repo is opened (will trigger a fatal error in db_xxx()). |
| 1268 | */ |
| 1269 | cson_value * json_julian_to_timestamp(double j){ |
| 1270 | return cson_value_new_integer((cson_int_t) |
| 1271 | db_int64(0,"SELECT cast(strftime('%%s',%lf) as int)",j) |
| 1272 | ); |
| 1273 | } |
| 1274 | |
| 1275 | /* |
| 1276 | ** Returns a timestamp value. |
| @@ -1525,25 +1530,43 @@ | |
| 1530 | ** Iterates through a prepared SELECT statement and converts each row |
| 1531 | ** to a JSON object. If pTgt is not NULL then it must be-a Array |
| 1532 | ** object and this function will return pTgt. If pTgt is NULL then a |
| 1533 | ** new Array object is created and returned (owned by the |
| 1534 | ** caller). Each row of pStmt is converted to an Object and appended |
| 1535 | ** to the array. If the result set has no rows AND pTgt is NULL then |
| 1536 | ** NULL is returned. |
| 1537 | */ |
| 1538 | cson_value * json_stmt_to_array_of_obj(Stmt *pStmt, |
| 1539 | cson_value * pTgt){ |
| 1540 | cson_value * v = pTgt; |
| 1541 | cson_array * a = NULL; |
| 1542 | char const * warnMsg = NULL; |
| 1543 | if(v && !cson_value_is_array(v)){ |
| 1544 | return NULL; |
| 1545 | } |
| 1546 | while( (SQLITE_ROW==db_step(pStmt)) ){ |
| 1547 | cson_value * row = NULL; |
| 1548 | if(!a){ |
| 1549 | if(!v){ |
| 1550 | v = cson_value_new_array(); |
| 1551 | } |
| 1552 | a = cson_value_get_array(v); |
| 1553 | assert(NULL!=a); |
| 1554 | } |
| 1555 | row = cson_sqlite3_row_to_object(pStmt->pStmt); |
| 1556 | if(!row && !warnMsg){ |
| 1557 | warnMsg = "Could not convert at least one result row to JSON."; |
| 1558 | continue; |
| 1559 | } |
| 1560 | if( 0 != cson_array_append(a, row) ){ |
| 1561 | cson_value_free(row); |
| 1562 | assert( 0 && "Alloc error."); |
| 1563 | if(pTgt != v) { |
| 1564 | cson_value_free(v); |
| 1565 | } |
| 1566 | return NULL; |
| 1567 | } |
| 1568 | } |
| 1569 | if(warnMsg){ |
| 1570 | json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED, warnMsg ); |
| 1571 | } |
| 1572 | return v; |
| 1573 |
+120
-1
| --- src/json_tag.c | ||
| +++ src/json_tag.c | ||
| @@ -186,11 +186,130 @@ | ||
| 186 | 186 | ** Impl of /json/tag/find. |
| 187 | 187 | */ |
| 188 | 188 | static cson_value * json_tag_find(){ |
| 189 | 189 | cson_value * payV = NULL; |
| 190 | 190 | cson_object * pay = NULL; |
| 191 | - g.json.resultCode = FSL_JSON_E_NYI; | |
| 191 | + cson_value * listV = NULL; | |
| 192 | + cson_array * list = NULL; | |
| 193 | + char const * zName = NULL; | |
| 194 | + char const * zType = NULL; | |
| 195 | + char fRaw = 0; | |
| 196 | + Stmt q = empty_Stmt; | |
| 197 | + int limit = 0; | |
| 198 | + int tagid = 0; | |
| 199 | + | |
| 200 | + if( !g.perm.Read ){ | |
| 201 | + json_set_err(FSL_JSON_E_DENIED, | |
| 202 | + "Requires 'o' permissions."); | |
| 203 | + return NULL; | |
| 204 | + } | |
| 205 | + zName = json_find_option_cstr("name",NULL,NULL); | |
| 206 | + if(!zName || !*zName){ | |
| 207 | + if(!fossil_is_json()){ | |
| 208 | + zName = json_command_arg(3); | |
| 209 | + } | |
| 210 | + if(!zName || !*zName){ | |
| 211 | + json_set_err(FSL_JSON_E_MISSING_ARGS, | |
| 212 | + "'name' parameter is missing."); | |
| 213 | + return NULL; | |
| 214 | + } | |
| 215 | + } | |
| 216 | + zType = json_find_option_cstr("type",NULL,"t"); | |
| 217 | + if(!zType || !*zType){ | |
| 218 | + zType = "*"; | |
| 219 | + } | |
| 220 | + | |
| 221 | + tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", | |
| 222 | + zName); | |
| 223 | +#if 0 | |
| 224 | + /* It is arguable to return an error in this case. We could | |
| 225 | + alternatively simply return an empty set. | |
| 226 | + */ | |
| 227 | + if( tagid<=0 ){ | |
| 228 | + json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND, | |
| 229 | + "Could not find tag ID for tag '%s'.", zName); | |
| 230 | + return NULL; | |
| 231 | + } | |
| 232 | +#endif | |
| 233 | + | |
| 234 | + limit = json_find_option_int("limit",NULL,"n",0); | |
| 235 | + fRaw = json_find_option_bool("raw",NULL,NULL,0); | |
| 236 | + payV = cson_value_new_object(); | |
| 237 | + pay = cson_value_get_object(payV); | |
| 238 | + cson_object_set(pay, "name", json_new_string(zName)); | |
| 239 | + cson_object_set(pay, "raw", cson_value_new_bool(fRaw)); | |
| 240 | + cson_object_set(pay, "type", json_new_string(zType)); | |
| 241 | + cson_object_set(pay, "limit", json_new_int(limit)); | |
| 242 | + | |
| 243 | +#if 1 | |
| 244 | + if( tagid<=0 ){ | |
| 245 | + cson_object_set(pay,"artifacts", cson_value_null()); | |
| 246 | + return payV; | |
| 247 | + } | |
| 248 | +#endif | |
| 249 | + | |
| 250 | + if( fRaw ){ | |
| 251 | + db_prepare(&q, | |
| 252 | + "SELECT blob.uuid FROM tagxref, blob" | |
| 253 | + " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" | |
| 254 | + " AND tagxref.tagtype>0" | |
| 255 | + " AND blob.rid=tagxref.rid" | |
| 256 | + "%s LIMIT %d", | |
| 257 | + zName, | |
| 258 | + (limit>0)?"":"--", limit | |
| 259 | + ); | |
| 260 | + printf("SQL=%s\n", blob_buffer(&q.sql)); | |
| 261 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 262 | + if(!listV){ | |
| 263 | + listV = cson_value_new_array(); | |
| 264 | + list = cson_value_get_array(listV); | |
| 265 | + } | |
| 266 | + cson_array_append(list, cson_sqlite3_column_to_value(q.pStmt,0)); | |
| 267 | + } | |
| 268 | + db_finalize(&q); | |
| 269 | + }else{ | |
| 270 | + char const * zSqlBase = /*modified from timeline_query_for_tty()*/ | |
| 271 | + " SELECT" | |
| 272 | +#if 0 | |
| 273 | + " blob.rid AS rid," | |
| 274 | +#endif | |
| 275 | + " uuid AS uuid," | |
| 276 | + " cast(strftime('%s',event.mtime) as int) AS mtime," | |
| 277 | + " coalesce(ecomment,comment) AS comment," | |
| 278 | + " coalesce(euser,user) AS user," | |
| 279 | + " CASE event.type" | |
| 280 | + " WHEN 'ci' THEN 'checkin'" | |
| 281 | + " WHEN 'w' THEN 'wiki'" | |
| 282 | + " WHEN 'e' THEN 'event'" | |
| 283 | + " WHEN 't' THEN 'ticket'" | |
| 284 | + " ELSE 'WTF?'" | |
| 285 | + " END" | |
| 286 | + " AS eventType" | |
| 287 | + " FROM event, blob" | |
| 288 | + " WHERE blob.rid=event.objid" | |
| 289 | + ; | |
| 290 | + /* FIXME: re-add tags. */ | |
| 291 | + db_prepare(&q, | |
| 292 | + "%s" | |
| 293 | + " AND event.type GLOB '%q'" | |
| 294 | + " AND blob.rid IN (" | |
| 295 | + " SELECT rid FROM tagxref" | |
| 296 | + " WHERE tagtype>0 AND tagid=%d" | |
| 297 | + " )" | |
| 298 | + " ORDER BY event.mtime DESC" | |
| 299 | + "%s LIMIT %d", | |
| 300 | + zSqlBase, zType, tagid, | |
| 301 | + (limit>0)?"":"--", limit | |
| 302 | + ); | |
| 303 | + listV = json_stmt_to_array_of_obj(&q, NULL); | |
| 304 | + db_finalize(&q); | |
| 305 | + } | |
| 306 | + | |
| 307 | + if(!listV) { | |
| 308 | + listV = cson_value_null(); | |
| 309 | + } | |
| 310 | + cson_object_set(pay, "artifacts", listV); | |
| 192 | 311 | return payV; |
| 193 | 312 | } |
| 194 | 313 | |
| 195 | 314 | |
| 196 | 315 | /* |
| 197 | 316 |
| --- src/json_tag.c | |
| +++ src/json_tag.c | |
| @@ -186,11 +186,130 @@ | |
| 186 | ** Impl of /json/tag/find. |
| 187 | */ |
| 188 | static cson_value * json_tag_find(){ |
| 189 | cson_value * payV = NULL; |
| 190 | cson_object * pay = NULL; |
| 191 | g.json.resultCode = FSL_JSON_E_NYI; |
| 192 | return payV; |
| 193 | } |
| 194 | |
| 195 | |
| 196 | /* |
| 197 |
| --- src/json_tag.c | |
| +++ src/json_tag.c | |
| @@ -186,11 +186,130 @@ | |
| 186 | ** Impl of /json/tag/find. |
| 187 | */ |
| 188 | static cson_value * json_tag_find(){ |
| 189 | cson_value * payV = NULL; |
| 190 | cson_object * pay = NULL; |
| 191 | cson_value * listV = NULL; |
| 192 | cson_array * list = NULL; |
| 193 | char const * zName = NULL; |
| 194 | char const * zType = NULL; |
| 195 | char fRaw = 0; |
| 196 | Stmt q = empty_Stmt; |
| 197 | int limit = 0; |
| 198 | int tagid = 0; |
| 199 | |
| 200 | if( !g.perm.Read ){ |
| 201 | json_set_err(FSL_JSON_E_DENIED, |
| 202 | "Requires 'o' permissions."); |
| 203 | return NULL; |
| 204 | } |
| 205 | zName = json_find_option_cstr("name",NULL,NULL); |
| 206 | if(!zName || !*zName){ |
| 207 | if(!fossil_is_json()){ |
| 208 | zName = json_command_arg(3); |
| 209 | } |
| 210 | if(!zName || !*zName){ |
| 211 | json_set_err(FSL_JSON_E_MISSING_ARGS, |
| 212 | "'name' parameter is missing."); |
| 213 | return NULL; |
| 214 | } |
| 215 | } |
| 216 | zType = json_find_option_cstr("type",NULL,"t"); |
| 217 | if(!zType || !*zType){ |
| 218 | zType = "*"; |
| 219 | } |
| 220 | |
| 221 | tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", |
| 222 | zName); |
| 223 | #if 0 |
| 224 | /* It is arguable to return an error in this case. We could |
| 225 | alternatively simply return an empty set. |
| 226 | */ |
| 227 | if( tagid<=0 ){ |
| 228 | json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND, |
| 229 | "Could not find tag ID for tag '%s'.", zName); |
| 230 | return NULL; |
| 231 | } |
| 232 | #endif |
| 233 | |
| 234 | limit = json_find_option_int("limit",NULL,"n",0); |
| 235 | fRaw = json_find_option_bool("raw",NULL,NULL,0); |
| 236 | payV = cson_value_new_object(); |
| 237 | pay = cson_value_get_object(payV); |
| 238 | cson_object_set(pay, "name", json_new_string(zName)); |
| 239 | cson_object_set(pay, "raw", cson_value_new_bool(fRaw)); |
| 240 | cson_object_set(pay, "type", json_new_string(zType)); |
| 241 | cson_object_set(pay, "limit", json_new_int(limit)); |
| 242 | |
| 243 | #if 1 |
| 244 | if( tagid<=0 ){ |
| 245 | cson_object_set(pay,"artifacts", cson_value_null()); |
| 246 | return payV; |
| 247 | } |
| 248 | #endif |
| 249 | |
| 250 | if( fRaw ){ |
| 251 | db_prepare(&q, |
| 252 | "SELECT blob.uuid FROM tagxref, blob" |
| 253 | " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" |
| 254 | " AND tagxref.tagtype>0" |
| 255 | " AND blob.rid=tagxref.rid" |
| 256 | "%s LIMIT %d", |
| 257 | zName, |
| 258 | (limit>0)?"":"--", limit |
| 259 | ); |
| 260 | printf("SQL=%s\n", blob_buffer(&q.sql)); |
| 261 | while( db_step(&q)==SQLITE_ROW ){ |
| 262 | if(!listV){ |
| 263 | listV = cson_value_new_array(); |
| 264 | list = cson_value_get_array(listV); |
| 265 | } |
| 266 | cson_array_append(list, cson_sqlite3_column_to_value(q.pStmt,0)); |
| 267 | } |
| 268 | db_finalize(&q); |
| 269 | }else{ |
| 270 | char const * zSqlBase = /*modified from timeline_query_for_tty()*/ |
| 271 | " SELECT" |
| 272 | #if 0 |
| 273 | " blob.rid AS rid," |
| 274 | #endif |
| 275 | " uuid AS uuid," |
| 276 | " cast(strftime('%s',event.mtime) as int) AS mtime," |
| 277 | " coalesce(ecomment,comment) AS comment," |
| 278 | " coalesce(euser,user) AS user," |
| 279 | " CASE event.type" |
| 280 | " WHEN 'ci' THEN 'checkin'" |
| 281 | " WHEN 'w' THEN 'wiki'" |
| 282 | " WHEN 'e' THEN 'event'" |
| 283 | " WHEN 't' THEN 'ticket'" |
| 284 | " ELSE 'WTF?'" |
| 285 | " END" |
| 286 | " AS eventType" |
| 287 | " FROM event, blob" |
| 288 | " WHERE blob.rid=event.objid" |
| 289 | ; |
| 290 | /* FIXME: re-add tags. */ |
| 291 | db_prepare(&q, |
| 292 | "%s" |
| 293 | " AND event.type GLOB '%q'" |
| 294 | " AND blob.rid IN (" |
| 295 | " SELECT rid FROM tagxref" |
| 296 | " WHERE tagtype>0 AND tagid=%d" |
| 297 | " )" |
| 298 | " ORDER BY event.mtime DESC" |
| 299 | "%s LIMIT %d", |
| 300 | zSqlBase, zType, tagid, |
| 301 | (limit>0)?"":"--", limit |
| 302 | ); |
| 303 | listV = json_stmt_to_array_of_obj(&q, NULL); |
| 304 | db_finalize(&q); |
| 305 | } |
| 306 | |
| 307 | if(!listV) { |
| 308 | listV = cson_value_null(); |
| 309 | } |
| 310 | cson_object_set(pay, "artifacts", listV); |
| 311 | return payV; |
| 312 | } |
| 313 | |
| 314 | |
| 315 | /* |
| 316 |