Fossil SCM
Performance and display improvements in /timeline for the use of bt= and ft= query parameters with from=.
Commit
c651369ce300226a02d7928de5bb8c0bb0e207c3fce4e4e730ad3071da3c4377
Parent
b2b373ff17e3bfb…
1 file changed
+50
-6
+50
-6
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -1596,24 +1596,27 @@ | ||
| 1596 | 1596 | if( bForward ){ |
| 1597 | 1597 | if( tagId ){ |
| 1598 | 1598 | db_prepare(&q, |
| 1599 | 1599 | "WITH RECURSIVE dx(id,mtime) AS (" |
| 1600 | 1600 | " SELECT %d, event.mtime FROM event WHERE objid=%d" |
| 1601 | - " UNION ALL" | |
| 1601 | + " UNION" | |
| 1602 | 1602 | " SELECT plink.cid, plink.mtime" |
| 1603 | 1603 | " FROM dx, plink" |
| 1604 | 1604 | " WHERE plink.pid=dx.id" |
| 1605 | + " AND plink.mtime<=(SELECT max(event.mtime) FROM tagxref, event" | |
| 1606 | + " WHERE tagxref.tagid=%d AND tagxref.tagtype>0" | |
| 1607 | + " AND event.objid=tagxref.rid)" | |
| 1605 | 1608 | " ORDER BY plink.mtime)" |
| 1606 | 1609 | "SELECT id FROM dx, tagxref" |
| 1607 | 1610 | " WHERE tagid=%d AND tagtype>0 AND rid=id LIMIT 1", |
| 1608 | - iFrom, iFrom, tagId | |
| 1611 | + iFrom, iFrom, tagId, tagId | |
| 1609 | 1612 | ); |
| 1610 | 1613 | }else{ |
| 1611 | 1614 | db_prepare(&q, |
| 1612 | 1615 | "WITH RECURSIVE dx(id,mtime) AS (" |
| 1613 | 1616 | " SELECT %d, event.mtime FROM event WHERE objid=%d" |
| 1614 | - " UNION ALL" | |
| 1617 | + " UNION" | |
| 1615 | 1618 | " SELECT plink.cid, plink.mtime" |
| 1616 | 1619 | " FROM dx, plink" |
| 1617 | 1620 | " WHERE plink.pid=dx.id" |
| 1618 | 1621 | " AND plink.mtime<=(SELECT mtime FROM event WHERE objid=%d)" |
| 1619 | 1622 | " ORDER BY plink.mtime)" |
| @@ -1624,24 +1627,27 @@ | ||
| 1624 | 1627 | }else{ |
| 1625 | 1628 | if( tagId ){ |
| 1626 | 1629 | db_prepare(&q, |
| 1627 | 1630 | "WITH RECURSIVE dx(id,mtime) AS (" |
| 1628 | 1631 | " SELECT %d, event.mtime FROM event WHERE objid=%d" |
| 1629 | - " UNION ALL" | |
| 1632 | + " UNION" | |
| 1630 | 1633 | " SELECT plink.pid, event.mtime" |
| 1631 | 1634 | " FROM dx, plink, event" |
| 1632 | 1635 | " WHERE plink.cid=dx.id AND event.objid=plink.pid" |
| 1636 | + " AND event.mtime>=(SELECT min(event.mtime) FROM tagxref, event" | |
| 1637 | + " WHERE tagxref.tagid=%d AND tagxref.tagtype>0" | |
| 1638 | + " AND event.objid=tagxref.rid)" | |
| 1633 | 1639 | " ORDER BY event.mtime DESC)" |
| 1634 | 1640 | "SELECT id FROM dx, tagxref" |
| 1635 | 1641 | " WHERE tagid=%d AND tagtype>0 AND rid=id LIMIT 1", |
| 1636 | - iFrom, iFrom, tagId | |
| 1642 | + iFrom, iFrom, tagId, tagId | |
| 1637 | 1643 | ); |
| 1638 | 1644 | }else{ |
| 1639 | 1645 | db_prepare(&q, |
| 1640 | 1646 | "WITH RECURSIVE dx(id,mtime) AS (" |
| 1641 | 1647 | " SELECT %d, event.mtime FROM event WHERE objid=%d" |
| 1642 | - " UNION ALL" | |
| 1648 | + " UNION" | |
| 1643 | 1649 | " SELECT plink.pid, event.mtime" |
| 1644 | 1650 | " FROM dx, plink, event" |
| 1645 | 1651 | " WHERE plink.cid=dx.id AND event.objid=plink.pid" |
| 1646 | 1652 | " AND event.mtime>=(SELECT mtime FROM event WHERE objid=%d)" |
| 1647 | 1653 | " ORDER BY event.mtime DESC)" |
| @@ -1654,10 +1660,41 @@ | ||
| 1654 | 1660 | ans = db_column_int(&q, 0); |
| 1655 | 1661 | } |
| 1656 | 1662 | db_finalize(&q); |
| 1657 | 1663 | return ans; |
| 1658 | 1664 | } |
| 1665 | + | |
| 1666 | +/* | |
| 1667 | +** COMMAND: test-endpoint | |
| 1668 | +** | |
| 1669 | +** Usage: fossil test-endpoint BASE TAG ?OPTIONS? | |
| 1670 | +** | |
| 1671 | +** Show the first check-in with TAG that is a descendent or ancestor | |
| 1672 | +** of BASE. The first descendent checkin is shown by default. Use | |
| 1673 | +** the --backto to see the first ancestor checkin. | |
| 1674 | +** | |
| 1675 | +** Options: | |
| 1676 | +** | |
| 1677 | +** --backto Show ancestor. Others defaults to descendents. | |
| 1678 | +*/ | |
| 1679 | +void timeline_test_endpoint(void){ | |
| 1680 | + int bForward = find_option("backto",0,0)==0; | |
| 1681 | + int from_rid; | |
| 1682 | + int ans; | |
| 1683 | + db_find_and_open_repository(0, 0); | |
| 1684 | + verify_all_options(); | |
| 1685 | + if( g.argc!=4 ){ | |
| 1686 | + usage("BASE-CHECKIN TAG ?--backto?"); | |
| 1687 | + } | |
| 1688 | + from_rid = symbolic_name_to_rid(g.argv[2],"ci"); | |
| 1689 | + ans = timeline_endpoint(from_rid, g.argv[3], bForward); | |
| 1690 | + if( ans ){ | |
| 1691 | + fossil_print("Result: %d (%S)\n", ans, rid_to_uuid(ans)); | |
| 1692 | + }else{ | |
| 1693 | + fossil_print("No path found\n"); | |
| 1694 | + } | |
| 1695 | +} | |
| 1659 | 1696 | |
| 1660 | 1697 | |
| 1661 | 1698 | /* |
| 1662 | 1699 | ** WEBPAGE: timeline |
| 1663 | 1700 | ** |
| @@ -2153,10 +2190,16 @@ | ||
| 2153 | 2190 | if( selectedRid==0 ) selectedRid = from_rid; |
| 2154 | 2191 | if( secondaryRid==0 ) secondaryRid = to_rid; |
| 2155 | 2192 | }else{ |
| 2156 | 2193 | blob_appendf(&desc, "There is no path from %h %s to %h.<br>Instead: ", |
| 2157 | 2194 | P("from"), from_to_mode==1 ? "forward" : "back", zTo); |
| 2195 | + p_rid = 0; | |
| 2196 | + d_rid = 0; | |
| 2197 | + zCirca = P("from"); | |
| 2198 | + zMark = zCirca; | |
| 2199 | + zType = "ci"; | |
| 2200 | + nEntry = 1; | |
| 2158 | 2201 | } |
| 2159 | 2202 | } |
| 2160 | 2203 | if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.perm.Read ){ |
| 2161 | 2204 | /* If from= and to= are present, display all nodes on a path connecting |
| 2162 | 2205 | ** the two */ |
| @@ -2809,10 +2852,11 @@ | ||
| 2809 | 2852 | @ <pre>%h(blob_sql_text(&sql2))</pre> |
| 2810 | 2853 | } |
| 2811 | 2854 | db_multi_exec("%s", blob_sql_text(&sql2)); |
| 2812 | 2855 | if( nEntry>0 ){ |
| 2813 | 2856 | nEntry -= db_int(0,"select count(*) from timeline"); |
| 2857 | + if( nEntry<=0 ) nEntry = 1; | |
| 2814 | 2858 | } |
| 2815 | 2859 | blob_reset(&sql2); |
| 2816 | 2860 | blob_append_sql(&sql, |
| 2817 | 2861 | " AND event.mtime<=%f ORDER BY event.mtime DESC", |
| 2818 | 2862 | rCirca |
| 2819 | 2863 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1596,24 +1596,27 @@ | |
| 1596 | if( bForward ){ |
| 1597 | if( tagId ){ |
| 1598 | db_prepare(&q, |
| 1599 | "WITH RECURSIVE dx(id,mtime) AS (" |
| 1600 | " SELECT %d, event.mtime FROM event WHERE objid=%d" |
| 1601 | " UNION ALL" |
| 1602 | " SELECT plink.cid, plink.mtime" |
| 1603 | " FROM dx, plink" |
| 1604 | " WHERE plink.pid=dx.id" |
| 1605 | " ORDER BY plink.mtime)" |
| 1606 | "SELECT id FROM dx, tagxref" |
| 1607 | " WHERE tagid=%d AND tagtype>0 AND rid=id LIMIT 1", |
| 1608 | iFrom, iFrom, tagId |
| 1609 | ); |
| 1610 | }else{ |
| 1611 | db_prepare(&q, |
| 1612 | "WITH RECURSIVE dx(id,mtime) AS (" |
| 1613 | " SELECT %d, event.mtime FROM event WHERE objid=%d" |
| 1614 | " UNION ALL" |
| 1615 | " SELECT plink.cid, plink.mtime" |
| 1616 | " FROM dx, plink" |
| 1617 | " WHERE plink.pid=dx.id" |
| 1618 | " AND plink.mtime<=(SELECT mtime FROM event WHERE objid=%d)" |
| 1619 | " ORDER BY plink.mtime)" |
| @@ -1624,24 +1627,27 @@ | |
| 1624 | }else{ |
| 1625 | if( tagId ){ |
| 1626 | db_prepare(&q, |
| 1627 | "WITH RECURSIVE dx(id,mtime) AS (" |
| 1628 | " SELECT %d, event.mtime FROM event WHERE objid=%d" |
| 1629 | " UNION ALL" |
| 1630 | " SELECT plink.pid, event.mtime" |
| 1631 | " FROM dx, plink, event" |
| 1632 | " WHERE plink.cid=dx.id AND event.objid=plink.pid" |
| 1633 | " ORDER BY event.mtime DESC)" |
| 1634 | "SELECT id FROM dx, tagxref" |
| 1635 | " WHERE tagid=%d AND tagtype>0 AND rid=id LIMIT 1", |
| 1636 | iFrom, iFrom, tagId |
| 1637 | ); |
| 1638 | }else{ |
| 1639 | db_prepare(&q, |
| 1640 | "WITH RECURSIVE dx(id,mtime) AS (" |
| 1641 | " SELECT %d, event.mtime FROM event WHERE objid=%d" |
| 1642 | " UNION ALL" |
| 1643 | " SELECT plink.pid, event.mtime" |
| 1644 | " FROM dx, plink, event" |
| 1645 | " WHERE plink.cid=dx.id AND event.objid=plink.pid" |
| 1646 | " AND event.mtime>=(SELECT mtime FROM event WHERE objid=%d)" |
| 1647 | " ORDER BY event.mtime DESC)" |
| @@ -1654,10 +1660,41 @@ | |
| 1654 | ans = db_column_int(&q, 0); |
| 1655 | } |
| 1656 | db_finalize(&q); |
| 1657 | return ans; |
| 1658 | } |
| 1659 | |
| 1660 | |
| 1661 | /* |
| 1662 | ** WEBPAGE: timeline |
| 1663 | ** |
| @@ -2153,10 +2190,16 @@ | |
| 2153 | if( selectedRid==0 ) selectedRid = from_rid; |
| 2154 | if( secondaryRid==0 ) secondaryRid = to_rid; |
| 2155 | }else{ |
| 2156 | blob_appendf(&desc, "There is no path from %h %s to %h.<br>Instead: ", |
| 2157 | P("from"), from_to_mode==1 ? "forward" : "back", zTo); |
| 2158 | } |
| 2159 | } |
| 2160 | if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.perm.Read ){ |
| 2161 | /* If from= and to= are present, display all nodes on a path connecting |
| 2162 | ** the two */ |
| @@ -2809,10 +2852,11 @@ | |
| 2809 | @ <pre>%h(blob_sql_text(&sql2))</pre> |
| 2810 | } |
| 2811 | db_multi_exec("%s", blob_sql_text(&sql2)); |
| 2812 | if( nEntry>0 ){ |
| 2813 | nEntry -= db_int(0,"select count(*) from timeline"); |
| 2814 | } |
| 2815 | blob_reset(&sql2); |
| 2816 | blob_append_sql(&sql, |
| 2817 | " AND event.mtime<=%f ORDER BY event.mtime DESC", |
| 2818 | rCirca |
| 2819 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -1596,24 +1596,27 @@ | |
| 1596 | if( bForward ){ |
| 1597 | if( tagId ){ |
| 1598 | db_prepare(&q, |
| 1599 | "WITH RECURSIVE dx(id,mtime) AS (" |
| 1600 | " SELECT %d, event.mtime FROM event WHERE objid=%d" |
| 1601 | " UNION" |
| 1602 | " SELECT plink.cid, plink.mtime" |
| 1603 | " FROM dx, plink" |
| 1604 | " WHERE plink.pid=dx.id" |
| 1605 | " AND plink.mtime<=(SELECT max(event.mtime) FROM tagxref, event" |
| 1606 | " WHERE tagxref.tagid=%d AND tagxref.tagtype>0" |
| 1607 | " AND event.objid=tagxref.rid)" |
| 1608 | " ORDER BY plink.mtime)" |
| 1609 | "SELECT id FROM dx, tagxref" |
| 1610 | " WHERE tagid=%d AND tagtype>0 AND rid=id LIMIT 1", |
| 1611 | iFrom, iFrom, tagId, tagId |
| 1612 | ); |
| 1613 | }else{ |
| 1614 | db_prepare(&q, |
| 1615 | "WITH RECURSIVE dx(id,mtime) AS (" |
| 1616 | " SELECT %d, event.mtime FROM event WHERE objid=%d" |
| 1617 | " UNION" |
| 1618 | " SELECT plink.cid, plink.mtime" |
| 1619 | " FROM dx, plink" |
| 1620 | " WHERE plink.pid=dx.id" |
| 1621 | " AND plink.mtime<=(SELECT mtime FROM event WHERE objid=%d)" |
| 1622 | " ORDER BY plink.mtime)" |
| @@ -1624,24 +1627,27 @@ | |
| 1627 | }else{ |
| 1628 | if( tagId ){ |
| 1629 | db_prepare(&q, |
| 1630 | "WITH RECURSIVE dx(id,mtime) AS (" |
| 1631 | " SELECT %d, event.mtime FROM event WHERE objid=%d" |
| 1632 | " UNION" |
| 1633 | " SELECT plink.pid, event.mtime" |
| 1634 | " FROM dx, plink, event" |
| 1635 | " WHERE plink.cid=dx.id AND event.objid=plink.pid" |
| 1636 | " AND event.mtime>=(SELECT min(event.mtime) FROM tagxref, event" |
| 1637 | " WHERE tagxref.tagid=%d AND tagxref.tagtype>0" |
| 1638 | " AND event.objid=tagxref.rid)" |
| 1639 | " ORDER BY event.mtime DESC)" |
| 1640 | "SELECT id FROM dx, tagxref" |
| 1641 | " WHERE tagid=%d AND tagtype>0 AND rid=id LIMIT 1", |
| 1642 | iFrom, iFrom, tagId, tagId |
| 1643 | ); |
| 1644 | }else{ |
| 1645 | db_prepare(&q, |
| 1646 | "WITH RECURSIVE dx(id,mtime) AS (" |
| 1647 | " SELECT %d, event.mtime FROM event WHERE objid=%d" |
| 1648 | " UNION" |
| 1649 | " SELECT plink.pid, event.mtime" |
| 1650 | " FROM dx, plink, event" |
| 1651 | " WHERE plink.cid=dx.id AND event.objid=plink.pid" |
| 1652 | " AND event.mtime>=(SELECT mtime FROM event WHERE objid=%d)" |
| 1653 | " ORDER BY event.mtime DESC)" |
| @@ -1654,10 +1660,41 @@ | |
| 1660 | ans = db_column_int(&q, 0); |
| 1661 | } |
| 1662 | db_finalize(&q); |
| 1663 | return ans; |
| 1664 | } |
| 1665 | |
| 1666 | /* |
| 1667 | ** COMMAND: test-endpoint |
| 1668 | ** |
| 1669 | ** Usage: fossil test-endpoint BASE TAG ?OPTIONS? |
| 1670 | ** |
| 1671 | ** Show the first check-in with TAG that is a descendent or ancestor |
| 1672 | ** of BASE. The first descendent checkin is shown by default. Use |
| 1673 | ** the --backto to see the first ancestor checkin. |
| 1674 | ** |
| 1675 | ** Options: |
| 1676 | ** |
| 1677 | ** --backto Show ancestor. Others defaults to descendents. |
| 1678 | */ |
| 1679 | void timeline_test_endpoint(void){ |
| 1680 | int bForward = find_option("backto",0,0)==0; |
| 1681 | int from_rid; |
| 1682 | int ans; |
| 1683 | db_find_and_open_repository(0, 0); |
| 1684 | verify_all_options(); |
| 1685 | if( g.argc!=4 ){ |
| 1686 | usage("BASE-CHECKIN TAG ?--backto?"); |
| 1687 | } |
| 1688 | from_rid = symbolic_name_to_rid(g.argv[2],"ci"); |
| 1689 | ans = timeline_endpoint(from_rid, g.argv[3], bForward); |
| 1690 | if( ans ){ |
| 1691 | fossil_print("Result: %d (%S)\n", ans, rid_to_uuid(ans)); |
| 1692 | }else{ |
| 1693 | fossil_print("No path found\n"); |
| 1694 | } |
| 1695 | } |
| 1696 | |
| 1697 | |
| 1698 | /* |
| 1699 | ** WEBPAGE: timeline |
| 1700 | ** |
| @@ -2153,10 +2190,16 @@ | |
| 2190 | if( selectedRid==0 ) selectedRid = from_rid; |
| 2191 | if( secondaryRid==0 ) secondaryRid = to_rid; |
| 2192 | }else{ |
| 2193 | blob_appendf(&desc, "There is no path from %h %s to %h.<br>Instead: ", |
| 2194 | P("from"), from_to_mode==1 ? "forward" : "back", zTo); |
| 2195 | p_rid = 0; |
| 2196 | d_rid = 0; |
| 2197 | zCirca = P("from"); |
| 2198 | zMark = zCirca; |
| 2199 | zType = "ci"; |
| 2200 | nEntry = 1; |
| 2201 | } |
| 2202 | } |
| 2203 | if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.perm.Read ){ |
| 2204 | /* If from= and to= are present, display all nodes on a path connecting |
| 2205 | ** the two */ |
| @@ -2809,10 +2852,11 @@ | |
| 2852 | @ <pre>%h(blob_sql_text(&sql2))</pre> |
| 2853 | } |
| 2854 | db_multi_exec("%s", blob_sql_text(&sql2)); |
| 2855 | if( nEntry>0 ){ |
| 2856 | nEntry -= db_int(0,"select count(*) from timeline"); |
| 2857 | if( nEntry<=0 ) nEntry = 1; |
| 2858 | } |
| 2859 | blob_reset(&sql2); |
| 2860 | blob_append_sql(&sql, |
| 2861 | " AND event.mtime<=%f ORDER BY event.mtime DESC", |
| 2862 | rCirca |
| 2863 |