diff --git a/lib/database/books.go b/lib/database/books.go index 94d0ddc..55b3849 100644 --- a/lib/database/books.go +++ b/lib/database/books.go @@ -171,49 +171,67 @@ type columnq struct { } func buildQuery(query string) (textQuery string, columnQuerys []columnq, trigramQuerys []columnq) { - words := strings.Split(query, " ") - for _, w := range words { - if w == "" { + tokens := extractTokens(query) + for _, token := range tokens { + if token == "" { continue } - tag := strings.SplitN(w, ":", 2) - if len(tag) > 1 && tag[1] != "" { - value := strings.Replace(tag[1], "%", "\\%", 0) + tag := strings.SplitN(token, ":", 2) + value := "" + if len(tag) > 1 { + value = strings.Replace(tag[1], "%", "\\%", 0) value = strings.Replace(value, "_", "\\_", 0) - switch tag[0] { - case "lang": - columnQuerys = append(columnQuerys, columnq{"lang", value}) - case "isbn": - columnQuerys = append(columnQuerys, columnq{"isbn", value}) - case "author": - trigramQuerys = append(trigramQuerys, columnq{"text(authors)", value}) - case "title": - trigramQuerys = append(trigramQuerys, columnq{"title", value}) - case "contributor": - trigramQuerys = append(trigramQuerys, columnq{"contributor", value}) - case "publisher": - trigramQuerys = append(trigramQuerys, columnq{"publisher", value}) - case "subject": - trigramQuerys = append(trigramQuerys, columnq{"text(tags)", value}) - case "tag": - trigramQuerys = append(trigramQuerys, columnq{"text(tags)", value}) - default: - if len(textQuery) != 0 { - textQuery += " | " - } - textQuery += w - } - } else { + } + + switch tag[0] { + case "lang": + columnQuerys = append(columnQuerys, columnq{"lang", value}) + case "isbn": + columnQuerys = append(columnQuerys, columnq{"isbn", value}) + case "author": + trigramQuerys = append(trigramQuerys, columnq{"text(authors)", value}) + case "title": + trigramQuerys = append(trigramQuerys, columnq{"title", value}) + case "contributor": + trigramQuerys = append(trigramQuerys, columnq{"contributor", value}) + case "publisher": + trigramQuerys = append(trigramQuerys, columnq{"publisher", value}) + case "subject": + trigramQuerys = append(trigramQuerys, columnq{"text(tags)", value}) + case "tag": + trigramQuerys = append(trigramQuerys, columnq{"text(tags)", value}) + default: if len(textQuery) != 0 { lastChar := textQuery[len(textQuery)-1:] - if w != "&" && w != "|" && lastChar != "&" && lastChar != "|" { + if token[:1] != "&" && token[:1] != "|" && lastChar != "&" && lastChar != "|" { textQuery += " | " } else { textQuery += " " } } - textQuery += w + textQuery += strings.Join(strings.Fields(token), " <-> ") } } return } + +func extractTokens(query string) []string { + tokens := []string{} + quoted := strings.Split(query, "\"") + for i, s := range quoted { + if i%2 == 0 { + tokens = append(tokens, strings.Fields(s)...) + } else { + // quoted string + if len(tokens) > 0 { + lastToken := tokens[len(tokens)-1] + if len(lastToken) > 0 && lastToken[len(lastToken)-1] == ':' { + tokens[len(tokens)-1] += s + continue + } + } + tokens = append(tokens, s) + } + } + return tokens +}