Fossil SCM

Add support for generated "mimetype" column in the <var>TICKET</var> table. Introduce integer mimetype codes and refactor <code>backlink_extract()</code> accordingly. Make the overall handling of the generated "mimetype" columns a bit more clear.

george 2022-05-18 20:21 generated-tkt-mimetype
Commit e39f77906e078d56058dc010e35cda46c14d57e44cb5821663d76da5841e683d
3 files changed +19 -5 +11 +54 -23
+19 -5
--- src/backlink.c
+++ src/backlink.c
@@ -179,11 +179,12 @@
179179
rid = db_int(0, "SELECT rid FROM tagxref WHERE tagid=%d"
180180
" ORDER BY mtime DESC LIMIT 1", tagid);
181181
if( rid==0 ) return;
182182
pWiki = manifest_get(rid, CFTYPE_WIKI, 0);
183183
if( pWiki ){
184
- backlink_extract(pWiki->zWiki, pWiki->zMimetype, tagid, BKLNK_WIKI,
184
+ int mimetype = parse_mimetype( pWiki->zMimetype );
185
+ backlink_extract(pWiki->zWiki, mimetype, tagid, BKLNK_WIKI,
185186
pWiki->rDate, 1);
186187
manifest_destroy(pWiki);
187188
}
188189
}
189190
@@ -295,17 +296,28 @@
295296
markdown(&out, &in, &html_renderer);
296297
blob_reset(&out);
297298
blob_reset(&in);
298299
}
299300
301
+/*
302
+** Transform mimetype string into an integer code.
303
+** NOTE: In the sake of compatability empty string is parsed as MT_UNKNOWN;
304
+** it is yet unclear whether it can safely be changed to MT_NONE.
305
+*/
306
+int parse_mimetype(const char* zMimetype){
307
+ if( zMimetype==0 ) return MT_NONE;
308
+ if( strstr(zMimetype,"wiki")!=0 ) return MT_WIKI;
309
+ if( strstr(zMimetype,"markdown")!=0 ) return MT_MARKDOWN;
310
+ return MT_UNKNOWN;
311
+}
300312
/*
301313
** Parse text looking for hyperlinks. Insert references into the
302314
** BACKLINK table.
303315
*/
304316
void backlink_extract(
305317
char *zSrc, /* Input text from which links are extracted */
306
- const char *zMimetype, /* Mimetype of input. NULL means fossil-wiki */
318
+ int mimetype, /* Mimetype of input. MT_NONE works as MT_WIKI */
307319
int srcid, /* srcid for the source document */
308320
int srctype, /* One of BKLNK_*. 0=comment 1=ticket 2=wiki */
309321
double mtime, /* mtime field for new BACKLINK table entries */
310322
int replaceFlag /* True to overwrite prior BACKLINK entries */
311323
){
@@ -314,15 +326,16 @@
314326
db_multi_exec("DELETE FROM backlink WHERE srctype=%d AND srcid=%d",
315327
srctype, srcid);
316328
}
317329
bklnk.srcid = srcid;
318330
assert( ValidBklnk(srctype) );
331
+ assert( ValidMTC(mimetype) );
319332
bklnk.srctype = srctype;
320333
bklnk.mtime = mtime;
321
- if( zMimetype==0 || strstr(zMimetype,"wiki")!=0 ){
334
+ if( mimetype==MT_NONE || mimetype==MT_WIKI ){
322335
wiki_extract_links(zSrc, &bklnk, srctype==BKLNK_COMMENT ? WIKI_INLINE : 0);
323
- }else if( strstr(zMimetype,"markdown")!=0 ){
336
+ }else if( mimetype==MT_MARKDOWN ){
324337
markdown_extract_links(zSrc, &bklnk);
325338
}
326339
}
327340
328341
/*
@@ -340,10 +353,11 @@
340353
** --mimetype TYPE Use an alternative mimetype.
341354
*/
342355
void test_backlinks_cmd(void){
343356
const char *zMTime = find_option("mtime",0,1);
344357
const char *zMimetype = find_option("mimetype",0,1);
358
+ const int mimetype = parse_mimetype(zMimetype);
345359
Blob in;
346360
int srcid;
347361
int srctype;
348362
double mtime;
349363
@@ -371,11 +385,11 @@
371385
" ' srcid='||quote(new.srcid)||"
372386
" ' mtime='||datetime(new.mtime));\n"
373387
" SELECT raise(ignore);\n"
374388
"END;"
375389
);
376
- backlink_extract(blob_str(&in),zMimetype,srcid,srctype,mtime,0);
390
+ backlink_extract(blob_str(&in),mimetype,srcid,srctype,mtime,0);
377391
blob_reset(&in);
378392
}
379393
380394
381395
/*
382396
--- src/backlink.c
+++ src/backlink.c
@@ -179,11 +179,12 @@
179 rid = db_int(0, "SELECT rid FROM tagxref WHERE tagid=%d"
180 " ORDER BY mtime DESC LIMIT 1", tagid);
181 if( rid==0 ) return;
182 pWiki = manifest_get(rid, CFTYPE_WIKI, 0);
183 if( pWiki ){
184 backlink_extract(pWiki->zWiki, pWiki->zMimetype, tagid, BKLNK_WIKI,
 
185 pWiki->rDate, 1);
186 manifest_destroy(pWiki);
187 }
188 }
189
@@ -295,17 +296,28 @@
295 markdown(&out, &in, &html_renderer);
296 blob_reset(&out);
297 blob_reset(&in);
298 }
299
 
 
 
 
 
 
 
 
 
 
 
300 /*
301 ** Parse text looking for hyperlinks. Insert references into the
302 ** BACKLINK table.
303 */
304 void backlink_extract(
305 char *zSrc, /* Input text from which links are extracted */
306 const char *zMimetype, /* Mimetype of input. NULL means fossil-wiki */
307 int srcid, /* srcid for the source document */
308 int srctype, /* One of BKLNK_*. 0=comment 1=ticket 2=wiki */
309 double mtime, /* mtime field for new BACKLINK table entries */
310 int replaceFlag /* True to overwrite prior BACKLINK entries */
311 ){
@@ -314,15 +326,16 @@
314 db_multi_exec("DELETE FROM backlink WHERE srctype=%d AND srcid=%d",
315 srctype, srcid);
316 }
317 bklnk.srcid = srcid;
318 assert( ValidBklnk(srctype) );
 
319 bklnk.srctype = srctype;
320 bklnk.mtime = mtime;
321 if( zMimetype==0 || strstr(zMimetype,"wiki")!=0 ){
322 wiki_extract_links(zSrc, &bklnk, srctype==BKLNK_COMMENT ? WIKI_INLINE : 0);
323 }else if( strstr(zMimetype,"markdown")!=0 ){
324 markdown_extract_links(zSrc, &bklnk);
325 }
326 }
327
328 /*
@@ -340,10 +353,11 @@
340 ** --mimetype TYPE Use an alternative mimetype.
341 */
342 void test_backlinks_cmd(void){
343 const char *zMTime = find_option("mtime",0,1);
344 const char *zMimetype = find_option("mimetype",0,1);
 
345 Blob in;
346 int srcid;
347 int srctype;
348 double mtime;
349
@@ -371,11 +385,11 @@
371 " ' srcid='||quote(new.srcid)||"
372 " ' mtime='||datetime(new.mtime));\n"
373 " SELECT raise(ignore);\n"
374 "END;"
375 );
376 backlink_extract(blob_str(&in),zMimetype,srcid,srctype,mtime,0);
377 blob_reset(&in);
378 }
379
380
381 /*
382
--- src/backlink.c
+++ src/backlink.c
@@ -179,11 +179,12 @@
179 rid = db_int(0, "SELECT rid FROM tagxref WHERE tagid=%d"
180 " ORDER BY mtime DESC LIMIT 1", tagid);
181 if( rid==0 ) return;
182 pWiki = manifest_get(rid, CFTYPE_WIKI, 0);
183 if( pWiki ){
184 int mimetype = parse_mimetype( pWiki->zMimetype );
185 backlink_extract(pWiki->zWiki, mimetype, tagid, BKLNK_WIKI,
186 pWiki->rDate, 1);
187 manifest_destroy(pWiki);
188 }
189 }
190
@@ -295,17 +296,28 @@
296 markdown(&out, &in, &html_renderer);
297 blob_reset(&out);
298 blob_reset(&in);
299 }
300
301 /*
302 ** Transform mimetype string into an integer code.
303 ** NOTE: In the sake of compatability empty string is parsed as MT_UNKNOWN;
304 ** it is yet unclear whether it can safely be changed to MT_NONE.
305 */
306 int parse_mimetype(const char* zMimetype){
307 if( zMimetype==0 ) return MT_NONE;
308 if( strstr(zMimetype,"wiki")!=0 ) return MT_WIKI;
309 if( strstr(zMimetype,"markdown")!=0 ) return MT_MARKDOWN;
310 return MT_UNKNOWN;
311 }
312 /*
313 ** Parse text looking for hyperlinks. Insert references into the
314 ** BACKLINK table.
315 */
316 void backlink_extract(
317 char *zSrc, /* Input text from which links are extracted */
318 int mimetype, /* Mimetype of input. MT_NONE works as MT_WIKI */
319 int srcid, /* srcid for the source document */
320 int srctype, /* One of BKLNK_*. 0=comment 1=ticket 2=wiki */
321 double mtime, /* mtime field for new BACKLINK table entries */
322 int replaceFlag /* True to overwrite prior BACKLINK entries */
323 ){
@@ -314,15 +326,16 @@
326 db_multi_exec("DELETE FROM backlink WHERE srctype=%d AND srcid=%d",
327 srctype, srcid);
328 }
329 bklnk.srcid = srcid;
330 assert( ValidBklnk(srctype) );
331 assert( ValidMTC(mimetype) );
332 bklnk.srctype = srctype;
333 bklnk.mtime = mtime;
334 if( mimetype==MT_NONE || mimetype==MT_WIKI ){
335 wiki_extract_links(zSrc, &bklnk, srctype==BKLNK_COMMENT ? WIKI_INLINE : 0);
336 }else if( mimetype==MT_MARKDOWN ){
337 markdown_extract_links(zSrc, &bklnk);
338 }
339 }
340
341 /*
@@ -340,10 +353,11 @@
353 ** --mimetype TYPE Use an alternative mimetype.
354 */
355 void test_backlinks_cmd(void){
356 const char *zMTime = find_option("mtime",0,1);
357 const char *zMimetype = find_option("mimetype",0,1);
358 const int mimetype = parse_mimetype(zMimetype);
359 Blob in;
360 int srcid;
361 int srctype;
362 double mtime;
363
@@ -371,11 +385,11 @@
385 " ' srcid='||quote(new.srcid)||"
386 " ' mtime='||datetime(new.mtime));\n"
387 " SELECT raise(ignore);\n"
388 "END;"
389 );
390 backlink_extract(blob_str(&in),mimetype,srcid,srctype,mtime,0);
391 blob_reset(&in);
392 }
393
394
395 /*
396
+11
--- src/schema.c
+++ src/schema.c
@@ -489,10 +489,21 @@
489489
# define BKLNK_EVENT 3 /* Technote */
490490
# define BKLNK_FORUM 4 /* Forum post */
491491
# define ValidBklnk(X) (X>=0 && X<=4) /* True if backlink.srctype is valid */
492492
#endif
493493
494
+/*
495
+** Allowed values for MIMEtype codes
496
+*/
497
+#if INTERFACE
498
+# define MT_NONE 0 /* unspecified */
499
+# define MT_WIKI 1 /* Wiki */
500
+# define MT_MARKDOWN 2 /* Markdonw */
501
+# define MT_UNKNOWN 3 /* unknown */
502
+# define ValidMTC(X) ((X)>=0 && (X)<=3) /* True if MIMEtype code is valid */
503
+#endif
504
+
494505
/*
495506
** Predefined tagid values
496507
*/
497508
#if INTERFACE
498509
# define TAG_BGCOLOR 1 /* Set the background color for display */
499510
--- src/schema.c
+++ src/schema.c
@@ -489,10 +489,21 @@
489 # define BKLNK_EVENT 3 /* Technote */
490 # define BKLNK_FORUM 4 /* Forum post */
491 # define ValidBklnk(X) (X>=0 && X<=4) /* True if backlink.srctype is valid */
492 #endif
493
 
 
 
 
 
 
 
 
 
 
 
494 /*
495 ** Predefined tagid values
496 */
497 #if INTERFACE
498 # define TAG_BGCOLOR 1 /* Set the background color for display */
499
--- src/schema.c
+++ src/schema.c
@@ -489,10 +489,21 @@
489 # define BKLNK_EVENT 3 /* Technote */
490 # define BKLNK_FORUM 4 /* Forum post */
491 # define ValidBklnk(X) (X>=0 && X<=4) /* True if backlink.srctype is valid */
492 #endif
493
494 /*
495 ** Allowed values for MIMEtype codes
496 */
497 #if INTERFACE
498 # define MT_NONE 0 /* unspecified */
499 # define MT_WIKI 1 /* Wiki */
500 # define MT_MARKDOWN 2 /* Markdonw */
501 # define MT_UNKNOWN 3 /* unknown */
502 # define ValidMTC(X) ((X)>=0 && (X)<=3) /* True if MIMEtype code is valid */
503 #endif
504
505 /*
506 ** Predefined tagid values
507 */
508 #if INTERFACE
509 # define TAG_BGCOLOR 1 /* Set the background color for display */
510
+54 -23
--- src/tkt.c
+++ src/tkt.c
@@ -40,11 +40,13 @@
4040
static u8 haveTicket = 0; /* True if the TICKET table exists */
4141
static u8 haveTicketCTime = 0; /* True if TICKET.TKT_CTIME exists */
4242
static u8 haveTicketChng = 0; /* True if the TICKETCHNG table exists */
4343
static u8 haveTicketChngRid = 0; /* True if TICKETCHNG.TKT_RID exists */
4444
static u8 haveTicketChngUser = 0;/* True if TICKETCHNG.TKT_USER exists */
45
-static u8 haveTicketChngGenMt= 0;/* True if TICKETCHNG.MIMETYPE is generated */
45
+static u8 useTicketGenMt = 0; /* use generated TICKET.MIMETYPE */
46
+static u8 useTicketChngGenMt = 0;/* use generated TICKETCHNG.MIMETYPE */
47
+
4648
4749
/*
4850
** Compare two entries in aField[] for sorting purposes
4951
*/
5052
static int nameCmpr(const void *a, const void *b){
@@ -71,11 +73,11 @@
7173
** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and
7274
** TICKETCHANGE tables exist, respectively.
7375
*/
7476
static void getAllTicketFields(void){
7577
Stmt q;
76
- int i, bRegularMimetype = 0;
78
+ int i, noRegularMimetype;
7779
static int once = 0;
7880
if( once ) return;
7981
once = 1;
8082
db_prepare(&q, "PRAGMA table_info(ticket)");
8183
while( db_step(&q)==SQLITE_ROW ){
@@ -103,13 +105,10 @@
103105
}else if( strcmp(zFieldName+4,"user")==0 ){
104106
haveTicketChngUser = 1; /* tkt_user */
105107
}
106108
continue;
107109
}
108
- if( strcmp(zFieldName,"mimetype")==0 ){
109
- bRegularMimetype = 1;
110
- }
111110
if( (i = fieldId(zFieldName))>=0 ){
112111
aField[i].mUsed |= USEDBY_TICKETCHNG;
113112
continue;
114113
}
115114
if( nField%10==0 ){
@@ -119,18 +118,25 @@
119118
aField[nField].mUsed = USEDBY_TICKETCHNG;
120119
nField++;
121120
}
122121
db_finalize(&q);
123122
qsort(aField, nField, sizeof(aField[0]), nameCmpr);
123
+ noRegularMimetype = 1;
124124
for(i=0; i<nField; i++){
125125
aField[i].zValue = "";
126126
aField[i].zAppend = 0;
127
+ if( strcmp(aField[i].zName,"mimetype")==0 ){
128
+ noRegularMimetype = 0;
129
+ }
127130
}
128
- if( !bRegularMimetype &&
129
- db_exists("SELECT 1 FROM pragma_table_xinfo('ticketchng') "
130
- "WHERE name = 'mimetype'") ){
131
- haveTicketChngGenMt = 1;
131
+ if( noRegularMimetype ){ /* check for generated "mimetype" columns */
132
+ useTicketGenMt = db_exists(
133
+ "SELECT 1 FROM pragma_table_xinfo('ticket') "
134
+ "WHERE name = 'mimetype'");
135
+ useTicketChngGenMt = db_exists(
136
+ "SELECT 1 FROM pragma_table_xinfo('ticketchng') "
137
+ "WHERE name = 'mimetype'");
132138
}
133139
}
134140
135141
/*
136142
** Query the database for all TICKET fields for the specific
@@ -210,11 +216,11 @@
210216
Blob sql2; /* list of TICKETCHNG's fields that are in the manifest */
211217
Blob sql3; /* list of values which correspond to the previous list */
212218
Stmt q;
213219
int i, j;
214220
char *aUsed;
215
- const char *zMimetype = 0;
221
+ int mimetype_tkt = MT_NONE, mimetype_tktchng = MT_NONE;
216222
217223
if( tktid==0 ){
218224
db_multi_exec("INSERT INTO ticket(tkt_uuid, tkt_mtime) "
219225
"VALUES(%Q, 0)", p->zTicketUuid);
220226
tktid = db_last_insert_rowid();
@@ -245,22 +251,34 @@
245251
if( aField[j].mUsed & USEDBY_TICKETCHNG ){
246252
blob_append_sql(&sql2, ",\"%w\"", zBaseName);
247253
blob_append_sql(&sql3, ",%Q", p->aField[i].zValue);
248254
}
249255
if( strcmp(zBaseName,"mimetype")==0 ){
250
- assert(!haveTicketChngGenMt); /* aField is for regular columns */
251
- zMimetype = p->aField[i].zValue;
256
+ const char *zMimetype = p->aField[i].zValue;
257
+ /* "mimetype" is a regular column => these two flags must be 0 */
258
+ assert(!useTicketGenMt);
259
+ assert(!useTicketChngGenMt);
260
+ mimetype_tkt = mimetype_tktchng = parse_mimetype( zMimetype );
252261
}
253262
}
254263
blob_append_sql(&sql1, " WHERE tkt_id=%d", tktid);
264
+ if( useTicketGenMt ){
265
+ blob_append_literal(&sql1, " RETURNING mimetype");
266
+ }
255267
db_prepare(&q, "%s", blob_sql_text(&sql1));
256268
db_bind_double(&q, ":mtime", p->rDate);
257269
db_step(&q);
270
+ if( useTicketGenMt ){
271
+ mimetype_tkt = parse_mimetype( db_column_text(&q,0) );
272
+ if( !useTicketChngGenMt ){
273
+ mimetype_tktchng = mimetype_tkt;
274
+ }
275
+ }
276
+ db_finalize(&q);
258277
blob_reset(&sql1);
259278
if( blob_size(&sql2)>0 || haveTicketChngRid || haveTicketChngUser ){
260279
int fromTkt = 0;
261
- db_finalize(&q);
262280
if( haveTicketChngRid ){
263281
blob_append_literal(&sql2, ",tkt_rid");
264282
blob_append_sql(&sql3, ",%d", rid);
265283
}
266284
if( haveTicketChngUser && p->zUser ){
@@ -281,39 +299,52 @@
281299
if( fromTkt ){
282300
db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
283301
"SELECT %d,:mtime%s FROM ticket WHERE tkt_id=%d%s",
284302
blob_sql_text(&sql2), tktid,
285303
blob_sql_text(&sql3), tktid,
286
- haveTicketChngGenMt ? " RETURNING mimetype" : "");
304
+ useTicketChngGenMt ? " RETURNING mimetype" : "");
287305
}else{
288306
db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
289307
"VALUES(%d,:mtime%s)%s",
290308
blob_sql_text(&sql2), tktid, blob_sql_text(&sql3),
291
- haveTicketChngGenMt ? " RETURNING mimetype" : "");
309
+ useTicketChngGenMt ? " RETURNING mimetype" : "");
292310
}
293311
db_bind_double(&q, ":mtime", p->rDate);
294312
db_step(&q);
295
- if( haveTicketChngGenMt ){
296
- zMimetype = db_column_text(&q, 0);
313
+ if( useTicketChngGenMt ){
314
+ mimetype_tktchng = parse_mimetype( db_column_text(&q, 0) );
315
+ /* substitute NULL with a value generated within another table */
316
+ if( !useTicketGenMt ){
317
+ mimetype_tkt = mimetype_tktchng;
318
+ }else if( mimetype_tktchng==MT_NONE ){
319
+ mimetype_tktchng = mimetype_tkt;
320
+ }else if( mimetype_tkt==MT_NONE ){
321
+ mimetype_tkt = mimetype_tktchng;
322
+ }
297323
}
324
+ db_finalize(&q);
298325
}
299
- fossil_free(aUsed);
300326
blob_reset(&sql2);
301327
blob_reset(&sql3);
302
- if( rid>0 ){
303
- int bReplace = 1;
328
+ fossil_free(aUsed);
329
+ if( rid>0 ){ /* extract backlinks */
330
+ int bReplace = 1, mimetype;
304331
for(i=0; i<p->nField; i++){
305332
const char *zName = p->aField[i].zName;
306333
const char *zBaseName = zName[0]=='+' ? zName+1 : zName;
307334
j = fieldId(zBaseName);
308
- if( j<0 /*|| strcmp(zBaseName,"mimetype")==0*/ ) continue;
309
- backlink_extract(p->aField[i].zValue, zMimetype, rid, BKLNK_TICKET,
335
+ if( j<0 ) continue;
336
+ if( aField[j].mUsed & USEDBY_TICKETCHNG ){
337
+ mimetype = mimetype_tktchng;
338
+ }else{
339
+ mimetype = mimetype_tkt;
340
+ }
341
+ backlink_extract(p->aField[i].zValue, mimetype, rid, BKLNK_TICKET,
310342
p->rDate, bReplace);
311343
bReplace = 0;
312344
}
313345
}
314
- db_finalize(&q);
315346
return tktid;
316347
}
317348
318349
/*
319350
** Returns non-zero if moderation is required for ticket changes and ticket
320351
--- src/tkt.c
+++ src/tkt.c
@@ -40,11 +40,13 @@
40 static u8 haveTicket = 0; /* True if the TICKET table exists */
41 static u8 haveTicketCTime = 0; /* True if TICKET.TKT_CTIME exists */
42 static u8 haveTicketChng = 0; /* True if the TICKETCHNG table exists */
43 static u8 haveTicketChngRid = 0; /* True if TICKETCHNG.TKT_RID exists */
44 static u8 haveTicketChngUser = 0;/* True if TICKETCHNG.TKT_USER exists */
45 static u8 haveTicketChngGenMt= 0;/* True if TICKETCHNG.MIMETYPE is generated */
 
 
46
47 /*
48 ** Compare two entries in aField[] for sorting purposes
49 */
50 static int nameCmpr(const void *a, const void *b){
@@ -71,11 +73,11 @@
71 ** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and
72 ** TICKETCHANGE tables exist, respectively.
73 */
74 static void getAllTicketFields(void){
75 Stmt q;
76 int i, bRegularMimetype = 0;
77 static int once = 0;
78 if( once ) return;
79 once = 1;
80 db_prepare(&q, "PRAGMA table_info(ticket)");
81 while( db_step(&q)==SQLITE_ROW ){
@@ -103,13 +105,10 @@
103 }else if( strcmp(zFieldName+4,"user")==0 ){
104 haveTicketChngUser = 1; /* tkt_user */
105 }
106 continue;
107 }
108 if( strcmp(zFieldName,"mimetype")==0 ){
109 bRegularMimetype = 1;
110 }
111 if( (i = fieldId(zFieldName))>=0 ){
112 aField[i].mUsed |= USEDBY_TICKETCHNG;
113 continue;
114 }
115 if( nField%10==0 ){
@@ -119,18 +118,25 @@
119 aField[nField].mUsed = USEDBY_TICKETCHNG;
120 nField++;
121 }
122 db_finalize(&q);
123 qsort(aField, nField, sizeof(aField[0]), nameCmpr);
 
124 for(i=0; i<nField; i++){
125 aField[i].zValue = "";
126 aField[i].zAppend = 0;
 
 
 
127 }
128 if( !bRegularMimetype &&
129 db_exists("SELECT 1 FROM pragma_table_xinfo('ticketchng') "
130 "WHERE name = 'mimetype'") ){
131 haveTicketChngGenMt = 1;
 
 
 
132 }
133 }
134
135 /*
136 ** Query the database for all TICKET fields for the specific
@@ -210,11 +216,11 @@
210 Blob sql2; /* list of TICKETCHNG's fields that are in the manifest */
211 Blob sql3; /* list of values which correspond to the previous list */
212 Stmt q;
213 int i, j;
214 char *aUsed;
215 const char *zMimetype = 0;
216
217 if( tktid==0 ){
218 db_multi_exec("INSERT INTO ticket(tkt_uuid, tkt_mtime) "
219 "VALUES(%Q, 0)", p->zTicketUuid);
220 tktid = db_last_insert_rowid();
@@ -245,22 +251,34 @@
245 if( aField[j].mUsed & USEDBY_TICKETCHNG ){
246 blob_append_sql(&sql2, ",\"%w\"", zBaseName);
247 blob_append_sql(&sql3, ",%Q", p->aField[i].zValue);
248 }
249 if( strcmp(zBaseName,"mimetype")==0 ){
250 assert(!haveTicketChngGenMt); /* aField is for regular columns */
251 zMimetype = p->aField[i].zValue;
 
 
 
252 }
253 }
254 blob_append_sql(&sql1, " WHERE tkt_id=%d", tktid);
 
 
 
255 db_prepare(&q, "%s", blob_sql_text(&sql1));
256 db_bind_double(&q, ":mtime", p->rDate);
257 db_step(&q);
 
 
 
 
 
 
 
258 blob_reset(&sql1);
259 if( blob_size(&sql2)>0 || haveTicketChngRid || haveTicketChngUser ){
260 int fromTkt = 0;
261 db_finalize(&q);
262 if( haveTicketChngRid ){
263 blob_append_literal(&sql2, ",tkt_rid");
264 blob_append_sql(&sql3, ",%d", rid);
265 }
266 if( haveTicketChngUser && p->zUser ){
@@ -281,39 +299,52 @@
281 if( fromTkt ){
282 db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
283 "SELECT %d,:mtime%s FROM ticket WHERE tkt_id=%d%s",
284 blob_sql_text(&sql2), tktid,
285 blob_sql_text(&sql3), tktid,
286 haveTicketChngGenMt ? " RETURNING mimetype" : "");
287 }else{
288 db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
289 "VALUES(%d,:mtime%s)%s",
290 blob_sql_text(&sql2), tktid, blob_sql_text(&sql3),
291 haveTicketChngGenMt ? " RETURNING mimetype" : "");
292 }
293 db_bind_double(&q, ":mtime", p->rDate);
294 db_step(&q);
295 if( haveTicketChngGenMt ){
296 zMimetype = db_column_text(&q, 0);
 
 
 
 
 
 
 
 
297 }
 
298 }
299 fossil_free(aUsed);
300 blob_reset(&sql2);
301 blob_reset(&sql3);
302 if( rid>0 ){
303 int bReplace = 1;
 
304 for(i=0; i<p->nField; i++){
305 const char *zName = p->aField[i].zName;
306 const char *zBaseName = zName[0]=='+' ? zName+1 : zName;
307 j = fieldId(zBaseName);
308 if( j<0 /*|| strcmp(zBaseName,"mimetype")==0*/ ) continue;
309 backlink_extract(p->aField[i].zValue, zMimetype, rid, BKLNK_TICKET,
 
 
 
 
 
310 p->rDate, bReplace);
311 bReplace = 0;
312 }
313 }
314 db_finalize(&q);
315 return tktid;
316 }
317
318 /*
319 ** Returns non-zero if moderation is required for ticket changes and ticket
320
--- src/tkt.c
+++ src/tkt.c
@@ -40,11 +40,13 @@
40 static u8 haveTicket = 0; /* True if the TICKET table exists */
41 static u8 haveTicketCTime = 0; /* True if TICKET.TKT_CTIME exists */
42 static u8 haveTicketChng = 0; /* True if the TICKETCHNG table exists */
43 static u8 haveTicketChngRid = 0; /* True if TICKETCHNG.TKT_RID exists */
44 static u8 haveTicketChngUser = 0;/* True if TICKETCHNG.TKT_USER exists */
45 static u8 useTicketGenMt = 0; /* use generated TICKET.MIMETYPE */
46 static u8 useTicketChngGenMt = 0;/* use generated TICKETCHNG.MIMETYPE */
47
48
49 /*
50 ** Compare two entries in aField[] for sorting purposes
51 */
52 static int nameCmpr(const void *a, const void *b){
@@ -71,11 +73,11 @@
73 ** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and
74 ** TICKETCHANGE tables exist, respectively.
75 */
76 static void getAllTicketFields(void){
77 Stmt q;
78 int i, noRegularMimetype;
79 static int once = 0;
80 if( once ) return;
81 once = 1;
82 db_prepare(&q, "PRAGMA table_info(ticket)");
83 while( db_step(&q)==SQLITE_ROW ){
@@ -103,13 +105,10 @@
105 }else if( strcmp(zFieldName+4,"user")==0 ){
106 haveTicketChngUser = 1; /* tkt_user */
107 }
108 continue;
109 }
 
 
 
110 if( (i = fieldId(zFieldName))>=0 ){
111 aField[i].mUsed |= USEDBY_TICKETCHNG;
112 continue;
113 }
114 if( nField%10==0 ){
@@ -119,18 +118,25 @@
118 aField[nField].mUsed = USEDBY_TICKETCHNG;
119 nField++;
120 }
121 db_finalize(&q);
122 qsort(aField, nField, sizeof(aField[0]), nameCmpr);
123 noRegularMimetype = 1;
124 for(i=0; i<nField; i++){
125 aField[i].zValue = "";
126 aField[i].zAppend = 0;
127 if( strcmp(aField[i].zName,"mimetype")==0 ){
128 noRegularMimetype = 0;
129 }
130 }
131 if( noRegularMimetype ){ /* check for generated "mimetype" columns */
132 useTicketGenMt = db_exists(
133 "SELECT 1 FROM pragma_table_xinfo('ticket') "
134 "WHERE name = 'mimetype'");
135 useTicketChngGenMt = db_exists(
136 "SELECT 1 FROM pragma_table_xinfo('ticketchng') "
137 "WHERE name = 'mimetype'");
138 }
139 }
140
141 /*
142 ** Query the database for all TICKET fields for the specific
@@ -210,11 +216,11 @@
216 Blob sql2; /* list of TICKETCHNG's fields that are in the manifest */
217 Blob sql3; /* list of values which correspond to the previous list */
218 Stmt q;
219 int i, j;
220 char *aUsed;
221 int mimetype_tkt = MT_NONE, mimetype_tktchng = MT_NONE;
222
223 if( tktid==0 ){
224 db_multi_exec("INSERT INTO ticket(tkt_uuid, tkt_mtime) "
225 "VALUES(%Q, 0)", p->zTicketUuid);
226 tktid = db_last_insert_rowid();
@@ -245,22 +251,34 @@
251 if( aField[j].mUsed & USEDBY_TICKETCHNG ){
252 blob_append_sql(&sql2, ",\"%w\"", zBaseName);
253 blob_append_sql(&sql3, ",%Q", p->aField[i].zValue);
254 }
255 if( strcmp(zBaseName,"mimetype")==0 ){
256 const char *zMimetype = p->aField[i].zValue;
257 /* "mimetype" is a regular column => these two flags must be 0 */
258 assert(!useTicketGenMt);
259 assert(!useTicketChngGenMt);
260 mimetype_tkt = mimetype_tktchng = parse_mimetype( zMimetype );
261 }
262 }
263 blob_append_sql(&sql1, " WHERE tkt_id=%d", tktid);
264 if( useTicketGenMt ){
265 blob_append_literal(&sql1, " RETURNING mimetype");
266 }
267 db_prepare(&q, "%s", blob_sql_text(&sql1));
268 db_bind_double(&q, ":mtime", p->rDate);
269 db_step(&q);
270 if( useTicketGenMt ){
271 mimetype_tkt = parse_mimetype( db_column_text(&q,0) );
272 if( !useTicketChngGenMt ){
273 mimetype_tktchng = mimetype_tkt;
274 }
275 }
276 db_finalize(&q);
277 blob_reset(&sql1);
278 if( blob_size(&sql2)>0 || haveTicketChngRid || haveTicketChngUser ){
279 int fromTkt = 0;
 
280 if( haveTicketChngRid ){
281 blob_append_literal(&sql2, ",tkt_rid");
282 blob_append_sql(&sql3, ",%d", rid);
283 }
284 if( haveTicketChngUser && p->zUser ){
@@ -281,39 +299,52 @@
299 if( fromTkt ){
300 db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
301 "SELECT %d,:mtime%s FROM ticket WHERE tkt_id=%d%s",
302 blob_sql_text(&sql2), tktid,
303 blob_sql_text(&sql3), tktid,
304 useTicketChngGenMt ? " RETURNING mimetype" : "");
305 }else{
306 db_prepare(&q, "INSERT INTO ticketchng(tkt_id,tkt_mtime%s)"
307 "VALUES(%d,:mtime%s)%s",
308 blob_sql_text(&sql2), tktid, blob_sql_text(&sql3),
309 useTicketChngGenMt ? " RETURNING mimetype" : "");
310 }
311 db_bind_double(&q, ":mtime", p->rDate);
312 db_step(&q);
313 if( useTicketChngGenMt ){
314 mimetype_tktchng = parse_mimetype( db_column_text(&q, 0) );
315 /* substitute NULL with a value generated within another table */
316 if( !useTicketGenMt ){
317 mimetype_tkt = mimetype_tktchng;
318 }else if( mimetype_tktchng==MT_NONE ){
319 mimetype_tktchng = mimetype_tkt;
320 }else if( mimetype_tkt==MT_NONE ){
321 mimetype_tkt = mimetype_tktchng;
322 }
323 }
324 db_finalize(&q);
325 }
 
326 blob_reset(&sql2);
327 blob_reset(&sql3);
328 fossil_free(aUsed);
329 if( rid>0 ){ /* extract backlinks */
330 int bReplace = 1, mimetype;
331 for(i=0; i<p->nField; i++){
332 const char *zName = p->aField[i].zName;
333 const char *zBaseName = zName[0]=='+' ? zName+1 : zName;
334 j = fieldId(zBaseName);
335 if( j<0 ) continue;
336 if( aField[j].mUsed & USEDBY_TICKETCHNG ){
337 mimetype = mimetype_tktchng;
338 }else{
339 mimetype = mimetype_tkt;
340 }
341 backlink_extract(p->aField[i].zValue, mimetype, rid, BKLNK_TICKET,
342 p->rDate, bReplace);
343 bReplace = 0;
344 }
345 }
 
346 return tktid;
347 }
348
349 /*
350 ** Returns non-zero if moderation is required for ticket changes and ticket
351

Keyboard Shortcuts

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