Fossil SCM
Add support for searching tickets. This is still a full-scan search.
Commit
e2230a446b24144d37606b30d367201415b9606c
Parent
ca833ff86f0a6a7…
1 file changed
+63
-1
+63
-1
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -640,10 +640,21 @@ | ||
| 640 | 640 | " printf('%R/timeline?c=%%s&n=8&y=ci',uuid)," |
| 641 | 641 | " datetime(mtime)," |
| 642 | 642 | " snippet(stext('c',rid,NULL))" |
| 643 | 643 | " FROM ckin;" |
| 644 | 644 | ); |
| 645 | + } | |
| 646 | + if( okTicket ){ | |
| 647 | + db_multi_exec( | |
| 648 | + "INSERT INTO x(label,url,date,snip)" | |
| 649 | + " SELECT printf('Ticket [%%.17s] on %%s'," | |
| 650 | + "tkt_uuid,datetime(tkt_mtime))," | |
| 651 | + " printf('%R/tktview/%%.20s',tkt_uuid)," | |
| 652 | + " datetime(tkt_mtime)," | |
| 653 | + " snippet(stext('t',tkt_id,NULL))" | |
| 654 | + " FROM ticket;" | |
| 655 | + ); | |
| 645 | 656 | } |
| 646 | 657 | db_prepare(&q, "SELECT url, substr(snip,9), label" |
| 647 | 658 | " FROM x WHERE snip IS NOT NULL" |
| 648 | 659 | " ORDER BY substr(snip,1,8) DESC, date DESC;"); |
| 649 | 660 | @ <ol> |
| @@ -686,10 +697,31 @@ | ||
| 686 | 697 | blob_init(pIn, 0, 0); |
| 687 | 698 | } |
| 688 | 699 | blob_reset(&html); |
| 689 | 700 | blob_reset(&title); |
| 690 | 701 | } |
| 702 | + | |
| 703 | +/* | |
| 704 | +** Query pQuery is pointing at a single row of output. Append a text | |
| 705 | +** representation of every text-compatible column to pAccum. | |
| 706 | +*/ | |
| 707 | +static void append_all_ticket_fields(Blob *pAccum, Stmt *pQuery){ | |
| 708 | + int n = db_column_count(pQuery); | |
| 709 | + int i; | |
| 710 | + for(i=0; i<n; i++){ | |
| 711 | + const char *zColName = db_column_name(pQuery,i); | |
| 712 | + if( fossil_strnicmp(zColName,"tkt_",4)==0 ) continue; | |
| 713 | + if( fossil_stricmp(zColName,"mimetype")==0 ) continue; | |
| 714 | + switch( db_column_type(pQuery,i) ){ | |
| 715 | + case SQLITE_INTEGER: | |
| 716 | + case SQLITE_FLOAT: | |
| 717 | + case SQLITE_TEXT: | |
| 718 | + blob_appendf(pAccum, "%s: %s |\n", zColName, db_column_text(pQuery,i)); | |
| 719 | + } | |
| 720 | + } | |
| 721 | +} | |
| 722 | + | |
| 691 | 723 | |
| 692 | 724 | /* |
| 693 | 725 | ** Return "search text" - a reduced version of a document appropriate for |
| 694 | 726 | ** full text search and/or for constructing a search result snippet. |
| 695 | 727 | ** |
| @@ -728,11 +760,11 @@ | ||
| 728 | 760 | pOut); |
| 729 | 761 | blob_reset(&wiki); |
| 730 | 762 | manifest_destroy(pWiki); |
| 731 | 763 | break; |
| 732 | 764 | } |
| 733 | - case 'c': { /* Ckeck-in Comments */ | |
| 765 | + case 'c': { /* Check-in Comments */ | |
| 734 | 766 | static Stmt q; |
| 735 | 767 | db_static_prepare(&q, |
| 736 | 768 | "SELECT coalesce(ecomment,comment)" |
| 737 | 769 | " ||' (user: '||coalesce(euser,user,'?')" |
| 738 | 770 | " ||', tags: '||" |
| @@ -747,10 +779,34 @@ | ||
| 747 | 779 | db_column_blob(&q, 0, pOut); |
| 748 | 780 | blob_append(pOut, "\n", 1); |
| 749 | 781 | } |
| 750 | 782 | db_reset(&q); |
| 751 | 783 | break; |
| 784 | + } | |
| 785 | + case 't': { /* Tickets */ | |
| 786 | + static Stmt q1; | |
| 787 | + Blob raw; | |
| 788 | + db_static_prepare(&q1, "SELECT * FROM ticket WHERE tkt_id=:rid"); | |
| 789 | + blob_init(&raw,0,0); | |
| 790 | + db_bind_int(&q1, ":rid", rid); | |
| 791 | + if( db_step(&q1)==SQLITE_ROW ){ | |
| 792 | + append_all_ticket_fields(&raw, &q1); | |
| 793 | + } | |
| 794 | + db_reset(&q1); | |
| 795 | + if( db_table_exists("repository","ticketchng") ){ | |
| 796 | + static Stmt q2; | |
| 797 | + db_static_prepare(&q2, "SELECT * FROM ticketchng WHERE tkt_id=:rid" | |
| 798 | + " ORDER BY tkt_mtime"); | |
| 799 | + db_bind_int(&q2, ":rid", rid); | |
| 800 | + while( db_step(&q2)==SQLITE_ROW ){ | |
| 801 | + append_all_ticket_fields(&raw, &q2); | |
| 802 | + } | |
| 803 | + db_reset(&q2); | |
| 804 | + } | |
| 805 | + html_to_plaintext(blob_str(&raw), pOut); | |
| 806 | + blob_reset(&raw); | |
| 807 | + break; | |
| 752 | 808 | } |
| 753 | 809 | } |
| 754 | 810 | } |
| 755 | 811 | |
| 756 | 812 | /* |
| @@ -783,10 +839,16 @@ | ||
| 783 | 839 | } |
| 784 | 840 | case 'c': { /* Ckeck-in Comment */ |
| 785 | 841 | char *zId = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 786 | 842 | zUrl = mprintf("/info/%z", zId); |
| 787 | 843 | break; |
| 844 | + } | |
| 845 | + case 't': { /* Tickets */ | |
| 846 | + char *zId = db_text(0, "SELECT tkt_uuid FROM ticket" | |
| 847 | + " WHERE tkt_id=%d", rid); | |
| 848 | + zUrl = mprintf("/tktview/%.20z", zId); | |
| 849 | + break; | |
| 788 | 850 | } |
| 789 | 851 | } |
| 790 | 852 | return zUrl; |
| 791 | 853 | } |
| 792 | 854 | |
| 793 | 855 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -640,10 +640,21 @@ | |
| 640 | " printf('%R/timeline?c=%%s&n=8&y=ci',uuid)," |
| 641 | " datetime(mtime)," |
| 642 | " snippet(stext('c',rid,NULL))" |
| 643 | " FROM ckin;" |
| 644 | ); |
| 645 | } |
| 646 | db_prepare(&q, "SELECT url, substr(snip,9), label" |
| 647 | " FROM x WHERE snip IS NOT NULL" |
| 648 | " ORDER BY substr(snip,1,8) DESC, date DESC;"); |
| 649 | @ <ol> |
| @@ -686,10 +697,31 @@ | |
| 686 | blob_init(pIn, 0, 0); |
| 687 | } |
| 688 | blob_reset(&html); |
| 689 | blob_reset(&title); |
| 690 | } |
| 691 | |
| 692 | /* |
| 693 | ** Return "search text" - a reduced version of a document appropriate for |
| 694 | ** full text search and/or for constructing a search result snippet. |
| 695 | ** |
| @@ -728,11 +760,11 @@ | |
| 728 | pOut); |
| 729 | blob_reset(&wiki); |
| 730 | manifest_destroy(pWiki); |
| 731 | break; |
| 732 | } |
| 733 | case 'c': { /* Ckeck-in Comments */ |
| 734 | static Stmt q; |
| 735 | db_static_prepare(&q, |
| 736 | "SELECT coalesce(ecomment,comment)" |
| 737 | " ||' (user: '||coalesce(euser,user,'?')" |
| 738 | " ||', tags: '||" |
| @@ -747,10 +779,34 @@ | |
| 747 | db_column_blob(&q, 0, pOut); |
| 748 | blob_append(pOut, "\n", 1); |
| 749 | } |
| 750 | db_reset(&q); |
| 751 | break; |
| 752 | } |
| 753 | } |
| 754 | } |
| 755 | |
| 756 | /* |
| @@ -783,10 +839,16 @@ | |
| 783 | } |
| 784 | case 'c': { /* Ckeck-in Comment */ |
| 785 | char *zId = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 786 | zUrl = mprintf("/info/%z", zId); |
| 787 | break; |
| 788 | } |
| 789 | } |
| 790 | return zUrl; |
| 791 | } |
| 792 | |
| 793 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -640,10 +640,21 @@ | |
| 640 | " printf('%R/timeline?c=%%s&n=8&y=ci',uuid)," |
| 641 | " datetime(mtime)," |
| 642 | " snippet(stext('c',rid,NULL))" |
| 643 | " FROM ckin;" |
| 644 | ); |
| 645 | } |
| 646 | if( okTicket ){ |
| 647 | db_multi_exec( |
| 648 | "INSERT INTO x(label,url,date,snip)" |
| 649 | " SELECT printf('Ticket [%%.17s] on %%s'," |
| 650 | "tkt_uuid,datetime(tkt_mtime))," |
| 651 | " printf('%R/tktview/%%.20s',tkt_uuid)," |
| 652 | " datetime(tkt_mtime)," |
| 653 | " snippet(stext('t',tkt_id,NULL))" |
| 654 | " FROM ticket;" |
| 655 | ); |
| 656 | } |
| 657 | db_prepare(&q, "SELECT url, substr(snip,9), label" |
| 658 | " FROM x WHERE snip IS NOT NULL" |
| 659 | " ORDER BY substr(snip,1,8) DESC, date DESC;"); |
| 660 | @ <ol> |
| @@ -686,10 +697,31 @@ | |
| 697 | blob_init(pIn, 0, 0); |
| 698 | } |
| 699 | blob_reset(&html); |
| 700 | blob_reset(&title); |
| 701 | } |
| 702 | |
| 703 | /* |
| 704 | ** Query pQuery is pointing at a single row of output. Append a text |
| 705 | ** representation of every text-compatible column to pAccum. |
| 706 | */ |
| 707 | static void append_all_ticket_fields(Blob *pAccum, Stmt *pQuery){ |
| 708 | int n = db_column_count(pQuery); |
| 709 | int i; |
| 710 | for(i=0; i<n; i++){ |
| 711 | const char *zColName = db_column_name(pQuery,i); |
| 712 | if( fossil_strnicmp(zColName,"tkt_",4)==0 ) continue; |
| 713 | if( fossil_stricmp(zColName,"mimetype")==0 ) continue; |
| 714 | switch( db_column_type(pQuery,i) ){ |
| 715 | case SQLITE_INTEGER: |
| 716 | case SQLITE_FLOAT: |
| 717 | case SQLITE_TEXT: |
| 718 | blob_appendf(pAccum, "%s: %s |\n", zColName, db_column_text(pQuery,i)); |
| 719 | } |
| 720 | } |
| 721 | } |
| 722 | |
| 723 | |
| 724 | /* |
| 725 | ** Return "search text" - a reduced version of a document appropriate for |
| 726 | ** full text search and/or for constructing a search result snippet. |
| 727 | ** |
| @@ -728,11 +760,11 @@ | |
| 760 | pOut); |
| 761 | blob_reset(&wiki); |
| 762 | manifest_destroy(pWiki); |
| 763 | break; |
| 764 | } |
| 765 | case 'c': { /* Check-in Comments */ |
| 766 | static Stmt q; |
| 767 | db_static_prepare(&q, |
| 768 | "SELECT coalesce(ecomment,comment)" |
| 769 | " ||' (user: '||coalesce(euser,user,'?')" |
| 770 | " ||', tags: '||" |
| @@ -747,10 +779,34 @@ | |
| 779 | db_column_blob(&q, 0, pOut); |
| 780 | blob_append(pOut, "\n", 1); |
| 781 | } |
| 782 | db_reset(&q); |
| 783 | break; |
| 784 | } |
| 785 | case 't': { /* Tickets */ |
| 786 | static Stmt q1; |
| 787 | Blob raw; |
| 788 | db_static_prepare(&q1, "SELECT * FROM ticket WHERE tkt_id=:rid"); |
| 789 | blob_init(&raw,0,0); |
| 790 | db_bind_int(&q1, ":rid", rid); |
| 791 | if( db_step(&q1)==SQLITE_ROW ){ |
| 792 | append_all_ticket_fields(&raw, &q1); |
| 793 | } |
| 794 | db_reset(&q1); |
| 795 | if( db_table_exists("repository","ticketchng") ){ |
| 796 | static Stmt q2; |
| 797 | db_static_prepare(&q2, "SELECT * FROM ticketchng WHERE tkt_id=:rid" |
| 798 | " ORDER BY tkt_mtime"); |
| 799 | db_bind_int(&q2, ":rid", rid); |
| 800 | while( db_step(&q2)==SQLITE_ROW ){ |
| 801 | append_all_ticket_fields(&raw, &q2); |
| 802 | } |
| 803 | db_reset(&q2); |
| 804 | } |
| 805 | html_to_plaintext(blob_str(&raw), pOut); |
| 806 | blob_reset(&raw); |
| 807 | break; |
| 808 | } |
| 809 | } |
| 810 | } |
| 811 | |
| 812 | /* |
| @@ -783,10 +839,16 @@ | |
| 839 | } |
| 840 | case 'c': { /* Ckeck-in Comment */ |
| 841 | char *zId = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 842 | zUrl = mprintf("/info/%z", zId); |
| 843 | break; |
| 844 | } |
| 845 | case 't': { /* Tickets */ |
| 846 | char *zId = db_text(0, "SELECT tkt_uuid FROM ticket" |
| 847 | " WHERE tkt_id=%d", rid); |
| 848 | zUrl = mprintf("/tktview/%.20z", zId); |
| 849 | break; |
| 850 | } |
| 851 | } |
| 852 | return zUrl; |
| 853 | } |
| 854 | |
| 855 |