Fossil SCM

Apply the logic in/around [ec68aaf42536b4fb] to the chat search so that it does not abort, and generate an error log entry, when given characters which fts5 does not like.

stephan 2024-07-03 10:26 fts5-chat-search
Commit b698ba99427d3a530e2d5ea7a64afd84e27074c93980d75a67d8e7bb0e277250
2 files changed +3 -1 +25 -11
+3 -1
--- src/chat.c
+++ src/chat.c
@@ -784,20 +784,22 @@
784784
" xmsg, octet_length(file), fname, fmime, mdel, lmtime "
785785
" FROM chat WHERE msgid=+%Q",
786786
zQuery
787787
);
788788
}else{
789
+ char * zPat = search_simplify_pattern(zQuery);
789790
blob_append_sql(&sql,
790791
"SELECT * FROM ("
791792
"SELECT c.msgid, datetime(c.mtime), c.xfrom, "
792793
" highlight(chatfts1, 0, '<span class=\"match\">', '</span>'), "
793794
" octet_length(c.file), c.fname, c.fmime, c.mdel, c.lmtime "
794795
" FROM chatfts1(%Q) f, chat c "
795796
" WHERE f.rowid=c.msgid"
796797
" ORDER BY f.rowid DESC LIMIT %d"
797
- ") ORDER BY 1 ASC", zQuery, nLimit
798
+ ") ORDER BY 1 ASC", zPat, nLimit
798799
);
800
+ fossil_free(zPat);
799801
}
800802
}else{
801803
blob_append_sql(&sql,
802804
"SELECT msgid, datetime(mtime), xfrom, "
803805
" xmsg, octet_length(file), fname, fmime, mdel, lmtime"
804806
--- src/chat.c
+++ src/chat.c
@@ -784,20 +784,22 @@
784 " xmsg, octet_length(file), fname, fmime, mdel, lmtime "
785 " FROM chat WHERE msgid=+%Q",
786 zQuery
787 );
788 }else{
 
789 blob_append_sql(&sql,
790 "SELECT * FROM ("
791 "SELECT c.msgid, datetime(c.mtime), c.xfrom, "
792 " highlight(chatfts1, 0, '<span class=\"match\">', '</span>'), "
793 " octet_length(c.file), c.fname, c.fmime, c.mdel, c.lmtime "
794 " FROM chatfts1(%Q) f, chat c "
795 " WHERE f.rowid=c.msgid"
796 " ORDER BY f.rowid DESC LIMIT %d"
797 ") ORDER BY 1 ASC", zQuery, nLimit
798 );
 
799 }
800 }else{
801 blob_append_sql(&sql,
802 "SELECT msgid, datetime(mtime), xfrom, "
803 " xmsg, octet_length(file), fname, fmime, mdel, lmtime"
804
--- src/chat.c
+++ src/chat.c
@@ -784,20 +784,22 @@
784 " xmsg, octet_length(file), fname, fmime, mdel, lmtime "
785 " FROM chat WHERE msgid=+%Q",
786 zQuery
787 );
788 }else{
789 char * zPat = search_simplify_pattern(zQuery);
790 blob_append_sql(&sql,
791 "SELECT * FROM ("
792 "SELECT c.msgid, datetime(c.mtime), c.xfrom, "
793 " highlight(chatfts1, 0, '<span class=\"match\">', '</span>'), "
794 " octet_length(c.file), c.fname, c.fmime, c.mdel, c.lmtime "
795 " FROM chatfts1(%Q) f, chat c "
796 " WHERE f.rowid=c.msgid"
797 " ORDER BY f.rowid DESC LIMIT %d"
798 ") ORDER BY 1 ASC", zPat, nLimit
799 );
800 fossil_free(zPat);
801 }
802 }else{
803 blob_append_sql(&sql,
804 "SELECT msgid, datetime(mtime), xfrom, "
805 " xmsg, octet_length(file), fname, fmime, mdel, lmtime"
806
+25 -11
--- src/search.c
+++ src/search.c
@@ -975,10 +975,33 @@
975975
}
976976
#else
977977
sqlite3_result_double(context, r);
978978
#endif
979979
}
980
+
981
+/*
982
+** Expects a search pattern string. Makes a copy of the string,
983
+** replaces all non-alphanum ASCII characters with a space, and
984
+** lower-cases all upper-case ASCII characters. The intent is to avoid
985
+** causing errors in FTS5 searches with inputs which contain AND, OR,
986
+** and symbols like #. The caller is responsible for passing the
987
+** result to fossil_free().
988
+*/
989
+char *search_simplify_pattern(const char * zPattern){
990
+ char *zPat = mprintf("%s",zPattern);
991
+ int i;
992
+ for(i=0; zPat[i]; i++){
993
+ if( (zPat[i]&0x80)==0 && !fossil_isalnum(zPat[i]) ) zPat[i] = ' ';
994
+ if( fossil_isupper(zPat[i]) ) zPat[i] = fossil_tolower(zPat[i]);
995
+ }
996
+ for(i--; i>=0 && zPat[i]==' '; i--){}
997
+ if( i<0 ){
998
+ fossil_free(zPat);
999
+ zPat = mprintf("\"\"");
1000
+ }
1001
+ return zPat;
1002
+}
9801003
9811004
/*
9821005
** When this routine is called, there already exists a table
9831006
**
9841007
** x(label,url,score,id,snip).
@@ -997,25 +1020,16 @@
9971020
LOCAL void search_indexed(
9981021
const char *zPattern, /* The query pattern */
9991022
unsigned int srchFlags /* What to search over */
10001023
){
10011024
Blob sql;
1002
- char *zPat = mprintf("%s",zPattern);
1003
- int i;
1025
+ char *zPat;
10041026
static const char *zSnippetCall;
10051027
if( srchFlags==0 ) return;
10061028
sqlite3_create_function(g.db, "rank", 1, SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
10071029
search_rank_sqlfunc, 0, 0);
1008
- for(i=0; zPat[i]; i++){
1009
- if( (zPat[i]&0x80)==0 && !fossil_isalnum(zPat[i]) ) zPat[i] = ' ';
1010
- if( fossil_isupper(zPat[i]) ) zPat[i] = fossil_tolower(zPat[i]);
1011
- }
1012
- for(i--; i>=0 && zPat[i]==' '; i--){}
1013
- if( i<0 ){
1014
- fossil_free(zPat);
1015
- zPat = mprintf("\"\"");
1016
- }
1030
+ zPat = search_simplify_pattern(zPattern);
10171031
blob_init(&sql, 0, 0);
10181032
if( search_index_type(0)==4 ){
10191033
/* If this repo is still using the legacy FTS4 search index, then
10201034
** the snippet() function is slightly different */
10211035
zSnippetCall = "snippet(ftsidx,'<mark>','</mark>',' ... ',-1,35)";
10221036
--- src/search.c
+++ src/search.c
@@ -975,10 +975,33 @@
975 }
976 #else
977 sqlite3_result_double(context, r);
978 #endif
979 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
980
981 /*
982 ** When this routine is called, there already exists a table
983 **
984 ** x(label,url,score,id,snip).
@@ -997,25 +1020,16 @@
997 LOCAL void search_indexed(
998 const char *zPattern, /* The query pattern */
999 unsigned int srchFlags /* What to search over */
1000 ){
1001 Blob sql;
1002 char *zPat = mprintf("%s",zPattern);
1003 int i;
1004 static const char *zSnippetCall;
1005 if( srchFlags==0 ) return;
1006 sqlite3_create_function(g.db, "rank", 1, SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
1007 search_rank_sqlfunc, 0, 0);
1008 for(i=0; zPat[i]; i++){
1009 if( (zPat[i]&0x80)==0 && !fossil_isalnum(zPat[i]) ) zPat[i] = ' ';
1010 if( fossil_isupper(zPat[i]) ) zPat[i] = fossil_tolower(zPat[i]);
1011 }
1012 for(i--; i>=0 && zPat[i]==' '; i--){}
1013 if( i<0 ){
1014 fossil_free(zPat);
1015 zPat = mprintf("\"\"");
1016 }
1017 blob_init(&sql, 0, 0);
1018 if( search_index_type(0)==4 ){
1019 /* If this repo is still using the legacy FTS4 search index, then
1020 ** the snippet() function is slightly different */
1021 zSnippetCall = "snippet(ftsidx,'<mark>','</mark>',' ... ',-1,35)";
1022
--- src/search.c
+++ src/search.c
@@ -975,10 +975,33 @@
975 }
976 #else
977 sqlite3_result_double(context, r);
978 #endif
979 }
980
981 /*
982 ** Expects a search pattern string. Makes a copy of the string,
983 ** replaces all non-alphanum ASCII characters with a space, and
984 ** lower-cases all upper-case ASCII characters. The intent is to avoid
985 ** causing errors in FTS5 searches with inputs which contain AND, OR,
986 ** and symbols like #. The caller is responsible for passing the
987 ** result to fossil_free().
988 */
989 char *search_simplify_pattern(const char * zPattern){
990 char *zPat = mprintf("%s",zPattern);
991 int i;
992 for(i=0; zPat[i]; i++){
993 if( (zPat[i]&0x80)==0 && !fossil_isalnum(zPat[i]) ) zPat[i] = ' ';
994 if( fossil_isupper(zPat[i]) ) zPat[i] = fossil_tolower(zPat[i]);
995 }
996 for(i--; i>=0 && zPat[i]==' '; i--){}
997 if( i<0 ){
998 fossil_free(zPat);
999 zPat = mprintf("\"\"");
1000 }
1001 return zPat;
1002 }
1003
1004 /*
1005 ** When this routine is called, there already exists a table
1006 **
1007 ** x(label,url,score,id,snip).
@@ -997,25 +1020,16 @@
1020 LOCAL void search_indexed(
1021 const char *zPattern, /* The query pattern */
1022 unsigned int srchFlags /* What to search over */
1023 ){
1024 Blob sql;
1025 char *zPat;
 
1026 static const char *zSnippetCall;
1027 if( srchFlags==0 ) return;
1028 sqlite3_create_function(g.db, "rank", 1, SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
1029 search_rank_sqlfunc, 0, 0);
1030 zPat = search_simplify_pattern(zPattern);
 
 
 
 
 
 
 
 
1031 blob_init(&sql, 0, 0);
1032 if( search_index_type(0)==4 ){
1033 /* If this repo is still using the legacy FTS4 search index, then
1034 ** the snippet() function is slightly different */
1035 zSnippetCall = "snippet(ftsidx,'<mark>','</mark>',' ... ',-1,35)";
1036

Keyboard Shortcuts

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