Using master pg library

This commit is contained in:
Las Zenow 2017-05-18 22:16:16 +00:00
parent d9a95a997c
commit e0854aa001
8 changed files with 43 additions and 76 deletions

View file

@ -1,4 +1,4 @@
CREATE EXTENSION pg_trgm; --CREATE EXTENSION pg_trgm;
CREATE TABLE books ( CREATE TABLE books (
id varchar(16) primary key, id varchar(16) primary key,
@ -21,6 +21,7 @@ CREATE TABLE books (
-- Books column indexes -- Books column indexes
CREATE INDEX CONCURRENTLY books_lang_idx ON books (lang); CREATE INDEX CONCURRENTLY books_lang_idx ON books (lang);
CREATE INDEX CONCURRENTLY books_isbn_idx ON books (isbn); CREATE INDEX CONCURRENTLY books_isbn_idx ON books (isbn);
CREATE INDEX CONCURRENTLY books_active_idx ON books (active);
-- Books trigram indexes -- Books trigram indexes
CREATE INDEX CONCURRENTLY books_title_idx ON books USING GIN (title gin_trgm_ops); CREATE INDEX CONCURRENTLY books_title_idx ON books USING GIN (title gin_trgm_ops);

View file

@ -38,13 +38,6 @@ func coverHandler(h handler) {
return return
} }
if !book.Active {
if !h.sess.IsModerator() {
notFound(h)
return
}
}
file := coverFile file := coverFile
if vars["size"] == "small" { if vars["size"] == "small" {
file = coverSmallFile file = coverSmallFile

View file

@ -18,8 +18,8 @@ type Book struct {
Lang string Lang string
Isbn string Isbn string
FileSize int FileSize int
Cover bool Cover bool `sql:",notnull"`
Active bool Active bool `sql:",notnull"`
UploadDate time.Time UploadDate time.Time
Tsv string Tsv string
} }
@ -31,7 +31,7 @@ func (db *pgDB) AddBook(book Book) error {
book.UploadDate = time.Now() book.UploadDate = time.Now()
} }
return db.sql.Create(&book) return db.sql.Insert(&book)
} }
// GetBooks matching query // GetBooks matching query
@ -39,8 +39,6 @@ func (db *pgDB) GetBooks(query string, length int, start int) (books []Book, num
return db.getBooks(true, query, length, start) return db.getBooks(true, query, length, start)
} }
// TODO: func (db *pgDB) GetBooksIter() Iter {
// GetNewBooks returns a list of books in the incoming queue and the number of books // GetNewBooks returns a list of books in the incoming queue and the number of books
// in the queue // in the queue
func (db *pgDB) GetNewBooks(query string, length int, start int) (books []Book, num int, err error) { func (db *pgDB) GetNewBooks(query string, length int, start int) (books []Book, num int, err error) {
@ -48,45 +46,42 @@ func (db *pgDB) GetNewBooks(query string, length int, start int) (books []Book,
} }
func (db *pgDB) getBooks(active bool, query string, length int, start int) (books []Book, num int, err error) { func (db *pgDB) getBooks(active bool, query string, length int, start int) (books []Book, num int, err error) {
column := []string{} rank := []string{}
columnParams := []interface{}{} rankParams := []interface{}{}
searchCondition := "active = " searchCondition := ""
if active { if active {
searchCondition = "true" searchCondition += "active is true"
} else { } else {
searchCondition = "false" searchCondition += "active is not true"
} }
searchParams := []interface{}{} searchParams := []interface{}{}
textQuery, columnQuerys, trigramQuerys := buildQuery(query) textQuery, columnQuerys, trigramQuerys := buildQuery(query)
for _, c := range columnQuerys { for _, c := range columnQuerys {
searchCondition = searchCondition + " AND " + c.column + " = ?" searchCondition += " AND " + c.column + " = ?"
searchParams = append(searchParams, c.value) searchParams = append(searchParams, c.value)
} }
for _, c := range trigramQuerys { for _, c := range trigramQuerys {
column = append(column, "word_similarity(?, "+c.column+")") rank = append(rank, "word_similarity(?, "+c.column+")")
columnParams = append(columnParams, c.value) rankParams = append(rankParams, c.value)
searchCondition = searchCondition + " AND " + c.column + " %> ?" searchCondition += " AND " + c.column + " %> ?"
searchParams = append(searchParams, c.value) searchParams = append(searchParams, c.value)
} }
if textQuery != "" { if textQuery != "" {
column = append(column, "ts_rank(tsv, to_tsquery(?))") rank = append(rank, "ts_rank(tsv, to_tsquery(?))")
columnParams = append(columnParams, textQuery) rankParams = append(rankParams, textQuery)
searchCondition = searchCondition + " AND to_tsquery(?) @@ tsv" searchCondition += " AND to_tsquery(?) @@ tsv"
searchParams = append(searchParams, textQuery) searchParams = append(searchParams, textQuery)
} }
columnStr := "*"
order := "upload_date DESC" order := "upload_date DESC"
if len(column) > 0 { if len(rank) > 0 {
columnStr = "*, " + strings.Join(column, "+") + " AS rank" order = strings.Join(rank, "+") + " DESC, upload_date DESC"
order = "rank DESC, upload_date DESC"
} }
num, err = db.sql.Model(&books). num, err = db.sql.Model(&books).
ColumnExpr(columnStr, columnParams...).
Where(searchCondition, searchParams...). Where(searchCondition, searchParams...).
Order(order). OrderExpr(order, rankParams...).
Offset(start). Offset(start).
Limit(length). Limit(length).
SelectAndCountEstimate(100) SelectAndCountEstimate(100)
@ -169,7 +164,6 @@ type columnq struct {
} }
func buildQuery(query string) (textQuery string, columnQuerys []columnq, trigramQuerys []columnq) { func buildQuery(query string) (textQuery string, columnQuerys []columnq, trigramQuerys []columnq) {
// FIXME: does *Querys need initialization??
words := strings.Split(query, " ") words := strings.Split(query, " ")
for _, w := range words { for _, w := range words {
if w == "" { if w == "" {

View file

@ -1,7 +1,7 @@
package database package database
import ( import (
"gopkg.in/pg.v4" "github.com/go-pg/pg"
) )
type DB interface { type DB interface {
@ -45,7 +45,12 @@ type Options struct {
// Init the database connection // Init the database connection
func Init(options Options) (DB, error) { func Init(options Options) (DB, error) {
network := "tcp"
if options.Addr[0] == '/' {
network = "unix"
}
sql := pg.Connect(&pg.Options{ sql := pg.Connect(&pg.Options{
Network: network,
Addr: options.Addr, Addr: options.Addr,
User: options.User, User: options.User,
Password: options.Password, Password: options.Password,

View file

@ -18,7 +18,7 @@ func (db *pgDB) AddNews(text string) error {
} }
func (db *pgDB) addRawNews(text string, date time.Time) error { func (db *pgDB) addRawNews(text string, date time.Time) error {
return db.sql.Create(&New{ return db.sql.Insert(&New{
Text: text, Text: text,
Date: date, Date: date,
}) })

View file

@ -46,7 +46,7 @@ func (db *pgDB) addRawUser(name string, hpass []byte, salt []byte, role string)
Salt: salt, Salt: salt,
Role: role, Role: role,
} }
return db.sql.Create(&u) return db.sql.Insert(&u)
} }
func (db *pgDB) GetRole(name string) (string, error) { func (db *pgDB) GetRole(name string) (string, error) {

View file

@ -11,6 +11,7 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/meskio/epubgo" "github.com/meskio/epubgo"
"gitlab.com/trantor/trantor/lib/database" "gitlab.com/trantor/trantor/lib/database"
"gitlab.com/trantor/trantor/lib/storage"
) )
type chapter struct { type chapter struct {
@ -105,7 +106,7 @@ func getChapters(e *epubgo.Epub, file string, id string, base string) []chapter
func listChapters(nav *epubgo.NavigationIterator, depth int) []chapter { func listChapters(nav *epubgo.NavigationIterator, depth int) []chapter {
var chapters []chapter var chapters []chapter
var err error = nil var err error
for err == nil { for err == nil {
var c chapter var c chapter
c.Label = nav.Title() c.Label = nav.Title()
@ -128,7 +129,7 @@ func listChapters(nav *epubgo.NavigationIterator, depth int) []chapter {
func readStartHandler(h handler) { func readStartHandler(h handler) {
id := mux.Vars(h.r)["id"] id := mux.Vars(h.r)["id"]
e, _ := openReadEpub(h) e := openReadEpub(id, h.store)
if e == nil { if e == nil {
log.Warn("Open epub returns an empty file") log.Warn("Open epub returns an empty file")
notFound(h) notFound(h)
@ -148,7 +149,7 @@ func readStartHandler(h handler) {
func readHandler(h handler) { func readHandler(h handler) {
id := mux.Vars(h.r)["id"] id := mux.Vars(h.r)["id"]
file := mux.Vars(h.r)["file"] file := mux.Vars(h.r)["file"]
e, book := openReadEpub(h) e := openReadEpub(id, h.store)
if e == nil { if e == nil {
notFound(h) notFound(h)
return return
@ -158,6 +159,11 @@ func readHandler(h handler) {
var data readData var data readData
data.S = GetStatus(h) data.S = GetStatus(h)
book, err := h.db.GetBookID(id)
if err != nil {
notFound(h)
return
}
author := "" author := ""
if len(book.Authors) > 0 { if len(book.Authors) > 0 {
author = " by " + book.Authors[0] author = " by " + book.Authors[0]
@ -177,38 +183,23 @@ func readHandler(h handler) {
h.template.load(h, "read", data) h.template.load(h, "read", data)
} }
func openReadEpub(h handler) (*epubgo.Epub, database.Book) { func openReadEpub(id string, store storage.Store) *epubgo.Epub {
var book database.Book f, err := store.Get(id, epubFile)
id := mux.Vars(h.r)["id"]
if id == "" {
return nil, book
}
book, err := h.db.GetBookID(id)
if err != nil { if err != nil {
return nil, book return nil
}
if !book.Active {
if !h.sess.IsModerator() {
return nil, book
}
}
f, err := h.store.Get(book.ID, epubFile)
if err != nil {
return nil, book
} }
defer f.Close() defer f.Close()
info, err := f.Stat() info, err := f.Stat()
if err != nil { if err != nil {
return nil, book return nil
} }
e, err := epubgo.Load(f, info.Size()) e, err := epubgo.Load(f, info.Size())
if err != nil { if err != nil {
return nil, book return nil
} }
return e, book return e
} }
func contentHandler(h handler) { func contentHandler(h handler) {
@ -228,16 +219,6 @@ func contentHandler(h handler) {
} }
func openEpubFile(h handler, id string, file string) error { func openEpubFile(h handler, id string, file string) error {
book, err := h.db.GetBookID(id)
if err != nil {
return err
}
if !book.Active {
if !h.sess.IsModerator() {
return err
}
}
f, err := h.store.Get(id, epubFile) f, err := h.store.Get(id, epubFile)
if err != nil { if err != nil {
return err return err

View file

@ -84,13 +84,6 @@ func downloadHandler(h handler) {
return return
} }
if !book.Active {
if !h.sess.IsModerator() {
notFound(h)
return
}
}
f, err := h.store.Get(book.ID, epubFile) f, err := h.store.Get(book.ID, epubFile)
if err != nil { if err != nil {
notFound(h) notFound(h)