Fix search, add mysql fulltext search support

master
Vitaliy Filippov 2017-04-28 01:15:59 +03:00
parent ac9a485ca2
commit b1c98f2199
6 changed files with 31 additions and 48 deletions

View File

@ -9,7 +9,6 @@ import (
"fmt"
"github.com/go-xorm/xorm"
"github.com/go-xorm/builder"
git "github.com/gogits/git-module"
)
@ -46,13 +45,13 @@ func FulltextSearchCommits(userid int64, q string, limit int, offset int) ([]*Co
sess := x.NewSession()
sess.Join("INNER", "repository", "repository.id = commit.repo_id")
if userid > 0 {
sess.Join("LEFT", "access", "access.repo_id = commit.repo_id AND access.user_id="+string(userid))
sess.Where("NOT repository.is_private OR access.user_id IS NOT NULL OR repository.owner_id="+string(userid))
sess.Join("LEFT", "access", "access.repo_id = commit.repo_id AND access.user_id=?", string(userid))
sess.Where("NOT repository.is_private OR access.user_id IS NOT NULL OR repository.owner_id=?", string(userid))
} else {
sess.Where("NOT repository.is_private")
}
if q != "" {
sess.Where(builder.Match{"message", q})
sess.Where(x.FulltextMatch("message"), q)
}
var countSess xorm.Session
countSess = *sess

View File

@ -1,36 +0,0 @@
// Copyright 2016 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import "fmt"
// Match defines full-text match condition
type Match [2]string
var _ Cond = Match{"", ""}
// WriteTo write SQL to Writer
func (m Match) WriteTo(w Writer) error {
if _, err := fmt.Fprintf(w, "to_tsvector(%s) @@ to_tsquery(?)", m[0]); err != nil {
return err
}
w.Append(m[1])
return nil
}
// And implements And with other conditions
func (m Match) And(conds ...Cond) Cond {
return And(m, And(conds...))
}
// Or implements Or with other conditions
func (m Match) Or(conds ...Cond) Cond {
return Or(m, Or(conds...))
}
// IsValid tests if this condition is valid
func (m Match) IsValid() bool {
return len(m[0]) > 0 && len(m[1]) > 0
}

View File

@ -52,6 +52,8 @@ type Dialect interface {
IndexOnTable() bool
ShowCreateNull() bool
FulltextMatch(column string) string
IndexCheckSql(tableName, idxName string) (string, []interface{})
TableCheckSql(tableName string) (string, []interface{})
@ -139,6 +141,10 @@ func (b *Base) EqStr() string {
return "="
}
func (db *Base) FulltextMatch(column string) string {
return "? = ''"
}
func (db *Base) RollBackStr() string {
return "ROLL BACK"
}

View File

@ -123,6 +123,10 @@ func (engine *Engine) QuoteStr() string {
return engine.dialect.QuoteStr()
}
func (engine *Engine) FulltextMatch(column string) string {
return engine.dialect.FulltextMatch(column)
}
// Quote Use QuoteStr quote the string sql
func (engine *Engine) Quote(value string) string {
value = strings.TrimSpace(value)

View File

@ -275,6 +275,10 @@ func (db *mysql) IndexOnTable() bool {
return true
}
func (db *mysql) FulltextMatch(column string) string {
return fmt.Sprintf("match(%s) against (? in boolean mode)", db.Quote(column))
}
func (db *mysql) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
args := []interface{}{db.DbName, tableName, idxName}
sql := "SELECT `INDEX_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS`"
@ -434,7 +438,7 @@ func (db *mysql) GetTables() ([]*core.Table, error) {
func (db *mysql) GetIndexes(tableName string) (map[string]*core.Index, error) {
args := []interface{}{db.DbName, tableName}
s := "SELECT `INDEX_NAME`, `NON_UNIQUE`, `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?"
s := "SELECT `INDEX_NAME`, `INDEX_TYPE`, `NON_UNIQUE`, `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?"
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...)
@ -445,9 +449,9 @@ func (db *mysql) GetIndexes(tableName string) (map[string]*core.Index, error) {
indexes := make(map[string]*core.Index, 0)
for rows.Next() {
var indexType int
var indexName, colName, nonUnique string
err = rows.Scan(&indexName, &nonUnique, &colName)
var xormType int
var indexName, indexType, colName, nonUnique string
err = rows.Scan(&indexName, &indexType, &nonUnique, &colName)
if err != nil {
return nil, err
}
@ -456,10 +460,12 @@ func (db *mysql) GetIndexes(tableName string) (map[string]*core.Index, error) {
continue
}
if "YES" == nonUnique || nonUnique == "1" {
indexType = core.IndexType
if "FULLTEXT" == indexType {
xormType = core.FulltextType
} else if "YES" == nonUnique || nonUnique == "1" {
xormType = core.IndexType
} else {
indexType = core.UniqueType
xormType = core.UniqueType
}
colName = strings.Trim(colName, "` ")
@ -474,7 +480,7 @@ func (db *mysql) GetIndexes(tableName string) (map[string]*core.Index, error) {
if index, ok = indexes[indexName]; !ok {
index = new(core.Index)
index.IsRegular = isRegular
index.Type = indexType
index.Type = xormType
index.Name = indexName
indexes[indexName] = index
}

View File

@ -862,6 +862,10 @@ func (db *postgres) IndexOnTable() bool {
return false
}
func (db *postgres) FulltextMatch(column string) string {
return fmt.Sprintf("to_tsvector(%s) @@ to_tsquery(?)", db.Quote(column))
}
func (db *postgres) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
args := []interface{}{tableName, idxName}
return `SELECT indexname FROM pg_indexes ` +