2019-02-09 12:30:49 +00:00
|
|
|
package models
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
2020-07-19 01:59:18 +00:00
|
|
|
"fmt"
|
2019-10-12 11:32:01 +00:00
|
|
|
"path/filepath"
|
2020-04-24 23:32:55 +00:00
|
|
|
"strconv"
|
2019-10-12 11:32:01 +00:00
|
|
|
|
2019-02-09 12:30:49 +00:00
|
|
|
"github.com/jmoiron/sqlx"
|
2019-02-14 23:42:52 +00:00
|
|
|
"github.com/stashapp/stash/pkg/database"
|
2019-02-09 12:30:49 +00:00
|
|
|
)
|
|
|
|
|
2020-06-21 11:43:57 +00:00
|
|
|
const galleryTable = "galleries"
|
|
|
|
|
2019-02-14 22:53:32 +00:00
|
|
|
type GalleryQueryBuilder struct{}
|
2019-02-09 12:30:49 +00:00
|
|
|
|
2019-02-14 22:53:32 +00:00
|
|
|
func NewGalleryQueryBuilder() GalleryQueryBuilder {
|
|
|
|
return GalleryQueryBuilder{}
|
2019-02-09 12:30:49 +00:00
|
|
|
}
|
|
|
|
|
2019-02-14 22:53:32 +00:00
|
|
|
func (qb *GalleryQueryBuilder) Create(newGallery Gallery, tx *sqlx.Tx) (*Gallery, error) {
|
2019-02-09 12:30:49 +00:00
|
|
|
ensureTx(tx)
|
|
|
|
result, err := tx.NamedExec(
|
2020-12-17 21:06:49 +00:00
|
|
|
`INSERT INTO galleries (path, checksum, zip, title, date, details, url, studio_id, rating, organized, scene_id, file_mod_time, created_at, updated_at)
|
|
|
|
VALUES (:path, :checksum, :zip, :title, :date, :details, :url, :studio_id, :rating, :organized, :scene_id, :file_mod_time, :created_at, :updated_at)
|
2019-02-09 12:30:49 +00:00
|
|
|
`,
|
|
|
|
newGallery,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
galleryID, err := result.LastInsertId()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := tx.Get(&newGallery, `SELECT * FROM galleries WHERE id = ? LIMIT 1`, galleryID); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &newGallery, nil
|
|
|
|
}
|
|
|
|
|
2019-02-14 22:53:32 +00:00
|
|
|
func (qb *GalleryQueryBuilder) Update(updatedGallery Gallery, tx *sqlx.Tx) (*Gallery, error) {
|
2019-02-09 12:30:49 +00:00
|
|
|
ensureTx(tx)
|
|
|
|
_, err := tx.NamedExec(
|
2019-02-14 22:53:32 +00:00
|
|
|
`UPDATE galleries SET `+SQLGenKeys(updatedGallery)+` WHERE galleries.id = :id`,
|
2019-02-09 12:30:49 +00:00
|
|
|
updatedGallery,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := tx.Get(&updatedGallery, `SELECT * FROM galleries WHERE id = ? LIMIT 1`, updatedGallery.ID); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &updatedGallery, nil
|
|
|
|
}
|
|
|
|
|
2020-10-12 23:12:46 +00:00
|
|
|
func (qb *GalleryQueryBuilder) UpdatePartial(updatedGallery GalleryPartial, tx *sqlx.Tx) (*Gallery, error) {
|
|
|
|
ensureTx(tx)
|
|
|
|
_, err := tx.NamedExec(
|
|
|
|
`UPDATE galleries SET `+SQLGenKeysPartial(updatedGallery)+` WHERE galleries.id = :id`,
|
|
|
|
updatedGallery,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return qb.Find(updatedGallery.ID, tx)
|
|
|
|
}
|
|
|
|
|
2020-11-04 23:26:51 +00:00
|
|
|
func (qb *GalleryQueryBuilder) UpdateChecksum(id int, checksum string, tx *sqlx.Tx) error {
|
|
|
|
ensureTx(tx)
|
|
|
|
_, err := tx.Exec(
|
|
|
|
`UPDATE galleries SET checksum = ? WHERE galleries.id = ? `,
|
|
|
|
checksum, id,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (qb *GalleryQueryBuilder) UpdateFileModTime(id int, modTime NullSQLiteTimestamp, tx *sqlx.Tx) error {
|
|
|
|
ensureTx(tx)
|
|
|
|
_, err := tx.Exec(
|
|
|
|
`UPDATE galleries SET file_mod_time = ? WHERE galleries.id = ? `,
|
|
|
|
modTime, id,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-04-24 23:32:55 +00:00
|
|
|
func (qb *GalleryQueryBuilder) Destroy(id int, tx *sqlx.Tx) error {
|
|
|
|
return executeDeleteQuery("galleries", strconv.Itoa(id), tx)
|
|
|
|
}
|
|
|
|
|
2019-10-12 11:32:01 +00:00
|
|
|
type GalleryNullSceneID struct {
|
|
|
|
SceneID sql.NullInt64
|
|
|
|
}
|
|
|
|
|
|
|
|
func (qb *GalleryQueryBuilder) ClearGalleryId(sceneID int, tx *sqlx.Tx) error {
|
|
|
|
ensureTx(tx)
|
|
|
|
_, err := tx.NamedExec(
|
|
|
|
`UPDATE galleries SET scene_id = null WHERE scene_id = :sceneid`,
|
|
|
|
GalleryNullSceneID{
|
|
|
|
SceneID: sql.NullInt64{
|
|
|
|
Int64: int64(sceneID),
|
|
|
|
Valid: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-10-12 23:12:46 +00:00
|
|
|
func (qb *GalleryQueryBuilder) Find(id int, tx *sqlx.Tx) (*Gallery, error) {
|
2019-02-09 12:30:49 +00:00
|
|
|
query := "SELECT * FROM galleries WHERE id = ? LIMIT 1"
|
|
|
|
args := []interface{}{id}
|
2020-10-12 23:12:46 +00:00
|
|
|
return qb.queryGallery(query, args, tx)
|
2019-02-09 12:30:49 +00:00
|
|
|
}
|
|
|
|
|
2020-07-19 01:59:18 +00:00
|
|
|
func (qb *GalleryQueryBuilder) FindMany(ids []int) ([]*Gallery, error) {
|
|
|
|
var galleries []*Gallery
|
|
|
|
for _, id := range ids {
|
2020-10-12 23:12:46 +00:00
|
|
|
gallery, err := qb.Find(id, nil)
|
2020-07-19 01:59:18 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if gallery == nil {
|
|
|
|
return nil, fmt.Errorf("gallery with id %d not found", id)
|
|
|
|
}
|
|
|
|
|
|
|
|
galleries = append(galleries, gallery)
|
|
|
|
}
|
|
|
|
|
|
|
|
return galleries, nil
|
|
|
|
}
|
|
|
|
|
2019-02-14 22:53:32 +00:00
|
|
|
func (qb *GalleryQueryBuilder) FindByChecksum(checksum string, tx *sqlx.Tx) (*Gallery, error) {
|
2019-02-09 12:30:49 +00:00
|
|
|
query := "SELECT * FROM galleries WHERE checksum = ? LIMIT 1"
|
|
|
|
args := []interface{}{checksum}
|
|
|
|
return qb.queryGallery(query, args, tx)
|
|
|
|
}
|
|
|
|
|
2019-02-14 22:53:32 +00:00
|
|
|
func (qb *GalleryQueryBuilder) FindByPath(path string) (*Gallery, error) {
|
2019-02-09 12:30:49 +00:00
|
|
|
query := "SELECT * FROM galleries WHERE path = ? LIMIT 1"
|
|
|
|
args := []interface{}{path}
|
|
|
|
return qb.queryGallery(query, args, nil)
|
|
|
|
}
|
|
|
|
|
2019-02-14 22:53:32 +00:00
|
|
|
func (qb *GalleryQueryBuilder) FindBySceneID(sceneID int, tx *sqlx.Tx) (*Gallery, error) {
|
2020-05-11 05:19:11 +00:00
|
|
|
query := "SELECT galleries.* FROM galleries WHERE galleries.scene_id = ? LIMIT 1"
|
2019-02-09 12:30:49 +00:00
|
|
|
args := []interface{}{sceneID}
|
|
|
|
return qb.queryGallery(query, args, tx)
|
|
|
|
}
|
|
|
|
|
2019-05-27 19:34:26 +00:00
|
|
|
func (qb *GalleryQueryBuilder) ValidGalleriesForScenePath(scenePath string) ([]*Gallery, error) {
|
2019-02-09 12:30:49 +00:00
|
|
|
sceneDirPath := filepath.Dir(scenePath)
|
|
|
|
query := "SELECT galleries.* FROM galleries WHERE galleries.scene_id IS NULL AND galleries.path LIKE '" + sceneDirPath + "%' ORDER BY path ASC"
|
|
|
|
return qb.queryGalleries(query, nil, nil)
|
|
|
|
}
|
|
|
|
|
2020-10-12 23:12:46 +00:00
|
|
|
func (qb *GalleryQueryBuilder) FindByImageID(imageID int, tx *sqlx.Tx) ([]*Gallery, error) {
|
|
|
|
query := selectAll(galleryTable) + `
|
|
|
|
LEFT JOIN galleries_images as images_join on images_join.gallery_id = galleries.id
|
|
|
|
WHERE images_join.image_id = ?
|
|
|
|
GROUP BY galleries.id
|
|
|
|
`
|
|
|
|
args := []interface{}{imageID}
|
|
|
|
return qb.queryGalleries(query, args, tx)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (qb *GalleryQueryBuilder) CountByImageID(imageID int) (int, error) {
|
|
|
|
query := `SELECT image_id FROM galleries_images
|
|
|
|
WHERE image_id = ?
|
|
|
|
GROUP BY gallery_id`
|
|
|
|
args := []interface{}{imageID}
|
|
|
|
return runCountQuery(buildCountQuery(query), args)
|
|
|
|
}
|
|
|
|
|
2019-02-14 22:53:32 +00:00
|
|
|
func (qb *GalleryQueryBuilder) Count() (int, error) {
|
2019-02-11 20:36:10 +00:00
|
|
|
return runCountQuery(buildCountQuery("SELECT galleries.id FROM galleries"), nil)
|
|
|
|
}
|
|
|
|
|
2019-05-27 19:34:26 +00:00
|
|
|
func (qb *GalleryQueryBuilder) All() ([]*Gallery, error) {
|
2019-02-14 22:53:32 +00:00
|
|
|
return qb.queryGalleries(selectAll("galleries")+qb.getGallerySort(nil), nil, nil)
|
2019-02-09 12:30:49 +00:00
|
|
|
}
|
|
|
|
|
2020-06-21 11:43:57 +00:00
|
|
|
func (qb *GalleryQueryBuilder) Query(galleryFilter *GalleryFilterType, findFilter *FindFilterType) ([]*Gallery, int) {
|
|
|
|
if galleryFilter == nil {
|
|
|
|
galleryFilter = &GalleryFilterType{}
|
|
|
|
}
|
2019-02-09 12:30:49 +00:00
|
|
|
if findFilter == nil {
|
|
|
|
findFilter = &FindFilterType{}
|
|
|
|
}
|
|
|
|
|
2020-06-21 11:43:57 +00:00
|
|
|
query := queryBuilder{
|
|
|
|
tableName: galleryTable,
|
|
|
|
}
|
|
|
|
|
|
|
|
query.body = selectDistinctIDs("galleries")
|
2020-10-12 23:12:46 +00:00
|
|
|
query.body += `
|
|
|
|
left join performers_galleries as performers_join on performers_join.gallery_id = galleries.id
|
|
|
|
left join studios as studio on studio.id = galleries.studio_id
|
|
|
|
left join galleries_tags as tags_join on tags_join.gallery_id = galleries.id
|
2020-10-15 23:35:50 +00:00
|
|
|
left join galleries_images as images_join on images_join.gallery_id = galleries.id
|
|
|
|
left join images on images_join.image_id = images.id
|
2020-10-12 23:12:46 +00:00
|
|
|
`
|
2019-02-09 12:30:49 +00:00
|
|
|
|
|
|
|
if q := findFilter.Q; q != nil && *q != "" {
|
|
|
|
searchColumns := []string{"galleries.path", "galleries.checksum"}
|
2020-03-02 22:18:14 +00:00
|
|
|
clause, thisArgs := getSearchBinding(searchColumns, *q, false)
|
2020-06-21 11:43:57 +00:00
|
|
|
query.addWhere(clause)
|
|
|
|
query.addArg(thisArgs...)
|
|
|
|
}
|
|
|
|
|
2020-10-12 23:12:46 +00:00
|
|
|
if zipFilter := galleryFilter.IsZip; zipFilter != nil {
|
|
|
|
var favStr string
|
|
|
|
if *zipFilter == true {
|
|
|
|
favStr = "1"
|
|
|
|
} else {
|
|
|
|
favStr = "0"
|
|
|
|
}
|
|
|
|
query.addWhere("galleries.zip = " + favStr)
|
|
|
|
}
|
|
|
|
|
2020-10-11 21:19:51 +00:00
|
|
|
query.handleStringCriterionInput(galleryFilter.Path, "galleries.path")
|
2020-10-19 23:11:15 +00:00
|
|
|
query.handleIntCriterionInput(galleryFilter.Rating, "galleries.rating")
|
|
|
|
qb.handleAverageResolutionFilter(&query, galleryFilter.AverageResolution)
|
2020-10-11 21:19:51 +00:00
|
|
|
|
2020-12-17 21:06:49 +00:00
|
|
|
if Organized := galleryFilter.Organized; Organized != nil {
|
|
|
|
var organized string
|
|
|
|
if *Organized == true {
|
|
|
|
organized = "1"
|
|
|
|
} else {
|
|
|
|
organized = "0"
|
|
|
|
}
|
|
|
|
query.addWhere("galleries.organized = " + organized)
|
|
|
|
}
|
|
|
|
|
2020-06-21 11:43:57 +00:00
|
|
|
if isMissingFilter := galleryFilter.IsMissing; isMissingFilter != nil && *isMissingFilter != "" {
|
|
|
|
switch *isMissingFilter {
|
|
|
|
case "scene":
|
|
|
|
query.addWhere("galleries.scene_id IS NULL")
|
2020-10-12 23:12:46 +00:00
|
|
|
case "studio":
|
|
|
|
query.addWhere("galleries.studio_id IS NULL")
|
|
|
|
case "performers":
|
|
|
|
query.addWhere("performers_join.gallery_id IS NULL")
|
|
|
|
case "date":
|
|
|
|
query.addWhere("galleries.date IS \"\" OR galleries.date IS \"0001-01-01\"")
|
|
|
|
case "tags":
|
|
|
|
query.addWhere("tags_join.gallery_id IS NULL")
|
|
|
|
default:
|
|
|
|
query.addWhere("galleries." + *isMissingFilter + " IS NULL")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if tagsFilter := galleryFilter.Tags; tagsFilter != nil && len(tagsFilter.Value) > 0 {
|
|
|
|
for _, tagID := range tagsFilter.Value {
|
|
|
|
query.addArg(tagID)
|
2020-06-21 11:43:57 +00:00
|
|
|
}
|
2020-10-12 23:12:46 +00:00
|
|
|
|
|
|
|
query.body += " LEFT JOIN tags on tags_join.tag_id = tags.id"
|
|
|
|
whereClause, havingClause := getMultiCriterionClause("galleries", "tags", "tags_join", "gallery_id", "tag_id", tagsFilter)
|
|
|
|
query.addWhere(whereClause)
|
|
|
|
query.addHaving(havingClause)
|
|
|
|
}
|
|
|
|
|
|
|
|
if performersFilter := galleryFilter.Performers; performersFilter != nil && len(performersFilter.Value) > 0 {
|
|
|
|
for _, performerID := range performersFilter.Value {
|
|
|
|
query.addArg(performerID)
|
|
|
|
}
|
|
|
|
|
|
|
|
query.body += " LEFT JOIN performers ON performers_join.performer_id = performers.id"
|
|
|
|
whereClause, havingClause := getMultiCriterionClause("galleries", "performers", "performers_join", "gallery_id", "performer_id", performersFilter)
|
|
|
|
query.addWhere(whereClause)
|
|
|
|
query.addHaving(havingClause)
|
|
|
|
}
|
|
|
|
|
|
|
|
if studiosFilter := galleryFilter.Studios; studiosFilter != nil && len(studiosFilter.Value) > 0 {
|
|
|
|
for _, studioID := range studiosFilter.Value {
|
|
|
|
query.addArg(studioID)
|
|
|
|
}
|
|
|
|
|
|
|
|
whereClause, havingClause := getMultiCriterionClause("galleries", "studio", "", "", "studio_id", studiosFilter)
|
|
|
|
query.addWhere(whereClause)
|
|
|
|
query.addHaving(havingClause)
|
2019-02-09 12:30:49 +00:00
|
|
|
}
|
|
|
|
|
2020-06-21 11:43:57 +00:00
|
|
|
query.sortAndPagination = qb.getGallerySort(findFilter) + getPagination(findFilter)
|
|
|
|
idsResult, countResult := query.executeFind()
|
2019-02-09 12:30:49 +00:00
|
|
|
|
2019-05-27 19:34:26 +00:00
|
|
|
var galleries []*Gallery
|
2019-02-09 12:30:49 +00:00
|
|
|
for _, id := range idsResult {
|
2020-10-12 23:12:46 +00:00
|
|
|
gallery, _ := qb.Find(id, nil)
|
2019-05-27 19:34:26 +00:00
|
|
|
galleries = append(galleries, gallery)
|
2019-02-09 12:30:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return galleries, countResult
|
|
|
|
}
|
|
|
|
|
2020-10-19 23:11:15 +00:00
|
|
|
func (qb *GalleryQueryBuilder) handleAverageResolutionFilter(query *queryBuilder, resolutionFilter *ResolutionEnum) {
|
|
|
|
if resolutionFilter == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if resolution := resolutionFilter.String(); resolutionFilter.IsValid() {
|
|
|
|
var low int
|
|
|
|
var high int
|
|
|
|
|
|
|
|
switch resolution {
|
2021-01-07 05:10:59 +00:00
|
|
|
case "VERY_LOW":
|
|
|
|
high = 240
|
2020-10-19 23:11:15 +00:00
|
|
|
case "LOW":
|
2021-01-07 05:10:59 +00:00
|
|
|
low = 240
|
|
|
|
high = 360
|
|
|
|
case "R360P":
|
|
|
|
low = 360
|
2020-10-19 23:11:15 +00:00
|
|
|
high = 480
|
|
|
|
case "STANDARD":
|
|
|
|
low = 480
|
2021-01-07 05:10:59 +00:00
|
|
|
high = 540
|
|
|
|
case "WEB_HD":
|
|
|
|
low = 540
|
2020-10-19 23:11:15 +00:00
|
|
|
high = 720
|
|
|
|
case "STANDARD_HD":
|
|
|
|
low = 720
|
|
|
|
high = 1080
|
|
|
|
case "FULL_HD":
|
|
|
|
low = 1080
|
2021-01-07 05:10:59 +00:00
|
|
|
high = 1440
|
|
|
|
case "QUAD_HD":
|
|
|
|
low = 1440
|
|
|
|
high = 1920
|
|
|
|
case "VR_HD":
|
|
|
|
low = 1920
|
2020-10-19 23:11:15 +00:00
|
|
|
high = 2160
|
|
|
|
case "FOUR_K":
|
|
|
|
low = 2160
|
2021-01-07 05:10:59 +00:00
|
|
|
high = 2880
|
|
|
|
case "FIVE_K":
|
|
|
|
low = 2880
|
|
|
|
high = 3384
|
|
|
|
case "SIX_K":
|
|
|
|
low = 3384
|
|
|
|
high = 4320
|
|
|
|
case "EIGHT_K":
|
|
|
|
low = 4320
|
2020-10-19 23:11:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
havingClause := ""
|
|
|
|
if low != 0 {
|
2021-01-07 05:10:59 +00:00
|
|
|
havingClause = "avg(MIN(images.width, images.height)) >= " + strconv.Itoa(low)
|
2020-10-19 23:11:15 +00:00
|
|
|
}
|
|
|
|
if high != 0 {
|
|
|
|
if havingClause != "" {
|
|
|
|
havingClause += " AND "
|
|
|
|
}
|
2021-01-07 05:10:59 +00:00
|
|
|
havingClause += "avg(MIN(images.width, images.height)) < " + strconv.Itoa(high)
|
2020-10-19 23:11:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if havingClause != "" {
|
|
|
|
query.addHaving(havingClause)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-14 22:53:32 +00:00
|
|
|
func (qb *GalleryQueryBuilder) getGallerySort(findFilter *FindFilterType) string {
|
2019-02-09 12:30:49 +00:00
|
|
|
var sort string
|
|
|
|
var direction string
|
2020-04-03 03:40:37 +00:00
|
|
|
if findFilter == nil {
|
|
|
|
sort = "path"
|
|
|
|
direction = "ASC"
|
|
|
|
} else {
|
|
|
|
sort = findFilter.GetSort("path")
|
|
|
|
direction = findFilter.GetDirection()
|
|
|
|
}
|
2019-02-09 12:30:49 +00:00
|
|
|
return getSort(sort, direction, "galleries")
|
|
|
|
}
|
|
|
|
|
2019-02-14 22:53:32 +00:00
|
|
|
func (qb *GalleryQueryBuilder) queryGallery(query string, args []interface{}, tx *sqlx.Tx) (*Gallery, error) {
|
2019-02-09 12:30:49 +00:00
|
|
|
results, err := qb.queryGalleries(query, args, tx)
|
|
|
|
if err != nil || len(results) < 1 {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-05-27 19:34:26 +00:00
|
|
|
return results[0], nil
|
2019-02-09 12:30:49 +00:00
|
|
|
}
|
|
|
|
|
2019-05-27 19:34:26 +00:00
|
|
|
func (qb *GalleryQueryBuilder) queryGalleries(query string, args []interface{}, tx *sqlx.Tx) ([]*Gallery, error) {
|
2019-02-09 12:30:49 +00:00
|
|
|
var rows *sqlx.Rows
|
|
|
|
var err error
|
|
|
|
if tx != nil {
|
|
|
|
rows, err = tx.Queryx(query, args...)
|
|
|
|
} else {
|
|
|
|
rows, err = database.DB.Queryx(query, args...)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil && err != sql.ErrNoRows {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
|
2019-05-27 19:34:26 +00:00
|
|
|
galleries := make([]*Gallery, 0)
|
2019-02-09 12:30:49 +00:00
|
|
|
for rows.Next() {
|
2019-05-27 19:34:26 +00:00
|
|
|
gallery := Gallery{}
|
2019-02-09 12:30:49 +00:00
|
|
|
if err := rows.StructScan(&gallery); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-05-27 19:34:26 +00:00
|
|
|
galleries = append(galleries, &gallery)
|
2019-02-09 12:30:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := rows.Err(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return galleries, nil
|
2019-02-14 22:53:32 +00:00
|
|
|
}
|