Fossil SCM
Add the bt= query parameter to /timeline. Used in conjunction with p=, the bt= entry (mnemonic: Back To) provides a limit to how far backwards in time the ancestor search will go.
Commit
8b7a979a74361efddd7d9f98f02e7bf5485716a3025e64eea7971182c18a4424
Parent
f505d8d518de333…
2 files changed
+11
-4
+4
-2
+11
-4
| --- src/descendants.c | ||
| +++ src/descendants.c | ||
| @@ -159,13 +159,14 @@ | ||
| 159 | 159 | } |
| 160 | 160 | } |
| 161 | 161 | |
| 162 | 162 | /* |
| 163 | 163 | ** Load the record ID rid and up to |N|-1 closest ancestors into |
| 164 | -** the "ok" table. If N is zero, no limit. | |
| 164 | +** the "ok" table. If N is zero, no limit. If ridBackTo is not zero | |
| 165 | +** then stop the search upon reaching the ancestor with rid==ridBackTo. | |
| 165 | 166 | */ |
| 166 | -void compute_ancestors(int rid, int N, int directOnly){ | |
| 167 | +void compute_ancestors(int rid, int N, int directOnly, int ridBackTo){ | |
| 167 | 168 | if( !N ){ |
| 168 | 169 | N = -1; |
| 169 | 170 | }else if( N<0 ){ |
| 170 | 171 | N = -N; |
| 171 | 172 | } |
| @@ -194,10 +195,15 @@ | ||
| 194 | 195 | ** (1) Primary parents |
| 195 | 196 | ** (2) Merge parents |
| 196 | 197 | ** (3) Cherrypick merge parents. |
| 197 | 198 | ** (4) All ancestores of 1 and 2 but not of 3. |
| 198 | 199 | */ |
| 200 | + double rLimitMtime = 0.0; | |
| 201 | + if( ridBackTo ){ | |
| 202 | + rLimitMtime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", | |
| 203 | + ridBackTo); | |
| 204 | + } | |
| 199 | 205 | db_multi_exec( |
| 200 | 206 | "WITH RECURSIVE " |
| 201 | 207 | " parent(pid,cid,isCP) AS (" |
| 202 | 208 | " SELECT plink.pid, plink.cid, 0 AS xisCP FROM plink" |
| 203 | 209 | " UNION ALL" |
| @@ -209,15 +215,16 @@ | ||
| 209 | 215 | " SELECT parent.pid, event.mtime, parent.isCP" |
| 210 | 216 | " FROM ancestor, parent, event" |
| 211 | 217 | " WHERE parent.cid=ancestor.rid" |
| 212 | 218 | " AND event.objid=parent.pid" |
| 213 | 219 | " AND NOT ancestor.isCP" |
| 220 | + " AND event.mtime>=%.17g" | |
| 214 | 221 | " ORDER BY mtime DESC LIMIT %d" |
| 215 | 222 | " )" |
| 216 | 223 | "INSERT INTO ok" |
| 217 | 224 | " SELECT rid FROM ancestor;", |
| 218 | - rid, rid, N | |
| 225 | + rid, rid, rLimitMtime, N | |
| 219 | 226 | ); |
| 220 | 227 | } |
| 221 | 228 | } |
| 222 | 229 | |
| 223 | 230 | /* |
| @@ -282,11 +289,11 @@ | ||
| 282 | 289 | |
| 283 | 290 | if( prevVid!=vid ){ |
| 284 | 291 | prevVid = vid; |
| 285 | 292 | db_multi_exec("CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);" |
| 286 | 293 | "DELETE FROM ok;"); |
| 287 | - compute_ancestors(vid, 100000000, 1); | |
| 294 | + compute_ancestors(vid, 100000000, 1, 0); | |
| 288 | 295 | } |
| 289 | 296 | db_static_prepare(&q, |
| 290 | 297 | "SELECT (max(event.mtime)-2440587.5)*86400 FROM mlink, event" |
| 291 | 298 | " WHERE mlink.mid=event.objid" |
| 292 | 299 | " AND +mlink.mid IN ok" |
| 293 | 300 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -159,13 +159,14 @@ | |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | /* |
| 163 | ** Load the record ID rid and up to |N|-1 closest ancestors into |
| 164 | ** the "ok" table. If N is zero, no limit. |
| 165 | */ |
| 166 | void compute_ancestors(int rid, int N, int directOnly){ |
| 167 | if( !N ){ |
| 168 | N = -1; |
| 169 | }else if( N<0 ){ |
| 170 | N = -N; |
| 171 | } |
| @@ -194,10 +195,15 @@ | |
| 194 | ** (1) Primary parents |
| 195 | ** (2) Merge parents |
| 196 | ** (3) Cherrypick merge parents. |
| 197 | ** (4) All ancestores of 1 and 2 but not of 3. |
| 198 | */ |
| 199 | db_multi_exec( |
| 200 | "WITH RECURSIVE " |
| 201 | " parent(pid,cid,isCP) AS (" |
| 202 | " SELECT plink.pid, plink.cid, 0 AS xisCP FROM plink" |
| 203 | " UNION ALL" |
| @@ -209,15 +215,16 @@ | |
| 209 | " SELECT parent.pid, event.mtime, parent.isCP" |
| 210 | " FROM ancestor, parent, event" |
| 211 | " WHERE parent.cid=ancestor.rid" |
| 212 | " AND event.objid=parent.pid" |
| 213 | " AND NOT ancestor.isCP" |
| 214 | " ORDER BY mtime DESC LIMIT %d" |
| 215 | " )" |
| 216 | "INSERT INTO ok" |
| 217 | " SELECT rid FROM ancestor;", |
| 218 | rid, rid, N |
| 219 | ); |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | /* |
| @@ -282,11 +289,11 @@ | |
| 282 | |
| 283 | if( prevVid!=vid ){ |
| 284 | prevVid = vid; |
| 285 | db_multi_exec("CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);" |
| 286 | "DELETE FROM ok;"); |
| 287 | compute_ancestors(vid, 100000000, 1); |
| 288 | } |
| 289 | db_static_prepare(&q, |
| 290 | "SELECT (max(event.mtime)-2440587.5)*86400 FROM mlink, event" |
| 291 | " WHERE mlink.mid=event.objid" |
| 292 | " AND +mlink.mid IN ok" |
| 293 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -159,13 +159,14 @@ | |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | /* |
| 163 | ** Load the record ID rid and up to |N|-1 closest ancestors into |
| 164 | ** the "ok" table. If N is zero, no limit. If ridBackTo is not zero |
| 165 | ** then stop the search upon reaching the ancestor with rid==ridBackTo. |
| 166 | */ |
| 167 | void compute_ancestors(int rid, int N, int directOnly, int ridBackTo){ |
| 168 | if( !N ){ |
| 169 | N = -1; |
| 170 | }else if( N<0 ){ |
| 171 | N = -N; |
| 172 | } |
| @@ -194,10 +195,15 @@ | |
| 195 | ** (1) Primary parents |
| 196 | ** (2) Merge parents |
| 197 | ** (3) Cherrypick merge parents. |
| 198 | ** (4) All ancestores of 1 and 2 but not of 3. |
| 199 | */ |
| 200 | double rLimitMtime = 0.0; |
| 201 | if( ridBackTo ){ |
| 202 | rLimitMtime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", |
| 203 | ridBackTo); |
| 204 | } |
| 205 | db_multi_exec( |
| 206 | "WITH RECURSIVE " |
| 207 | " parent(pid,cid,isCP) AS (" |
| 208 | " SELECT plink.pid, plink.cid, 0 AS xisCP FROM plink" |
| 209 | " UNION ALL" |
| @@ -209,15 +215,16 @@ | |
| 215 | " SELECT parent.pid, event.mtime, parent.isCP" |
| 216 | " FROM ancestor, parent, event" |
| 217 | " WHERE parent.cid=ancestor.rid" |
| 218 | " AND event.objid=parent.pid" |
| 219 | " AND NOT ancestor.isCP" |
| 220 | " AND event.mtime>=%.17g" |
| 221 | " ORDER BY mtime DESC LIMIT %d" |
| 222 | " )" |
| 223 | "INSERT INTO ok" |
| 224 | " SELECT rid FROM ancestor;", |
| 225 | rid, rid, rLimitMtime, N |
| 226 | ); |
| 227 | } |
| 228 | } |
| 229 | |
| 230 | /* |
| @@ -282,11 +289,11 @@ | |
| 289 | |
| 290 | if( prevVid!=vid ){ |
| 291 | prevVid = vid; |
| 292 | db_multi_exec("CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);" |
| 293 | "DELETE FROM ok;"); |
| 294 | compute_ancestors(vid, 100000000, 1, 0); |
| 295 | } |
| 296 | db_static_prepare(&q, |
| 297 | "SELECT (max(event.mtime)-2440587.5)*86400 FROM mlink, event" |
| 298 | " WHERE mlink.mid=event.objid" |
| 299 | " AND +mlink.mid IN ok" |
| 300 |
+4
-2
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -1590,10 +1590,11 @@ | ||
| 1590 | 1590 | ** c=TIMEORTAG "Circa" this event |
| 1591 | 1591 | ** cf=FILEHASH "Circa" the first use of the file with FILEHASH |
| 1592 | 1592 | ** m=TIMEORTAG Mark this event |
| 1593 | 1593 | ** n=COUNT Maximum number of events. "all" for no limit |
| 1594 | 1594 | ** p=CHECKIN Parents and ancestors of CHECKIN |
| 1595 | +** bt=PRIOR ... going back to PRIOR | |
| 1595 | 1596 | ** d=CHECKIN Children and descendants of CHECKIN |
| 1596 | 1597 | ** dp=CHECKIN The same as d=CHECKIN&p=CHECKIN |
| 1597 | 1598 | ** t=TAG Show only check-ins with the given TAG |
| 1598 | 1599 | ** r=TAG Show check-ins related to TAG, equivalent to t=TAG&rel |
| 1599 | 1600 | ** rel Show related check-ins as well as those matching t=TAG |
| @@ -2064,11 +2065,12 @@ | ||
| 2064 | 2065 | if( nd>0 ) blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s"); |
| 2065 | 2066 | if( useDividers ) selectedRid = d_rid; |
| 2066 | 2067 | db_multi_exec("DELETE FROM ok"); |
| 2067 | 2068 | } |
| 2068 | 2069 | if( p_rid ){ |
| 2069 | - compute_ancestors(p_rid, nEntry==0 ? 0 : nEntry+1, 0); | |
| 2070 | + int ridBackTo = name_to_typed_rid(P("bt"),"ci"); | |
| 2071 | + compute_ancestors(p_rid, nEntry==0 ? 0 : nEntry+1, 0, ridBackTo); | |
| 2070 | 2072 | np = db_int(0, "SELECT count(*)-1 FROM ok"); |
| 2071 | 2073 | if( np>0 ){ |
| 2072 | 2074 | if( nd>0 ) blob_appendf(&desc, " and "); |
| 2073 | 2075 | blob_appendf(&desc, "%d ancestors", np); |
| 2074 | 2076 | db_multi_exec("%s", blob_sql_text(&sql)); |
| @@ -2948,11 +2950,11 @@ | ||
| 2948 | 2950 | if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){ |
| 2949 | 2951 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 2950 | 2952 | if( mode==TIMELINE_MODE_CHILDREN ){ |
| 2951 | 2953 | compute_descendants(objid, (zFilePattern ? 0 : n)); |
| 2952 | 2954 | }else{ |
| 2953 | - compute_ancestors(objid, (zFilePattern ? 0 : n), 0); | |
| 2955 | + compute_ancestors(objid, (zFilePattern ? 0 : n), 0, 0); | |
| 2954 | 2956 | } |
| 2955 | 2957 | blob_append_sql(&sql, "\n AND blob.rid IN ok"); |
| 2956 | 2958 | } |
| 2957 | 2959 | if( zType && (zType[0]!='a') ){ |
| 2958 | 2960 | blob_append_sql(&sql, "\n AND event.type=%Q ", zType); |
| 2959 | 2961 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1590,10 +1590,11 @@ | |
| 1590 | ** c=TIMEORTAG "Circa" this event |
| 1591 | ** cf=FILEHASH "Circa" the first use of the file with FILEHASH |
| 1592 | ** m=TIMEORTAG Mark this event |
| 1593 | ** n=COUNT Maximum number of events. "all" for no limit |
| 1594 | ** p=CHECKIN Parents and ancestors of CHECKIN |
| 1595 | ** d=CHECKIN Children and descendants of CHECKIN |
| 1596 | ** dp=CHECKIN The same as d=CHECKIN&p=CHECKIN |
| 1597 | ** t=TAG Show only check-ins with the given TAG |
| 1598 | ** r=TAG Show check-ins related to TAG, equivalent to t=TAG&rel |
| 1599 | ** rel Show related check-ins as well as those matching t=TAG |
| @@ -2064,11 +2065,12 @@ | |
| 2064 | if( nd>0 ) blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s"); |
| 2065 | if( useDividers ) selectedRid = d_rid; |
| 2066 | db_multi_exec("DELETE FROM ok"); |
| 2067 | } |
| 2068 | if( p_rid ){ |
| 2069 | compute_ancestors(p_rid, nEntry==0 ? 0 : nEntry+1, 0); |
| 2070 | np = db_int(0, "SELECT count(*)-1 FROM ok"); |
| 2071 | if( np>0 ){ |
| 2072 | if( nd>0 ) blob_appendf(&desc, " and "); |
| 2073 | blob_appendf(&desc, "%d ancestors", np); |
| 2074 | db_multi_exec("%s", blob_sql_text(&sql)); |
| @@ -2948,11 +2950,11 @@ | |
| 2948 | if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){ |
| 2949 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 2950 | if( mode==TIMELINE_MODE_CHILDREN ){ |
| 2951 | compute_descendants(objid, (zFilePattern ? 0 : n)); |
| 2952 | }else{ |
| 2953 | compute_ancestors(objid, (zFilePattern ? 0 : n), 0); |
| 2954 | } |
| 2955 | blob_append_sql(&sql, "\n AND blob.rid IN ok"); |
| 2956 | } |
| 2957 | if( zType && (zType[0]!='a') ){ |
| 2958 | blob_append_sql(&sql, "\n AND event.type=%Q ", zType); |
| 2959 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1590,10 +1590,11 @@ | |
| 1590 | ** c=TIMEORTAG "Circa" this event |
| 1591 | ** cf=FILEHASH "Circa" the first use of the file with FILEHASH |
| 1592 | ** m=TIMEORTAG Mark this event |
| 1593 | ** n=COUNT Maximum number of events. "all" for no limit |
| 1594 | ** p=CHECKIN Parents and ancestors of CHECKIN |
| 1595 | ** bt=PRIOR ... going back to PRIOR |
| 1596 | ** d=CHECKIN Children and descendants of CHECKIN |
| 1597 | ** dp=CHECKIN The same as d=CHECKIN&p=CHECKIN |
| 1598 | ** t=TAG Show only check-ins with the given TAG |
| 1599 | ** r=TAG Show check-ins related to TAG, equivalent to t=TAG&rel |
| 1600 | ** rel Show related check-ins as well as those matching t=TAG |
| @@ -2064,11 +2065,12 @@ | |
| 2065 | if( nd>0 ) blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s"); |
| 2066 | if( useDividers ) selectedRid = d_rid; |
| 2067 | db_multi_exec("DELETE FROM ok"); |
| 2068 | } |
| 2069 | if( p_rid ){ |
| 2070 | int ridBackTo = name_to_typed_rid(P("bt"),"ci"); |
| 2071 | compute_ancestors(p_rid, nEntry==0 ? 0 : nEntry+1, 0, ridBackTo); |
| 2072 | np = db_int(0, "SELECT count(*)-1 FROM ok"); |
| 2073 | if( np>0 ){ |
| 2074 | if( nd>0 ) blob_appendf(&desc, " and "); |
| 2075 | blob_appendf(&desc, "%d ancestors", np); |
| 2076 | db_multi_exec("%s", blob_sql_text(&sql)); |
| @@ -2948,11 +2950,11 @@ | |
| 2950 | if( mode==TIMELINE_MODE_CHILDREN || mode==TIMELINE_MODE_PARENTS ){ |
| 2951 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 2952 | if( mode==TIMELINE_MODE_CHILDREN ){ |
| 2953 | compute_descendants(objid, (zFilePattern ? 0 : n)); |
| 2954 | }else{ |
| 2955 | compute_ancestors(objid, (zFilePattern ? 0 : n), 0, 0); |
| 2956 | } |
| 2957 | blob_append_sql(&sql, "\n AND blob.rid IN ok"); |
| 2958 | } |
| 2959 | if( zType && (zType[0]!='a') ){ |
| 2960 | blob_append_sql(&sql, "\n AND event.type=%Q ", zType); |
| 2961 |