Fossil SCM

Enhancements to the TICKETCHNG table: (1) Add the tkt_rid column and populate it (if present) with the recordID of the artifact. (2) For columns that appear in both TICKET and TICKETCHNG but are missing from the artifact, fill in the TICKETCHNG value with the value from TICKET at that point in time. (3) Add the test-ticket-rebuild command for testing the above.

drh 2013-01-11 18:03 trunk
Commit a18a49c875a0e7c642ecb135482285a5b936963b
--- src/schema.c
+++ src/schema.c
@@ -400,10 +400,11 @@
400400
@ comment TEXT
401401
@ );
402402
@ CREATE TABLE ticketchng(
403403
@ -- Do not change any column that begins with tkt_
404404
@ tkt_id INTEGER REFERENCES ticket,
405
+@ tkt_rid INTEGER REFERENCES blob,
405406
@ tkt_mtime DATE,
406407
@ -- Add as many fields as required below this line
407408
@ login TEXT,
408409
@ username TEXT,
409410
@ mimetype TEXT,
410411
--- src/schema.c
+++ src/schema.c
@@ -400,10 +400,11 @@
400 @ comment TEXT
401 @ );
402 @ CREATE TABLE ticketchng(
403 @ -- Do not change any column that begins with tkt_
404 @ tkt_id INTEGER REFERENCES ticket,
 
405 @ tkt_mtime DATE,
406 @ -- Add as many fields as required below this line
407 @ login TEXT,
408 @ username TEXT,
409 @ mimetype TEXT,
410
--- src/schema.c
+++ src/schema.c
@@ -400,10 +400,11 @@
400 @ comment TEXT
401 @ );
402 @ CREATE TABLE ticketchng(
403 @ -- Do not change any column that begins with tkt_
404 @ tkt_id INTEGER REFERENCES ticket,
405 @ tkt_rid INTEGER REFERENCES blob,
406 @ tkt_mtime DATE,
407 @ -- Add as many fields as required below this line
408 @ login TEXT,
409 @ username TEXT,
410 @ mimetype TEXT,
411
+59 -11
--- src/tkt.c
+++ src/tkt.c
@@ -34,12 +34,14 @@
3434
char *zAppend; /* Value to append */
3535
unsigned mUsed; /* 01: TICKET 02: TICKETCHNG */
3636
} *aField;
3737
#define USEDBY_TICKET 01
3838
#define USEDBY_TICKETCHNG 02
39
+#define USEDBY_BOTH 03
3940
static int haveTicket = 0; /* True if the TICKET table exists */
4041
static int haveTicketChng = 0; /* True if the TICKETCHNG table exists */
42
+static int haveTicketChngRid = 0; /* True if TICKETCHNG.TKT_RID exists */
4143
4244
/*
4345
** Compare two entries in aField[] for sorting purposes
4446
*/
4547
static int nameCmpr(const void *a, const void *b){
@@ -87,10 +89,11 @@
8789
db_finalize(&q);
8890
db_prepare(&q, "PRAGMA table_info(ticketchng)");
8991
while( db_step(&q)==SQLITE_ROW ){
9092
const char *zFieldName = db_column_text(&q, 1);
9193
haveTicketChng = 1;
94
+ if( strcmp(zFieldName,"tkt_rid")==0 ) haveTicketChngRid = 1;
9295
if( memcmp(zFieldName,"tkt_",4)==0 ) continue;
9396
if( (i = fieldId(zFieldName))>=0 ){
9497
aField[i].mUsed |= USEDBY_TICKETCHNG;
9598
continue;
9699
}
@@ -183,10 +186,11 @@
183186
*/
184187
static int ticket_insert(const Manifest *p, int rid, int tktid){
185188
Blob sql1, sql2, sql3;
186189
Stmt q;
187190
int i, j;
191
+ char *aUsed;
188192
189193
if( tktid==0 ){
190194
db_multi_exec("INSERT INTO ticket(tkt_uuid, tkt_mtime) "
191195
"VALUES(%Q, 0)", p->zTicketUuid);
192196
tktid = db_last_insert_rowid();
@@ -193,22 +197,22 @@
193197
}
194198
blob_zero(&sql1);
195199
blob_zero(&sql2);
196200
blob_zero(&sql3);
197201
blob_appendf(&sql1, "UPDATE OR REPLACE ticket SET tkt_mtime=:mtime");
202
+ aUsed = fossil_malloc( nField );
203
+ memset(aUsed, 0, nField);
198204
for(i=0; i<p->nField; i++){
199205
const char *zName = p->aField[i].zName;
200
- if( zName[0]=='+' ){
201
- zName++;
202
- if( (j = fieldId(zName))<0 ) continue;
203
- if( aField[j].mUsed & USEDBY_TICKET ){
206
+ if( (j = fieldId(zName))<0 ) continue;
207
+ aUsed[j] = 1;
208
+ if( aField[j].mUsed & USEDBY_TICKET ){
209
+ if( zName[0]=='+' ){
210
+ zName++;
204211
blob_appendf(&sql1,", %s=coalesce(%s,'') || %Q",
205212
zName, zName, p->aField[i].zValue);
206
- }
207
- }else{
208
- if( (j = fieldId(zName))<0 ) continue;
209
- if( aField[j].mUsed & USEDBY_TICKET ){
213
+ }else{
210214
blob_appendf(&sql1,", %s=%Q", zName, p->aField[i].zValue);
211215
}
212216
}
213217
if( aField[j].mUsed & USEDBY_TICKETCHNG ){
214218
blob_appendf(&sql2, ",%s", zName);
@@ -223,19 +227,40 @@
223227
db_bind_double(&q, ":mtime", p->rDate);
224228
db_step(&q);
225229
db_finalize(&q);
226230
blob_reset(&sql1);
227231
if( blob_size(&sql2)>0 ){
228
- db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
229
- "VALUES(%d,:mtime%s)",
230
- blob_str(&sql2), tktid, blob_str(&sql3));
232
+ int fromTkt = 0;
233
+ if( haveTicketChngRid ){
234
+ blob_append(&sql2, ",tkt_rid", -1);
235
+ blob_appendf(&sql3, ",%d", rid);
236
+ }
237
+ for(i=0; i<nField; i++){
238
+ if( aUsed[i]==0
239
+ && (aField[i].mUsed & USEDBY_BOTH)==USEDBY_BOTH
240
+ ){
241
+ fromTkt = 1;
242
+ blob_appendf(&sql2, ",%s", aField[i].zName);
243
+ blob_appendf(&sql3, ",%s", aField[i].zName);
244
+ }
245
+ }
246
+ if( fromTkt ){
247
+ db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
248
+ "SELECT %d,:mtime%s FROM ticket WHERE tkt_id=%d",
249
+ blob_str(&sql2), tktid, blob_str(&sql3), tktid);
250
+ }else{
251
+ db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
252
+ "VALUES(%d,:mtime%s)",
253
+ blob_str(&sql2), tktid, blob_str(&sql3));
254
+ }
231255
db_bind_double(&q, ":mtime", p->rDate);
232256
db_step(&q);
233257
db_finalize(&q);
234258
}
235259
blob_reset(&sql2);
236260
blob_reset(&sql3);
261
+ fossil_free(aUsed);
237262
return tktid;
238263
}
239264
240265
/*
241266
** Rebuild an entire entry in the TICKET table
@@ -268,10 +293,11 @@
268293
}
269294
createFlag = 0;
270295
}
271296
db_finalize(&q);
272297
}
298
+
273299
274300
/*
275301
** Create the TH1 interpreter and load the "common" code.
276302
*/
277303
void ticket_init(void){
@@ -328,10 +354,32 @@
328354
ticket_rebuild_entry(zName);
329355
}
330356
db_finalize(&q);
331357
db_end_transaction(0);
332358
}
359
+
360
+/*
361
+** COMMAND: test-ticket-rebuild
362
+**
363
+** Usage: %fossil test-ticket-rebuild TICKETID|all
364
+**
365
+** Rebuild the TICKET and TICKETCHNG tables for the given ticket ID
366
+** or for ALL.
367
+*/
368
+void test_ticket_rebuild(void){
369
+ db_find_and_open_repository(0, 0);
370
+ if( g.argc!=3 ) usage("TICKETID|all");
371
+ if( fossil_strcmp(g.argv[2], "all")==0 ){
372
+ ticket_rebuild();
373
+ }else{
374
+ const char *zUuid;
375
+ zUuid = db_text(0, "SELECT substr(tagname,5) FROM tag"
376
+ " WHERE tagname GLOB 'tkt-%q*'", g.argv[2]);
377
+ if( zUuid==0 ) fossil_fatal("no such ticket: %s", g.argv[2]);
378
+ ticket_rebuild_entry(zUuid);
379
+ }
380
+}
333381
334382
/*
335383
** For trouble-shooting purposes, render a dump of the aField[] table to
336384
** the webpage currently under construction.
337385
*/
338386
--- src/tkt.c
+++ src/tkt.c
@@ -34,12 +34,14 @@
34 char *zAppend; /* Value to append */
35 unsigned mUsed; /* 01: TICKET 02: TICKETCHNG */
36 } *aField;
37 #define USEDBY_TICKET 01
38 #define USEDBY_TICKETCHNG 02
 
39 static int haveTicket = 0; /* True if the TICKET table exists */
40 static int haveTicketChng = 0; /* True if the TICKETCHNG table exists */
 
41
42 /*
43 ** Compare two entries in aField[] for sorting purposes
44 */
45 static int nameCmpr(const void *a, const void *b){
@@ -87,10 +89,11 @@
87 db_finalize(&q);
88 db_prepare(&q, "PRAGMA table_info(ticketchng)");
89 while( db_step(&q)==SQLITE_ROW ){
90 const char *zFieldName = db_column_text(&q, 1);
91 haveTicketChng = 1;
 
92 if( memcmp(zFieldName,"tkt_",4)==0 ) continue;
93 if( (i = fieldId(zFieldName))>=0 ){
94 aField[i].mUsed |= USEDBY_TICKETCHNG;
95 continue;
96 }
@@ -183,10 +186,11 @@
183 */
184 static int ticket_insert(const Manifest *p, int rid, int tktid){
185 Blob sql1, sql2, sql3;
186 Stmt q;
187 int i, j;
 
188
189 if( tktid==0 ){
190 db_multi_exec("INSERT INTO ticket(tkt_uuid, tkt_mtime) "
191 "VALUES(%Q, 0)", p->zTicketUuid);
192 tktid = db_last_insert_rowid();
@@ -193,22 +197,22 @@
193 }
194 blob_zero(&sql1);
195 blob_zero(&sql2);
196 blob_zero(&sql3);
197 blob_appendf(&sql1, "UPDATE OR REPLACE ticket SET tkt_mtime=:mtime");
 
 
198 for(i=0; i<p->nField; i++){
199 const char *zName = p->aField[i].zName;
200 if( zName[0]=='+' ){
201 zName++;
202 if( (j = fieldId(zName))<0 ) continue;
203 if( aField[j].mUsed & USEDBY_TICKET ){
 
204 blob_appendf(&sql1,", %s=coalesce(%s,'') || %Q",
205 zName, zName, p->aField[i].zValue);
206 }
207 }else{
208 if( (j = fieldId(zName))<0 ) continue;
209 if( aField[j].mUsed & USEDBY_TICKET ){
210 blob_appendf(&sql1,", %s=%Q", zName, p->aField[i].zValue);
211 }
212 }
213 if( aField[j].mUsed & USEDBY_TICKETCHNG ){
214 blob_appendf(&sql2, ",%s", zName);
@@ -223,19 +227,40 @@
223 db_bind_double(&q, ":mtime", p->rDate);
224 db_step(&q);
225 db_finalize(&q);
226 blob_reset(&sql1);
227 if( blob_size(&sql2)>0 ){
228 db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
229 "VALUES(%d,:mtime%s)",
230 blob_str(&sql2), tktid, blob_str(&sql3));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231 db_bind_double(&q, ":mtime", p->rDate);
232 db_step(&q);
233 db_finalize(&q);
234 }
235 blob_reset(&sql2);
236 blob_reset(&sql3);
 
237 return tktid;
238 }
239
240 /*
241 ** Rebuild an entire entry in the TICKET table
@@ -268,10 +293,11 @@
268 }
269 createFlag = 0;
270 }
271 db_finalize(&q);
272 }
 
273
274 /*
275 ** Create the TH1 interpreter and load the "common" code.
276 */
277 void ticket_init(void){
@@ -328,10 +354,32 @@
328 ticket_rebuild_entry(zName);
329 }
330 db_finalize(&q);
331 db_end_transaction(0);
332 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
334 /*
335 ** For trouble-shooting purposes, render a dump of the aField[] table to
336 ** the webpage currently under construction.
337 */
338
--- src/tkt.c
+++ src/tkt.c
@@ -34,12 +34,14 @@
34 char *zAppend; /* Value to append */
35 unsigned mUsed; /* 01: TICKET 02: TICKETCHNG */
36 } *aField;
37 #define USEDBY_TICKET 01
38 #define USEDBY_TICKETCHNG 02
39 #define USEDBY_BOTH 03
40 static int haveTicket = 0; /* True if the TICKET table exists */
41 static int haveTicketChng = 0; /* True if the TICKETCHNG table exists */
42 static int haveTicketChngRid = 0; /* True if TICKETCHNG.TKT_RID exists */
43
44 /*
45 ** Compare two entries in aField[] for sorting purposes
46 */
47 static int nameCmpr(const void *a, const void *b){
@@ -87,10 +89,11 @@
89 db_finalize(&q);
90 db_prepare(&q, "PRAGMA table_info(ticketchng)");
91 while( db_step(&q)==SQLITE_ROW ){
92 const char *zFieldName = db_column_text(&q, 1);
93 haveTicketChng = 1;
94 if( strcmp(zFieldName,"tkt_rid")==0 ) haveTicketChngRid = 1;
95 if( memcmp(zFieldName,"tkt_",4)==0 ) continue;
96 if( (i = fieldId(zFieldName))>=0 ){
97 aField[i].mUsed |= USEDBY_TICKETCHNG;
98 continue;
99 }
@@ -183,10 +186,11 @@
186 */
187 static int ticket_insert(const Manifest *p, int rid, int tktid){
188 Blob sql1, sql2, sql3;
189 Stmt q;
190 int i, j;
191 char *aUsed;
192
193 if( tktid==0 ){
194 db_multi_exec("INSERT INTO ticket(tkt_uuid, tkt_mtime) "
195 "VALUES(%Q, 0)", p->zTicketUuid);
196 tktid = db_last_insert_rowid();
@@ -193,22 +197,22 @@
197 }
198 blob_zero(&sql1);
199 blob_zero(&sql2);
200 blob_zero(&sql3);
201 blob_appendf(&sql1, "UPDATE OR REPLACE ticket SET tkt_mtime=:mtime");
202 aUsed = fossil_malloc( nField );
203 memset(aUsed, 0, nField);
204 for(i=0; i<p->nField; i++){
205 const char *zName = p->aField[i].zName;
206 if( (j = fieldId(zName))<0 ) continue;
207 aUsed[j] = 1;
208 if( aField[j].mUsed & USEDBY_TICKET ){
209 if( zName[0]=='+' ){
210 zName++;
211 blob_appendf(&sql1,", %s=coalesce(%s,'') || %Q",
212 zName, zName, p->aField[i].zValue);
213 }else{
 
 
 
214 blob_appendf(&sql1,", %s=%Q", zName, p->aField[i].zValue);
215 }
216 }
217 if( aField[j].mUsed & USEDBY_TICKETCHNG ){
218 blob_appendf(&sql2, ",%s", zName);
@@ -223,19 +227,40 @@
227 db_bind_double(&q, ":mtime", p->rDate);
228 db_step(&q);
229 db_finalize(&q);
230 blob_reset(&sql1);
231 if( blob_size(&sql2)>0 ){
232 int fromTkt = 0;
233 if( haveTicketChngRid ){
234 blob_append(&sql2, ",tkt_rid", -1);
235 blob_appendf(&sql3, ",%d", rid);
236 }
237 for(i=0; i<nField; i++){
238 if( aUsed[i]==0
239 && (aField[i].mUsed & USEDBY_BOTH)==USEDBY_BOTH
240 ){
241 fromTkt = 1;
242 blob_appendf(&sql2, ",%s", aField[i].zName);
243 blob_appendf(&sql3, ",%s", aField[i].zName);
244 }
245 }
246 if( fromTkt ){
247 db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
248 "SELECT %d,:mtime%s FROM ticket WHERE tkt_id=%d",
249 blob_str(&sql2), tktid, blob_str(&sql3), tktid);
250 }else{
251 db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
252 "VALUES(%d,:mtime%s)",
253 blob_str(&sql2), tktid, blob_str(&sql3));
254 }
255 db_bind_double(&q, ":mtime", p->rDate);
256 db_step(&q);
257 db_finalize(&q);
258 }
259 blob_reset(&sql2);
260 blob_reset(&sql3);
261 fossil_free(aUsed);
262 return tktid;
263 }
264
265 /*
266 ** Rebuild an entire entry in the TICKET table
@@ -268,10 +293,11 @@
293 }
294 createFlag = 0;
295 }
296 db_finalize(&q);
297 }
298
299
300 /*
301 ** Create the TH1 interpreter and load the "common" code.
302 */
303 void ticket_init(void){
@@ -328,10 +354,32 @@
354 ticket_rebuild_entry(zName);
355 }
356 db_finalize(&q);
357 db_end_transaction(0);
358 }
359
360 /*
361 ** COMMAND: test-ticket-rebuild
362 **
363 ** Usage: %fossil test-ticket-rebuild TICKETID|all
364 **
365 ** Rebuild the TICKET and TICKETCHNG tables for the given ticket ID
366 ** or for ALL.
367 */
368 void test_ticket_rebuild(void){
369 db_find_and_open_repository(0, 0);
370 if( g.argc!=3 ) usage("TICKETID|all");
371 if( fossil_strcmp(g.argv[2], "all")==0 ){
372 ticket_rebuild();
373 }else{
374 const char *zUuid;
375 zUuid = db_text(0, "SELECT substr(tagname,5) FROM tag"
376 " WHERE tagname GLOB 'tkt-%q*'", g.argv[2]);
377 if( zUuid==0 ) fossil_fatal("no such ticket: %s", g.argv[2]);
378 ticket_rebuild_entry(zUuid);
379 }
380 }
381
382 /*
383 ** For trouble-shooting purposes, render a dump of the aField[] table to
384 ** the webpage currently under construction.
385 */
386
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -82,10 +82,11 @@
8282
@ comment TEXT
8383
@ );
8484
@ CREATE TABLE ticketchng(
8585
@ -- Do not change any column that begins with tkt_
8686
@ tkt_id INTEGER REFERENCES ticket,
87
+@ tkt_rid INTEGER REFERENCES blob,
8788
@ tkt_mtime DATE,
8889
@ -- Add as many fields as required below this line
8990
@ login TEXT,
9091
@ username TEXT,
9192
@ mimetype TEXT,
9293
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -82,10 +82,11 @@
82 @ comment TEXT
83 @ );
84 @ CREATE TABLE ticketchng(
85 @ -- Do not change any column that begins with tkt_
86 @ tkt_id INTEGER REFERENCES ticket,
 
87 @ tkt_mtime DATE,
88 @ -- Add as many fields as required below this line
89 @ login TEXT,
90 @ username TEXT,
91 @ mimetype TEXT,
92
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -82,10 +82,11 @@
82 @ comment TEXT
83 @ );
84 @ CREATE TABLE ticketchng(
85 @ -- Do not change any column that begins with tkt_
86 @ tkt_id INTEGER REFERENCES ticket,
87 @ tkt_rid INTEGER REFERENCES blob,
88 @ tkt_mtime DATE,
89 @ -- Add as many fields as required below this line
90 @ login TEXT,
91 @ username TEXT,
92 @ mimetype TEXT,
93

Keyboard Shortcuts

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