diff --git a/kernel/sql/span.go b/kernel/sql/span.go index 9b785743a..267abacf6 100644 --- a/kernel/sql/span.go +++ b/kernel/sql/span.go @@ -25,6 +25,18 @@ import ( "github.com/siyuan-note/logging" ) +func escapeLikePattern(s string) string { + var b strings.Builder + b.Grow(len(s)) + for _, r := range s { + if r == '%' || r == '_' || r == '\\' { + b.WriteRune('\\') + } + b.WriteRune(r) + } + return b.String() +} + type Span struct { ID string BlockID string @@ -82,12 +94,14 @@ func SelectSpansRawStmt(stmt string, limit int) (ret []*Span) { func QueryTagSpansByLabel(label string) (ret []*Span) { var stmt string + var args []any if "" != label { - stmt = "SELECT * FROM spans WHERE type LIKE '%tag%' AND content LIKE '%" + label + "%' GROUP BY block_id" + stmt = "SELECT * FROM spans WHERE type LIKE '%tag%' AND content LIKE ? ESCAPE '\\' GROUP BY block_id" + args = append(args, "%"+escapeLikePattern(label)+"%") } else { stmt = "SELECT * FROM spans WHERE type LIKE '%tag%' AND content = '' GROUP BY block_id" } - rows, err := query(stmt) + rows, err := query(stmt, args...) if err != nil { logging.LogErrorf("sql query failed: %s", err) return @@ -104,19 +118,18 @@ func QueryTagSpansByKeyword(keyword string, limit int) (ret []*Span) { // 标签搜索支持空格分隔关键字 Tag search supports space-separated keywords https://github.com/siyuan-note/siyuan/issues/14580 keywords := strings.Fields(keyword) var stmt string + var args []any if len(keywords) == 0 { stmt = "SELECT * FROM spans WHERE type LIKE '%tag%' AND content != '' GROUP BY markdown LIMIT " + strconv.Itoa(limit) } else { - contentLikes := "" + var likes []string for _, k := range keywords { - if contentLikes != "" { - contentLikes += " AND " - } - contentLikes += "content LIKE '%" + k + "%'" + likes = append(likes, "content LIKE ? ESCAPE '\\'") + args = append(args, "%"+escapeLikePattern(k)+"%") } - stmt = "SELECT * FROM spans WHERE type LIKE '%tag%' AND (" + contentLikes + ") GROUP BY markdown LIMIT " + strconv.Itoa(limit) + stmt = "SELECT * FROM spans WHERE type LIKE '%tag%' AND (" + strings.Join(likes, " AND ") + ") GROUP BY markdown LIMIT " + strconv.Itoa(limit) } - rows, err := query(stmt) + rows, err := query(stmt, args...) if err != nil { logging.LogErrorf("sql query failed: %s", err) return @@ -131,10 +144,12 @@ func QueryTagSpansByKeyword(keyword string, limit int) (ret []*Span) { func QueryTagSpans(p string) (ret []*Span) { stmt := "SELECT * FROM spans WHERE type LIKE '%tag%'" + var args []any if "" != p { - stmt += " AND path = '" + p + "'" + stmt += " AND path = ?" + args = append(args, p) } - rows, err := query(stmt) + rows, err := query(stmt, args...) if err != nil { logging.LogErrorf("sql query failed: %s", err) return