diff --git a/kernel/api/history.go b/kernel/api/history.go index 813f677f0..f3ede8714 100644 --- a/kernel/api/history.go +++ b/kernel/api/history.go @@ -44,9 +44,11 @@ func searchHistory(c *gin.Context) { if nil != arg["op"] { op = arg["op"].(string) } - histories := model.FullTextSearchHistory(query, op, page) + histories, pageCount, totalCount := model.FullTextSearchHistory(query, op, page) ret.Data = map[string]interface{}{ - "histories": histories, + "histories": histories, + "pageCount": pageCount, + "totalCount": totalCount, } } diff --git a/kernel/model/history.go b/kernel/model/history.go index e99a14b5c..7088d4db5 100644 --- a/kernel/model/history.go +++ b/kernel/model/history.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "io/fs" + "math" "os" "path/filepath" "sort" @@ -275,7 +276,7 @@ func GetDocHistory(boxID string, page int) (ret []*History, err error) { return } -func FullTextSearchHistory(query, op string, page int) (ret []*History) { +func FullTextSearchHistory(query, op string, page int) (ret []*History, pageCount, totalCount int) { query = gulu.Str.RemoveInvisible(query) query = stringQuery(query) @@ -288,9 +289,19 @@ func FullTextSearchHistory(query, op string, page int) (ret []*History) { if "all" != op { stmt += " AND op = '" + op + "'" } + countStmt := strings.ReplaceAll(stmt, "SELECT *", "SELECT COUNT(*) AS total") stmt += " ORDER BY created DESC LIMIT " + strconv.Itoa(from) + ", " + strconv.Itoa(to) sqlHistories := sql.SelectHistoriesRawStmt(stmt) ret = fromSQLHistories(sqlHistories) + result, err := sql.QueryHistory(countStmt) + if nil != err { + return + } + if 1 > len(result) { + return + } + totalCount = int(result[0]["matches"].(int64)) + pageCount = int(math.Ceil(float64(totalCount) / float64(pageSize))) return } diff --git a/kernel/sql/history.go b/kernel/sql/history.go index d46b774c4..593b5f851 100644 --- a/kernel/sql/history.go +++ b/kernel/sql/history.go @@ -18,6 +18,7 @@ package sql import ( "database/sql" + "errors" "fmt" "strings" @@ -33,6 +34,49 @@ type History struct { Path string } +func QueryHistory(stmt string) (ret []map[string]interface{}, err error) { + ret = []map[string]interface{}{} + rows, err := queryHistory(stmt) + if nil != err { + logging.LogWarnf("sql query [%s] failed: %s", stmt, err) + return + } + defer rows.Close() + + cols, _ := rows.Columns() + if nil == cols { + return + } + + for rows.Next() { + columns := make([]interface{}, len(cols)) + columnPointers := make([]interface{}, len(cols)) + for i := range columns { + columnPointers[i] = &columns[i] + } + + if err = rows.Scan(columnPointers...); nil != err { + return + } + + m := make(map[string]interface{}) + for i, colName := range cols { + val := columnPointers[i].(*interface{}) + m[colName] = *val + } + ret = append(ret, m) + } + return +} + +func queryHistory(query string, args ...interface{}) (*sql.Rows, error) { + query = strings.TrimSpace(query) + if "" == query { + return nil, errors.New("statement is empty") + } + return historyDB.Query(query, args...) +} + func SelectHistoriesRawStmt(stmt string) (ret []*History) { rows, err := historyDB.Query(stmt) if nil != err {