Fossil SCM

Populate the search index with check-ins, tickets, and wiki.

drh 2015-02-03 03:29 UTC indexed-fts
Commit 786a3632a8e0d10494facab0ff3812a751c2f891
1 file changed +100 -88
+100 -88
--- src/search.c
+++ src/search.c
@@ -778,10 +778,11 @@
778778
"CREATE TEMP TABLE x(label,url,score,date,snip);"
779779
);
780780
if( !search_index_exists() ){
781781
search_fullscan(zPattern, srchFlags);
782782
}else{
783
+ search_update_index();
783784
search_indexed(zPattern, srchFlags);
784785
}
785786
db_prepare(&q, "SELECT url, snip, label"
786787
" FROM x"
787788
" ORDER BY score DESC, date DESC;");
@@ -983,66 +984,21 @@
983984
break;
984985
}
985986
}
986987
}
987988
988
-/*
989
-** The arguments cType,rid,zName define an object that can be searched
990
-** for. Return a URL (relative to the root of the Fossil project) that
991
-** will jump to that document.
992
-**
993
-** Space to hold the returned string is obtained from mprintf() and should
994
-** be freed by the caller using fossil_free() or the equivalent.
995
-*/
996
-char *search_url(
997
- char cType, /* Type of document */
998
- int rid, /* BLOB.RID or TAG.TAGID for the object */
999
- const char *zName /* Name of the object */
1000
-){
1001
- char *zUrl = 0;
1002
- switch( cType ){
1003
- case 'd': { /* Documents */
1004
- zUrl = db_text(0,
1005
- "SELECT printf('/doc/%%s%%s', substr(blob.uuid,20), %Q)"
1006
- " FROM mlink, blob"
1007
- " WHERE mlink.fid=%d AND mlink.mid=blob.rid",
1008
- zName, rid);
1009
- break;
1010
- }
1011
- case 'w': { /* Wiki */
1012
- char *zId = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1013
- zUrl = mprintf("/wiki?id=%z&name=%t", zId, zName);
1014
- break;
1015
- }
1016
- case 'c': { /* Ckeck-in Comment */
1017
- char *zId = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1018
- zUrl = mprintf("/info/%z", zId);
1019
- break;
1020
- }
1021
- case 't': { /* Tickets */
1022
- char *zId = db_text(0, "SELECT tkt_uuid FROM ticket"
1023
- " WHERE tkt_id=%d", rid);
1024
- zUrl = mprintf("/tktview/%.20z", zId);
1025
- break;
1026
- }
1027
- }
1028
- return zUrl;
1029
-}
1030
-
1031989
/*
1032990
** COMMAND: test-search-stext
1033991
**
1034992
** Usage: fossil test-search-stext TYPE ARG1 ARG2
1035993
*/
1036994
void test_search_stext(void){
1037995
Blob out;
1038
- char *zUrl;
1039996
db_find_and_open_repository(0,0);
1040997
if( g.argc!=5 ) usage("TYPE RID NAME");
1041998
search_stext(g.argv[2][0], atoi(g.argv[3]), g.argv[4], &out);
1042
- zUrl = search_url(g.argv[2][0], atoi(g.argv[3]), g.argv[4]);
1043
- fossil_print("%s\n%z\n",blob_str(&out),zUrl);
999
+ fossil_print("%s\n",blob_str(&out));
10441000
blob_reset(&out);
10451001
}
10461002
10471003
/* The schema for the full-text index
10481004
*/
@@ -1058,10 +1014,11 @@
10581014
@ url TEXT, -- URL to access this document
10591015
@ mtime DATE, -- Date when document created
10601016
@ UNIQUE(type,rid)
10611017
@ );
10621018
@ CREATE INDEX "%w".ftsdocIdxed ON ftsdocs(type,rid,name) WHERE idxed==0;
1019
+@ CREATE INDEX "%w".ftsdocName ON ftsdocs(name) WHERE type='w';
10631020
@ CREATE VIEW IF NOT EXISTS "%w".ftscontent AS
10641021
@ SELECT rowid, type, rid, name, idxed, label, url, mtime,
10651022
@ stext(type,rid,name) AS 'stext'
10661023
@ FROM ftsdocs;
10671024
@ CREATE VIRTUAL TABLE IF NOT EXISTS "%w".ftsidx
@@ -1077,11 +1034,12 @@
10771034
** Create or drop the tables associated with a full-text index.
10781035
*/
10791036
void search_create_index(void){
10801037
const char *zDb = db_name("repository");
10811038
search_sql_setup(g.db);
1082
- db_multi_exec(zFtsSchema/*works-like:"%w%w%w%w"*/, zDb, zDb, zDb, zDb);
1039
+ db_multi_exec(zFtsSchema/*works-like:"%w%w%w%w%w"*/,
1040
+ zDb, zDb, zDb, zDb, zDb);
10831041
}
10841042
void search_drop_index(void){
10851043
const char *zDb = db_name("repository");
10861044
db_multi_exec(zFtsDrop/*works-like:"%w%w%w"*/, zDb, zDb, zDb);
10871045
}
@@ -1130,20 +1088,34 @@
11301088
** now while we still have access to the old content. Add the document
11311089
** to the queue of documents that need to be indexed or reindexed.
11321090
*/
11331091
void search_doc_touch(char cType, int rid, const char *zName){
11341092
if( search_index_exists() ){
1093
+ char zType[2];
1094
+ zType[0] = cType;
1095
+ zType[1] = 0;
11351096
db_multi_exec(
11361097
"DELETE FROM ftsidx WHERE docid IN"
11371098
" (SELECT rowid FROM ftsdocs WHERE type=%Q AND rid=%d AND idxed)",
1138
- cType, rid
1099
+ zType, rid
11391100
);
11401101
db_multi_exec(
11411102
"REPLACE INTO ftsdocs(type,rid,name,idxed)"
11421103
" VALUES(%Q,%d,%Q,0)",
1143
- cType, rid, zName
1104
+ zType, rid, zName
11441105
);
1106
+ if( cType=='w' ){
1107
+ db_multi_exec(
1108
+ "DELETE FROM ftsidx WHERE docid IN"
1109
+ " (SELECT rowid FROM ftsdocs WHERE type='w' AND name=%Q AND idxed)",
1110
+ zName
1111
+ );
1112
+ db_multi_exec(
1113
+ "DELETE FROM ftsdocs WHERE type='w' AND name=%Q AND rid!=%d",
1114
+ zName, rid
1115
+ );
1116
+ }
11451117
}
11461118
}
11471119
11481120
/*
11491121
** If the doc-glob and doc-br settings are valid for document search
@@ -1197,21 +1169,90 @@
11971169
);
11981170
db_multi_exec(
11991171
"UPDATE ftsdocs SET idxed=1 WHERE type='d' AND NOT idxed"
12001172
);
12011173
}
1174
+
1175
+/*
1176
+** Deal with all of the unindexed 'c' terms in FTSDOCS
1177
+*/
1178
+static void search_update_checkin_index(void){
1179
+ db_multi_exec(
1180
+ "INSERT INTO ftsidx(docid,stext)"
1181
+ " SELECT rowid, stext('c',rid,NULL) FROM ftsdocs"
1182
+ " WHERE type='c' AND NOT idxed;"
1183
+ );
1184
+ db_multi_exec(
1185
+ "REPLACE INTO ftsdocs(rowid,idxed,type,rid,name,label,url,mtime)"
1186
+ " SELECT ftsdocs.rowid, 1, 'c', ftsdocs.rid, NULL,"
1187
+ " printf('Check-in [%%.16s] on %%s',blob.uuid,datetime(event.mtime)),"
1188
+ " printf('/timeline?y=ci&n=9&c=%%.20s',blob.uuid),"
1189
+ " event.mtime"
1190
+ " FROM ftsdocs, event, blob"
1191
+ " WHERE ftsdocs.type='c' AND NOT ftsdocs.idxed"
1192
+ " AND event.objid=ftsdocs.rid"
1193
+ " AND blob.rid=ftsdocs.rid"
1194
+ );
1195
+}
1196
+
1197
+/*
1198
+** Deal with all of the unindexed 't' terms in FTSDOCS
1199
+*/
1200
+static void search_update_ticket_index(void){
1201
+ db_multi_exec(
1202
+ "INSERT INTO ftsidx(docid,stext)"
1203
+ " SELECT rowid, stext('t',rid,NULL) FROM ftsdocs"
1204
+ " WHERE type='t' AND NOT idxed;"
1205
+ );
1206
+ if( db_changes()==0 ) return;
1207
+ db_multi_exec(
1208
+ "REPLACE INTO ftsdocs(rowid,idxed,type,rid,name,label,url,mtime)"
1209
+ " SELECT ftsdocs.rowid, 1, 't', ftsdocs.rid, NULL,"
1210
+ " printf('Ticket [%%.16s] on %%s',tkt_uuid,datetime(tkt_mtime)),"
1211
+ " printf('/tktview/%%.20s',tkt_uuid),"
1212
+ " tkt_mtime"
1213
+ " FROM ftsdocs, ticket"
1214
+ " WHERE ftsdocs.type='t' AND NOT ftsdocs.idxed"
1215
+ " AND ticket.tkt_id=ftsdocs.rid"
1216
+ );
1217
+}
1218
+
1219
+/*
1220
+** Deal with all of the unindexed 'w' terms in FTSDOCS
1221
+*/
1222
+static void search_update_wiki_index(void){
1223
+ db_multi_exec(
1224
+ "INSERT INTO ftsidx(docid,stext)"
1225
+ " SELECT rowid, stext('w',rid,NULL) FROM ftsdocs"
1226
+ " WHERE type='t' AND NOT idxed;"
1227
+ );
1228
+ if( db_changes()==0 ) return;
1229
+ db_multi_exec(
1230
+ "REPLACE INTO ftsdocs(rowid,idxed,type,rid,name,label,url,mtime)"
1231
+ " SELECT ftsdocs.rowid, 1, 'w', ftsdocs.rid, ftsdocs.name,"
1232
+ " 'Wiki: '||tsdocs.name),"
1233
+ " '/wiki?name='||urlencode(ftsdocs.name),"
1234
+ " tagxref.mtime"
1235
+ " FROM ftsdocs, tagxref"
1236
+ " WHERE ftsdocs.type='t' AND NOT ftsdocs.idxed"
1237
+ " AND tagxref.rid=ftsdocs.rid"
1238
+ );
1239
+}
12021240
12031241
/*
12041242
** Deal with all of the unindexed entries in the FTSDOCS table - that
12051243
** is to say, all the entries with FTSDOCS.IDXED=0. Add them to the
12061244
** index.
12071245
*/
12081246
void search_update_index(void){
12091247
if( !search_index_exists() ) return;
1248
+ if( !db_exists("SELECT 1 FROM ftsdocs WHERE NOT idxed") ) return;
12101249
search_sql_setup(g.db);
12111250
search_update_doc_index();
1212
-
1251
+ search_update_checkin_index();
1252
+ search_update_ticket_index();
1253
+ search_update_wiki_index();
12131254
}
12141255
12151256
/*
12161257
** COMMAND: test-fts
12171258
*/
@@ -1221,13 +1262,12 @@
12211262
static const struct { int iCmd; const char *z; } aCmd[] = {
12221263
{ 1, "create" },
12231264
{ 2, "drop" },
12241265
{ 3, "exists" },
12251266
{ 4, "fill" },
1226
- { 8, "refill" },
1267
+ { 8, "refill" },
12271268
{ 5, "pending" },
1228
- { 6, "all" },
12291269
{ 7, "update" },
12301270
};
12311271
db_find_and_open_repository(0, 0);
12321272
if( g.argc<3 ) usage("SUBCMD ...");
12331273
zSubCmd = g.argv[2];
@@ -1267,46 +1307,18 @@
12671307
break;
12681308
}
12691309
case 5: { assert( fossil_strncmp(zSubCmd, "pending", n)==0 );
12701310
Stmt q;
12711311
if( !search_index_exists() ) break;
1272
- db_prepare(&q, "SELECT rowid, type, rid, quote(label), url, date(mtime)"
1273
- " FROM ftsdocs"
1274
- " WHERE NOT idxed");
1275
- while( db_step(&q)==SQLITE_ROW ){
1276
- const char *zUrl = db_column_text(&q,4);
1277
- if( zUrl && zUrl[0] ){
1278
- fossil_print("%6d: %s %6d %s %s\n %s\n",
1279
- db_column_int(&q, 0),
1280
- db_column_text(&q, 1),
1281
- db_column_int(&q, 2),
1282
- db_column_text(&q, 5),
1283
- db_column_text(&q, 3),
1284
- zUrl);
1285
- }else{
1286
- fossil_print("%6d: %s %6d %s %s\n",
1287
- db_column_int(&q, 0),
1288
- db_column_text(&q, 1),
1289
- db_column_int(&q, 2),
1290
- db_column_text(&q, 5),
1291
- db_column_text(&q, 3));
1292
- }
1293
- }
1294
- db_finalize(&q);
1295
- break;
1296
- }
1297
- case 6: { assert( fossil_strncmp(zSubCmd, "all", n)==0 );
1298
- Stmt q;
1299
- if( !search_index_exists() ) break;
1300
- db_prepare(&q, "SELECT rowid,type,rid,quote(name),idxed FROM ftsdocs");
1301
- while( db_step(&q)==SQLITE_ROW ){
1302
- fossil_print("%6d: %s %6d %s%s\n",
1303
- db_column_int(&q, 0),
1304
- db_column_text(&q, 1),
1305
- db_column_int(&q, 2),
1306
- db_column_text(&q, 3),
1307
- db_column_int(&q, 4) ? "" : " (NOT INDEXED)"
1312
+ db_prepare(&q, "SELECT rowid,type,rid,quote(name) FROM ftsdocs"
1313
+ " WHERE NOT idxed");
1314
+ while( db_step(&q)==SQLITE_ROW ){
1315
+ fossil_print("%6d: %s %6d %s\n",
1316
+ db_column_int(&q, 0),
1317
+ db_column_text(&q, 1),
1318
+ db_column_int(&q, 2),
1319
+ db_column_text(&q, 3)
13081320
);
13091321
}
13101322
db_finalize(&q);
13111323
break;
13121324
}
13131325
--- src/search.c
+++ src/search.c
@@ -778,10 +778,11 @@
778 "CREATE TEMP TABLE x(label,url,score,date,snip);"
779 );
780 if( !search_index_exists() ){
781 search_fullscan(zPattern, srchFlags);
782 }else{
 
783 search_indexed(zPattern, srchFlags);
784 }
785 db_prepare(&q, "SELECT url, snip, label"
786 " FROM x"
787 " ORDER BY score DESC, date DESC;");
@@ -983,66 +984,21 @@
983 break;
984 }
985 }
986 }
987
988 /*
989 ** The arguments cType,rid,zName define an object that can be searched
990 ** for. Return a URL (relative to the root of the Fossil project) that
991 ** will jump to that document.
992 **
993 ** Space to hold the returned string is obtained from mprintf() and should
994 ** be freed by the caller using fossil_free() or the equivalent.
995 */
996 char *search_url(
997 char cType, /* Type of document */
998 int rid, /* BLOB.RID or TAG.TAGID for the object */
999 const char *zName /* Name of the object */
1000 ){
1001 char *zUrl = 0;
1002 switch( cType ){
1003 case 'd': { /* Documents */
1004 zUrl = db_text(0,
1005 "SELECT printf('/doc/%%s%%s', substr(blob.uuid,20), %Q)"
1006 " FROM mlink, blob"
1007 " WHERE mlink.fid=%d AND mlink.mid=blob.rid",
1008 zName, rid);
1009 break;
1010 }
1011 case 'w': { /* Wiki */
1012 char *zId = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1013 zUrl = mprintf("/wiki?id=%z&name=%t", zId, zName);
1014 break;
1015 }
1016 case 'c': { /* Ckeck-in Comment */
1017 char *zId = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1018 zUrl = mprintf("/info/%z", zId);
1019 break;
1020 }
1021 case 't': { /* Tickets */
1022 char *zId = db_text(0, "SELECT tkt_uuid FROM ticket"
1023 " WHERE tkt_id=%d", rid);
1024 zUrl = mprintf("/tktview/%.20z", zId);
1025 break;
1026 }
1027 }
1028 return zUrl;
1029 }
1030
1031 /*
1032 ** COMMAND: test-search-stext
1033 **
1034 ** Usage: fossil test-search-stext TYPE ARG1 ARG2
1035 */
1036 void test_search_stext(void){
1037 Blob out;
1038 char *zUrl;
1039 db_find_and_open_repository(0,0);
1040 if( g.argc!=5 ) usage("TYPE RID NAME");
1041 search_stext(g.argv[2][0], atoi(g.argv[3]), g.argv[4], &out);
1042 zUrl = search_url(g.argv[2][0], atoi(g.argv[3]), g.argv[4]);
1043 fossil_print("%s\n%z\n",blob_str(&out),zUrl);
1044 blob_reset(&out);
1045 }
1046
1047 /* The schema for the full-text index
1048 */
@@ -1058,10 +1014,11 @@
1058 @ url TEXT, -- URL to access this document
1059 @ mtime DATE, -- Date when document created
1060 @ UNIQUE(type,rid)
1061 @ );
1062 @ CREATE INDEX "%w".ftsdocIdxed ON ftsdocs(type,rid,name) WHERE idxed==0;
 
1063 @ CREATE VIEW IF NOT EXISTS "%w".ftscontent AS
1064 @ SELECT rowid, type, rid, name, idxed, label, url, mtime,
1065 @ stext(type,rid,name) AS 'stext'
1066 @ FROM ftsdocs;
1067 @ CREATE VIRTUAL TABLE IF NOT EXISTS "%w".ftsidx
@@ -1077,11 +1034,12 @@
1077 ** Create or drop the tables associated with a full-text index.
1078 */
1079 void search_create_index(void){
1080 const char *zDb = db_name("repository");
1081 search_sql_setup(g.db);
1082 db_multi_exec(zFtsSchema/*works-like:"%w%w%w%w"*/, zDb, zDb, zDb, zDb);
 
1083 }
1084 void search_drop_index(void){
1085 const char *zDb = db_name("repository");
1086 db_multi_exec(zFtsDrop/*works-like:"%w%w%w"*/, zDb, zDb, zDb);
1087 }
@@ -1130,20 +1088,34 @@
1130 ** now while we still have access to the old content. Add the document
1131 ** to the queue of documents that need to be indexed or reindexed.
1132 */
1133 void search_doc_touch(char cType, int rid, const char *zName){
1134 if( search_index_exists() ){
 
 
 
1135 db_multi_exec(
1136 "DELETE FROM ftsidx WHERE docid IN"
1137 " (SELECT rowid FROM ftsdocs WHERE type=%Q AND rid=%d AND idxed)",
1138 cType, rid
1139 );
1140 db_multi_exec(
1141 "REPLACE INTO ftsdocs(type,rid,name,idxed)"
1142 " VALUES(%Q,%d,%Q,0)",
1143 cType, rid, zName
1144 );
 
 
 
 
 
 
 
 
 
 
 
1145 }
1146 }
1147
1148 /*
1149 ** If the doc-glob and doc-br settings are valid for document search
@@ -1197,21 +1169,90 @@
1197 );
1198 db_multi_exec(
1199 "UPDATE ftsdocs SET idxed=1 WHERE type='d' AND NOT idxed"
1200 );
1201 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1202
1203 /*
1204 ** Deal with all of the unindexed entries in the FTSDOCS table - that
1205 ** is to say, all the entries with FTSDOCS.IDXED=0. Add them to the
1206 ** index.
1207 */
1208 void search_update_index(void){
1209 if( !search_index_exists() ) return;
 
1210 search_sql_setup(g.db);
1211 search_update_doc_index();
1212
 
 
1213 }
1214
1215 /*
1216 ** COMMAND: test-fts
1217 */
@@ -1221,13 +1262,12 @@
1221 static const struct { int iCmd; const char *z; } aCmd[] = {
1222 { 1, "create" },
1223 { 2, "drop" },
1224 { 3, "exists" },
1225 { 4, "fill" },
1226 { 8, "refill" },
1227 { 5, "pending" },
1228 { 6, "all" },
1229 { 7, "update" },
1230 };
1231 db_find_and_open_repository(0, 0);
1232 if( g.argc<3 ) usage("SUBCMD ...");
1233 zSubCmd = g.argv[2];
@@ -1267,46 +1307,18 @@
1267 break;
1268 }
1269 case 5: { assert( fossil_strncmp(zSubCmd, "pending", n)==0 );
1270 Stmt q;
1271 if( !search_index_exists() ) break;
1272 db_prepare(&q, "SELECT rowid, type, rid, quote(label), url, date(mtime)"
1273 " FROM ftsdocs"
1274 " WHERE NOT idxed");
1275 while( db_step(&q)==SQLITE_ROW ){
1276 const char *zUrl = db_column_text(&q,4);
1277 if( zUrl && zUrl[0] ){
1278 fossil_print("%6d: %s %6d %s %s\n %s\n",
1279 db_column_int(&q, 0),
1280 db_column_text(&q, 1),
1281 db_column_int(&q, 2),
1282 db_column_text(&q, 5),
1283 db_column_text(&q, 3),
1284 zUrl);
1285 }else{
1286 fossil_print("%6d: %s %6d %s %s\n",
1287 db_column_int(&q, 0),
1288 db_column_text(&q, 1),
1289 db_column_int(&q, 2),
1290 db_column_text(&q, 5),
1291 db_column_text(&q, 3));
1292 }
1293 }
1294 db_finalize(&q);
1295 break;
1296 }
1297 case 6: { assert( fossil_strncmp(zSubCmd, "all", n)==0 );
1298 Stmt q;
1299 if( !search_index_exists() ) break;
1300 db_prepare(&q, "SELECT rowid,type,rid,quote(name),idxed FROM ftsdocs");
1301 while( db_step(&q)==SQLITE_ROW ){
1302 fossil_print("%6d: %s %6d %s%s\n",
1303 db_column_int(&q, 0),
1304 db_column_text(&q, 1),
1305 db_column_int(&q, 2),
1306 db_column_text(&q, 3),
1307 db_column_int(&q, 4) ? "" : " (NOT INDEXED)"
1308 );
1309 }
1310 db_finalize(&q);
1311 break;
1312 }
1313
--- src/search.c
+++ src/search.c
@@ -778,10 +778,11 @@
778 "CREATE TEMP TABLE x(label,url,score,date,snip);"
779 );
780 if( !search_index_exists() ){
781 search_fullscan(zPattern, srchFlags);
782 }else{
783 search_update_index();
784 search_indexed(zPattern, srchFlags);
785 }
786 db_prepare(&q, "SELECT url, snip, label"
787 " FROM x"
788 " ORDER BY score DESC, date DESC;");
@@ -983,66 +984,21 @@
984 break;
985 }
986 }
987 }
988
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
989 /*
990 ** COMMAND: test-search-stext
991 **
992 ** Usage: fossil test-search-stext TYPE ARG1 ARG2
993 */
994 void test_search_stext(void){
995 Blob out;
 
996 db_find_and_open_repository(0,0);
997 if( g.argc!=5 ) usage("TYPE RID NAME");
998 search_stext(g.argv[2][0], atoi(g.argv[3]), g.argv[4], &out);
999 fossil_print("%s\n",blob_str(&out));
 
1000 blob_reset(&out);
1001 }
1002
1003 /* The schema for the full-text index
1004 */
@@ -1058,10 +1014,11 @@
1014 @ url TEXT, -- URL to access this document
1015 @ mtime DATE, -- Date when document created
1016 @ UNIQUE(type,rid)
1017 @ );
1018 @ CREATE INDEX "%w".ftsdocIdxed ON ftsdocs(type,rid,name) WHERE idxed==0;
1019 @ CREATE INDEX "%w".ftsdocName ON ftsdocs(name) WHERE type='w';
1020 @ CREATE VIEW IF NOT EXISTS "%w".ftscontent AS
1021 @ SELECT rowid, type, rid, name, idxed, label, url, mtime,
1022 @ stext(type,rid,name) AS 'stext'
1023 @ FROM ftsdocs;
1024 @ CREATE VIRTUAL TABLE IF NOT EXISTS "%w".ftsidx
@@ -1077,11 +1034,12 @@
1034 ** Create or drop the tables associated with a full-text index.
1035 */
1036 void search_create_index(void){
1037 const char *zDb = db_name("repository");
1038 search_sql_setup(g.db);
1039 db_multi_exec(zFtsSchema/*works-like:"%w%w%w%w%w"*/,
1040 zDb, zDb, zDb, zDb, zDb);
1041 }
1042 void search_drop_index(void){
1043 const char *zDb = db_name("repository");
1044 db_multi_exec(zFtsDrop/*works-like:"%w%w%w"*/, zDb, zDb, zDb);
1045 }
@@ -1130,20 +1088,34 @@
1088 ** now while we still have access to the old content. Add the document
1089 ** to the queue of documents that need to be indexed or reindexed.
1090 */
1091 void search_doc_touch(char cType, int rid, const char *zName){
1092 if( search_index_exists() ){
1093 char zType[2];
1094 zType[0] = cType;
1095 zType[1] = 0;
1096 db_multi_exec(
1097 "DELETE FROM ftsidx WHERE docid IN"
1098 " (SELECT rowid FROM ftsdocs WHERE type=%Q AND rid=%d AND idxed)",
1099 zType, rid
1100 );
1101 db_multi_exec(
1102 "REPLACE INTO ftsdocs(type,rid,name,idxed)"
1103 " VALUES(%Q,%d,%Q,0)",
1104 zType, rid, zName
1105 );
1106 if( cType=='w' ){
1107 db_multi_exec(
1108 "DELETE FROM ftsidx WHERE docid IN"
1109 " (SELECT rowid FROM ftsdocs WHERE type='w' AND name=%Q AND idxed)",
1110 zName
1111 );
1112 db_multi_exec(
1113 "DELETE FROM ftsdocs WHERE type='w' AND name=%Q AND rid!=%d",
1114 zName, rid
1115 );
1116 }
1117 }
1118 }
1119
1120 /*
1121 ** If the doc-glob and doc-br settings are valid for document search
@@ -1197,21 +1169,90 @@
1169 );
1170 db_multi_exec(
1171 "UPDATE ftsdocs SET idxed=1 WHERE type='d' AND NOT idxed"
1172 );
1173 }
1174
1175 /*
1176 ** Deal with all of the unindexed 'c' terms in FTSDOCS
1177 */
1178 static void search_update_checkin_index(void){
1179 db_multi_exec(
1180 "INSERT INTO ftsidx(docid,stext)"
1181 " SELECT rowid, stext('c',rid,NULL) FROM ftsdocs"
1182 " WHERE type='c' AND NOT idxed;"
1183 );
1184 db_multi_exec(
1185 "REPLACE INTO ftsdocs(rowid,idxed,type,rid,name,label,url,mtime)"
1186 " SELECT ftsdocs.rowid, 1, 'c', ftsdocs.rid, NULL,"
1187 " printf('Check-in [%%.16s] on %%s',blob.uuid,datetime(event.mtime)),"
1188 " printf('/timeline?y=ci&n=9&c=%%.20s',blob.uuid),"
1189 " event.mtime"
1190 " FROM ftsdocs, event, blob"
1191 " WHERE ftsdocs.type='c' AND NOT ftsdocs.idxed"
1192 " AND event.objid=ftsdocs.rid"
1193 " AND blob.rid=ftsdocs.rid"
1194 );
1195 }
1196
1197 /*
1198 ** Deal with all of the unindexed 't' terms in FTSDOCS
1199 */
1200 static void search_update_ticket_index(void){
1201 db_multi_exec(
1202 "INSERT INTO ftsidx(docid,stext)"
1203 " SELECT rowid, stext('t',rid,NULL) FROM ftsdocs"
1204 " WHERE type='t' AND NOT idxed;"
1205 );
1206 if( db_changes()==0 ) return;
1207 db_multi_exec(
1208 "REPLACE INTO ftsdocs(rowid,idxed,type,rid,name,label,url,mtime)"
1209 " SELECT ftsdocs.rowid, 1, 't', ftsdocs.rid, NULL,"
1210 " printf('Ticket [%%.16s] on %%s',tkt_uuid,datetime(tkt_mtime)),"
1211 " printf('/tktview/%%.20s',tkt_uuid),"
1212 " tkt_mtime"
1213 " FROM ftsdocs, ticket"
1214 " WHERE ftsdocs.type='t' AND NOT ftsdocs.idxed"
1215 " AND ticket.tkt_id=ftsdocs.rid"
1216 );
1217 }
1218
1219 /*
1220 ** Deal with all of the unindexed 'w' terms in FTSDOCS
1221 */
1222 static void search_update_wiki_index(void){
1223 db_multi_exec(
1224 "INSERT INTO ftsidx(docid,stext)"
1225 " SELECT rowid, stext('w',rid,NULL) FROM ftsdocs"
1226 " WHERE type='t' AND NOT idxed;"
1227 );
1228 if( db_changes()==0 ) return;
1229 db_multi_exec(
1230 "REPLACE INTO ftsdocs(rowid,idxed,type,rid,name,label,url,mtime)"
1231 " SELECT ftsdocs.rowid, 1, 'w', ftsdocs.rid, ftsdocs.name,"
1232 " 'Wiki: '||tsdocs.name),"
1233 " '/wiki?name='||urlencode(ftsdocs.name),"
1234 " tagxref.mtime"
1235 " FROM ftsdocs, tagxref"
1236 " WHERE ftsdocs.type='t' AND NOT ftsdocs.idxed"
1237 " AND tagxref.rid=ftsdocs.rid"
1238 );
1239 }
1240
1241 /*
1242 ** Deal with all of the unindexed entries in the FTSDOCS table - that
1243 ** is to say, all the entries with FTSDOCS.IDXED=0. Add them to the
1244 ** index.
1245 */
1246 void search_update_index(void){
1247 if( !search_index_exists() ) return;
1248 if( !db_exists("SELECT 1 FROM ftsdocs WHERE NOT idxed") ) return;
1249 search_sql_setup(g.db);
1250 search_update_doc_index();
1251 search_update_checkin_index();
1252 search_update_ticket_index();
1253 search_update_wiki_index();
1254 }
1255
1256 /*
1257 ** COMMAND: test-fts
1258 */
@@ -1221,13 +1262,12 @@
1262 static const struct { int iCmd; const char *z; } aCmd[] = {
1263 { 1, "create" },
1264 { 2, "drop" },
1265 { 3, "exists" },
1266 { 4, "fill" },
1267 { 8, "refill" },
1268 { 5, "pending" },
 
1269 { 7, "update" },
1270 };
1271 db_find_and_open_repository(0, 0);
1272 if( g.argc<3 ) usage("SUBCMD ...");
1273 zSubCmd = g.argv[2];
@@ -1267,46 +1307,18 @@
1307 break;
1308 }
1309 case 5: { assert( fossil_strncmp(zSubCmd, "pending", n)==0 );
1310 Stmt q;
1311 if( !search_index_exists() ) break;
1312 db_prepare(&q, "SELECT rowid,type,rid,quote(name) FROM ftsdocs"
1313 " WHERE NOT idxed");
1314 while( db_step(&q)==SQLITE_ROW ){
1315 fossil_print("%6d: %s %6d %s\n",
1316 db_column_int(&q, 0),
1317 db_column_text(&q, 1),
1318 db_column_int(&q, 2),
1319 db_column_text(&q, 3)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1320 );
1321 }
1322 db_finalize(&q);
1323 break;
1324 }
1325

Keyboard Shortcuts

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