Fossil SCM

Enhance the files_of_checkin virtual table so that it can work as a table valued function, allowing queries such as: "SELECT * FROM files_of_checkin('version-1.34');"

drh 2016-05-30 11:23 trunk
Commit 24cfcee7ccd17a81a088b08bcde86a61f1131fde
2 files changed +48 -19 +3 -7
+48 -19
--- src/foci.c
+++ src/foci.c
@@ -14,31 +14,37 @@
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
1717
**
1818
** This routine implements eponymous virtual table for SQLite that gives
19
-** all of the files associated with a single check-in.
19
+** all of the files associated with a single check-in. The table works
20
+** as a table-valued function.
2021
**
2122
** The source code filename "foci" is short for "Files of Check-in".
2223
**
2324
** Usage example:
2425
**
25
-** SELECT * FROM files_of_checkin
26
-** WHERE checkinID=symbolic_name_to_rid('trunk');
26
+** SELECT * FROM files_of_checkin('trunk');
2727
**
28
-** The symbolic_name_to_rid('trunk') function finds the BLOB.RID value
29
-** corresponding to the 'trunk' tag. Then the foci virtual table
30
-** decodes the manifest defined by that BLOB and returns all files described
31
-** by that manifest. The "schema" for the temp.foci table is:
28
+** The "schema" for the temp.foci table is:
3229
**
3330
** CREATE TABLE files_of_checkin(
3431
** checkinID INTEGER, -- RID for the check-in manifest
3532
** filename TEXT, -- Name of a file
3633
** uuid TEXT, -- SHA1 hash of the file
3734
** previousName TEXT, -- Name of the file in previous check-in
38
-** perm TEXT -- Permissions on the file
35
+** perm TEXT, -- Permissions on the file
36
+** symname TEXT HIDDEN -- Symbolic name of the check-in.
3937
** );
38
+**
39
+** The hidden symname column is (optionally) used as a query parameter to
40
+** identify the particular check-in to parse. The checkinID parameter
41
+** (such is a unique numeric RID rather than symbolic name) can also be used
42
+** to identify the check-in. Example:
43
+**
44
+** SELECT * FROM files_of_checkin
45
+** WHERE checkinID=symbolic_name_to_rid('trunk');
4046
**
4147
*/
4248
#include "config.h"
4349
#include "foci.h"
4450
#include <assert.h>
@@ -50,13 +56,21 @@
5056
@ CREATE TABLE files_of_checkin(
5157
@ checkinID INTEGER, -- RID for the check-in manifest
5258
@ filename TEXT, -- Name of a file
5359
@ uuid TEXT, -- SHA1 hash of the file
5460
@ previousName TEXT, -- Name of the file in previous check-in
55
-@ perm TEXT -- Permissions on the file
61
+@ perm TEXT, -- Permissions on the file
62
+@ symname TEXT HIDDEN -- Symbolic name of the check-in
5663
@ );
5764
;
65
+
66
+#define FOCI_CHECKINID 0
67
+#define FOCI_FILENAME 1
68
+#define FOCI_UUID 2
69
+#define FOCI_PREVNAME 3
70
+#define FOCI_PERM 4
71
+#define FOCI_SYMNAME 5
5872
5973
#if INTERFACE
6074
/*
6175
** The subclasses of sqlite3_vtab and sqlite3_vtab_cursor tables
6276
** that implement the files_of_checkin virtual table.
@@ -102,19 +116,26 @@
102116
103117
/*
104118
** Available scan methods:
105119
**
106120
** (0) A full scan. Visit every manifest in the repo. (Slow)
107
-** (1) checkinID=?. visit only the single manifest specifed.
121
+** (1) checkinID=?. visit only the single manifest specified.
122
+** (2) symName=? visit only the single manifest specified.
108123
*/
109124
static int fociBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
110125
int i;
111126
pIdxInfo->estimatedCost = 10000.0;
112127
for(i=0; i<pIdxInfo->nConstraint; i++){
113
- if( pIdxInfo->aConstraint[i].iColumn==0
114
- && pIdxInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ ){
115
- pIdxInfo->idxNum = 1;
128
+ if( pIdxInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ
129
+ && (pIdxInfo->aConstraint[i].iColumn==FOCI_CHECKINID
130
+ || pIdxInfo->aConstraint[i].iColumn==FOCI_SYMNAME)
131
+ ){
132
+ if( pIdxInfo->aConstraint[i].iColumn==FOCI_CHECKINID ){
133
+ pIdxInfo->idxNum = 1;
134
+ }else{
135
+ pIdxInfo->idxNum = 2;
136
+ }
116137
pIdxInfo->estimatedCost = 1.0;
117138
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
118139
pIdxInfo->aConstraintUsage[i].omit = 1;
119140
break;
120141
}
@@ -165,11 +186,17 @@
165186
int argc, sqlite3_value **argv
166187
){
167188
FociCursor *pCur = (FociCursor *)pCursor;
168189
manifest_destroy(pCur->pMan);
169190
if( idxNum ){
170
- pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0);
191
+ int rid;
192
+ if( idxNum==1 ){
193
+ rid = sqlite3_value_int(argv[0]);
194
+ }else{
195
+ rid = symbolic_name_to_rid(sqlite3_value_text(argv[0]), "ci");
196
+ }
197
+ pCur->pMan = manifest_get(rid, CFTYPE_MANIFEST, 0);
171198
if( pCur->pMan ){
172199
manifest_file_rewind(pCur->pMan);
173200
pCur->pFile = manifest_file_next(pCur->pMan, 0);
174201
}
175202
}else{
@@ -184,28 +211,30 @@
184211
sqlite3_context *ctx,
185212
int i
186213
){
187214
FociCursor *pCsr = (FociCursor *)pCursor;
188215
switch( i ){
189
- case 0: /* checkinID */
216
+ case FOCI_CHECKINID:
190217
sqlite3_result_int(ctx, pCsr->pMan->rid);
191218
break;
192
- case 1: /* filename */
219
+ case FOCI_FILENAME:
193220
sqlite3_result_text(ctx, pCsr->pFile->zName, -1,
194221
SQLITE_TRANSIENT);
195222
break;
196
- case 2: /* uuid */
223
+ case FOCI_UUID:
197224
sqlite3_result_text(ctx, pCsr->pFile->zUuid, -1,
198225
SQLITE_TRANSIENT);
199226
break;
200
- case 3: /* previousName */
227
+ case FOCI_PREVNAME:
201228
sqlite3_result_text(ctx, pCsr->pFile->zPrior, -1,
202229
SQLITE_TRANSIENT);
203230
break;
204
- case 4: /* perm */
231
+ case FOCI_PERM:
205232
sqlite3_result_text(ctx, pCsr->pFile->zPerm, -1,
206233
SQLITE_TRANSIENT);
234
+ break;
235
+ case FOCI_SYMNAME:
207236
break;
208237
}
209238
return SQLITE_OK;
210239
}
211240
212241
--- src/foci.c
+++ src/foci.c
@@ -14,31 +14,37 @@
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This routine implements eponymous virtual table for SQLite that gives
19 ** all of the files associated with a single check-in.
 
20 **
21 ** The source code filename "foci" is short for "Files of Check-in".
22 **
23 ** Usage example:
24 **
25 ** SELECT * FROM files_of_checkin
26 ** WHERE checkinID=symbolic_name_to_rid('trunk');
27 **
28 ** The symbolic_name_to_rid('trunk') function finds the BLOB.RID value
29 ** corresponding to the 'trunk' tag. Then the foci virtual table
30 ** decodes the manifest defined by that BLOB and returns all files described
31 ** by that manifest. The "schema" for the temp.foci table is:
32 **
33 ** CREATE TABLE files_of_checkin(
34 ** checkinID INTEGER, -- RID for the check-in manifest
35 ** filename TEXT, -- Name of a file
36 ** uuid TEXT, -- SHA1 hash of the file
37 ** previousName TEXT, -- Name of the file in previous check-in
38 ** perm TEXT -- Permissions on the file
 
39 ** );
 
 
 
 
 
 
 
 
40 **
41 */
42 #include "config.h"
43 #include "foci.h"
44 #include <assert.h>
@@ -50,13 +56,21 @@
50 @ CREATE TABLE files_of_checkin(
51 @ checkinID INTEGER, -- RID for the check-in manifest
52 @ filename TEXT, -- Name of a file
53 @ uuid TEXT, -- SHA1 hash of the file
54 @ previousName TEXT, -- Name of the file in previous check-in
55 @ perm TEXT -- Permissions on the file
 
56 @ );
57 ;
 
 
 
 
 
 
 
58
59 #if INTERFACE
60 /*
61 ** The subclasses of sqlite3_vtab and sqlite3_vtab_cursor tables
62 ** that implement the files_of_checkin virtual table.
@@ -102,19 +116,26 @@
102
103 /*
104 ** Available scan methods:
105 **
106 ** (0) A full scan. Visit every manifest in the repo. (Slow)
107 ** (1) checkinID=?. visit only the single manifest specifed.
 
108 */
109 static int fociBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
110 int i;
111 pIdxInfo->estimatedCost = 10000.0;
112 for(i=0; i<pIdxInfo->nConstraint; i++){
113 if( pIdxInfo->aConstraint[i].iColumn==0
114 && pIdxInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ ){
115 pIdxInfo->idxNum = 1;
 
 
 
 
 
 
116 pIdxInfo->estimatedCost = 1.0;
117 pIdxInfo->aConstraintUsage[i].argvIndex = 1;
118 pIdxInfo->aConstraintUsage[i].omit = 1;
119 break;
120 }
@@ -165,11 +186,17 @@
165 int argc, sqlite3_value **argv
166 ){
167 FociCursor *pCur = (FociCursor *)pCursor;
168 manifest_destroy(pCur->pMan);
169 if( idxNum ){
170 pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0);
 
 
 
 
 
 
171 if( pCur->pMan ){
172 manifest_file_rewind(pCur->pMan);
173 pCur->pFile = manifest_file_next(pCur->pMan, 0);
174 }
175 }else{
@@ -184,28 +211,30 @@
184 sqlite3_context *ctx,
185 int i
186 ){
187 FociCursor *pCsr = (FociCursor *)pCursor;
188 switch( i ){
189 case 0: /* checkinID */
190 sqlite3_result_int(ctx, pCsr->pMan->rid);
191 break;
192 case 1: /* filename */
193 sqlite3_result_text(ctx, pCsr->pFile->zName, -1,
194 SQLITE_TRANSIENT);
195 break;
196 case 2: /* uuid */
197 sqlite3_result_text(ctx, pCsr->pFile->zUuid, -1,
198 SQLITE_TRANSIENT);
199 break;
200 case 3: /* previousName */
201 sqlite3_result_text(ctx, pCsr->pFile->zPrior, -1,
202 SQLITE_TRANSIENT);
203 break;
204 case 4: /* perm */
205 sqlite3_result_text(ctx, pCsr->pFile->zPerm, -1,
206 SQLITE_TRANSIENT);
 
 
207 break;
208 }
209 return SQLITE_OK;
210 }
211
212
--- src/foci.c
+++ src/foci.c
@@ -14,31 +14,37 @@
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This routine implements eponymous virtual table for SQLite that gives
19 ** all of the files associated with a single check-in. The table works
20 ** as a table-valued function.
21 **
22 ** The source code filename "foci" is short for "Files of Check-in".
23 **
24 ** Usage example:
25 **
26 ** SELECT * FROM files_of_checkin('trunk');
 
27 **
28 ** The "schema" for the temp.foci table is:
 
 
 
29 **
30 ** CREATE TABLE files_of_checkin(
31 ** checkinID INTEGER, -- RID for the check-in manifest
32 ** filename TEXT, -- Name of a file
33 ** uuid TEXT, -- SHA1 hash of the file
34 ** previousName TEXT, -- Name of the file in previous check-in
35 ** perm TEXT, -- Permissions on the file
36 ** symname TEXT HIDDEN -- Symbolic name of the check-in.
37 ** );
38 **
39 ** The hidden symname column is (optionally) used as a query parameter to
40 ** identify the particular check-in to parse. The checkinID parameter
41 ** (such is a unique numeric RID rather than symbolic name) can also be used
42 ** to identify the check-in. Example:
43 **
44 ** SELECT * FROM files_of_checkin
45 ** WHERE checkinID=symbolic_name_to_rid('trunk');
46 **
47 */
48 #include "config.h"
49 #include "foci.h"
50 #include <assert.h>
@@ -50,13 +56,21 @@
56 @ CREATE TABLE files_of_checkin(
57 @ checkinID INTEGER, -- RID for the check-in manifest
58 @ filename TEXT, -- Name of a file
59 @ uuid TEXT, -- SHA1 hash of the file
60 @ previousName TEXT, -- Name of the file in previous check-in
61 @ perm TEXT, -- Permissions on the file
62 @ symname TEXT HIDDEN -- Symbolic name of the check-in
63 @ );
64 ;
65
66 #define FOCI_CHECKINID 0
67 #define FOCI_FILENAME 1
68 #define FOCI_UUID 2
69 #define FOCI_PREVNAME 3
70 #define FOCI_PERM 4
71 #define FOCI_SYMNAME 5
72
73 #if INTERFACE
74 /*
75 ** The subclasses of sqlite3_vtab and sqlite3_vtab_cursor tables
76 ** that implement the files_of_checkin virtual table.
@@ -102,19 +116,26 @@
116
117 /*
118 ** Available scan methods:
119 **
120 ** (0) A full scan. Visit every manifest in the repo. (Slow)
121 ** (1) checkinID=?. visit only the single manifest specified.
122 ** (2) symName=? visit only the single manifest specified.
123 */
124 static int fociBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
125 int i;
126 pIdxInfo->estimatedCost = 10000.0;
127 for(i=0; i<pIdxInfo->nConstraint; i++){
128 if( pIdxInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ
129 && (pIdxInfo->aConstraint[i].iColumn==FOCI_CHECKINID
130 || pIdxInfo->aConstraint[i].iColumn==FOCI_SYMNAME)
131 ){
132 if( pIdxInfo->aConstraint[i].iColumn==FOCI_CHECKINID ){
133 pIdxInfo->idxNum = 1;
134 }else{
135 pIdxInfo->idxNum = 2;
136 }
137 pIdxInfo->estimatedCost = 1.0;
138 pIdxInfo->aConstraintUsage[i].argvIndex = 1;
139 pIdxInfo->aConstraintUsage[i].omit = 1;
140 break;
141 }
@@ -165,11 +186,17 @@
186 int argc, sqlite3_value **argv
187 ){
188 FociCursor *pCur = (FociCursor *)pCursor;
189 manifest_destroy(pCur->pMan);
190 if( idxNum ){
191 int rid;
192 if( idxNum==1 ){
193 rid = sqlite3_value_int(argv[0]);
194 }else{
195 rid = symbolic_name_to_rid(sqlite3_value_text(argv[0]), "ci");
196 }
197 pCur->pMan = manifest_get(rid, CFTYPE_MANIFEST, 0);
198 if( pCur->pMan ){
199 manifest_file_rewind(pCur->pMan);
200 pCur->pFile = manifest_file_next(pCur->pMan, 0);
201 }
202 }else{
@@ -184,28 +211,30 @@
211 sqlite3_context *ctx,
212 int i
213 ){
214 FociCursor *pCsr = (FociCursor *)pCursor;
215 switch( i ){
216 case FOCI_CHECKINID:
217 sqlite3_result_int(ctx, pCsr->pMan->rid);
218 break;
219 case FOCI_FILENAME:
220 sqlite3_result_text(ctx, pCsr->pFile->zName, -1,
221 SQLITE_TRANSIENT);
222 break;
223 case FOCI_UUID:
224 sqlite3_result_text(ctx, pCsr->pFile->zUuid, -1,
225 SQLITE_TRANSIENT);
226 break;
227 case FOCI_PREVNAME:
228 sqlite3_result_text(ctx, pCsr->pFile->zPrior, -1,
229 SQLITE_TRANSIENT);
230 break;
231 case FOCI_PERM:
232 sqlite3_result_text(ctx, pCsr->pFile->zPerm, -1,
233 SQLITE_TRANSIENT);
234 break;
235 case FOCI_SYMNAME:
236 break;
237 }
238 return SQLITE_OK;
239 }
240
241
+3 -7
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -188,17 +188,13 @@
188188
** now() Return the number of seconds since 1970.
189189
**
190190
** REGEXP The REGEXP operator works, unlike in
191191
** standard SQLite.
192192
**
193
-** files_of_checkin The "files_of_checkin" virtual table is
194
-** available for decoding manifests.
195
-**
196
-** Usage example for files_of_checkin:
197
-**
198
-** CREATE VIRTUAL TABLE temp.foci USING files_of_checkin;
199
-** SELECT * FROM foci WHERE checkinID=symbolic_name_to_rid('trunk');
193
+** files_of_checkin(X) A table-valued function that returns info on
194
+** all files contained in check-in X. Example:
195
+** SELECT * FROM files_of_checkin('trunk');
200196
*/
201197
void cmd_sqlite3(void){
202198
int noRepository;
203199
extern int sqlite3_shell(int, char**);
204200
noRepository = find_option("no-repository", 0, 0)!=0;
205201
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -188,17 +188,13 @@
188 ** now() Return the number of seconds since 1970.
189 **
190 ** REGEXP The REGEXP operator works, unlike in
191 ** standard SQLite.
192 **
193 ** files_of_checkin The "files_of_checkin" virtual table is
194 ** available for decoding manifests.
195 **
196 ** Usage example for files_of_checkin:
197 **
198 ** CREATE VIRTUAL TABLE temp.foci USING files_of_checkin;
199 ** SELECT * FROM foci WHERE checkinID=symbolic_name_to_rid('trunk');
200 */
201 void cmd_sqlite3(void){
202 int noRepository;
203 extern int sqlite3_shell(int, char**);
204 noRepository = find_option("no-repository", 0, 0)!=0;
205
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -188,17 +188,13 @@
188 ** now() Return the number of seconds since 1970.
189 **
190 ** REGEXP The REGEXP operator works, unlike in
191 ** standard SQLite.
192 **
193 ** files_of_checkin(X) A table-valued function that returns info on
194 ** all files contained in check-in X. Example:
195 ** SELECT * FROM files_of_checkin('trunk');
 
 
 
 
196 */
197 void cmd_sqlite3(void){
198 int noRepository;
199 extern int sqlite3_shell(int, char**);
200 noRepository = find_option("no-repository", 0, 0)!=0;
201

Keyboard Shortcuts

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