Files
stash/pkg/sqlite/tx.go
WithoutPants 9b31b20fed [Files Refactor] Performance tuning (#2813)
* Do database txn in same thread. Retry on locked db
* Remove captions from slimscenedata
* Fix tracing
* Use where in instead of individual selects
* Remove scenes_query view
* Remove image query view
* Remove gallery query view
* Use where in for FindMany
* Don't interrupt scanning zip files
* Fix image filesize sort
2022-09-06 07:03:42 +00:00

120 lines
2.9 KiB
Go

package sqlite
import (
"context"
"database/sql"
"fmt"
"time"
"github.com/jmoiron/sqlx"
"github.com/stashapp/stash/pkg/logger"
)
const (
slowLogTime = time.Millisecond * 200
)
type dbReader interface {
Get(dest interface{}, query string, args ...interface{}) error
Select(dest interface{}, query string, args ...interface{}) error
Queryx(query string, args ...interface{}) (*sqlx.Rows, error)
QueryxContext(ctx context.Context, query string, args ...interface{}) (*sqlx.Rows, error)
}
func logSQL(start time.Time, query string, args ...interface{}) {
since := time.Since(start)
if since >= slowLogTime {
logger.Debugf("SLOW SQL [%v]: %s, args: %v", since, query, args)
} else {
logger.Tracef("SQL [%v]: %s, args: %v", since, query, args)
}
}
type dbWrapper struct{}
func sqlError(err error, sql string, args ...interface{}) error {
if err == nil {
return nil
}
return fmt.Errorf("error executing `%s` [%v]: %w", sql, args, err)
}
func (*dbWrapper) Get(ctx context.Context, dest interface{}, query string, args ...interface{}) error {
tx, err := getDBReader(ctx)
if err != nil {
return sqlError(err, query, args...)
}
start := time.Now()
err = tx.Get(dest, query, args...)
logSQL(start, query, args...)
return sqlError(err, query, args...)
}
func (*dbWrapper) Select(ctx context.Context, dest interface{}, query string, args ...interface{}) error {
tx, err := getDBReader(ctx)
if err != nil {
return sqlError(err, query, args...)
}
start := time.Now()
err = tx.Select(dest, query, args...)
logSQL(start, query, args...)
return sqlError(err, query, args...)
}
func (*dbWrapper) Queryx(ctx context.Context, query string, args ...interface{}) (*sqlx.Rows, error) {
tx, err := getDBReader(ctx)
if err != nil {
return nil, sqlError(err, query, args...)
}
start := time.Now()
ret, err := tx.Queryx(query, args...)
logSQL(start, query, args...)
return ret, sqlError(err, query, args...)
}
func (*dbWrapper) QueryxContext(ctx context.Context, query string, args ...interface{}) (*sqlx.Rows, error) {
tx, err := getDBReader(ctx)
if err != nil {
return nil, sqlError(err, query, args...)
}
start := time.Now()
ret, err := tx.QueryxContext(ctx, query, args...)
logSQL(start, query, args...)
return ret, sqlError(err, query, args...)
}
func (*dbWrapper) NamedExec(ctx context.Context, query string, arg interface{}) (sql.Result, error) {
tx, err := getTx(ctx)
if err != nil {
return nil, sqlError(err, query, arg)
}
start := time.Now()
ret, err := tx.NamedExec(query, arg)
logSQL(start, query, arg)
return ret, sqlError(err, query, arg)
}
func (*dbWrapper) Exec(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
tx, err := getTx(ctx)
if err != nil {
return nil, sqlError(err, query, args...)
}
start := time.Now()
ret, err := tx.Exec(query, args...)
logSQL(start, query, args...)
return ret, sqlError(err, query, args...)
}