2019-03-12 23:44:05 +01:00
|
|
|
package app
|
|
|
|
|
|
|
|
import (
|
2019-03-15 00:35:49 +01:00
|
|
|
"database/sql"
|
2019-03-12 23:44:05 +01:00
|
|
|
"errors"
|
2019-03-15 22:50:48 +01:00
|
|
|
"fmt"
|
2019-03-15 00:35:49 +01:00
|
|
|
_ "github.com/mattn/go-sqlite3"
|
2019-03-15 22:50:48 +01:00
|
|
|
"github.com/sirupsen/logrus"
|
2019-03-12 23:44:05 +01:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2019-03-15 22:50:48 +01:00
|
|
|
var ErrorRecordNotFound = errors.New("Record not found")
|
|
|
|
|
2019-03-12 23:44:05 +01:00
|
|
|
type ImageMetaData struct {
|
|
|
|
ImageId int
|
2019-03-15 00:35:49 +01:00
|
|
|
PiwigoId int
|
2019-03-12 23:44:05 +01:00
|
|
|
RelativeImagePath string
|
|
|
|
Filename string
|
|
|
|
Md5Sum string
|
|
|
|
LastChange time.Time
|
|
|
|
CategoryPath string
|
|
|
|
CategoryId int
|
2019-03-17 22:59:18 +01:00
|
|
|
UploadRequired bool
|
2019-03-12 23:44:05 +01:00
|
|
|
}
|
|
|
|
|
2019-03-15 22:50:48 +01:00
|
|
|
func (img *ImageMetaData) String() string {
|
|
|
|
return fmt.Sprintf("ImageMetaData{ImageId:%d, PiwigoId:%d, CategoryId:%d, RelPath:%s, File:%s, Md5:%s, Change:%sS, catpath:%s}", img.ImageId, img.PiwigoId, img.CategoryId, img.RelativeImagePath, img.Filename, img.Md5Sum, img.LastChange.String(), img.CategoryPath)
|
2019-03-12 23:44:05 +01:00
|
|
|
}
|
|
|
|
|
2019-03-15 22:50:48 +01:00
|
|
|
type ImageMetadataProvider interface {
|
|
|
|
GetImageMetadata(relativePath string) (ImageMetaData, error)
|
2019-03-12 23:44:05 +01:00
|
|
|
SaveImageMetadata(m ImageMetaData) error
|
|
|
|
}
|
|
|
|
|
|
|
|
type localDataStore struct {
|
|
|
|
connectionString string
|
|
|
|
}
|
|
|
|
|
2019-03-15 00:35:49 +01:00
|
|
|
func (d *localDataStore) Initialize(connectionString string) error {
|
2019-03-12 23:44:05 +01:00
|
|
|
if connectionString == "" {
|
|
|
|
return errors.New("connection string could not be empty.")
|
|
|
|
}
|
|
|
|
|
|
|
|
d.connectionString = connectionString
|
|
|
|
|
2019-03-15 00:35:49 +01:00
|
|
|
db, err := d.openDatabase()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer db.Close()
|
|
|
|
|
|
|
|
err = d.createTablesIfNeeded(db)
|
|
|
|
|
|
|
|
return err
|
2019-03-12 23:44:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d *localDataStore) GetImageMetadata(relativePath string) (ImageMetaData, error) {
|
2019-03-17 22:59:18 +01:00
|
|
|
logrus.Tracef("Query image metadata for file %s", relativePath)
|
2019-03-15 22:50:48 +01:00
|
|
|
img := ImageMetaData{}
|
|
|
|
|
2019-03-15 00:35:49 +01:00
|
|
|
db, err := d.openDatabase()
|
|
|
|
if err != nil {
|
2019-03-15 22:50:48 +01:00
|
|
|
return img, err
|
2019-03-15 00:35:49 +01:00
|
|
|
}
|
|
|
|
defer db.Close()
|
|
|
|
|
2019-03-17 22:59:18 +01:00
|
|
|
stmt, err := db.Prepare("SELECT imageId, piwigoId, relativePath, fileName, md5sum, lastChanged, categoryPath, categoryId, uploadRequired FROM image WHERE relativePath = ?")
|
2019-03-15 00:35:49 +01:00
|
|
|
if err != nil {
|
2019-03-15 22:50:48 +01:00
|
|
|
return img, err
|
2019-03-15 00:35:49 +01:00
|
|
|
}
|
|
|
|
|
2019-03-15 22:50:48 +01:00
|
|
|
rows, err := stmt.Query(relativePath)
|
2019-03-15 00:35:49 +01:00
|
|
|
if err != nil {
|
2019-03-15 22:50:48 +01:00
|
|
|
return img, err
|
2019-03-15 00:35:49 +01:00
|
|
|
}
|
2019-03-15 22:50:48 +01:00
|
|
|
defer rows.Close()
|
2019-03-15 00:35:49 +01:00
|
|
|
|
2019-03-15 22:50:48 +01:00
|
|
|
if rows.Next() {
|
2019-03-17 22:59:18 +01:00
|
|
|
err = rows.Scan(&img.ImageId, &img.PiwigoId, &img.RelativeImagePath, &img.Filename, &img.Md5Sum, &img.LastChange, &img.CategoryPath, &img.CategoryId, &img.UploadRequired)
|
2019-03-15 22:50:48 +01:00
|
|
|
if err != nil {
|
|
|
|
return img, err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return img, ErrorRecordNotFound
|
|
|
|
}
|
|
|
|
err = rows.Err()
|
|
|
|
|
|
|
|
return img, err
|
2019-03-12 23:44:05 +01:00
|
|
|
}
|
|
|
|
|
2019-03-15 22:50:48 +01:00
|
|
|
func (d *localDataStore) SaveImageMetadata(img ImageMetaData) error {
|
2019-03-17 22:59:18 +01:00
|
|
|
logrus.Tracef("Saving imagemetadata: %s", img.String())
|
2019-03-15 00:35:49 +01:00
|
|
|
db, err := d.openDatabase()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer db.Close()
|
|
|
|
|
|
|
|
tx, err := db.Begin()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-03-15 22:50:48 +01:00
|
|
|
if img.ImageId <= 0 {
|
|
|
|
err = d.insertImageMetaData(tx, img)
|
2019-03-15 00:35:49 +01:00
|
|
|
} else {
|
2019-03-15 22:50:48 +01:00
|
|
|
err = d.updateImageMetaData(tx, img)
|
2019-03-15 00:35:49 +01:00
|
|
|
}
|
|
|
|
|
2019-03-15 22:50:48 +01:00
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("Rolling back transaction for metadata of %s", img.RelativeImagePath)
|
|
|
|
errTx := tx.Rollback()
|
|
|
|
if errTx != nil {
|
|
|
|
logrus.Errorf("Rollback of transaction for metadata of %s failed!", img.RelativeImagePath)
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-03-17 22:59:18 +01:00
|
|
|
logrus.Tracef("Commiting metadata for image %s", img.String())
|
2019-03-15 22:50:48 +01:00
|
|
|
return tx.Commit()
|
2019-03-15 00:35:49 +01:00
|
|
|
}
|
|
|
|
|
2019-03-15 22:50:48 +01:00
|
|
|
func (d *localDataStore) insertImageMetaData(tx *sql.Tx, data ImageMetaData) error {
|
2019-03-17 22:59:18 +01:00
|
|
|
stmt, err := tx.Prepare("INSERT INTO image (piwigoId, relativePath, fileName, md5sum, lastChanged, categoryPath, categoryId, uploadRequired) VALUES (?,?,?,?,?,?,?,?)")
|
2019-03-15 00:35:49 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-03-17 22:59:18 +01:00
|
|
|
_, err = stmt.Exec(data.PiwigoId, data.RelativeImagePath, data.Filename, data.Md5Sum, data.LastChange, data.CategoryPath, data.CategoryId, data.UploadRequired)
|
2019-03-15 00:35:49 +01:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *localDataStore) openDatabase() (*sql.DB, error) {
|
|
|
|
db, err := sql.Open("sqlite3", d.connectionString)
|
|
|
|
if err != nil {
|
2019-03-15 22:50:48 +01:00
|
|
|
logrus.Warnf("Could not open database %s", d.connectionString)
|
2019-03-15 00:35:49 +01:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
db.SetMaxOpenConns(1)
|
|
|
|
|
|
|
|
return db, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *localDataStore) createTablesIfNeeded(db *sql.DB) error {
|
|
|
|
_, err := db.Exec("CREATE TABLE IF NOT EXISTS image (" +
|
2019-03-15 22:50:48 +01:00
|
|
|
"imageId INTEGER PRIMARY KEY," +
|
2019-03-15 00:35:49 +01:00
|
|
|
"piwigoId INTEGER NULL," +
|
|
|
|
"relativePath NVARCHAR(1000) NOT NULL," +
|
|
|
|
"fileName NVARCHAR(255) NOT NULL," +
|
|
|
|
"md5sum NVARCHAR(50) NOT NULL," +
|
|
|
|
"lastChanged DATETIME NOT NULL," +
|
|
|
|
"categoryPath NVARCHAR(1000) NOT NULL," +
|
2019-03-17 22:59:18 +01:00
|
|
|
"categoryId INTEGER NULL," +
|
|
|
|
"uploadRequired BIT NOT NULL" +
|
2019-03-15 00:35:49 +01:00
|
|
|
");")
|
2019-03-15 22:50:48 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = db.Exec("CREATE UNIQUE INDEX IF NOT EXISTS UX_ImageRelativePath ON image (relativePath);")
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *localDataStore) updateImageMetaData(tx *sql.Tx, data ImageMetaData) error {
|
|
|
|
stmt, err := tx.Prepare("UPDATE image SET piwigoId = ?, relativePath = ?, fileName = ?, md5sum = ?, lastChanged = ?, categoryPath = ?, categoryId = ? WHERE imageId = ?")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
_, err = stmt.Exec(data.PiwigoId, data.RelativeImagePath, data.Filename, data.Md5Sum, data.LastChange, data.CategoryPath, data.CategoryId, data.ImageId)
|
2019-03-15 00:35:49 +01:00
|
|
|
return err
|
2019-03-12 23:44:05 +01:00
|
|
|
}
|