Fossil SCM

Fix the "files_of_checkin" virtual table implementation so that it works with delta manifests. Change the implementation of compute_fileage() to use common table expressions and the files_of_checkin virtual table for a pure SQL implementation (which turns out to be faster).

drh 2014-12-15 18:24 trunk merge
Commit c556f8c61cb11f9a7dcd0488045f6fa3879e37c1
2 files changed +96 -83 +10 -6
+96 -83
--- src/browse.c
+++ src/browse.c
@@ -724,87 +724,111 @@
724724
}else{
725725
zClass = mprintf("file");
726726
}
727727
return zClass;
728728
}
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
+
729761
730762
/*
731763
** Look at all file containing in the version "vid". Construct a
732764
** temporary table named "fileage" that contains the file-id for each
733765
** files, the pathname, the check-in where the file was added, and the
734766
** mtime on that checkin. If zGlob and *zGlob then only files matching
735767
** the given glob are computed.
736768
*/
737769
int compute_fileage(int vid, const char* zGlob){
738
- Manifest *pManifest;
739
- ManifestFile *pFile;
740
- int nFile = 0;
741
- double vmtime;
742
- Stmt ins;
743
- Stmt q1, q2, q3;
744
- Stmt upd;
745
- if(zGlob && !*zGlob) zGlob = NULL;
746
- db_multi_exec(
747
- /*"DROP TABLE IF EXISTS temp.fileage;"*/
748
- "CREATE TEMP TABLE fileage("
749
- " fid INTEGER,"
750
- " mid INTEGER,"
751
- " mtime DATETIME,"
752
- " pathname TEXT"
753
- ");"
754
- "CREATE INDEX fileage_fid ON fileage(fid);"
755
- );
756
- pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0);
757
- if( pManifest==0 ) return 1;
758
- manifest_file_rewind(pManifest);
759
- db_prepare(&ins,
760
- "INSERT INTO temp.fileage(fid, pathname)"
761
- " SELECT rid, :path FROM blob WHERE uuid=:uuid"
762
- );
763
- while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
764
- if( zGlob && sqlite3_strglob(zGlob, pFile->zName)!=0 ) continue;
765
- db_bind_text(&ins, ":uuid", pFile->zUuid);
766
- db_bind_text(&ins, ":path", pFile->zName);
767
- db_step(&ins);
768
- db_reset(&ins);
769
- nFile++;
770
- }
771
- db_finalize(&ins);
772
- manifest_destroy(pManifest);
773
- db_prepare(&q1,"SELECT fid FROM mlink WHERE mid=:mid");
774
- db_prepare(&upd, "UPDATE fileage SET mid=:mid, mtime=:vmtime"
775
- " WHERE fid=:fid AND mid IS NULL");
776
- db_prepare(&q2,"SELECT pid FROM plink WHERE cid=:vid AND isprim");
777
- db_prepare(&q3,"SELECT mtime FROM event WHERE objid=:vid");
778
- while( nFile>0 && vid>0 ){
779
- db_bind_int(&q3, ":vid", vid);
780
- if( db_step(&q3)==SQLITE_ROW ){
781
- vmtime = db_column_double(&q3, 0);
782
- }else{
783
- break;
784
- }
785
- db_reset(&q3);
786
- db_bind_int(&q1, ":mid", vid);
787
- db_bind_int(&upd, ":mid", vid);
788
- db_bind_double(&upd, ":vmtime", vmtime);
789
- while( db_step(&q1)==SQLITE_ROW ){
790
- db_bind_int(&upd, ":fid", db_column_int(&q1, 0));
791
- db_step(&upd);
792
- nFile -= db_changes();
793
- db_reset(&upd);
794
- }
795
- db_reset(&q1);
796
- db_bind_int(&q2, ":vid", vid);
797
- if( db_step(&q2)!=SQLITE_ROW ) break;
798
- vid = db_column_int(&q2, 0);
799
- db_reset(&q2);
800
- }
801
- db_finalize(&q1);
802
- db_finalize(&upd);
803
- db_finalize(&q2);
804
- db_finalize(&q3);
805
- return 0;
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.
782
+** Different units (seconds, minutes, hours, days, months, years) are
783
+** selected depending on the magnitude of rAge.
784
+**
785
+** The string returned is obtained from fossil_malloc() and should be
786
+** freed by the caller.
787
+*/
788
+char *human_readable_age(double rAge){
789
+ if( rAge*86400.0<120 ){
790
+ return mprintf("%d seconds", (int)(rAge*86400.0));
791
+ }else if( rAge*1440.0<90 ){
792
+ return mprintf("%.1f minutes", rAge*1440.0);
793
+ }else if( rAge*24.0<36 ){
794
+ return mprintf("%.1f hours", rAge*24.0);
795
+ }else if( rAge<365.0 ){
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
+*/
807
+void test_fileage_cmd(void){
808
+ int mid;
809
+ Stmt q;
810
+ const char *zGlob = find_option("glob",0,1);
811
+ db_find_and_open_repository(0,0);
812
+ verify_all_options();
813
+ if( g.argc!=3 ) usage("test-fileage CHECKIN");
814
+ mid = name_to_typed_rid(g.argv[2],"ci");
815
+ compute_fileage(mid, zGlob);
816
+ db_prepare(&q,
817
+ "SELECT fid, mid, julianday('now') - mtime, pathname"
818
+ " FROM fileage"
819
+ );
820
+ while( db_step(&q)==SQLITE_ROW ){
821
+ char *zAge = human_readable_age(db_column_double(&q,2));
822
+ fossil_print("%8d %8d %16s %s\n",
823
+ db_column_int(&q,0),
824
+ db_column_int(&q,1),
825
+ zAge,
826
+ db_column_text(&q,3));
827
+ fossil_free(zAge);
828
+ }
829
+ db_finalize(&q);
806830
}
807831
808832
/*
809833
** WEBPAGE: fileage
810834
**
@@ -851,35 +875,24 @@
851875
);
852876
while( db_step(&q)==SQLITE_ROW ){
853877
double age = baseTime - db_column_double(&q, 0);
854878
int mid = db_column_int(&q, 2);
855879
const char *zFUuid = db_column_text(&q, 1);
856
- char zAge[200];
880
+ char *zAge = 0;
857881
if( lastMid!=mid ){
858882
@ <tr><td colspan=3><hr></tr>
859883
lastMid = mid;
860
- if( age*86400.0<120 ){
861
- sqlite3_snprintf(sizeof(zAge), zAge, "%d seconds", (int)(age*86400.0));
862
- }else if( age*1440.0<90 ){
863
- sqlite3_snprintf(sizeof(zAge), zAge, "%.1f minutes", age*1440.0);
864
- }else if( age*24.0<36 ){
865
- sqlite3_snprintf(sizeof(zAge), zAge, "%.1f hours", age*24.0);
866
- }else if( age<365.0 ){
867
- sqlite3_snprintf(sizeof(zAge), zAge, "%.1f days", age);
868
- }else{
869
- sqlite3_snprintf(sizeof(zAge), zAge, "%.2f years", age/365.0);
870
- }
871
- }else{
872
- zAge[0] = 0;
884
+ zAge = human_readable_age(age);
873885
}
874886
@ <tr>
875
- @ <td>%s(zAge)
887
+ @ <td>%s(zAge?zAge:"")
876888
@ <td width="25">
877889
@ <td>%z(href("%R/artifact/%s?ln", zFUuid))%h(db_column_text(&q, 3))</a>
878890
@ </tr>
879891
@
892
+ fossil_free(zAge);
880893
}
881894
@ <tr><td colspan=3><hr></tr>
882895
@ </table>
883896
db_finalize(&q);
884897
style_footer();
885898
}
886899
--- src/browse.c
+++ src/browse.c
@@ -724,87 +724,111 @@
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 Manifest *pManifest;
739 ManifestFile *pFile;
740 int nFile = 0;
741 double vmtime;
742 Stmt ins;
743 Stmt q1, q2, q3;
744 Stmt upd;
745 if(zGlob && !*zGlob) zGlob = NULL;
746 db_multi_exec(
747 /*"DROP TABLE IF EXISTS temp.fileage;"*/
748 "CREATE TEMP TABLE fileage("
749 " fid INTEGER,"
750 " mid INTEGER,"
751 " mtime DATETIME,"
752 " pathname TEXT"
753 ");"
754 "CREATE INDEX fileage_fid ON fileage(fid);"
755 );
756 pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0);
757 if( pManifest==0 ) return 1;
758 manifest_file_rewind(pManifest);
759 db_prepare(&ins,
760 "INSERT INTO temp.fileage(fid, pathname)"
761 " SELECT rid, :path FROM blob WHERE uuid=:uuid"
762 );
763 while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
764 if( zGlob && sqlite3_strglob(zGlob, pFile->zName)!=0 ) continue;
765 db_bind_text(&ins, ":uuid", pFile->zUuid);
766 db_bind_text(&ins, ":path", pFile->zName);
767 db_step(&ins);
768 db_reset(&ins);
769 nFile++;
770 }
771 db_finalize(&ins);
772 manifest_destroy(pManifest);
773 db_prepare(&q1,"SELECT fid FROM mlink WHERE mid=:mid");
774 db_prepare(&upd, "UPDATE fileage SET mid=:mid, mtime=:vmtime"
775 " WHERE fid=:fid AND mid IS NULL");
776 db_prepare(&q2,"SELECT pid FROM plink WHERE cid=:vid AND isprim");
777 db_prepare(&q3,"SELECT mtime FROM event WHERE objid=:vid");
778 while( nFile>0 && vid>0 ){
779 db_bind_int(&q3, ":vid", vid);
780 if( db_step(&q3)==SQLITE_ROW ){
781 vmtime = db_column_double(&q3, 0);
782 }else{
783 break;
784 }
785 db_reset(&q3);
786 db_bind_int(&q1, ":mid", vid);
787 db_bind_int(&upd, ":mid", vid);
788 db_bind_double(&upd, ":vmtime", vmtime);
789 while( db_step(&q1)==SQLITE_ROW ){
790 db_bind_int(&upd, ":fid", db_column_int(&q1, 0));
791 db_step(&upd);
792 nFile -= db_changes();
793 db_reset(&upd);
794 }
795 db_reset(&q1);
796 db_bind_int(&q2, ":vid", vid);
797 if( db_step(&q2)!=SQLITE_ROW ) break;
798 vid = db_column_int(&q2, 0);
799 db_reset(&q2);
800 }
801 db_finalize(&q1);
802 db_finalize(&upd);
803 db_finalize(&q2);
804 db_finalize(&q3);
805 return 0;
806 }
807
808 /*
809 ** WEBPAGE: fileage
810 **
@@ -851,35 +875,24 @@
851 );
852 while( db_step(&q)==SQLITE_ROW ){
853 double age = baseTime - db_column_double(&q, 0);
854 int mid = db_column_int(&q, 2);
855 const char *zFUuid = db_column_text(&q, 1);
856 char zAge[200];
857 if( lastMid!=mid ){
858 @ <tr><td colspan=3><hr></tr>
859 lastMid = mid;
860 if( age*86400.0<120 ){
861 sqlite3_snprintf(sizeof(zAge), zAge, "%d seconds", (int)(age*86400.0));
862 }else if( age*1440.0<90 ){
863 sqlite3_snprintf(sizeof(zAge), zAge, "%.1f minutes", age*1440.0);
864 }else if( age*24.0<36 ){
865 sqlite3_snprintf(sizeof(zAge), zAge, "%.1f hours", age*24.0);
866 }else if( age<365.0 ){
867 sqlite3_snprintf(sizeof(zAge), zAge, "%.1f days", age);
868 }else{
869 sqlite3_snprintf(sizeof(zAge), zAge, "%.2f years", age/365.0);
870 }
871 }else{
872 zAge[0] = 0;
873 }
874 @ <tr>
875 @ <td>%s(zAge)
876 @ <td width="25">
877 @ <td>%z(href("%R/artifact/%s?ln", zFUuid))%h(db_column_text(&q, 3))</a>
878 @ </tr>
879 @
 
880 }
881 @ <tr><td colspan=3><hr></tr>
882 @ </table>
883 db_finalize(&q);
884 style_footer();
885 }
886
--- src/browse.c
+++ src/browse.c
@@ -724,87 +724,111 @@
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.
782 ** Different units (seconds, minutes, hours, days, months, years) are
783 ** selected depending on the magnitude of rAge.
784 **
785 ** The string returned is obtained from fossil_malloc() and should be
786 ** freed by the caller.
787 */
788 char *human_readable_age(double rAge){
789 if( rAge*86400.0<120 ){
790 return mprintf("%d seconds", (int)(rAge*86400.0));
791 }else if( rAge*1440.0<90 ){
792 return mprintf("%.1f minutes", rAge*1440.0);
793 }else if( rAge*24.0<36 ){
794 return mprintf("%.1f hours", rAge*24.0);
795 }else if( rAge<365.0 ){
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 */
807 void test_fileage_cmd(void){
808 int mid;
809 Stmt q;
810 const char *zGlob = find_option("glob",0,1);
811 db_find_and_open_repository(0,0);
812 verify_all_options();
813 if( g.argc!=3 ) usage("test-fileage CHECKIN");
814 mid = name_to_typed_rid(g.argv[2],"ci");
815 compute_fileage(mid, zGlob);
816 db_prepare(&q,
817 "SELECT fid, mid, julianday('now') - mtime, pathname"
818 " FROM fileage"
819 );
820 while( db_step(&q)==SQLITE_ROW ){
821 char *zAge = human_readable_age(db_column_double(&q,2));
822 fossil_print("%8d %8d %16s %s\n",
823 db_column_int(&q,0),
824 db_column_int(&q,1),
825 zAge,
826 db_column_text(&q,3));
827 fossil_free(zAge);
828 }
829 db_finalize(&q);
 
 
 
 
 
 
 
 
830 }
831
832 /*
833 ** WEBPAGE: fileage
834 **
@@ -851,35 +875,24 @@
875 );
876 while( db_step(&q)==SQLITE_ROW ){
877 double age = baseTime - db_column_double(&q, 0);
878 int mid = db_column_int(&q, 2);
879 const char *zFUuid = db_column_text(&q, 1);
880 char *zAge = 0;
881 if( lastMid!=mid ){
882 @ <tr><td colspan=3><hr></tr>
883 lastMid = mid;
884 zAge = human_readable_age(age);
 
 
 
 
 
 
 
 
 
 
 
 
885 }
886 @ <tr>
887 @ <td>%s(zAge?zAge:"")
888 @ <td width="25">
889 @ <td>%z(href("%R/artifact/%s?ln", zFUuid))%h(db_column_text(&q, 3))</a>
890 @ </tr>
891 @
892 fossil_free(zAge);
893 }
894 @ <tr><td colspan=3><hr></tr>
895 @ </table>
896 db_finalize(&q);
897 style_footer();
898 }
899
+10 -6
--- src/foci.c
+++ src/foci.c
@@ -46,11 +46,12 @@
4646
sqlite3_vtab base; /* Base class - must be first */
4747
};
4848
struct FociCursor {
4949
sqlite3_vtab_cursor base; /* Base class - must be first */
5050
Manifest *pMan; /* Current manifest */
51
- int iFile; /* Index of current file */
51
+ ManifestFile *pFile; /* Current file */
52
+ int iFile; /* File index */
5253
};
5354
#endif /* INTERFACE */
5455
5556
5657
/*
@@ -127,17 +128,18 @@
127128
/*
128129
** Move a focivfs cursor to the next entry in the file.
129130
*/
130131
static int fociNext(sqlite3_vtab_cursor *pCursor){
131132
FociCursor *pCsr = (FociCursor *)pCursor;
133
+ pCsr->pFile = manifest_file_next(pCsr->pMan, 0);
132134
pCsr->iFile++;
133135
return SQLITE_OK;
134136
}
135137
136138
static int fociEof(sqlite3_vtab_cursor *pCursor){
137139
FociCursor *pCsr = (FociCursor *)pCursor;
138
- return pCsr->pMan==0 || pCsr->iFile>=pCsr->pMan->nFile;
140
+ return pCsr->pFile==0;
139141
}
140142
141143
static int fociFilter(
142144
sqlite3_vtab_cursor *pCursor,
143145
int idxNum, const char *idxStr,
@@ -146,10 +148,12 @@
146148
FociCursor *pCur = (FociCursor *)pCursor;
147149
manifest_destroy(pCur->pMan);
148150
if( idxNum ){
149151
pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0);
150152
pCur->iFile = 0;
153
+ manifest_file_rewind(pCur->pMan);
154
+ pCur->pFile = manifest_file_next(pCur->pMan, 0);
151155
}else{
152156
pCur->pMan = 0;
153157
pCur->iFile = 0;
154158
}
155159
return SQLITE_OK;
@@ -164,23 +168,23 @@
164168
switch( i ){
165169
case 0: /* checkinID */
166170
sqlite3_result_int(ctx, pCsr->pMan->rid);
167171
break;
168172
case 1: /* filename */
169
- sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zName, -1,
173
+ sqlite3_result_text(ctx, pCsr->pFile->zName, -1,
170174
SQLITE_TRANSIENT);
171175
break;
172176
case 2: /* uuid */
173
- sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zUuid, -1,
177
+ sqlite3_result_text(ctx, pCsr->pFile->zUuid, -1,
174178
SQLITE_TRANSIENT);
175179
break;
176180
case 3: /* previousName */
177
- sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPrior, -1,
181
+ sqlite3_result_text(ctx, pCsr->pFile->zPrior, -1,
178182
SQLITE_TRANSIENT);
179183
break;
180184
case 4: /* perm */
181
- sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPerm, -1,
185
+ sqlite3_result_text(ctx, pCsr->pFile->zPerm, -1,
182186
SQLITE_TRANSIENT);
183187
break;
184188
}
185189
return SQLITE_OK;
186190
}
187191
--- src/foci.c
+++ src/foci.c
@@ -46,11 +46,12 @@
46 sqlite3_vtab base; /* Base class - must be first */
47 };
48 struct FociCursor {
49 sqlite3_vtab_cursor base; /* Base class - must be first */
50 Manifest *pMan; /* Current manifest */
51 int iFile; /* Index of current file */
 
52 };
53 #endif /* INTERFACE */
54
55
56 /*
@@ -127,17 +128,18 @@
127 /*
128 ** Move a focivfs cursor to the next entry in the file.
129 */
130 static int fociNext(sqlite3_vtab_cursor *pCursor){
131 FociCursor *pCsr = (FociCursor *)pCursor;
 
132 pCsr->iFile++;
133 return SQLITE_OK;
134 }
135
136 static int fociEof(sqlite3_vtab_cursor *pCursor){
137 FociCursor *pCsr = (FociCursor *)pCursor;
138 return pCsr->pMan==0 || pCsr->iFile>=pCsr->pMan->nFile;
139 }
140
141 static int fociFilter(
142 sqlite3_vtab_cursor *pCursor,
143 int idxNum, const char *idxStr,
@@ -146,10 +148,12 @@
146 FociCursor *pCur = (FociCursor *)pCursor;
147 manifest_destroy(pCur->pMan);
148 if( idxNum ){
149 pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0);
150 pCur->iFile = 0;
 
 
151 }else{
152 pCur->pMan = 0;
153 pCur->iFile = 0;
154 }
155 return SQLITE_OK;
@@ -164,23 +168,23 @@
164 switch( i ){
165 case 0: /* checkinID */
166 sqlite3_result_int(ctx, pCsr->pMan->rid);
167 break;
168 case 1: /* filename */
169 sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zName, -1,
170 SQLITE_TRANSIENT);
171 break;
172 case 2: /* uuid */
173 sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zUuid, -1,
174 SQLITE_TRANSIENT);
175 break;
176 case 3: /* previousName */
177 sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPrior, -1,
178 SQLITE_TRANSIENT);
179 break;
180 case 4: /* perm */
181 sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPerm, -1,
182 SQLITE_TRANSIENT);
183 break;
184 }
185 return SQLITE_OK;
186 }
187
--- src/foci.c
+++ src/foci.c
@@ -46,11 +46,12 @@
46 sqlite3_vtab base; /* Base class - must be first */
47 };
48 struct FociCursor {
49 sqlite3_vtab_cursor base; /* Base class - must be first */
50 Manifest *pMan; /* Current manifest */
51 ManifestFile *pFile; /* Current file */
52 int iFile; /* File index */
53 };
54 #endif /* INTERFACE */
55
56
57 /*
@@ -127,17 +128,18 @@
128 /*
129 ** Move a focivfs cursor to the next entry in the file.
130 */
131 static int fociNext(sqlite3_vtab_cursor *pCursor){
132 FociCursor *pCsr = (FociCursor *)pCursor;
133 pCsr->pFile = manifest_file_next(pCsr->pMan, 0);
134 pCsr->iFile++;
135 return SQLITE_OK;
136 }
137
138 static int fociEof(sqlite3_vtab_cursor *pCursor){
139 FociCursor *pCsr = (FociCursor *)pCursor;
140 return pCsr->pFile==0;
141 }
142
143 static int fociFilter(
144 sqlite3_vtab_cursor *pCursor,
145 int idxNum, const char *idxStr,
@@ -146,10 +148,12 @@
148 FociCursor *pCur = (FociCursor *)pCursor;
149 manifest_destroy(pCur->pMan);
150 if( idxNum ){
151 pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0);
152 pCur->iFile = 0;
153 manifest_file_rewind(pCur->pMan);
154 pCur->pFile = manifest_file_next(pCur->pMan, 0);
155 }else{
156 pCur->pMan = 0;
157 pCur->iFile = 0;
158 }
159 return SQLITE_OK;
@@ -164,23 +168,23 @@
168 switch( i ){
169 case 0: /* checkinID */
170 sqlite3_result_int(ctx, pCsr->pMan->rid);
171 break;
172 case 1: /* filename */
173 sqlite3_result_text(ctx, pCsr->pFile->zName, -1,
174 SQLITE_TRANSIENT);
175 break;
176 case 2: /* uuid */
177 sqlite3_result_text(ctx, pCsr->pFile->zUuid, -1,
178 SQLITE_TRANSIENT);
179 break;
180 case 3: /* previousName */
181 sqlite3_result_text(ctx, pCsr->pFile->zPrior, -1,
182 SQLITE_TRANSIENT);
183 break;
184 case 4: /* perm */
185 sqlite3_result_text(ctx, pCsr->pFile->zPerm, -1,
186 SQLITE_TRANSIENT);
187 break;
188 }
189 return SQLITE_OK;
190 }
191

Keyboard Shortcuts

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