Fossil SCM
A new, faster, implementation of the compute_fileage() utility that is implemented in SQL, using the files_of_checkin virtual tables and a common table expression.
Commit
cc1e96550423b2b3efb5d6a0bbc3f2a74a2a1cd6
Parent
a0cc614326fa40e…
1 file changed
+39
-57
+39
-57
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -724,75 +724,58 @@ | ||
| 724 | 724 | }else{ |
| 725 | 725 | zClass = mprintf("file"); |
| 726 | 726 | } |
| 727 | 727 | return zClass; |
| 728 | 728 | } |
| 729 | + | |
| 730 | +/* | |
| 731 | +** SQL used to compute the age of all files in checkin :ckin whose | |
| 732 | +** names match :glob | |
| 733 | +*/ | |
| 734 | +static const char zComputeFileAgeSetup[] = | |
| 735 | +@ CREATE TABLE IF NOT EXISTS temp.fileage( | |
| 736 | +@ fnid INTEGER PRIMARY KEY, | |
| 737 | +@ fid INTEGER, | |
| 738 | +@ mid INTEGER, | |
| 739 | +@ mtime DATETIME, | |
| 740 | +@ pathname TEXT | |
| 741 | +@ ); | |
| 742 | +@ CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin; | |
| 743 | +; | |
| 744 | + | |
| 745 | +static const char zComputeFileAgeRun[] = | |
| 746 | +@ WITH RECURSIVE | |
| 747 | +@ ckin(x) AS (VALUES(:ckin) UNION ALL | |
| 748 | +@ SELECT pid FROM ckin, plink WHERE cid=x AND isprim) | |
| 749 | +@ INSERT OR IGNORE INTO fileage(fnid, fid, mid, mtime, pathname) | |
| 750 | +@ SELECT mlink.fnid, mlink.fid, x, event.mtime, filename.name | |
| 751 | +@ FROM ckin, mlink, event, filename | |
| 752 | +@ WHERE mlink.mid=ckin.x | |
| 753 | +@ AND mlink.fnid IN (SELECT fnid FROM foci, filename | |
| 754 | +@ WHERE foci.checkinID=:ckin | |
| 755 | +@ AND filename.name=foci.filename | |
| 756 | +@ AND filename.name GLOB :glob) | |
| 757 | +@ AND filename.fnid=mlink.fnid | |
| 758 | +@ AND event.objid=mlink.mid; | |
| 759 | +; | |
| 760 | + | |
| 729 | 761 | |
| 730 | 762 | /* |
| 731 | 763 | ** Look at all file containing in the version "vid". Construct a |
| 732 | 764 | ** temporary table named "fileage" that contains the file-id for each |
| 733 | 765 | ** files, the pathname, the check-in where the file was added, and the |
| 734 | 766 | ** mtime on that checkin. If zGlob and *zGlob then only files matching |
| 735 | 767 | ** the given glob are computed. |
| 736 | 768 | */ |
| 737 | 769 | int compute_fileage(int vid, const char* zGlob){ |
| 738 | - int nFile = 0; | |
| 739 | - double vmtime; | |
| 740 | - Stmt q1, q2, q3; | |
| 741 | - Stmt upd; | |
| 742 | - if(zGlob && !*zGlob) zGlob = NULL; | |
| 743 | - db_multi_exec( | |
| 744 | - /*"DROP TABLE IF EXISTS temp.fileage;"*/ | |
| 745 | - "CREATE TEMP TABLE fileage(\n" | |
| 746 | - " fid INTEGER,\n" | |
| 747 | - " mid INTEGER,\n" | |
| 748 | - " mtime DATETIME,\n" | |
| 749 | - " pathname TEXT\n" | |
| 750 | - ");\n" | |
| 751 | - "CREATE INDEX fileage_fid ON fileage(fid);\n" | |
| 752 | - "CREATE VIRTUAL TABLE temp.foci USING files_of_checkin;\n" | |
| 753 | - "INSERT INTO temp.fileage(fid,pathname)" | |
| 754 | - " SELECT blob.rid, foci.filename\n" | |
| 755 | - " FROM foci, blob\n" | |
| 756 | - " WHERE foci.checkinID=%d\n" | |
| 757 | - " AND blob.uuid=foci.uuid\n" | |
| 758 | - " AND foci.filename GLOB '%q';", | |
| 759 | - vid, zGlob ? zGlob : "*" | |
| 760 | - ); | |
| 761 | - nFile = db_int(0, "SELECT count(*) FROM fileage"); | |
| 762 | - db_prepare(&q1,"SELECT fid FROM mlink WHERE mid=:mid"); | |
| 763 | - db_prepare(&upd, "UPDATE fileage SET mid=:mid, mtime=:vmtime" | |
| 764 | - " WHERE fid=:fid AND mid IS NULL"); | |
| 765 | - db_prepare(&q2,"SELECT pid FROM plink WHERE cid=:vid AND isprim"); | |
| 766 | - db_prepare(&q3,"SELECT mtime FROM event WHERE objid=:vid"); | |
| 767 | - while( nFile>0 && vid>0 ){ | |
| 768 | - db_bind_int(&q3, ":vid", vid); | |
| 769 | - if( db_step(&q3)==SQLITE_ROW ){ | |
| 770 | - vmtime = db_column_double(&q3, 0); | |
| 771 | - }else{ | |
| 772 | - break; | |
| 773 | - } | |
| 774 | - db_reset(&q3); | |
| 775 | - db_bind_int(&q1, ":mid", vid); | |
| 776 | - db_bind_int(&upd, ":mid", vid); | |
| 777 | - db_bind_double(&upd, ":vmtime", vmtime); | |
| 778 | - while( db_step(&q1)==SQLITE_ROW ){ | |
| 779 | - db_bind_int(&upd, ":fid", db_column_int(&q1, 0)); | |
| 780 | - db_step(&upd); | |
| 781 | - nFile -= db_changes(); | |
| 782 | - db_reset(&upd); | |
| 783 | - } | |
| 784 | - db_reset(&q1); | |
| 785 | - db_bind_int(&q2, ":vid", vid); | |
| 786 | - if( db_step(&q2)!=SQLITE_ROW ) break; | |
| 787 | - vid = db_column_int(&q2, 0); | |
| 788 | - db_reset(&q2); | |
| 789 | - } | |
| 790 | - db_finalize(&q1); | |
| 791 | - db_finalize(&upd); | |
| 792 | - db_finalize(&q2); | |
| 793 | - db_finalize(&q3); | |
| 770 | + Stmt q; | |
| 771 | + db_multi_exec(zComputeFileAgeSetup /*works-like:"constant"*/); | |
| 772 | + db_prepare(&q, zComputeFileAgeRun /*works-like:"constant"*/); | |
| 773 | + db_bind_int(&q, ":ckin", vid); | |
| 774 | + db_bind_text(&q, ":glob", zGlob && zGlob[0] ? zGlob : "*"); | |
| 775 | + db_exec(&q); | |
| 776 | + db_finalize(&q); | |
| 794 | 777 | return 0; |
| 795 | 778 | } |
| 796 | 779 | |
| 797 | 780 | /* |
| 798 | 781 | ** Render the number of days in rAge as a more human-readable time span. |
| @@ -813,11 +796,10 @@ | ||
| 813 | 796 | return mprintf("%.1f days", rAge); |
| 814 | 797 | }else{ |
| 815 | 798 | return mprintf("%.2f years", rAge/365.0); |
| 816 | 799 | } |
| 817 | 800 | } |
| 818 | - | |
| 819 | 801 | |
| 820 | 802 | /* |
| 821 | 803 | ** COMMAND: test-fileage |
| 822 | 804 | ** |
| 823 | 805 | ** Usage: %fossil test-fileage CHECKIN |
| 824 | 806 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -724,75 +724,58 @@ | |
| 724 | }else{ |
| 725 | zClass = mprintf("file"); |
| 726 | } |
| 727 | return zClass; |
| 728 | } |
| 729 | |
| 730 | /* |
| 731 | ** Look at all file containing in the version "vid". Construct a |
| 732 | ** temporary table named "fileage" that contains the file-id for each |
| 733 | ** files, the pathname, the check-in where the file was added, and the |
| 734 | ** mtime on that checkin. If zGlob and *zGlob then only files matching |
| 735 | ** the given glob are computed. |
| 736 | */ |
| 737 | int compute_fileage(int vid, const char* zGlob){ |
| 738 | int nFile = 0; |
| 739 | double vmtime; |
| 740 | Stmt q1, q2, q3; |
| 741 | Stmt upd; |
| 742 | if(zGlob && !*zGlob) zGlob = NULL; |
| 743 | db_multi_exec( |
| 744 | /*"DROP TABLE IF EXISTS temp.fileage;"*/ |
| 745 | "CREATE TEMP TABLE fileage(\n" |
| 746 | " fid INTEGER,\n" |
| 747 | " mid INTEGER,\n" |
| 748 | " mtime DATETIME,\n" |
| 749 | " pathname TEXT\n" |
| 750 | ");\n" |
| 751 | "CREATE INDEX fileage_fid ON fileage(fid);\n" |
| 752 | "CREATE VIRTUAL TABLE temp.foci USING files_of_checkin;\n" |
| 753 | "INSERT INTO temp.fileage(fid,pathname)" |
| 754 | " SELECT blob.rid, foci.filename\n" |
| 755 | " FROM foci, blob\n" |
| 756 | " WHERE foci.checkinID=%d\n" |
| 757 | " AND blob.uuid=foci.uuid\n" |
| 758 | " AND foci.filename GLOB '%q';", |
| 759 | vid, zGlob ? zGlob : "*" |
| 760 | ); |
| 761 | nFile = db_int(0, "SELECT count(*) FROM fileage"); |
| 762 | db_prepare(&q1,"SELECT fid FROM mlink WHERE mid=:mid"); |
| 763 | db_prepare(&upd, "UPDATE fileage SET mid=:mid, mtime=:vmtime" |
| 764 | " WHERE fid=:fid AND mid IS NULL"); |
| 765 | db_prepare(&q2,"SELECT pid FROM plink WHERE cid=:vid AND isprim"); |
| 766 | db_prepare(&q3,"SELECT mtime FROM event WHERE objid=:vid"); |
| 767 | while( nFile>0 && vid>0 ){ |
| 768 | db_bind_int(&q3, ":vid", vid); |
| 769 | if( db_step(&q3)==SQLITE_ROW ){ |
| 770 | vmtime = db_column_double(&q3, 0); |
| 771 | }else{ |
| 772 | break; |
| 773 | } |
| 774 | db_reset(&q3); |
| 775 | db_bind_int(&q1, ":mid", vid); |
| 776 | db_bind_int(&upd, ":mid", vid); |
| 777 | db_bind_double(&upd, ":vmtime", vmtime); |
| 778 | while( db_step(&q1)==SQLITE_ROW ){ |
| 779 | db_bind_int(&upd, ":fid", db_column_int(&q1, 0)); |
| 780 | db_step(&upd); |
| 781 | nFile -= db_changes(); |
| 782 | db_reset(&upd); |
| 783 | } |
| 784 | db_reset(&q1); |
| 785 | db_bind_int(&q2, ":vid", vid); |
| 786 | if( db_step(&q2)!=SQLITE_ROW ) break; |
| 787 | vid = db_column_int(&q2, 0); |
| 788 | db_reset(&q2); |
| 789 | } |
| 790 | db_finalize(&q1); |
| 791 | db_finalize(&upd); |
| 792 | db_finalize(&q2); |
| 793 | db_finalize(&q3); |
| 794 | return 0; |
| 795 | } |
| 796 | |
| 797 | /* |
| 798 | ** Render the number of days in rAge as a more human-readable time span. |
| @@ -813,11 +796,10 @@ | |
| 813 | return mprintf("%.1f days", rAge); |
| 814 | }else{ |
| 815 | return mprintf("%.2f years", rAge/365.0); |
| 816 | } |
| 817 | } |
| 818 | |
| 819 | |
| 820 | /* |
| 821 | ** COMMAND: test-fileage |
| 822 | ** |
| 823 | ** Usage: %fossil test-fileage CHECKIN |
| 824 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -724,75 +724,58 @@ | |
| 724 | }else{ |
| 725 | zClass = mprintf("file"); |
| 726 | } |
| 727 | return zClass; |
| 728 | } |
| 729 | |
| 730 | /* |
| 731 | ** SQL used to compute the age of all files in checkin :ckin whose |
| 732 | ** names match :glob |
| 733 | */ |
| 734 | static const char zComputeFileAgeSetup[] = |
| 735 | @ CREATE TABLE IF NOT EXISTS temp.fileage( |
| 736 | @ fnid INTEGER PRIMARY KEY, |
| 737 | @ fid INTEGER, |
| 738 | @ mid INTEGER, |
| 739 | @ mtime DATETIME, |
| 740 | @ pathname TEXT |
| 741 | @ ); |
| 742 | @ CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin; |
| 743 | ; |
| 744 | |
| 745 | static const char zComputeFileAgeRun[] = |
| 746 | @ WITH RECURSIVE |
| 747 | @ ckin(x) AS (VALUES(:ckin) UNION ALL |
| 748 | @ SELECT pid FROM ckin, plink WHERE cid=x AND isprim) |
| 749 | @ INSERT OR IGNORE INTO fileage(fnid, fid, mid, mtime, pathname) |
| 750 | @ SELECT mlink.fnid, mlink.fid, x, event.mtime, filename.name |
| 751 | @ FROM ckin, mlink, event, filename |
| 752 | @ WHERE mlink.mid=ckin.x |
| 753 | @ AND mlink.fnid IN (SELECT fnid FROM foci, filename |
| 754 | @ WHERE foci.checkinID=:ckin |
| 755 | @ AND filename.name=foci.filename |
| 756 | @ AND filename.name GLOB :glob) |
| 757 | @ AND filename.fnid=mlink.fnid |
| 758 | @ AND event.objid=mlink.mid; |
| 759 | ; |
| 760 | |
| 761 | |
| 762 | /* |
| 763 | ** Look at all file containing in the version "vid". Construct a |
| 764 | ** temporary table named "fileage" that contains the file-id for each |
| 765 | ** files, the pathname, the check-in where the file was added, and the |
| 766 | ** mtime on that checkin. If zGlob and *zGlob then only files matching |
| 767 | ** the given glob are computed. |
| 768 | */ |
| 769 | int compute_fileage(int vid, const char* zGlob){ |
| 770 | Stmt q; |
| 771 | db_multi_exec(zComputeFileAgeSetup /*works-like:"constant"*/); |
| 772 | db_prepare(&q, zComputeFileAgeRun /*works-like:"constant"*/); |
| 773 | db_bind_int(&q, ":ckin", vid); |
| 774 | db_bind_text(&q, ":glob", zGlob && zGlob[0] ? zGlob : "*"); |
| 775 | db_exec(&q); |
| 776 | db_finalize(&q); |
| 777 | return 0; |
| 778 | } |
| 779 | |
| 780 | /* |
| 781 | ** Render the number of days in rAge as a more human-readable time span. |
| @@ -813,11 +796,10 @@ | |
| 796 | return mprintf("%.1f days", rAge); |
| 797 | }else{ |
| 798 | return mprintf("%.2f years", rAge/365.0); |
| 799 | } |
| 800 | } |
| 801 | |
| 802 | /* |
| 803 | ** COMMAND: test-fileage |
| 804 | ** |
| 805 | ** Usage: %fossil test-fileage CHECKIN |
| 806 |