Browse Source

:art: Global search ignores `LIMIT` clause when using SQL method https://github.com/siyuan-note/siyuan/issues/8071

Liang Ding 2 years ago
parent
commit
4cc8e18342
2 changed files with 33 additions and 3 deletions
  1. 21 2
      kernel/model/search.go
  2. 12 1
      kernel/sql/block_query.go

+ 21 - 2
kernel/model/search.go

@@ -35,6 +35,7 @@ import (
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/lex"
 	"github.com/88250/lute/parse"
+	"github.com/88250/vitess-sqlparser/sqlparser"
 	"github.com/jinzhu/copier"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/logging"
@@ -604,7 +605,7 @@ func buildTypeFilter(types map[string]bool) string {
 func searchBySQL(stmt string, beforeLen, page int) (ret []*Block, matchedBlockCount, matchedRootCount int) {
 	stmt = gulu.Str.RemoveInvisible(stmt)
 	stmt = strings.TrimSpace(stmt)
-	blocks := sql.SelectBlocksRawStmt(stmt, page, Conf.Search.Limit)
+	blocks := sql.SelectBlocksRawStmt(stmt, page, pageSize)
 	ret = fromSQLBlocks(&blocks, "", beforeLen)
 	if 1 > len(ret) {
 		ret = []*Block{}
@@ -617,6 +618,7 @@ func searchBySQL(stmt string, beforeLen, page int) (ret []*Block, matchedBlockCo
 	} else {
 		stmt = strings.ReplaceAll(stmt, "select * ", "select COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` ")
 	}
+	stmt = removeLimitClause(stmt)
 	result, _ := sql.Query(stmt)
 	if 1 > len(ret) {
 		return
@@ -627,6 +629,23 @@ func searchBySQL(stmt string, beforeLen, page int) (ret []*Block, matchedBlockCo
 	return
 }
 
+func removeLimitClause(stmt string) string {
+	parsedStmt, err := sqlparser.Parse(stmt)
+	if nil != err {
+		return stmt
+	}
+
+	switch parsedStmt.(type) {
+	case *sqlparser.Select:
+		slct := parsedStmt.(*sqlparser.Select)
+		if nil != slct.Limit {
+			slct.Limit = nil
+		}
+		stmt = sqlparser.String(slct)
+	}
+	return stmt
+}
+
 func fullTextSearchRefBlock(keyword string, beforeLen int, onlyDoc bool) (ret []*Block) {
 	keyword = gulu.Str.RemoveInvisible(keyword)
 
@@ -748,7 +767,7 @@ func fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy strin
 	stmt += boxFilter + pathFilter
 	stmt += " " + orderBy
 	stmt += " LIMIT " + strconv.Itoa(pageSize) + " OFFSET " + strconv.Itoa((page-1)*pageSize)
-	blocks := sql.SelectBlocksRawStmt(stmt, page, Conf.Search.Limit)
+	blocks := sql.SelectBlocksRawStmt(stmt, page, pageSize)
 	ret = fromSQLBlocks(&blocks, "", beforeLen)
 	if 1 > len(ret) {
 		ret = []*Block{}

+ 12 - 1
kernel/sql/block_query.go

@@ -433,14 +433,25 @@ func SelectBlocksRawStmt(stmt string, page, limit int) (ret []*Block) {
 					Val:  []byte(strconv.Itoa(limit)),
 				},
 			}
+			slct.Limit.Offset = &sqlparser.SQLVal{
+				Type: sqlparser.IntVal,
+				Val:  []byte(strconv.Itoa((page - 1) * limit)),
+			}
 		} else {
+			if nil != slct.Limit.Rowcount && 0 < len(slct.Limit.Rowcount.(*sqlparser.SQLVal).Val) {
+				limit, _ = strconv.Atoi(string(slct.Limit.Rowcount.(*sqlparser.SQLVal).Val))
+				if 0 >= limit {
+					limit = 32
+				}
+			}
+
 			slct.Limit.Rowcount = &sqlparser.SQLVal{
 				Type: sqlparser.IntVal,
 				Val:  []byte(strconv.Itoa(limit)),
 			}
 			slct.Limit.Offset = &sqlparser.SQLVal{
 				Type: sqlparser.IntVal,
-				Val:  []byte(strconv.Itoa((page - 1) * 32)),
+				Val:  []byte(strconv.Itoa((page - 1) * limit)),
 			}
 		}