Index: src/blob.c ================================================================== --- src/blob.c +++ src/blob.c @@ -53,10 +53,15 @@ /* ** The buffer holding the blob data */ #define blob_buffer(X) ((X)->aData) +/* +** Number of elements that fits into the current blob's size +*/ +#define blob_count(X,elType) (blob_size(X)/sizeof(elType)) + /* ** Append blob contents to another */ #define blob_appendb(dest, src) \ blob_append((dest), blob_buffer(src), blob_size(src)) Index: src/tkt.c ================================================================== --- src/tkt.c +++ src/tkt.c @@ -232,10 +232,20 @@ for(i=0; (z = cgi_parameter_name(i))!=0; i++){ Th_Store(z, P(z)); } } +/* +** Information about a single J-card +*/ +struct jCardInfo { + char *zValue; + int mimetype; + int rid; + double mtime; +}; + /* ** Update an entry of the TICKET and TICKETCHNG tables according to the ** information in the ticket artifact given in p. Attempt to create ** the appropriate TICKET table entry if tktid is zero. If tktid is nonzero ** then it will be the ROWID of an existing TICKET entry. @@ -242,11 +252,12 @@ ** ** Parameter rid is the recordID for the ticket artifact in the BLOB table. ** ** Return the new rowid of the TICKET table entry. */ -static int ticket_insert(const Manifest *p, const int rid, int tktid){ +static int ticket_insert(const Manifest *p, const int rid, int tktid, + Blob *fields){ Blob sql1; /* update or replace TICKET ... */ Blob sql2; /* list of TICKETCHNG's fields that are in the manifest */ Blob sql3; /* list of values which correspond to the previous list */ Stmt q; int i, j; @@ -361,24 +372,37 @@ } blob_reset(&sql2); blob_reset(&sql3); fossil_free(aUsed); if( rid>0 ){ /* extract backlinks */ - int bReplace = 1, mimetype; for(i=0; inField; i++){ const char *zName = p->aField[i].zName; const char *zBaseName = zName[0]=='+' ? zName+1 : zName; j = fieldId(zBaseName); if( j<0 ) continue; if( aField[j].mUsed & USEDBY_TICKETCHNG ){ - mimetype = mimetype_tktchng; + backlink_extract(p->aField[i].zValue, mimetype_tktchng, + rid, BKLNK_TICKET, p->rDate, + /* existing backlinks must have been + * already deleted by the caller */ 0 ); }else{ - mimetype = mimetype_tkt; + /* update field's data with the most recent values */ + Blob *cards = fields + j; + struct jCardInfo card = { + fossil_strdup(p->aField[i].zValue), + mimetype_tkt, rid, p->rDate + }; + if( blob_size(cards) && zName[0]!='+' ){ + struct jCardInfo *x = (struct jCardInfo *)blob_buffer(cards); + struct jCardInfo *end = x + blob_count(cards,struct jCardInfo); + for(; x!=end; x++){ + fossil_free( x->zValue ); + } + blob_truncate(cards,0); + } + blob_append(cards, (const char*)(&card), sizeof(card)); } - backlink_extract(p->aField[i].zValue, mimetype, rid, BKLNK_TICKET, - p->rDate, bReplace); - bReplace = 0; } } return tktid; } @@ -411,12 +435,13 @@ void ticket_rebuild_entry(const char *zTktUuid){ char *zTag = mprintf("tkt-%s", zTktUuid); int tagid = tag_findid(zTag, 1); Stmt q; Manifest *pTicket; - int tktid; + int tktid, i; int createFlag = 1; + Blob *fields; /* array of blobs; each blob holds array of jCardInfo */ fossil_free(zTag); getAllTicketFields(); if( haveTicket==0 ) return; tktid = db_int(0, "SELECT tkt_id FROM ticket WHERE tkt_uuid=%Q", zTktUuid); @@ -424,22 +449,41 @@ if( haveTicketChng ){ db_multi_exec("DELETE FROM ticketchng WHERE tkt_id=%d;", tktid); } db_multi_exec("DELETE FROM ticket WHERE tkt_id=%d", tktid); tktid = 0; + fields = blobarray_new( nField ); + db_multi_exec("DELETE FROM backlink WHERE srctype=%d AND srcid IN " + "(SELECT rid FROM tagxref WHERE tagid=%d)",BKLNK_TICKET, tagid); db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%d ORDER BY mtime",tagid); while( db_step(&q)==SQLITE_ROW ){ int rid = db_column_int(&q, 0); pTicket = manifest_get(rid, CFTYPE_TICKET, 0); if( pTicket ){ - tktid = ticket_insert(pTicket, rid, tktid); + tktid = ticket_insert(pTicket, rid, tktid, fields); manifest_ticket_event(rid, pTicket, createFlag, tagid); manifest_destroy(pTicket); } createFlag = 0; } db_finalize(&q); + /* Extract backlinks from the most recent values of TICKET fields */ + for(i=0; izValue ); + backlink_extract(x->zValue,x->mimetype, + x->rid,BKLNK_TICKET,x->mtime,0); + fossil_free( x->zValue ); + } + } + blob_truncate(cards,0); + } + blobarray_delete(fields,nField); } /* ** Create the TH1 interpreter and load the "common" code.