Reuse prepared statements, close rows

This commit is contained in:
Meutel 2017-08-02 19:54:09 +02:00
parent a1df078f90
commit b82967565b
2 changed files with 69 additions and 14 deletions

View File

@ -2,6 +2,8 @@ package bouquins
import (
"database/sql"
"errors"
"fmt"
"log"
)
@ -56,6 +58,10 @@ const (
BOOKS QueryType = iota
BOOKS_TAGS QueryType = iota
BOOKS_AUTHORS QueryType = iota
BOOK QueryType = iota
BOOK_TAGS QueryType = iota
BOOK_DATA QueryType = iota
BOOKS_COUNT QueryType = iota
)
var QUERIES = map[Query]string{
@ -71,7 +77,12 @@ var QUERIES = map[Query]string{
Query{BOOKS_AUTHORS, true, false}: STMT_BOOKS_AUTHORS_TITLE_ASC,
Query{BOOKS_AUTHORS, false, true}: STMT_BOOKS_AUTHORS_ID_DESC,
Query{BOOKS_AUTHORS, false, false}: STMT_BOOKS_AUTHORS_ID_ASC,
Query{BOOK, false, false}: STMT_BOOK,
Query{BOOK_TAGS, false, false}: STMT_BOOK_TAGS,
Query{BOOK_DATA, false, false}: STMT_BOOK_DATA,
Query{BOOKS_COUNT, false, false}: STMT_BOOKS_COUNT,
}
var STMTS = make(map[Query]*sql.Stmt)
type QueryType uint
type Query struct {
@ -81,11 +92,42 @@ type Query struct {
}
// PREPARED STATEMENTS //
func (app *Bouquins) psBooks(qt QueryType, sort, order string) (*sql.Stmt, error) {
//TODO cache
query := QUERIES[Query{qt, sort == "title", order == "desc"}]
func (app *Bouquins) PrepareAll() error {
errcount := 0
for q, v := range QUERIES {
stmt, err := app.DB.Prepare(v)
if err != nil {
log.Println(err, v)
errcount++
}
STMTS[q] = stmt
}
if errcount > 0 {
return errors.New(fmt.Sprintf("%d errors on queries, see logs", errcount))
}
return nil
}
// prepared statement with sort on books
func (app *Bouquins) psSortBooks(qt QueryType, sort, order string) (*sql.Stmt, error) {
q := Query{qt, sort == "title", order == "desc"}
query := QUERIES[q]
log.Println(query)
return app.DB.Prepare(query)
stmt := STMTS[q]
if stmt == nil {
log.Println("Missing statement for ", q)
var err error
stmt, err = app.DB.Prepare(query)
if err != nil {
return nil, err
}
}
return stmt, nil
}
// prepared statement without sort
func (app *Bouquins) ps(qt QueryType) (*sql.Stmt, error) {
return app.psSortBooks(qt, "", "")
}
// MERGE SUB QUERIES //
@ -100,7 +142,7 @@ func assignAuthorsTagsBooks(books []*BookAdv, authors map[int64][]*Author, tags
func (app *Bouquins) queryBooks(limit, offset int, sort, order string) ([]*BookAdv, error) {
books := make([]*BookAdv, 0, limit)
stmt, err := app.psBooks(BOOKS, sort, order)
stmt, err := app.psSortBooks(BOOKS, sort, order)
if err != nil {
return nil, err
}
@ -108,6 +150,7 @@ func (app *Bouquins) queryBooks(limit, offset int, sort, order string) ([]*BookA
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
book := new(BookAdv)
var series_name sql.NullString
@ -131,7 +174,7 @@ func (app *Bouquins) queryBooks(limit, offset int, sort, order string) ([]*BookA
func (app *Bouquins) queryBooksAuthors(limit, offset int, sort, order string) (map[int64][]*Author, error) {
authors := make(map[int64][]*Author)
stmt, err := app.psBooks(BOOKS_AUTHORS, sort, order)
stmt, err := app.psSortBooks(BOOKS_AUTHORS, sort, order)
if err != nil {
return nil, err
}
@ -139,6 +182,7 @@ func (app *Bouquins) queryBooksAuthors(limit, offset int, sort, order string) (m
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
author := new(Author)
var book int64
@ -158,7 +202,7 @@ func (app *Bouquins) queryBooksAuthors(limit, offset int, sort, order string) (m
}
func (app *Bouquins) queryBooksTags(limit, offset int, sort, order string) (map[int64][]string, error) {
stmt, err := app.psBooks(BOOKS_TAGS, sort, order)
stmt, err := app.psSortBooks(BOOKS_TAGS, sort, order)
if err != nil {
return nil, err
}
@ -166,6 +210,7 @@ func (app *Bouquins) queryBooksTags(limit, offset int, sort, order string) (map[
if err != nil {
return nil, err
}
defer rows.Close()
tags := make(map[int64][]string)
for rows.Next() {
var tag string
@ -186,7 +231,7 @@ func (app *Bouquins) queryBooksTags(limit, offset int, sort, order string) (map[
return tags, nil
}
func (app *Bouquins) queryBook(id int64) (*BookFull, error) {
stmt, err := app.DB.Prepare(STMT_BOOK)
stmt, err := app.ps(BOOK)
if err != nil {
return nil, err
}
@ -231,7 +276,7 @@ func (app *Bouquins) queryBook(id int64) (*BookFull, error) {
return book, nil
}
func (app *Bouquins) queryBookTags(book *BookFull) error {
stmt, err := app.DB.Prepare(STMT_BOOK_TAGS)
stmt, err := app.ps(BOOK_TAGS)
if err != nil {
return err
}
@ -239,6 +284,7 @@ func (app *Bouquins) queryBookTags(book *BookFull) error {
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var tag string
if err = rows.Scan(&tag); err != nil {
@ -251,8 +297,8 @@ func (app *Bouquins) queryBookTags(book *BookFull) error {
}
return nil
}
func (app *Bouquins) queryBookAuthors(book *BookFull) error {
stmt, err := app.DB.Prepare(STMT_BOOK_DATA)
func (app *Bouquins) queryBookData(book *BookFull) error {
stmt, err := app.ps(BOOK_DATA)
if err != nil {
return err
}
@ -260,6 +306,7 @@ func (app *Bouquins) queryBookAuthors(book *BookFull) error {
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
data := new(BookData)
if err = rows.Scan(&data.Name, &data.Format, &data.Size); err != nil {
@ -272,7 +319,7 @@ func (app *Bouquins) queryBookAuthors(book *BookFull) error {
}
return nil
}
func (app *Bouquins) queryBookData(book *BookFull) error {
func (app *Bouquins) queryBookAuthors(book *BookFull) error {
return nil
}
@ -280,8 +327,12 @@ func (app *Bouquins) queryBookData(book *BookFull) error {
func (app *Bouquins) BookCount() (int64, error) {
var count int64
row := app.DB.QueryRow(STMT_BOOKS_COUNT)
err := row.Scan(&count)
stmt, err := app.ps(BOOKS_COUNT)
if err != nil {
return 0, err
}
row := stmt.QueryRow()
err = row.Scan(&count)
return count, err
}
func (app *Bouquins) SeriesAdv(limit, offset int, sort, order string) ([]*SeriesAdv, error) {

View File

@ -63,6 +63,10 @@ func initApp() *BouquinsConf {
tpl,
db,
}
err = app.PrepareAll()
if err != nil {
log.Fatalln(err)
}
assets()
router(app)
return conf