Fix search, add mysql fulltext search support
parent
ac9a485ca2
commit
b1c98f2199
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 ` +
|
||||
|
|
Loading…
Reference in New Issue