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.
Commit
2ddf62a32036acc177b5c2efb8bb18e1600df21f0be4c8cff44058d9bf0e8c81
Parent
537d9e00cfc20a3…
1 file changed
+73
-34
+73
-34
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -583,10 +583,11 @@ | ||
| 583 | 583 | ** returned. The -width option can be used to set the output width used |
| 584 | 584 | ** when printing matches. |
| 585 | 585 | ** |
| 586 | 586 | ** Options: |
| 587 | 587 | ** -a|--all Output all matches, not just best matches |
| 588 | +** --fts Use the full-text search mechanism (testing only) | |
| 588 | 589 | ** -n|--limit N Limit output to N matches |
| 589 | 590 | ** -W|--width WIDTH Set display width to WIDTH columns, 0 for |
| 590 | 591 | ** unlimited. Defaults the terminal's width. |
| 591 | 592 | */ |
| 592 | 593 | void search_cmd(void){ |
| @@ -593,18 +594,17 @@ | ||
| 593 | 594 | Blob pattern; |
| 594 | 595 | int i; |
| 595 | 596 | Blob sql = empty_blob; |
| 596 | 597 | Stmt q; |
| 597 | 598 | 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); | |
| 601 | 600 | const char *zLimit = find_option("limit","n",1); |
| 602 | 601 | 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; | |
| 605 | 603 | int width; |
| 604 | + int bFts = find_option("fts",0,0)!=0; | |
| 605 | + | |
| 606 | 606 | if( zWidth ){ |
| 607 | 607 | width = atoi(zWidth); |
| 608 | 608 | if( (width!=0) && (width<=20) ){ |
| 609 | 609 | fossil_fatal("-W|--width value must be >20 or 0"); |
| 610 | 610 | } |
| @@ -616,37 +616,76 @@ | ||
| 616 | 616 | if( g.argc<3 ) return; |
| 617 | 617 | blob_init(&pattern, g.argv[2], -1); |
| 618 | 618 | for(i=3; i<g.argc; i++){ |
| 619 | 619 | blob_appendf(&pattern, " %s", g.argv[i]); |
| 620 | 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); | |
| 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 | + } | |
| 648 | 687 | } |
| 649 | 688 | |
| 650 | 689 | #if INTERFACE |
| 651 | 690 | /* What to search for */ |
| 652 | 691 | #define SRCH_CKIN 0x0001 /* Search over check-in comments */ |
| @@ -706,11 +745,11 @@ | ||
| 706 | 745 | ** And the srchFlags parameter has been validated. This routine |
| 707 | 746 | ** fills the X table with search results using a full-scan search. |
| 708 | 747 | ** |
| 709 | 748 | ** The companion indexed search routine is search_indexed(). |
| 710 | 749 | */ |
| 711 | -static void search_fullscan( | |
| 750 | +LOCAL void search_fullscan( | |
| 712 | 751 | const char *zPattern, /* The query pattern */ |
| 713 | 752 | unsigned int srchFlags /* What to search over */ |
| 714 | 753 | ){ |
| 715 | 754 | search_init(zPattern, "<mark>", "</mark>", " ... ", |
| 716 | 755 | SRCHFLG_STATIC|SRCHFLG_HTML); |
| @@ -914,11 +953,11 @@ | ||
| 914 | 953 | ** And the srchFlags parameter has been validated. This routine |
| 915 | 954 | ** fills the X table with search results using FTS indexed search. |
| 916 | 955 | ** |
| 917 | 956 | ** The companion full-scan search routine is search_fullscan(). |
| 918 | 957 | */ |
| 919 | -static void search_indexed( | |
| 958 | +LOCAL void search_indexed( | |
| 920 | 959 | const char *zPattern, /* The query pattern */ |
| 921 | 960 | unsigned int srchFlags /* What to search over */ |
| 922 | 961 | ){ |
| 923 | 962 | Blob sql; |
| 924 | 963 | char *zPat = mprintf("%s",zPattern); |
| 925 | 964 |
| --- 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 |