Fossil SCM

Add the --fts option to the "fossil search" command. This option uses the same search mechanism as web search. Useful for debugging web search.

drh 2024-01-09 15:14 trunk
Commit 2ddf62a32036acc177b5c2efb8bb18e1600df21f0be4c8cff44058d9bf0e8c81
1 file changed +73 -34
+73 -34
--- src/search.c
+++ src/search.c
@@ -583,10 +583,11 @@
583583
** returned. The -width option can be used to set the output width used
584584
** when printing matches.
585585
**
586586
** Options:
587587
** -a|--all Output all matches, not just best matches
588
+** --fts Use the full-text search mechanism (testing only)
588589
** -n|--limit N Limit output to N matches
589590
** -W|--width WIDTH Set display width to WIDTH columns, 0 for
590591
** unlimited. Defaults the terminal's width.
591592
*/
592593
void search_cmd(void){
@@ -593,18 +594,17 @@
593594
Blob pattern;
594595
int i;
595596
Blob sql = empty_blob;
596597
Stmt q;
597598
int iBest;
598
- char fAll = NULL != find_option("all", "a", 0); /* If set, do not lop
599
- off the end of the
600
- results. */
599
+ char fAll = NULL != find_option("all", "a", 0);
601600
const char *zLimit = find_option("limit","n",1);
602601
const char *zWidth = find_option("width","W",1);
603
- int nLimit = zLimit ? atoi(zLimit) : -1000; /* Max number of matching
604
- lines/entries to list */
602
+ int nLimit = zLimit ? atoi(zLimit) : -1000;
605603
int width;
604
+ int bFts = find_option("fts",0,0)!=0;
605
+
606606
if( zWidth ){
607607
width = atoi(zWidth);
608608
if( (width!=0) && (width<=20) ){
609609
fossil_fatal("-W|--width value must be >20 or 0");
610610
}
@@ -616,37 +616,76 @@
616616
if( g.argc<3 ) return;
617617
blob_init(&pattern, g.argv[2], -1);
618618
for(i=3; i<g.argc; i++){
619619
blob_appendf(&pattern, " %s", g.argv[i]);
620620
}
621
- (void)search_init(blob_str(&pattern),"*","*","...",SRCHFLG_STATIC);
622
- blob_reset(&pattern);
623
- search_sql_setup(g.db);
624
-
625
- db_multi_exec(
626
- "CREATE TEMP TABLE srch(rid,uuid,date,comment,x);"
627
- "CREATE INDEX srch_idx1 ON srch(x);"
628
- "INSERT INTO srch(rid,uuid,date,comment,x)"
629
- " SELECT blob.rid, uuid, datetime(event.mtime,toLocal()),"
630
- " coalesce(ecomment,comment),"
631
- " search_score()"
632
- " FROM event, blob"
633
- " WHERE blob.rid=event.objid"
634
- " AND search_match(coalesce(ecomment,comment));"
635
- );
636
- iBest = db_int(0, "SELECT max(x) FROM srch");
637
- blob_append(&sql,
638
- "SELECT rid, uuid, date, comment, 0, 0 FROM srch "
639
- "WHERE 1 ", -1);
640
- if(!fAll){
641
- blob_append_sql(&sql,"AND x>%d ", iBest/3);
642
- }
643
- blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
644
- db_prepare(&q, "%s", blob_sql_text(&sql));
645
- blob_reset(&sql);
646
- print_timeline(&q, nLimit, width, 0, 0);
647
- db_finalize(&q);
621
+ if( bFts ){
622
+ /* Search using FTS */
623
+ Blob com;
624
+ const char *zPattern = blob_str(&pattern);
625
+ int srchFlags = SRCH_ALL;
626
+ search_sql_setup(g.db);
627
+ add_content_sql_commands(g.db);
628
+ db_multi_exec(
629
+ "CREATE TEMP TABLE x(label,url,score,id,date,snip);"
630
+ );
631
+ if( !search_index_exists() ){
632
+ search_fullscan(zPattern, srchFlags); /* Full-scan search */
633
+ }else{
634
+ search_update_index(srchFlags); /* Update the index */
635
+ search_indexed(zPattern, srchFlags); /* Indexed search */
636
+ }
637
+ db_prepare(&q, "SELECT snip, label, score, id, substr(date,1,10)"
638
+ " FROM x"
639
+ " ORDER BY score DESC, date DESC;");
640
+ blob_init(&com, 0, 0);
641
+ if( width<0 ) width = 80;
642
+ while( db_step(&q)==SQLITE_ROW ){
643
+ const char *zSnippet = db_column_text(&q, 0);
644
+ const char *zLabel = db_column_text(&q, 1);
645
+ const char *zDate = db_column_text(&q, 4);
646
+ const char *zScore = db_column_text(&q, 2);
647
+ const char *zId = db_column_text(&q, 3);
648
+ blob_appendf(&com, "%s\n%s\n%s score=%s id=%d", zLabel, zSnippet,
649
+ zDate, zScore, zId);
650
+ comment_print(blob_str(&com), 0, 5, width,
651
+ COMMENT_PRINT_TRIM_CRLF |
652
+ COMMENT_PRINT_TRIM_SPACE);
653
+ blob_reset(&com);
654
+ }
655
+ db_finalize(&q);
656
+ blob_reset(&pattern);
657
+ }else{
658
+ /* Legacy timeline search (the default) */
659
+ (void)search_init(blob_str(&pattern),"*","*","...",SRCHFLG_STATIC);
660
+ blob_reset(&pattern);
661
+ search_sql_setup(g.db);
662
+
663
+ db_multi_exec(
664
+ "CREATE TEMP TABLE srch(rid,uuid,date,comment,x);"
665
+ "CREATE INDEX srch_idx1 ON srch(x);"
666
+ "INSERT INTO srch(rid,uuid,date,comment,x)"
667
+ " SELECT blob.rid, uuid, datetime(event.mtime,toLocal()),"
668
+ " coalesce(ecomment,comment),"
669
+ " search_score()"
670
+ " FROM event, blob"
671
+ " WHERE blob.rid=event.objid"
672
+ " AND search_match(coalesce(ecomment,comment));"
673
+ );
674
+ iBest = db_int(0, "SELECT max(x) FROM srch");
675
+ blob_append(&sql,
676
+ "SELECT rid, uuid, date, comment, 0, 0 FROM srch "
677
+ "WHERE 1 ", -1);
678
+ if(!fAll){
679
+ blob_append_sql(&sql,"AND x>%d ", iBest/3);
680
+ }
681
+ blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
682
+ db_prepare(&q, "%s", blob_sql_text(&sql));
683
+ blob_reset(&sql);
684
+ print_timeline(&q, nLimit, width, 0, 0);
685
+ db_finalize(&q);
686
+ }
648687
}
649688
650689
#if INTERFACE
651690
/* What to search for */
652691
#define SRCH_CKIN 0x0001 /* Search over check-in comments */
@@ -706,11 +745,11 @@
706745
** And the srchFlags parameter has been validated. This routine
707746
** fills the X table with search results using a full-scan search.
708747
**
709748
** The companion indexed search routine is search_indexed().
710749
*/
711
-static void search_fullscan(
750
+LOCAL void search_fullscan(
712751
const char *zPattern, /* The query pattern */
713752
unsigned int srchFlags /* What to search over */
714753
){
715754
search_init(zPattern, "<mark>", "</mark>", " ... ",
716755
SRCHFLG_STATIC|SRCHFLG_HTML);
@@ -914,11 +953,11 @@
914953
** And the srchFlags parameter has been validated. This routine
915954
** fills the X table with search results using FTS indexed search.
916955
**
917956
** The companion full-scan search routine is search_fullscan().
918957
*/
919
-static void search_indexed(
958
+LOCAL void search_indexed(
920959
const char *zPattern, /* The query pattern */
921960
unsigned int srchFlags /* What to search over */
922961
){
923962
Blob sql;
924963
char *zPat = mprintf("%s",zPattern);
925964
--- src/search.c
+++ src/search.c
@@ -583,10 +583,11 @@
583 ** returned. The -width option can be used to set the output width used
584 ** when printing matches.
585 **
586 ** Options:
587 ** -a|--all Output all matches, not just best matches
 
588 ** -n|--limit N Limit output to N matches
589 ** -W|--width WIDTH Set display width to WIDTH columns, 0 for
590 ** unlimited. Defaults the terminal's width.
591 */
592 void search_cmd(void){
@@ -593,18 +594,17 @@
593 Blob pattern;
594 int i;
595 Blob sql = empty_blob;
596 Stmt q;
597 int iBest;
598 char fAll = NULL != find_option("all", "a", 0); /* If set, do not lop
599 off the end of the
600 results. */
601 const char *zLimit = find_option("limit","n",1);
602 const char *zWidth = find_option("width","W",1);
603 int nLimit = zLimit ? atoi(zLimit) : -1000; /* Max number of matching
604 lines/entries to list */
605 int width;
 
 
606 if( zWidth ){
607 width = atoi(zWidth);
608 if( (width!=0) && (width<=20) ){
609 fossil_fatal("-W|--width value must be >20 or 0");
610 }
@@ -616,37 +616,76 @@
616 if( g.argc<3 ) return;
617 blob_init(&pattern, g.argv[2], -1);
618 for(i=3; i<g.argc; i++){
619 blob_appendf(&pattern, " %s", g.argv[i]);
620 }
621 (void)search_init(blob_str(&pattern),"*","*","...",SRCHFLG_STATIC);
622 blob_reset(&pattern);
623 search_sql_setup(g.db);
624
625 db_multi_exec(
626 "CREATE TEMP TABLE srch(rid,uuid,date,comment,x);"
627 "CREATE INDEX srch_idx1 ON srch(x);"
628 "INSERT INTO srch(rid,uuid,date,comment,x)"
629 " SELECT blob.rid, uuid, datetime(event.mtime,toLocal()),"
630 " coalesce(ecomment,comment),"
631 " search_score()"
632 " FROM event, blob"
633 " WHERE blob.rid=event.objid"
634 " AND search_match(coalesce(ecomment,comment));"
635 );
636 iBest = db_int(0, "SELECT max(x) FROM srch");
637 blob_append(&sql,
638 "SELECT rid, uuid, date, comment, 0, 0 FROM srch "
639 "WHERE 1 ", -1);
640 if(!fAll){
641 blob_append_sql(&sql,"AND x>%d ", iBest/3);
642 }
643 blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
644 db_prepare(&q, "%s", blob_sql_text(&sql));
645 blob_reset(&sql);
646 print_timeline(&q, nLimit, width, 0, 0);
647 db_finalize(&q);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
648 }
649
650 #if INTERFACE
651 /* What to search for */
652 #define SRCH_CKIN 0x0001 /* Search over check-in comments */
@@ -706,11 +745,11 @@
706 ** And the srchFlags parameter has been validated. This routine
707 ** fills the X table with search results using a full-scan search.
708 **
709 ** The companion indexed search routine is search_indexed().
710 */
711 static void search_fullscan(
712 const char *zPattern, /* The query pattern */
713 unsigned int srchFlags /* What to search over */
714 ){
715 search_init(zPattern, "<mark>", "</mark>", " ... ",
716 SRCHFLG_STATIC|SRCHFLG_HTML);
@@ -914,11 +953,11 @@
914 ** And the srchFlags parameter has been validated. This routine
915 ** fills the X table with search results using FTS indexed search.
916 **
917 ** The companion full-scan search routine is search_fullscan().
918 */
919 static void search_indexed(
920 const char *zPattern, /* The query pattern */
921 unsigned int srchFlags /* What to search over */
922 ){
923 Blob sql;
924 char *zPat = mprintf("%s",zPattern);
925
--- src/search.c
+++ src/search.c
@@ -583,10 +583,11 @@
583 ** returned. The -width option can be used to set the output width used
584 ** when printing matches.
585 **
586 ** Options:
587 ** -a|--all Output all matches, not just best matches
588 ** --fts Use the full-text search mechanism (testing only)
589 ** -n|--limit N Limit output to N matches
590 ** -W|--width WIDTH Set display width to WIDTH columns, 0 for
591 ** unlimited. Defaults the terminal's width.
592 */
593 void search_cmd(void){
@@ -593,18 +594,17 @@
594 Blob pattern;
595 int i;
596 Blob sql = empty_blob;
597 Stmt q;
598 int iBest;
599 char fAll = NULL != find_option("all", "a", 0);
 
 
600 const char *zLimit = find_option("limit","n",1);
601 const char *zWidth = find_option("width","W",1);
602 int nLimit = zLimit ? atoi(zLimit) : -1000;
 
603 int width;
604 int bFts = find_option("fts",0,0)!=0;
605
606 if( zWidth ){
607 width = atoi(zWidth);
608 if( (width!=0) && (width<=20) ){
609 fossil_fatal("-W|--width value must be >20 or 0");
610 }
@@ -616,37 +616,76 @@
616 if( g.argc<3 ) return;
617 blob_init(&pattern, g.argv[2], -1);
618 for(i=3; i<g.argc; i++){
619 blob_appendf(&pattern, " %s", g.argv[i]);
620 }
621 if( bFts ){
622 /* Search using FTS */
623 Blob com;
624 const char *zPattern = blob_str(&pattern);
625 int srchFlags = SRCH_ALL;
626 search_sql_setup(g.db);
627 add_content_sql_commands(g.db);
628 db_multi_exec(
629 "CREATE TEMP TABLE x(label,url,score,id,date,snip);"
630 );
631 if( !search_index_exists() ){
632 search_fullscan(zPattern, srchFlags); /* Full-scan search */
633 }else{
634 search_update_index(srchFlags); /* Update the index */
635 search_indexed(zPattern, srchFlags); /* Indexed search */
636 }
637 db_prepare(&q, "SELECT snip, label, score, id, substr(date,1,10)"
638 " FROM x"
639 " ORDER BY score DESC, date DESC;");
640 blob_init(&com, 0, 0);
641 if( width<0 ) width = 80;
642 while( db_step(&q)==SQLITE_ROW ){
643 const char *zSnippet = db_column_text(&q, 0);
644 const char *zLabel = db_column_text(&q, 1);
645 const char *zDate = db_column_text(&q, 4);
646 const char *zScore = db_column_text(&q, 2);
647 const char *zId = db_column_text(&q, 3);
648 blob_appendf(&com, "%s\n%s\n%s score=%s id=%d", zLabel, zSnippet,
649 zDate, zScore, zId);
650 comment_print(blob_str(&com), 0, 5, width,
651 COMMENT_PRINT_TRIM_CRLF |
652 COMMENT_PRINT_TRIM_SPACE);
653 blob_reset(&com);
654 }
655 db_finalize(&q);
656 blob_reset(&pattern);
657 }else{
658 /* Legacy timeline search (the default) */
659 (void)search_init(blob_str(&pattern),"*","*","...",SRCHFLG_STATIC);
660 blob_reset(&pattern);
661 search_sql_setup(g.db);
662
663 db_multi_exec(
664 "CREATE TEMP TABLE srch(rid,uuid,date,comment,x);"
665 "CREATE INDEX srch_idx1 ON srch(x);"
666 "INSERT INTO srch(rid,uuid,date,comment,x)"
667 " SELECT blob.rid, uuid, datetime(event.mtime,toLocal()),"
668 " coalesce(ecomment,comment),"
669 " search_score()"
670 " FROM event, blob"
671 " WHERE blob.rid=event.objid"
672 " AND search_match(coalesce(ecomment,comment));"
673 );
674 iBest = db_int(0, "SELECT max(x) FROM srch");
675 blob_append(&sql,
676 "SELECT rid, uuid, date, comment, 0, 0 FROM srch "
677 "WHERE 1 ", -1);
678 if(!fAll){
679 blob_append_sql(&sql,"AND x>%d ", iBest/3);
680 }
681 blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
682 db_prepare(&q, "%s", blob_sql_text(&sql));
683 blob_reset(&sql);
684 print_timeline(&q, nLimit, width, 0, 0);
685 db_finalize(&q);
686 }
687 }
688
689 #if INTERFACE
690 /* What to search for */
691 #define SRCH_CKIN 0x0001 /* Search over check-in comments */
@@ -706,11 +745,11 @@
745 ** And the srchFlags parameter has been validated. This routine
746 ** fills the X table with search results using a full-scan search.
747 **
748 ** The companion indexed search routine is search_indexed().
749 */
750 LOCAL void search_fullscan(
751 const char *zPattern, /* The query pattern */
752 unsigned int srchFlags /* What to search over */
753 ){
754 search_init(zPattern, "<mark>", "</mark>", " ... ",
755 SRCHFLG_STATIC|SRCHFLG_HTML);
@@ -914,11 +953,11 @@
953 ** And the srchFlags parameter has been validated. This routine
954 ** fills the X table with search results using FTS indexed search.
955 **
956 ** The companion full-scan search routine is search_fullscan().
957 */
958 LOCAL void search_indexed(
959 const char *zPattern, /* The query pattern */
960 unsigned int srchFlags /* What to search over */
961 ){
962 Blob sql;
963 char *zPat = mprintf("%s",zPattern);
964

Keyboard Shortcuts

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