Overview
SHA1 Hash: | 3b5514ed825c5cd629359a712b357254a81fe719 |
---|---|
Date: | 2007-09-22 15:50:14 |
User: | drh |
Comment: | The "tag" command allows tag artifacts to be inserted for creating and cancelling tags and properties. Timeline responds to bgcolor, br-bgcolor, comment, and user properties. |
Timelines: | ancestors | descendants | both | trunk |
Other Links: | files | ZIP archive | manifest |
Tags And Properties
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
Changes
[hide diffs]Modified src/info.c from [1d02bccab4] to [ae734c2dfe].
@@ -114,11 +114,12 @@ static int showDescendents(int pid, int depth, const char *zTitle){ Stmt q; int cnt = 0; db_prepare(&q, "SELECT plink.cid, blob.uuid, datetime(plink.mtime, 'localtime')," - " event.user, event.comment" + " coalesce(event.euser,event.user)," + " coalesce(event.comment,event.ecomment)" " FROM plink, blob, event" " WHERE plink.pid=%d" " AND blob.rid=plink.cid" " AND event.objid=plink.cid" " ORDER BY plink.mtime ASC", @@ -149,10 +150,11 @@ if( n==0 ){ db_multi_exec("DELETE FROM leaves WHERE rid=%d", cid); @ <b>leaf</b> } } + db_finalize(&q); if( cnt ){ @ </ul> } return cnt; } @@ -164,11 +166,12 @@ static void showAncestors(int pid, int depth, const char *zTitle){ Stmt q; int cnt = 0; db_prepare(&q, "SELECT plink.pid, blob.uuid, datetime(event.mtime, 'localtime')," - " event.user, event.comment" + " coalesce(event.euser,event.user)," + " coalesce(event.comment,event.ecomment)" " FROM plink, blob, event" " WHERE plink.cid=%d" " AND blob.rid=plink.pid" " AND event.objid=plink.pid" " ORDER BY event.mtime DESC", @@ -192,10 +195,11 @@ @ %s(zCom) (by %s(zUser) on %s(zDate)) if( depth ){ showAncestors(cid, depth-1, 0); } } + db_finalize(&q); if( cnt ){ @ </ul> } } @@ -206,11 +210,12 @@ static void showLeaves(void){ Stmt q; int cnt = 0; db_prepare(&q, "SELECT blob.uuid, datetime(event.mtime, 'localtime')," - " event.user, event.comment" + " coalesce(event.euser, event.user)," + " coalesce(event.ecomment,event.comment)" " FROM leaves, plink, blob, event" " WHERE plink.cid=leaves.rid" " AND blob.rid=leaves.rid" " AND event.objid=leaves.rid" " ORDER BY event.mtime DESC" @@ -227,10 +232,61 @@ } @ <li> hyperlink_to_uuid(zUuid); @ %s(zCom) (by %s(zUser) on %s(zDate)) } + db_finalize(&q); + if( cnt ){ + @ </ul> + } +} + +/* +** Show information about all tags on a given node. +*/ +static void showTags(int rid){ + Stmt q; + int cnt = 0; + db_prepare(&q, + "SELECT tag.tagid, tagname, srcid, blob.uuid, value," + " datetime(tagxref.mtime,'localtime'), addflag" + " FROM tagxref JOIN tag ON tagxref.tagid=tag.tagid" + " LEFT JOIN blob ON blob.rid=tagxref.srcid" + " WHERE tagxref.rid=%d" + " ORDER BY tagname", rid + ); + while( db_step(&q)==SQLITE_ROW ){ + int tagid = db_column_int(&q, 0); + const char *zTagname = db_column_text(&q, 1); + int srcid = db_column_int(&q, 2); + const char *zUuid = db_column_text(&q, 3); + const char *zValue = db_column_text(&q, 4); + const char *zDate = db_column_text(&q, 5); + int addFlag = db_column_int(&q, 6); + cnt++; + if( cnt==1 ){ + @ <h2>Tags And Properties</h2> + @ <ul> + } + @ <li> + @ <b>%h(zTagname)</b> + if( zValue ){ + @ = %h(zValue)<i> + }else if( !addFlag ){ + @ <i>Cancelled + }else{ + @ <i> + } + if( srcid==0 ){ + @ Inherited + }else if( zUuid ){ + @ From + hyperlink_to_uuid(zUuid); + } + @ on %s(zDate)</i> + } + db_finalize(&q); if( cnt ){ @ </ul> } } @@ -266,21 +322,22 @@ if( db_step(&q)==SQLITE_ROW ){ const char *zUuid = db_column_text(&q, 0); @ <h2>Version %s(zUuid)</h2> @ <ul> @ <li><b>Date:</b> %s(db_column_text(&q, 1))</li> - @ <li><b>User:</b> %s(db_column_text(&q, 2))</li> - @ <li><b>Comment:</b> %s(db_column_text(&q, 3))</li> + @ <li><b>Original User:</b> %s(db_column_text(&q, 2))</li> + @ <li><b>Original Comment:</b> %s(db_column_text(&q, 3))</li> @ <li><a href="%s(g.zBaseURL)/vdiff/%d(rid)">diff</a></li> @ <li><a href="%s(g.zBaseURL)/zip/%s(zUuid).zip">ZIP archive</a></li> @ <li><a href="%s(g.zBaseURL)/fview/%d(rid)">manifest</a></li> if( g.okSetup ){ @ <li><b>Record ID:</b> %d(rid)</li> } @ </ul> } db_finalize(&q); + showTags(rid); @ <p><h2>Changes:</h2> @ <ul> db_prepare(&q, "SELECT name, pid, fid" " FROM mlink, filename" @@ -324,11 +381,13 @@ style_header("File History"); zPrevDate[0] = 0; db_prepare(&q, "SELECT a.uuid, substr(b.uuid,1,10), datetime(event.mtime,'localtime')," - " event.comment, event.user, mlink.pid, mlink.fid" + " coalesce(event.ecomment, event.comment)," + " coalesce(event.euser, event.user)," + " mlink.pid, mlink.fid" " FROM mlink, blob a, blob b, event" " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" " AND a.rid=mlink.mid" " AND b.rid=mlink.fid" " AND event.objid=mlink.mid" @@ -449,11 +508,13 @@ static void object_description(int rid, int linkToView){ Stmt q; int cnt = 0; db_prepare(&q, "SELECT filename.name, datetime(event.mtime), substr(a.uuid,1,10)," - " event.comment, event.user, b.uuid" + " coalesce(event.comment,event.ecomment)," + " coalesce(event.euser,event.user)," + " b.uuid" " FROM mlink, filename, event, blob a, blob b" " WHERE filename.fnid=mlink.fnid" " AND event.objid=mlink.mid" " AND a.rid=mlink.fid" " AND b.rid=mlink.mid"
Modified src/manifest.c from [f007901442] to [d1a0570f09].
@@ -19,22 +19,31 @@ ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** -** This file contains code used to cross link manifests +** This file contains code used to cross link control files and +** manifests. */ #include "config.h" #include "manifest.h" #include <assert.h> #if INTERFACE /* +** Types of control files +*/ +#define CFTYPE_MANIFEST 1 +#define CFTYPE_CLUSTER 2 +#define CFTYPE_CONTROL 3 + +/* ** A parsed manifest or cluster. */ struct Manifest { Blob content; /* The original content blob */ + int type; /* Type of file */ char *zComment; /* Decoded comment */ double rDate; /* Time in the "D" line */ char *zUser; /* Name of the user */ char *zRepoCksum; /* MD5 checksum of the baseline content */ int nFile; /* Number of F lines */ @@ -244,10 +253,14 @@ if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error; defossilize(zName); if( zName[0]!='-' && zName[0]!='+' ){ goto manifest_syntax_error; } + if( validate16(&zName[1], strlen(&zName[1])) ){ + /* Do not allow tags whose names look like UUIDs */ + goto manifest_syntax_error; + } if( p->nTag>=p->nTagAlloc ){ p->nTagAlloc = p->nTagAlloc*2 + 10; p->aTag = realloc(p->aTag, p->nTagAlloc*sizeof(p->aTag[0]) ); if( p->aTag==0 ) fossil_panic("out of memory"); } @@ -347,21 +360,24 @@ if( !seenHeader ) goto manifest_syntax_error; if( p->nFile>0 ){ if( p->nCChild>0 ) goto manifest_syntax_error; if( p->rDate==0.0 ) goto manifest_syntax_error; + p->type = CFTYPE_MANIFEST; }else if( p->nCChild>0 ){ if( p->rDate>0.0 ) goto manifest_syntax_error; if( p->zComment!=0 ) goto manifest_syntax_error; if( p->zUser!=0 ) goto manifest_syntax_error; if( p->nTag>0 ) goto manifest_syntax_error; if( p->nParent>0 ) goto manifest_syntax_error; if( p->zRepoCksum!=0 ) goto manifest_syntax_error; + p->type = CFTYPE_CLUSTER; }else if( p->nTag>0 ){ if( p->rDate<=0.0 ) goto manifest_syntax_error; if( p->zRepoCksum!=0 ) goto manifest_syntax_error; if( p->nParent>0 ) goto manifest_syntax_error; + p->type = CFTYPE_CONTROL; }else{ goto manifest_syntax_error; } md5sum_init(); @@ -481,37 +497,49 @@ if( manifest_parse(&m, pContent)==0 ){ return 0; } db_begin_transaction(); - if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){ - for(i=0; i<m.nParent; i++){ - int pid = uuid_to_rid(m.azParent[i], 1); - db_multi_exec("INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime)" - "VALUES(%d, %d, %d, %.17g)", pid, rid, i==0, m.rDate); - if( i==0 ){ - add_mlink(pid, 0, rid, &m); + if( m.type==CFTYPE_MANIFEST ){ + if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){ + for(i=0; i<m.nParent; i++){ + int pid = uuid_to_rid(m.azParent[i], 1); + db_multi_exec("INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime)" + "VALUES(%d, %d, %d, %.17g)", pid, rid, i==0, m.rDate); + if( i==0 ){ + add_mlink(pid, 0, rid, &m); + } + } + db_prepare(&q, "SELECT cid FROM plink WHERE pid=%d AND isprim", rid); + while( db_step(&q)==SQLITE_ROW ){ + int cid = db_column_int(&q, 0); + add_mlink(rid, &m, cid, 0); + } + db_finalize(&q); + db_multi_exec( + "INSERT INTO event(type,mtime,objid,user,comment)" + "VALUES('ci',%.17g,%d,%Q,%Q)", + m.rDate, rid, m.zUser, m.zComment + ); + } + } + if( m.type==CFTYPE_CLUSTER ){ + for(i=0; i<m.nCChild; i++){ + int mid; + mid = uuid_to_rid(m.azCChild[i], 1); + if( mid>0 ){ + db_multi_exec("DELETE FROM unclustered WHERE rid=%d", mid); } } - db_prepare(&q, "SELECT cid FROM plink WHERE pid=%d AND isprim", rid); - while( db_step(&q)==SQLITE_ROW ){ - int cid = db_column_int(&q, 0); - add_mlink(rid, &m, cid, 0); - } - db_finalize(&q); - db_multi_exec( - "INSERT INTO event(type,mtime,objid,user,comment)" - "VALUES('ci',%.17g,%d,%Q,%Q)", - m.rDate, rid, m.zUser, m.zComment - ); } - for(i=0; i<m.nCChild; i++){ - int rid; - rid = uuid_to_rid(m.azCChild[i], 1); - if( rid>0 ){ - db_multi_exec("DELETE FROM unclustered WHERE rid=%d", rid); + if( m.type==CFTYPE_CONTROL || m.type==CFTYPE_MANIFEST ){ + for(i=0; i<m.nTag; i++){ + int tid; + tid = uuid_to_rid(m.aTag[i].zUuid, 1); + tag_insert(&m.aTag[i].zName[1], m.aTag[i].zName[0]=='+', + m.aTag[i].zValue, rid, m.rDate, tid); } } db_end_transaction(0); manifest_clear(&m); return 1; }
Modified src/name.c from [c08d513136] to [36506ea789].
@@ -34,19 +34,46 @@ /* ** This routine takes a user-entered UUID which might be in mixed ** case and might only be a prefix of the full UUID and converts it ** into the full-length UUID in canonical form. ** +** If the input is not a UUID or a UUID prefix, then try to resolve +** the name as a tag. +** ** Return the number of errors. */ int name_to_uuid(Blob *pName, int iErrPriority){ int rc; int sz; sz = blob_size(pName); if( sz>UUID_SIZE || sz<4 || !validate16(blob_buffer(pName), sz) ){ - fossil_error(iErrPriority, "not a valid object name: %b", pName); - return 1; + Stmt q; + Blob uuid; + + db_prepare(&q, + "SELECT (SELECT uuid FROM blob WHERE rid=objid)" + " FROM tagxref JOIN event ON rid=objid" + " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%B)" + " AND addflag" + " AND value IS NULL" + " ORDER BY event.mtime DESC", + pName + ); + blob_zero(&uuid); + if( db_step(&q)==SQLITE_ROW ){ + db_column_blob(&q, 0, &uuid); + } + db_finalize(&q); + if( blob_size(&uuid)==0 ){ + fossil_error(iErrPriority, "not a valid object name: %b", pName); + blob_reset(&uuid); + return 1; + }else{ + blob_reset(pName); + *pName = uuid; + return 0; + } } blob_materialize(pName); canonical16(blob_buffer(pName), sz); if( sz==UUID_SIZE ){ rc = db_int(1, "SELECT 0 FROM blob WHERE uuid=%B", pName); @@ -120,11 +147,11 @@ return rid; } } blob_init(&name, zName, -1); if( name_to_uuid(&name, 1) ){ - fossil_panic("%s", g.zErrMsg); + fossil_fatal("%s", g.zErrMsg); } rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &name); blob_reset(&name); return rid; }
Modified src/schema.c from [c58feea55a] to [a15ec88bcc].
@@ -156,11 +156,15 @@ @ CREATE TABLE event( @ type TEXT, -- Type of event @ mtime DATETIME, -- Date and time when the event occurs @ objid INTEGER PRIMARY KEY, -- Associated record ID @ uid INTEGER REFERENCES user, -- User who caused the event +@ bgcolor TEXT, -- Color set by 'bgcolor' property +@ brbgcolor TEXT, -- Color set by 'br-bgcolor' property +@ euser TEXT, -- User set by 'user' property @ user TEXT, -- Name of the user +@ ecomment TEXT, -- Comment set by 'comment' property @ comment TEXT -- Comment describing the event @ ); @ CREATE INDEX event_i1 ON event(mtime); @ @ -- A record of phantoms. A phantom is a record for which we know the @@ -199,10 +203,14 @@ @ -- @ CREATE TABLE tag( @ tagid INTEGER PRIMARY KEY, -- Numeric tag ID @ tagname TEXT UNIQUE -- Tag name. Prefixed by 'v' or 'b' @ ); +@ INSERT INTO tag VALUES(1, 'bgcolor'); -- TAG_BGCOLOR +@ INSERT INTO tag VALUES(2, 'br-bgcolor'); -- TAG_BR_BGCOLOR +@ INSERT INTO tag VALUES(3, 'comment'); -- TAG_COMMENT +@ INSERT INTO tag VALUES(4, 'user'); -- TAG_USER @ @ -- Assignments of tags to baselines. Note that we allow tags to @ -- have values assigned to them. So we are not really dealing with @ -- tags here. These are really properties. But we are going to @ -- keep calling them tags because in many cases the value is ignored. @@ -216,10 +224,20 @@ @ rid INTEGER REFERENCE blob, -- Baseline that tag added/removed from @ UNIQUE(rid, tagid) @ ); @ CREATE INDEX tagxref_i1 ON tagxref(tagid); ; + +/* +** Predefined tagid values +*/ +#if INTERFACE +# define TAG_BGCOLOR 1 +# define TAG_BR_BGCOLOR 2 +# define TAG_COMMENT 3 +# define TAG_USER 4 +#endif /* ** The schema for the locate FOSSIL database file found at the root ** of very check-out. This database contains the complete state of ** the checkout.
Modified src/tag.c from [8fad57b8b1] to [c028c6b677].
@@ -42,11 +42,11 @@ int addFlag, /* True to add the tag. False to delete it. */ const char *zValue, /* Value of the tag. Might be NULL */ double mtime /* Timestamp on the tag */ ){ PQueue queue; - Stmt s, ins; + Stmt s, ins, eventupdate; pqueue_init(&queue); pqueue_insert(&queue, pid, 0.0); db_prepare(&s, "SELECT cid, plink.mtime," " coalesce(srcid=0 AND tagxref.mtime<:mtime, %d) AS doit" @@ -61,12 +61,18 @@ "VALUES(%d,1,0,%Q,:mtime,:rid)", tagid, zValue ); db_bind_double(&ins, ":mtime", mtime); }else{ + zValue = 0; db_prepare(&ins, "DELETE FROM tagxref WHERE tagid=%d AND rid=:rid", tagid + ); + } + if( tagid==TAG_BR_BGCOLOR ){ + db_prepare(&eventupdate, + "UPDATE event SET brbgcolor=%Q WHERE objid=:rid", zValue ); } while( (pid = pqueue_extract(&queue))!=0 ){ db_bind_int(&s, ":pid", pid); while( db_step(&s)==SQLITE_ROW ){ @@ -76,17 +82,25 @@ double mtime = db_column_double(&s, 1); pqueue_insert(&queue, cid, mtime); db_bind_int(&ins, ":rid", cid); db_step(&ins); db_reset(&ins); + if( tagid==TAG_BR_BGCOLOR ){ + db_bind_int(&eventupdate, ":rid", cid); + db_step(&eventupdate); + db_reset(&eventupdate); + } } } db_reset(&s); } pqueue_clear(&queue); db_finalize(&ins); db_finalize(&s); + if( tagid==TAG_BR_BGCOLOR ){ + db_finalize(&eventupdate); + } } /* ** Propagate all propagatable tags in pid to its children. */ @@ -144,12 +158,33 @@ tagid, addFlag, srcId, zValue, rid ); db_bind_double(&s, ":mtime", mtime); db_step(&s); db_finalize(&s); + if( addFlag==0 ){ + zValue = 0; + } + switch( tagid ){ + case TAG_BGCOLOR: { + db_multi_exec("UPDATE event SET bgcolor=%Q WHERE objid=%d", zValue, rid); + break; + } + case TAG_BR_BGCOLOR: { + db_multi_exec("UPDATE event SET brbgcolor=%Q WHERE objid=%d", zValue,rid); + break; + } + case TAG_COMMENT: { + db_multi_exec("UPDATE event SET ecomment=%Q WHERE objid=%d", zValue, rid); + break; + } + case TAG_USER: { + db_multi_exec("UPDATE event SET euser=%Q WHERE objid=%d", zValue, rid); + break; + } + } if( strncmp(zTag, "br", 2)==0 ){ - tag_propagate(rid, tagid, 1, zValue, mtime); + tag_propagate(rid, tagid, addFlag, zValue, mtime); } } /* @@ -201,6 +236,165 @@ fossil_fatal("no such object: %s", g.argv[3]); } db_begin_transaction(); tag_insert(zTag, 0, 0, -1, 0.0, rid); db_end_transaction(0); +} + +/* +** Add a control record to the repository that either creates +** or cancels a tag. +*/ +static void tag_add_artifact( + const char *zTagname, /* The tag to add or cancel */ + const char *zObjName, /* Name of object attached to */ + const char *zValue, /* Value for the tag. Might be NULL */ + int addFlag /* True to add. false to cancel */ +){ + int rid; + int nrid; + char *zDate; + Blob uuid; + Blob ctrl; + Blob cksum; + + user_select(); + rid = name_to_rid(zObjName); + blob_zero(&uuid); + db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid); + blob_zero(&ctrl); + + if( validate16(zTagname, strlen(zTagname)) ){ + fossil_fatal("invalid tag name \"%s\" - might be confused with a UUID", + zTagname); + } + zDate = db_text(0, "SELECT datetime('now')"); + zDate[10] = 'T'; + blob_appendf(&ctrl, "D %s\n", zDate); + blob_appendf(&ctrl, "T %c%F %b", addFlag ? '+' : '-', zTagname, &uuid); + if( addFlag && zValue && zValue[0] ){ + blob_appendf(&ctrl, " %F\n", zValue); + }else{ + blob_appendf(&ctrl, "\n"); + } + blob_appendf(&ctrl, "U %F\n", g.zLogin); + md5sum_blob(&ctrl, &cksum); + blob_appendf(&ctrl, "Z %b\n", &cksum); + db_begin_transaction(); + nrid = content_put(&ctrl, 0, 0); + manifest_crosslink(nrid, &ctrl); + db_end_transaction(0); +} + +/* +** COMMAND: tag +** Usage: %fossil tag SUBCOMMAND ... +** +** Run various subcommands to control tags and properties +** +** %fossil tag add TAGNAME UUID ?VALUE? +** +** Add a new tag or property to UUID. +** +** %fossil tag delete TAGNAME UUID +** +** Delete the tag TAGNAME from UUID +** +** %fossil tag find TAGNAME +** +** List all baselines that use TAGNAME +** +** %fossil tag list ?UUID? +** +** List all tags, or if UUID is supplied, list +** all tags and their values for UUID. +*/ +void tag_cmd(void){ + int n; + db_find_and_open_repository(); + if( g.argc<3 ){ + goto tag_cmd_usage; + } + n = strlen(g.argv[2]); + if( n==0 ){ + goto tag_cmd_usage; + } + + if( strncmp(g.argv[2],"add",n)==0 ){ + char *zValue; + if( g.argc!=5 && g.argc!=6 ){ + usage("tag add TAGNAME UUID ?VALUE?"); + } + zValue = g.argc==6 ? g.argv[5] : 0; + tag_add_artifact(g.argv[3], g.argv[4], zValue, 1); + }else + + if( strncmp(g.argv[2],"delete",n)==0 ){ + if( g.argc!=5 ){ + usage("tag delete TAGNAME UUID"); + } + tag_add_artifact(g.argv[3], g.argv[4], 0, 0); + }else + + if( strncmp(g.argv[2],"find",n)==0 ){ + Stmt q; + if( g.argc!=4 ){ + usage("tag find TAGNAME"); + } + db_prepare(&q, + "SELECT blob.uuid FROM tagxref, blob" + " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)" + " AND blob.rid=tagxref.rid", g.argv[3] + ); + while( db_step(&q)==SQLITE_ROW ){ + printf("%s\n", db_column_text(&q, 0)); + } + db_finalize(&q); + }else + + if( strncmp(g.argv[2],"list",n)==0 ){ + Stmt q; + if( g.argc==3 ){ + db_prepare(&q, + "SELECT tagname" + " FROM tag" + " WHERE EXISTS(SELECT 1 FROM tagxref" + " WHERE tagid=tag.tagid" + " AND addflag)" + " ORDER BY tagname" + ); + while( db_step(&q)==SQLITE_ROW ){ + printf("%s\n", db_column_text(&q, 0)); + } + db_finalize(&q); + }else if( g.argc==4 ){ + int rid = name_to_rid(g.argv[3]); + db_prepare(&q, + "SELECT tagname, value" + " FROM tagxref, tag" + " WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid" + " AND addflag" + " ORDER BY tagname", + rid + ); + while( db_step(&q)==SQLITE_ROW ){ + const char *zName = db_column_text(&q, 0); + const char *zValue = db_column_text(&q, 1); + if( zValue ){ + printf("%s=%s\n", zName, zValue); + }else{ + printf("%s\n", zName); + } + } + db_finalize(&q); + }else{ + usage("tag list ?UUID?"); + } + }else + { + goto tag_cmd_usage; + } + return; + +tag_cmd_usage: + usage("add|delete|find|list ..."); }
Modified src/timeline.c from [34dd916f04] to [e450db18e8].
@@ -198,28 +198,16 @@ static const char zBaseSql[] = @ SELECT @ blob.rid, @ uuid, @ datetime(event.mtime,'localtime'), - @ coalesce((SELECT value FROM tagxref - @ WHERE rid=blob.rid - @ AND tagid=(SELECT tagid FROM tag WHERE tagname='comment')), - @ comment), - @ coalesce((SELECT value FROM tagxref - @ WHERE rid=blob.rid - @ AND tagid=(SELECT tagid FROM tag WHERE tagname='user')), - @ user), + @ coalesce(ecomment, comment), + @ coalesce(euser, user), @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim=1), @ (SELECT count(*) FROM plink WHERE cid=blob.rid), @ NOT EXISTS (SELECT 1 FROM plink WHERE pid=blob.rid), - @ (SELECT value FROM tagxref - @ WHERE rid=blob.rid - @ AND tagid=(SELECT tagid FROM tag WHERE tagname='bgcolor') - @ UNION ALL - @ SELECT value FROM tagxref - @ WHERE rid=blob.rid - @ AND tagid=(SELECT tagid FROM tag WHERE tagname='br-bgcolor')) + @ coalesce(bgcolor, brbgcolor) @ FROM event JOIN blob @ WHERE blob.rid=event.objid ; return zBaseSql; } @@ -450,20 +438,11 @@ static const char zBaseSql[] = @ SELECT @ blob.rid, @ uuid, @ datetime(event.mtime,'localtime'), - @ coalesce((SELECT value FROM tagxref - @ WHERE rid=blob.rid - @ AND tagid=(SELECT tagid FROM tag WHERE tagname='comment')), - @ comment) - @ || ' (by ' || - @ coalesce((SELECT value FROM tagxref - @ WHERE rid=blob.rid - @ AND tagid=(SELECT tagid FROM tag WHERE tagname='user')), - @ user) - @ || ')', + @ coalesce(ecomment,comment) || ' (by ' || coalesce(euser,user) || ')', @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim), @ (SELECT count(*) FROM plink WHERE cid=blob.rid) @ FROM event, blob @ WHERE blob.rid=event.objid ;