Movie group renames (#5039)

* Rename Movie and MoviePartial to Group/GroupPartial
* Rename Movie interfaces
* Update movie url builders to use group
* Rename movieRoutes to groupRoutes
* Update dataloader
* Update names in sqlite package
* Rename in resolvers
* Add GroupByURL to scraper config
* Scraper backward compatibility hacks
This commit is contained in:
WithoutPants
2024-07-04 09:10:26 +10:00
committed by GitHub
parent b69d9cc840
commit 15a7b8a859
83 changed files with 1765 additions and 1646 deletions

View File

@@ -57,7 +57,7 @@ func (db *Anonymiser) Anonymise(ctx context.Context) error {
func() error { return db.anonymisePerformers(ctx) },
func() error { return db.anonymiseStudios(ctx) },
func() error { return db.anonymiseTags(ctx) },
func() error { return db.anonymiseMovies(ctx) },
func() error { return db.anonymiseGroups(ctx) },
func() error { return db.Optimise(ctx) },
})
}(); err != nil {
@@ -825,9 +825,9 @@ func (db *Anonymiser) anonymiseTags(ctx context.Context) error {
return nil
}
func (db *Anonymiser) anonymiseMovies(ctx context.Context) error {
logger.Infof("Anonymising movies")
table := movieTableMgr.table
func (db *Anonymiser) anonymiseGroups(ctx context.Context) error {
logger.Infof("Anonymising groups")
table := groupTableMgr.table
lastID := 0
total := 0
const logEvery = 10000
@@ -883,7 +883,7 @@ func (db *Anonymiser) anonymiseMovies(ctx context.Context) error {
total++
if total%logEvery == 0 {
logger.Infof("Anonymised %d movies", total)
logger.Infof("Anonymised %d groups", total)
}
return nil
@@ -893,7 +893,7 @@ func (db *Anonymiser) anonymiseMovies(ctx context.Context) error {
}
}
if err := db.anonymiseURLs(ctx, goqu.T(movieURLsTable), "movie_id"); err != nil {
if err := db.anonymiseURLs(ctx, goqu.T(groupURLsTable), "movie_id"); err != nil {
return err
}

View File

@@ -12,7 +12,7 @@ import (
)
type updateImageFunc func(ctx context.Context, id int, image []byte) error
type getImageFunc func(ctx context.Context, movieID int) ([]byte, error)
type getImageFunc func(ctx context.Context, id int) ([]byte, error)
func testUpdateImage(t *testing.T, ctx context.Context, id int, updateFn updateImageFunc, getFn getImageFunc) error {
image := []byte("image")

View File

@@ -74,7 +74,7 @@ type storeRepository struct {
SavedFilter *SavedFilterStore
Studio *StudioStore
Tag *TagStore
Movie *MovieStore
Group *GroupStore
}
type Database struct {
@@ -110,7 +110,7 @@ func NewDatabase() *Database {
Performer: performerStore,
Studio: studioStore,
Tag: tagStore,
Movie: NewMovieStore(blobStore),
Group: NewGroupStore(blobStore),
SavedFilter: NewSavedFilterStore(),
}

View File

@@ -17,19 +17,19 @@ import (
)
const (
movieTable = "movies"
movieIDColumn = "movie_id"
groupTable = "movies"
groupIDColumn = "movie_id"
movieFrontImageBlobColumn = "front_image_blob"
movieBackImageBlobColumn = "back_image_blob"
groupFrontImageBlobColumn = "front_image_blob"
groupBackImageBlobColumn = "back_image_blob"
moviesTagsTable = "movies_tags"
groupsTagsTable = "movies_tags"
movieURLsTable = "movie_urls"
movieURLColumn = "url"
groupURLsTable = "movie_urls"
groupURLColumn = "url"
)
type movieRow struct {
type groupRow struct {
ID int `db:"id" goqu:"skipinsert"`
Name zero.String `db:"name"`
Aliases zero.String `db:"aliases"`
@@ -48,7 +48,7 @@ type movieRow struct {
BackImageBlob zero.String `db:"back_image_blob"`
}
func (r *movieRow) fromMovie(o models.Movie) {
func (r *groupRow) fromGroup(o models.Group) {
r.ID = o.ID
r.Name = zero.StringFrom(o.Name)
r.Aliases = zero.StringFrom(o.Aliases)
@@ -62,8 +62,8 @@ func (r *movieRow) fromMovie(o models.Movie) {
r.UpdatedAt = Timestamp{Timestamp: o.UpdatedAt}
}
func (r *movieRow) resolve() *models.Movie {
ret := &models.Movie{
func (r *groupRow) resolve() *models.Group {
ret := &models.Group{
ID: r.ID,
Name: r.Name.String,
Aliases: r.Aliases.String,
@@ -80,11 +80,11 @@ func (r *movieRow) resolve() *models.Movie {
return ret
}
type movieRowRecord struct {
type groupRowRecord struct {
updateRecord
}
func (r *movieRowRecord) fromPartial(o models.MoviePartial) {
func (r *groupRowRecord) fromPartial(o models.GroupPartial) {
r.setNullString("name", o.Name)
r.setNullString("aliases", o.Aliases)
r.setNullInt("duration", o.Duration)
@@ -97,26 +97,26 @@ func (r *movieRowRecord) fromPartial(o models.MoviePartial) {
r.setTimestamp("updated_at", o.UpdatedAt)
}
type movieRepositoryType struct {
type groupRepositoryType struct {
repository
scenes repository
tags joinRepository
}
var (
movieRepository = movieRepositoryType{
groupRepository = groupRepositoryType{
repository: repository{
tableName: movieTable,
tableName: groupTable,
idColumn: idColumn,
},
scenes: repository{
tableName: moviesScenesTable,
idColumn: movieIDColumn,
tableName: groupsScenesTable,
idColumn: groupIDColumn,
},
tags: joinRepository{
repository: repository{
tableName: moviesTagsTable,
idColumn: movieIDColumn,
tableName: groupsTagsTable,
idColumn: groupIDColumn,
},
fkColumn: tagIDColumn,
foreignTable: tagTable,
@@ -125,40 +125,40 @@ var (
}
)
type MovieStore struct {
type GroupStore struct {
blobJoinQueryBuilder
tagRelationshipStore
tableMgr *table
}
func NewMovieStore(blobStore *BlobStore) *MovieStore {
return &MovieStore{
func NewGroupStore(blobStore *BlobStore) *GroupStore {
return &GroupStore{
blobJoinQueryBuilder: blobJoinQueryBuilder{
blobStore: blobStore,
joinTable: movieTable,
joinTable: groupTable,
},
tagRelationshipStore: tagRelationshipStore{
idRelationshipStore: idRelationshipStore{
joinTable: moviesTagsTableMgr,
joinTable: groupsTagsTableMgr,
},
},
tableMgr: movieTableMgr,
tableMgr: groupTableMgr,
}
}
func (qb *MovieStore) table() exp.IdentifierExpression {
func (qb *GroupStore) table() exp.IdentifierExpression {
return qb.tableMgr.table
}
func (qb *MovieStore) selectDataset() *goqu.SelectDataset {
func (qb *GroupStore) selectDataset() *goqu.SelectDataset {
return dialect.From(qb.table()).Select(qb.table().All())
}
func (qb *MovieStore) Create(ctx context.Context, newObject *models.Movie) error {
var r movieRow
r.fromMovie(*newObject)
func (qb *GroupStore) Create(ctx context.Context, newObject *models.Group) error {
var r groupRow
r.fromGroup(*newObject)
id, err := qb.tableMgr.insertID(ctx, r)
if err != nil {
@@ -167,7 +167,7 @@ func (qb *MovieStore) Create(ctx context.Context, newObject *models.Movie) error
if newObject.URLs.Loaded() {
const startPos = 0
if err := moviesURLsTableMgr.insertJoins(ctx, id, startPos, newObject.URLs.List()); err != nil {
if err := groupsURLsTableMgr.insertJoins(ctx, id, startPos, newObject.URLs.List()); err != nil {
return err
}
}
@@ -186,8 +186,8 @@ func (qb *MovieStore) Create(ctx context.Context, newObject *models.Movie) error
return nil
}
func (qb *MovieStore) UpdatePartial(ctx context.Context, id int, partial models.MoviePartial) (*models.Movie, error) {
r := movieRowRecord{
func (qb *GroupStore) UpdatePartial(ctx context.Context, id int, partial models.GroupPartial) (*models.Group, error) {
r := groupRowRecord{
updateRecord{
Record: make(exp.Record),
},
@@ -202,7 +202,7 @@ func (qb *MovieStore) UpdatePartial(ctx context.Context, id int, partial models.
}
if partial.URLs != nil {
if err := moviesURLsTableMgr.modifyJoins(ctx, id, partial.URLs.Values, partial.URLs.Mode); err != nil {
if err := groupsURLsTableMgr.modifyJoins(ctx, id, partial.URLs.Values, partial.URLs.Mode); err != nil {
return nil, err
}
}
@@ -214,16 +214,16 @@ func (qb *MovieStore) UpdatePartial(ctx context.Context, id int, partial models.
return qb.find(ctx, id)
}
func (qb *MovieStore) Update(ctx context.Context, updatedObject *models.Movie) error {
var r movieRow
r.fromMovie(*updatedObject)
func (qb *GroupStore) Update(ctx context.Context, updatedObject *models.Group) error {
var r groupRow
r.fromGroup(*updatedObject)
if err := qb.tableMgr.updateByID(ctx, updatedObject.ID, r); err != nil {
return err
}
if updatedObject.URLs.Loaded() {
if err := moviesURLsTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.URLs.List()); err != nil {
if err := groupsURLsTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.URLs.List()); err != nil {
return err
}
}
@@ -235,17 +235,17 @@ func (qb *MovieStore) Update(ctx context.Context, updatedObject *models.Movie) e
return nil
}
func (qb *MovieStore) Destroy(ctx context.Context, id int) error {
func (qb *GroupStore) Destroy(ctx context.Context, id int) error {
// must handle image checksums manually
if err := qb.destroyImages(ctx, id); err != nil {
return err
}
return movieRepository.destroyExisting(ctx, []int{id})
return groupRepository.destroyExisting(ctx, []int{id})
}
// returns nil, nil if not found
func (qb *MovieStore) Find(ctx context.Context, id int) (*models.Movie, error) {
func (qb *GroupStore) Find(ctx context.Context, id int) (*models.Group, error) {
ret, err := qb.find(ctx, id)
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
@@ -253,8 +253,8 @@ func (qb *MovieStore) Find(ctx context.Context, id int) (*models.Movie, error) {
return ret, err
}
func (qb *MovieStore) FindMany(ctx context.Context, ids []int) ([]*models.Movie, error) {
ret := make([]*models.Movie, len(ids))
func (qb *GroupStore) FindMany(ctx context.Context, ids []int) ([]*models.Group, error) {
ret := make([]*models.Group, len(ids))
table := qb.table()
if err := batchExec(ids, defaultBatchSize, func(batch []int) error {
@@ -276,7 +276,7 @@ func (qb *MovieStore) FindMany(ctx context.Context, ids []int) ([]*models.Movie,
for i := range ret {
if ret[i] == nil {
return nil, fmt.Errorf("movie with id %d not found", ids[i])
return nil, fmt.Errorf("group with id %d not found", ids[i])
}
}
@@ -284,7 +284,7 @@ func (qb *MovieStore) FindMany(ctx context.Context, ids []int) ([]*models.Movie,
}
// returns nil, sql.ErrNoRows if not found
func (qb *MovieStore) find(ctx context.Context, id int) (*models.Movie, error) {
func (qb *GroupStore) find(ctx context.Context, id int) (*models.Group, error) {
q := qb.selectDataset().Where(qb.tableMgr.byID(id))
ret, err := qb.get(ctx, q)
@@ -296,7 +296,7 @@ func (qb *MovieStore) find(ctx context.Context, id int) (*models.Movie, error) {
}
// returns nil, sql.ErrNoRows if not found
func (qb *MovieStore) get(ctx context.Context, q *goqu.SelectDataset) (*models.Movie, error) {
func (qb *GroupStore) get(ctx context.Context, q *goqu.SelectDataset) (*models.Group, error) {
ret, err := qb.getMany(ctx, q)
if err != nil {
return nil, err
@@ -309,11 +309,11 @@ func (qb *MovieStore) get(ctx context.Context, q *goqu.SelectDataset) (*models.M
return ret[0], nil
}
func (qb *MovieStore) getMany(ctx context.Context, q *goqu.SelectDataset) ([]*models.Movie, error) {
func (qb *GroupStore) getMany(ctx context.Context, q *goqu.SelectDataset) ([]*models.Group, error) {
const single = false
var ret []*models.Movie
var ret []*models.Group
if err := queryFunc(ctx, q, single, func(r *sqlx.Rows) error {
var f movieRow
var f groupRow
if err := r.StructScan(&f); err != nil {
return err
}
@@ -329,7 +329,7 @@ func (qb *MovieStore) getMany(ctx context.Context, q *goqu.SelectDataset) ([]*mo
return ret, nil
}
func (qb *MovieStore) FindByName(ctx context.Context, name string, nocase bool) (*models.Movie, error) {
func (qb *GroupStore) FindByName(ctx context.Context, name string, nocase bool) (*models.Group, error) {
// query := "SELECT * FROM movies WHERE name = ?"
// if nocase {
// query += " COLLATE NOCASE"
@@ -349,7 +349,7 @@ func (qb *MovieStore) FindByName(ctx context.Context, name string, nocase bool)
return ret, nil
}
func (qb *MovieStore) FindByNames(ctx context.Context, names []string, nocase bool) ([]*models.Movie, error) {
func (qb *GroupStore) FindByNames(ctx context.Context, names []string, nocase bool) ([]*models.Group, error) {
// query := "SELECT * FROM movies WHERE name"
// if nocase {
// query += " COLLATE NOCASE"
@@ -374,12 +374,12 @@ func (qb *MovieStore) FindByNames(ctx context.Context, names []string, nocase bo
return ret, nil
}
func (qb *MovieStore) Count(ctx context.Context) (int, error) {
func (qb *GroupStore) Count(ctx context.Context) (int, error) {
q := dialect.Select(goqu.COUNT("*")).From(qb.table())
return count(ctx, q)
}
func (qb *MovieStore) All(ctx context.Context) ([]*models.Movie, error) {
func (qb *GroupStore) All(ctx context.Context) ([]*models.Group, error) {
table := qb.table()
return qb.getMany(ctx, qb.selectDataset().Order(
@@ -388,24 +388,24 @@ func (qb *MovieStore) All(ctx context.Context) ([]*models.Movie, error) {
))
}
func (qb *MovieStore) makeQuery(ctx context.Context, movieFilter *models.MovieFilterType, findFilter *models.FindFilterType) (*queryBuilder, error) {
func (qb *GroupStore) makeQuery(ctx context.Context, groupFilter *models.GroupFilterType, findFilter *models.FindFilterType) (*queryBuilder, error) {
if findFilter == nil {
findFilter = &models.FindFilterType{}
}
if movieFilter == nil {
movieFilter = &models.MovieFilterType{}
if groupFilter == nil {
groupFilter = &models.GroupFilterType{}
}
query := movieRepository.newQuery()
distinctIDs(&query, movieTable)
query := groupRepository.newQuery()
distinctIDs(&query, groupTable)
if q := findFilter.Q; q != nil && *q != "" {
searchColumns := []string{"movies.name", "movies.aliases"}
query.parseQueryString(searchColumns, *q)
}
filter := filterBuilderFromHandler(ctx, &movieFilterHandler{
movieFilter: movieFilter,
filter := filterBuilderFromHandler(ctx, &groupFilterHandler{
groupFilter: groupFilter,
})
if err := query.addFilter(filter); err != nil {
@@ -413,7 +413,7 @@ func (qb *MovieStore) makeQuery(ctx context.Context, movieFilter *models.MovieFi
}
var err error
query.sortAndPagination, err = qb.getMovieSort(findFilter)
query.sortAndPagination, err = qb.getGroupSort(findFilter)
if err != nil {
return nil, err
}
@@ -423,8 +423,8 @@ func (qb *MovieStore) makeQuery(ctx context.Context, movieFilter *models.MovieFi
return &query, nil
}
func (qb *MovieStore) Query(ctx context.Context, movieFilter *models.MovieFilterType, findFilter *models.FindFilterType) ([]*models.Movie, int, error) {
query, err := qb.makeQuery(ctx, movieFilter, findFilter)
func (qb *GroupStore) Query(ctx context.Context, groupFilter *models.GroupFilterType, findFilter *models.FindFilterType) ([]*models.Group, int, error) {
query, err := qb.makeQuery(ctx, groupFilter, findFilter)
if err != nil {
return nil, 0, err
}
@@ -434,16 +434,16 @@ func (qb *MovieStore) Query(ctx context.Context, movieFilter *models.MovieFilter
return nil, 0, err
}
movies, err := qb.FindMany(ctx, idsResult)
groups, err := qb.FindMany(ctx, idsResult)
if err != nil {
return nil, 0, err
}
return movies, countResult, nil
return groups, countResult, nil
}
func (qb *MovieStore) QueryCount(ctx context.Context, movieFilter *models.MovieFilterType, findFilter *models.FindFilterType) (int, error) {
query, err := qb.makeQuery(ctx, movieFilter, findFilter)
func (qb *GroupStore) QueryCount(ctx context.Context, groupFilter *models.GroupFilterType, findFilter *models.FindFilterType) (int, error) {
query, err := qb.makeQuery(ctx, groupFilter, findFilter)
if err != nil {
return 0, err
}
@@ -451,7 +451,7 @@ func (qb *MovieStore) QueryCount(ctx context.Context, movieFilter *models.MovieF
return query.executeCount(ctx)
}
var movieSortOptions = sortOptions{
var groupSortOptions = sortOptions{
"created_at",
"date",
"duration",
@@ -464,7 +464,7 @@ var movieSortOptions = sortOptions{
"updated_at",
}
func (qb *MovieStore) getMovieSort(findFilter *models.FindFilterType) (string, error) {
func (qb *GroupStore) getGroupSort(findFilter *models.FindFilterType) (string, error) {
var sort string
var direction string
if findFilter == nil {
@@ -476,16 +476,16 @@ func (qb *MovieStore) getMovieSort(findFilter *models.FindFilterType) (string, e
}
// CVE-2024-32231 - ensure sort is in the list of allowed sorts
if err := movieSortOptions.validateSort(sort); err != nil {
if err := groupSortOptions.validateSort(sort); err != nil {
return "", err
}
sortQuery := ""
switch sort {
case "tag_count":
sortQuery += getCountSort(movieTable, moviesTagsTable, movieIDColumn, direction)
sortQuery += getCountSort(groupTable, groupsTagsTable, groupIDColumn, direction)
case "scenes_count": // generic getSort won't work for this
sortQuery += getCountSort(movieTable, moviesScenesTable, movieIDColumn, direction)
sortQuery += getCountSort(groupTable, groupsScenesTable, groupIDColumn, direction)
default:
sortQuery += getSort(sort, direction, "movies")
}
@@ -495,11 +495,11 @@ func (qb *MovieStore) getMovieSort(findFilter *models.FindFilterType) (string, e
return sortQuery, nil
}
func (qb *MovieStore) queryMovies(ctx context.Context, query string, args []interface{}) ([]*models.Movie, error) {
func (qb *GroupStore) queryGroups(ctx context.Context, query string, args []interface{}) ([]*models.Group, error) {
const single = false
var ret []*models.Movie
if err := movieRepository.queryFunc(ctx, query, args, single, func(r *sqlx.Rows) error {
var f movieRow
var ret []*models.Group
if err := groupRepository.queryFunc(ctx, query, args, single, func(r *sqlx.Rows) error {
var f groupRow
if err := r.StructScan(&f); err != nil {
return err
}
@@ -515,42 +515,42 @@ func (qb *MovieStore) queryMovies(ctx context.Context, query string, args []inte
return ret, nil
}
func (qb *MovieStore) UpdateFrontImage(ctx context.Context, movieID int, frontImage []byte) error {
return qb.UpdateImage(ctx, movieID, movieFrontImageBlobColumn, frontImage)
func (qb *GroupStore) UpdateFrontImage(ctx context.Context, groupID int, frontImage []byte) error {
return qb.UpdateImage(ctx, groupID, groupFrontImageBlobColumn, frontImage)
}
func (qb *MovieStore) UpdateBackImage(ctx context.Context, movieID int, backImage []byte) error {
return qb.UpdateImage(ctx, movieID, movieBackImageBlobColumn, backImage)
func (qb *GroupStore) UpdateBackImage(ctx context.Context, groupID int, backImage []byte) error {
return qb.UpdateImage(ctx, groupID, groupBackImageBlobColumn, backImage)
}
func (qb *MovieStore) destroyImages(ctx context.Context, movieID int) error {
if err := qb.DestroyImage(ctx, movieID, movieFrontImageBlobColumn); err != nil {
func (qb *GroupStore) destroyImages(ctx context.Context, groupID int) error {
if err := qb.DestroyImage(ctx, groupID, groupFrontImageBlobColumn); err != nil {
return err
}
if err := qb.DestroyImage(ctx, movieID, movieBackImageBlobColumn); err != nil {
if err := qb.DestroyImage(ctx, groupID, groupBackImageBlobColumn); err != nil {
return err
}
return nil
}
func (qb *MovieStore) GetFrontImage(ctx context.Context, movieID int) ([]byte, error) {
return qb.GetImage(ctx, movieID, movieFrontImageBlobColumn)
func (qb *GroupStore) GetFrontImage(ctx context.Context, groupID int) ([]byte, error) {
return qb.GetImage(ctx, groupID, groupFrontImageBlobColumn)
}
func (qb *MovieStore) HasFrontImage(ctx context.Context, movieID int) (bool, error) {
return qb.HasImage(ctx, movieID, movieFrontImageBlobColumn)
func (qb *GroupStore) HasFrontImage(ctx context.Context, groupID int) (bool, error) {
return qb.HasImage(ctx, groupID, groupFrontImageBlobColumn)
}
func (qb *MovieStore) GetBackImage(ctx context.Context, movieID int) ([]byte, error) {
return qb.GetImage(ctx, movieID, movieBackImageBlobColumn)
func (qb *GroupStore) GetBackImage(ctx context.Context, groupID int) ([]byte, error) {
return qb.GetImage(ctx, groupID, groupBackImageBlobColumn)
}
func (qb *MovieStore) HasBackImage(ctx context.Context, movieID int) (bool, error) {
return qb.HasImage(ctx, movieID, movieBackImageBlobColumn)
func (qb *GroupStore) HasBackImage(ctx context.Context, groupID int) (bool, error) {
return qb.HasImage(ctx, groupID, groupBackImageBlobColumn)
}
func (qb *MovieStore) FindByPerformerID(ctx context.Context, performerID int) ([]*models.Movie, error) {
func (qb *GroupStore) FindByPerformerID(ctx context.Context, performerID int) ([]*models.Group, error) {
query := `SELECT DISTINCT movies.*
FROM movies
INNER JOIN movies_scenes ON movies.id = movies_scenes.movie_id
@@ -558,37 +558,37 @@ INNER JOIN performers_scenes ON performers_scenes.scene_id = movies_scenes.scene
WHERE performers_scenes.performer_id = ?
`
args := []interface{}{performerID}
return qb.queryMovies(ctx, query, args)
return qb.queryGroups(ctx, query, args)
}
func (qb *MovieStore) CountByPerformerID(ctx context.Context, performerID int) (int, error) {
func (qb *GroupStore) CountByPerformerID(ctx context.Context, performerID int) (int, error) {
query := `SELECT COUNT(DISTINCT movies_scenes.movie_id) AS count
FROM movies_scenes
INNER JOIN performers_scenes ON performers_scenes.scene_id = movies_scenes.scene_id
WHERE performers_scenes.performer_id = ?
`
args := []interface{}{performerID}
return movieRepository.runCountQuery(ctx, query, args)
return groupRepository.runCountQuery(ctx, query, args)
}
func (qb *MovieStore) FindByStudioID(ctx context.Context, studioID int) ([]*models.Movie, error) {
func (qb *GroupStore) FindByStudioID(ctx context.Context, studioID int) ([]*models.Group, error) {
query := `SELECT movies.*
FROM movies
WHERE movies.studio_id = ?
`
args := []interface{}{studioID}
return qb.queryMovies(ctx, query, args)
return qb.queryGroups(ctx, query, args)
}
func (qb *MovieStore) CountByStudioID(ctx context.Context, studioID int) (int, error) {
func (qb *GroupStore) CountByStudioID(ctx context.Context, studioID int) (int, error) {
query := `SELECT COUNT(1) AS count
FROM movies
WHERE movies.studio_id = ?
`
args := []interface{}{studioID}
return movieRepository.runCountQuery(ctx, query, args)
return groupRepository.runCountQuery(ctx, query, args)
}
func (qb *MovieStore) GetURLs(ctx context.Context, movieID int) ([]string, error) {
return moviesURLsTableMgr.get(ctx, movieID)
func (qb *GroupStore) GetURLs(ctx context.Context, groupID int) ([]string, error) {
return groupsURLsTableMgr.get(ctx, groupID)
}

View File

@@ -7,22 +7,22 @@ import (
"github.com/stashapp/stash/pkg/models"
)
type movieFilterHandler struct {
movieFilter *models.MovieFilterType
type groupFilterHandler struct {
groupFilter *models.GroupFilterType
}
func (qb *movieFilterHandler) validate() error {
movieFilter := qb.movieFilter
if movieFilter == nil {
func (qb *groupFilterHandler) validate() error {
groupFilter := qb.groupFilter
if groupFilter == nil {
return nil
}
if err := validateFilterCombination(movieFilter.OperatorFilter); err != nil {
if err := validateFilterCombination(groupFilter.OperatorFilter); err != nil {
return err
}
if subFilter := movieFilter.SubFilter(); subFilter != nil {
sqb := &movieFilterHandler{movieFilter: subFilter}
if subFilter := groupFilter.SubFilter(); subFilter != nil {
sqb := &groupFilterHandler{groupFilter: subFilter}
if err := sqb.validate(); err != nil {
return err
}
@@ -31,9 +31,9 @@ func (qb *movieFilterHandler) validate() error {
return nil
}
func (qb *movieFilterHandler) handle(ctx context.Context, f *filterBuilder) {
movieFilter := qb.movieFilter
if movieFilter == nil {
func (qb *groupFilterHandler) handle(ctx context.Context, f *filterBuilder) {
groupFilter := qb.groupFilter
if groupFilter == nil {
return
}
@@ -42,51 +42,51 @@ func (qb *movieFilterHandler) handle(ctx context.Context, f *filterBuilder) {
return
}
sf := movieFilter.SubFilter()
sf := groupFilter.SubFilter()
if sf != nil {
sub := &movieFilterHandler{sf}
handleSubFilter(ctx, sub, f, movieFilter.OperatorFilter)
sub := &groupFilterHandler{sf}
handleSubFilter(ctx, sub, f, groupFilter.OperatorFilter)
}
f.handleCriterion(ctx, qb.criterionHandler())
}
func (qb *movieFilterHandler) criterionHandler() criterionHandler {
movieFilter := qb.movieFilter
func (qb *groupFilterHandler) criterionHandler() criterionHandler {
groupFilter := qb.groupFilter
return compoundHandler{
stringCriterionHandler(movieFilter.Name, "movies.name"),
stringCriterionHandler(movieFilter.Director, "movies.director"),
stringCriterionHandler(movieFilter.Synopsis, "movies.synopsis"),
intCriterionHandler(movieFilter.Rating100, "movies.rating", nil),
floatIntCriterionHandler(movieFilter.Duration, "movies.duration", nil),
qb.missingCriterionHandler(movieFilter.IsMissing),
qb.urlsCriterionHandler(movieFilter.URL),
studioCriterionHandler(movieTable, movieFilter.Studios),
qb.performersCriterionHandler(movieFilter.Performers),
qb.tagsCriterionHandler(movieFilter.Tags),
qb.tagCountCriterionHandler(movieFilter.TagCount),
&dateCriterionHandler{movieFilter.Date, "movies.date", nil},
&timestampCriterionHandler{movieFilter.CreatedAt, "movies.created_at", nil},
&timestampCriterionHandler{movieFilter.UpdatedAt, "movies.updated_at", nil},
stringCriterionHandler(groupFilter.Name, "movies.name"),
stringCriterionHandler(groupFilter.Director, "movies.director"),
stringCriterionHandler(groupFilter.Synopsis, "movies.synopsis"),
intCriterionHandler(groupFilter.Rating100, "movies.rating", nil),
floatIntCriterionHandler(groupFilter.Duration, "movies.duration", nil),
qb.missingCriterionHandler(groupFilter.IsMissing),
qb.urlsCriterionHandler(groupFilter.URL),
studioCriterionHandler(groupTable, groupFilter.Studios),
qb.performersCriterionHandler(groupFilter.Performers),
qb.tagsCriterionHandler(groupFilter.Tags),
qb.tagCountCriterionHandler(groupFilter.TagCount),
&dateCriterionHandler{groupFilter.Date, "movies.date", nil},
&timestampCriterionHandler{groupFilter.CreatedAt, "movies.created_at", nil},
&timestampCriterionHandler{groupFilter.UpdatedAt, "movies.updated_at", nil},
&relatedFilterHandler{
relatedIDCol: "movies_scenes.scene_id",
relatedRepo: sceneRepository.repository,
relatedHandler: &sceneFilterHandler{movieFilter.ScenesFilter},
relatedHandler: &sceneFilterHandler{groupFilter.ScenesFilter},
joinFn: func(f *filterBuilder) {
movieRepository.scenes.innerJoin(f, "", "movies.id")
groupRepository.scenes.innerJoin(f, "", "movies.id")
},
},
&relatedFilterHandler{
relatedIDCol: "movies.studio_id",
relatedRepo: studioRepository.repository,
relatedHandler: &studioFilterHandler{movieFilter.StudiosFilter},
relatedHandler: &studioFilterHandler{groupFilter.StudiosFilter},
},
}
}
func (qb *movieFilterHandler) missingCriterionHandler(isMissing *string) criterionHandlerFunc {
func (qb *groupFilterHandler) missingCriterionHandler(isMissing *string) criterionHandlerFunc {
return func(ctx context.Context, f *filterBuilder) {
if isMissing != nil && *isMissing != "" {
switch *isMissing {
@@ -104,21 +104,21 @@ func (qb *movieFilterHandler) missingCriterionHandler(isMissing *string) criteri
}
}
func (qb *movieFilterHandler) urlsCriterionHandler(url *models.StringCriterionInput) criterionHandlerFunc {
func (qb *groupFilterHandler) urlsCriterionHandler(url *models.StringCriterionInput) criterionHandlerFunc {
h := stringListCriterionHandlerBuilder{
primaryTable: movieTable,
primaryFK: movieIDColumn,
joinTable: movieURLsTable,
stringColumn: movieURLColumn,
primaryTable: groupTable,
primaryFK: groupIDColumn,
joinTable: groupURLsTable,
stringColumn: groupURLColumn,
addJoinTable: func(f *filterBuilder) {
moviesURLsTableMgr.join(f, "", "movies.id")
groupsURLsTableMgr.join(f, "", "movies.id")
},
}
return h.handler(url)
}
func (qb *movieFilterHandler) performersCriterionHandler(performers *models.MultiCriterionInput) criterionHandlerFunc {
func (qb *groupFilterHandler) performersCriterionHandler(performers *models.MultiCriterionInput) criterionHandlerFunc {
return func(ctx context.Context, f *filterBuilder) {
if performers != nil {
if performers.Modifier == models.CriterionModifierIsNull || performers.Modifier == models.CriterionModifierNotNull {
@@ -165,26 +165,26 @@ func (qb *movieFilterHandler) performersCriterionHandler(performers *models.Mult
}
}
func (qb *movieFilterHandler) tagsCriterionHandler(tags *models.HierarchicalMultiCriterionInput) criterionHandlerFunc {
func (qb *groupFilterHandler) tagsCriterionHandler(tags *models.HierarchicalMultiCriterionInput) criterionHandlerFunc {
h := joinedHierarchicalMultiCriterionHandlerBuilder{
primaryTable: movieTable,
primaryTable: groupTable,
foreignTable: tagTable,
foreignFK: "tag_id",
relationsTable: "tags_relations",
joinAs: "movie_tag",
joinTable: moviesTagsTable,
primaryFK: movieIDColumn,
joinTable: groupsTagsTable,
primaryFK: groupIDColumn,
}
return h.handler(tags)
}
func (qb *movieFilterHandler) tagCountCriterionHandler(count *models.IntCriterionInput) criterionHandlerFunc {
func (qb *groupFilterHandler) tagCountCriterionHandler(count *models.IntCriterionInput) criterionHandlerFunc {
h := countCriterionHandlerBuilder{
primaryTable: movieTable,
joinTable: moviesTagsTable,
primaryFK: movieIDColumn,
primaryTable: groupTable,
joinTable: groupsTagsTable,
primaryFK: groupIDColumn,
}
return h.handler(count)

View File

@@ -16,14 +16,14 @@ import (
"github.com/stashapp/stash/pkg/models"
)
func loadMovieRelationships(ctx context.Context, expected models.Movie, actual *models.Movie) error {
func loadGroupRelationships(ctx context.Context, expected models.Group, actual *models.Group) error {
if expected.URLs.Loaded() {
if err := actual.LoadURLs(ctx, db.Movie); err != nil {
if err := actual.LoadURLs(ctx, db.Group); err != nil {
return err
}
}
if expected.TagIDs.Loaded() {
if err := actual.LoadTagIDs(ctx, db.Movie); err != nil {
if err := actual.LoadTagIDs(ctx, db.Group); err != nil {
return err
}
}
@@ -31,7 +31,7 @@ func loadMovieRelationships(ctx context.Context, expected models.Movie, actual *
return nil
}
func Test_MovieStore_Create(t *testing.T) {
func Test_GroupStore_Create(t *testing.T) {
var (
name = "name"
url = "url"
@@ -47,21 +47,21 @@ func Test_MovieStore_Create(t *testing.T) {
tests := []struct {
name string
newObject models.Movie
newObject models.Group
wantErr bool
}{
{
"full",
models.Movie{
models.Group{
Name: name,
Duration: &duration,
Date: &date,
Rating: &rating,
StudioID: &studioIDs[studioIdxWithMovie],
StudioID: &studioIDs[studioIdxWithGroup],
Director: director,
Synopsis: synopsis,
URLs: models.NewRelatedStrings([]string{url}),
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithMovie]}),
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithGroup]}),
Aliases: aliases,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
@@ -70,7 +70,7 @@ func Test_MovieStore_Create(t *testing.T) {
},
{
"invalid tag id",
models.Movie{
models.Group{
Name: name,
TagIDs: models.NewRelatedIDs([]int{invalidID}),
},
@@ -78,7 +78,7 @@ func Test_MovieStore_Create(t *testing.T) {
},
}
qb := db.Movie
qb := db.Group
for _, tt := range tests {
runWithRollbackTxn(t, tt.name, func(t *testing.T, ctx context.Context) {
@@ -86,7 +86,7 @@ func Test_MovieStore_Create(t *testing.T) {
p := tt.newObject
if err := qb.Create(ctx, &p); (err != nil) != tt.wantErr {
t.Errorf("MovieStore.Create() error = %v, wantErr = %v", err, tt.wantErr)
t.Errorf("GroupStore.Create() error = %v, wantErr = %v", err, tt.wantErr)
}
if tt.wantErr {
@@ -100,17 +100,17 @@ func Test_MovieStore_Create(t *testing.T) {
copy.ID = p.ID
// load relationships
if err := loadMovieRelationships(ctx, copy, &p); err != nil {
t.Errorf("loadMovieRelationships() error = %v", err)
if err := loadGroupRelationships(ctx, copy, &p); err != nil {
t.Errorf("loadGroupRelationships() error = %v", err)
return
}
assert.Equal(copy, p)
// ensure can find the movie
// ensure can find the group
found, err := qb.Find(ctx, p.ID)
if err != nil {
t.Errorf("MovieStore.Find() error = %v", err)
t.Errorf("GroupStore.Find() error = %v", err)
}
if !assert.NotNil(found) {
@@ -118,8 +118,8 @@ func Test_MovieStore_Create(t *testing.T) {
}
// load relationships
if err := loadMovieRelationships(ctx, copy, found); err != nil {
t.Errorf("loadMovieRelationships() error = %v", err)
if err := loadGroupRelationships(ctx, copy, found); err != nil {
t.Errorf("loadGroupRelationships() error = %v", err)
return
}
assert.Equal(copy, *found)
@@ -129,7 +129,7 @@ func Test_MovieStore_Create(t *testing.T) {
}
}
func Test_movieQueryBuilder_Update(t *testing.T) {
func Test_groupQueryBuilder_Update(t *testing.T) {
var (
name = "name"
url = "url"
@@ -145,22 +145,22 @@ func Test_movieQueryBuilder_Update(t *testing.T) {
tests := []struct {
name string
updatedObject *models.Movie
updatedObject *models.Group
wantErr bool
}{
{
"full",
&models.Movie{
ID: movieIDs[movieIdxWithTag],
&models.Group{
ID: groupIDs[groupIdxWithTag],
Name: name,
Duration: &duration,
Date: &date,
Rating: &rating,
StudioID: &studioIDs[studioIdxWithMovie],
StudioID: &studioIDs[studioIdxWithGroup],
Director: director,
Synopsis: synopsis,
URLs: models.NewRelatedStrings([]string{url}),
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithMovie]}),
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithGroup]}),
Aliases: aliases,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
@@ -169,8 +169,8 @@ func Test_movieQueryBuilder_Update(t *testing.T) {
},
{
"clear tag ids",
&models.Movie{
ID: movieIDs[movieIdxWithTag],
&models.Group{
ID: groupIDs[groupIdxWithTag],
Name: name,
TagIDs: models.NewRelatedIDs([]int{}),
},
@@ -178,8 +178,8 @@ func Test_movieQueryBuilder_Update(t *testing.T) {
},
{
"invalid studio id",
&models.Movie{
ID: movieIDs[movieIdxWithScene],
&models.Group{
ID: groupIDs[groupIdxWithScene],
Name: name,
StudioID: &invalidID,
},
@@ -187,8 +187,8 @@ func Test_movieQueryBuilder_Update(t *testing.T) {
},
{
"invalid tag id",
&models.Movie{
ID: movieIDs[movieIdxWithScene],
&models.Group{
ID: groupIDs[groupIdxWithScene],
Name: name,
TagIDs: models.NewRelatedIDs([]int{invalidID}),
},
@@ -196,7 +196,7 @@ func Test_movieQueryBuilder_Update(t *testing.T) {
},
}
qb := db.Movie
qb := db.Group
for _, tt := range tests {
runWithRollbackTxn(t, tt.name, func(t *testing.T, ctx context.Context) {
assert := assert.New(t)
@@ -204,7 +204,7 @@ func Test_movieQueryBuilder_Update(t *testing.T) {
copy := *tt.updatedObject
if err := qb.Update(ctx, tt.updatedObject); (err != nil) != tt.wantErr {
t.Errorf("movieQueryBuilder.Update() error = %v, wantErr %v", err, tt.wantErr)
t.Errorf("groupQueryBuilder.Update() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.wantErr {
@@ -213,12 +213,12 @@ func Test_movieQueryBuilder_Update(t *testing.T) {
s, err := qb.Find(ctx, tt.updatedObject.ID)
if err != nil {
t.Errorf("movieQueryBuilder.Find() error = %v", err)
t.Errorf("groupQueryBuilder.Find() error = %v", err)
}
// load relationships
if err := loadMovieRelationships(ctx, copy, s); err != nil {
t.Errorf("loadMovieRelationships() error = %v", err)
if err := loadGroupRelationships(ctx, copy, s); err != nil {
t.Errorf("loadGroupRelationships() error = %v", err)
return
}
@@ -227,9 +227,9 @@ func Test_movieQueryBuilder_Update(t *testing.T) {
}
}
func clearMoviePartial() models.MoviePartial {
func clearGroupPartial() models.GroupPartial {
// leave mandatory fields
return models.MoviePartial{
return models.GroupPartial{
Aliases: models.OptionalString{Set: true, Null: true},
Synopsis: models.OptionalString{Set: true, Null: true},
Director: models.OptionalString{Set: true, Null: true},
@@ -242,7 +242,7 @@ func clearMoviePartial() models.MoviePartial {
}
}
func Test_movieQueryBuilder_UpdatePartial(t *testing.T) {
func Test_groupQueryBuilder_UpdatePartial(t *testing.T) {
var (
name = "name"
url = "url"
@@ -259,14 +259,14 @@ func Test_movieQueryBuilder_UpdatePartial(t *testing.T) {
tests := []struct {
name string
id int
partial models.MoviePartial
want models.Movie
partial models.GroupPartial
want models.Group
wantErr bool
}{
{
"full",
movieIDs[movieIdxWithScene],
models.MoviePartial{
groupIDs[groupIdxWithScene],
models.GroupPartial{
Name: models.NewOptionalString(name),
Director: models.NewOptionalString(director),
Synopsis: models.NewOptionalString(synopsis),
@@ -278,16 +278,16 @@ func Test_movieQueryBuilder_UpdatePartial(t *testing.T) {
Date: models.NewOptionalDate(date),
Duration: models.NewOptionalInt(duration),
Rating: models.NewOptionalInt(rating),
StudioID: models.NewOptionalInt(studioIDs[studioIdxWithMovie]),
StudioID: models.NewOptionalInt(studioIDs[studioIdxWithGroup]),
CreatedAt: models.NewOptionalTime(createdAt),
UpdatedAt: models.NewOptionalTime(updatedAt),
TagIDs: &models.UpdateIDs{
IDs: []int{tagIDs[tagIdx1WithMovie], tagIDs[tagIdx1WithDupName]},
IDs: []int{tagIDs[tagIdx1WithGroup], tagIDs[tagIdx1WithDupName]},
Mode: models.RelationshipUpdateModeSet,
},
},
models.Movie{
ID: movieIDs[movieIdxWithScene],
models.Group{
ID: groupIDs[groupIdxWithScene],
Name: name,
Director: director,
Synopsis: synopsis,
@@ -296,20 +296,20 @@ func Test_movieQueryBuilder_UpdatePartial(t *testing.T) {
Date: &date,
Duration: &duration,
Rating: &rating,
StudioID: &studioIDs[studioIdxWithMovie],
StudioID: &studioIDs[studioIdxWithGroup],
CreatedAt: createdAt,
UpdatedAt: updatedAt,
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithMovie]}),
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithGroup]}),
},
false,
},
{
"clear all",
movieIDs[movieIdxWithScene],
clearMoviePartial(),
models.Movie{
ID: movieIDs[movieIdxWithScene],
Name: movieNames[movieIdxWithScene],
groupIDs[groupIdxWithScene],
clearGroupPartial(),
models.Group{
ID: groupIDs[groupIdxWithScene],
Name: groupNames[groupIdxWithScene],
TagIDs: models.NewRelatedIDs([]int{}),
},
false,
@@ -317,20 +317,20 @@ func Test_movieQueryBuilder_UpdatePartial(t *testing.T) {
{
"invalid id",
invalidID,
models.MoviePartial{},
models.Movie{},
models.GroupPartial{},
models.Group{},
true,
},
}
for _, tt := range tests {
qb := db.Movie
qb := db.Group
runWithRollbackTxn(t, tt.name, func(t *testing.T, ctx context.Context) {
assert := assert.New(t)
got, err := qb.UpdatePartial(ctx, tt.id, tt.partial)
if (err != nil) != tt.wantErr {
t.Errorf("movieQueryBuilder.UpdatePartial() error = %v, wantErr %v", err, tt.wantErr)
t.Errorf("groupQueryBuilder.UpdatePartial() error = %v, wantErr %v", err, tt.wantErr)
return
}
@@ -339,8 +339,8 @@ func Test_movieQueryBuilder_UpdatePartial(t *testing.T) {
}
// load relationships
if err := loadMovieRelationships(ctx, tt.want, got); err != nil {
t.Errorf("loadMovieRelationships() error = %v", err)
if err := loadGroupRelationships(ctx, tt.want, got); err != nil {
t.Errorf("loadGroupRelationships() error = %v", err)
return
}
@@ -348,12 +348,12 @@ func Test_movieQueryBuilder_UpdatePartial(t *testing.T) {
s, err := qb.Find(ctx, tt.id)
if err != nil {
t.Errorf("movieQueryBuilder.Find() error = %v", err)
t.Errorf("groupQueryBuilder.Find() error = %v", err)
}
// load relationships
if err := loadMovieRelationships(ctx, tt.want, s); err != nil {
t.Errorf("loadMovieRelationships() error = %v", err)
if err := loadGroupRelationships(ctx, tt.want, s); err != nil {
t.Errorf("loadGroupRelationships() error = %v", err)
return
}
@@ -362,65 +362,65 @@ func Test_movieQueryBuilder_UpdatePartial(t *testing.T) {
}
}
func TestMovieFindByName(t *testing.T) {
func TestGroupFindByName(t *testing.T) {
withTxn(func(ctx context.Context) error {
mqb := db.Movie
mqb := db.Group
name := movieNames[movieIdxWithScene] // find a movie by name
name := groupNames[groupIdxWithScene] // find a group by name
movie, err := mqb.FindByName(ctx, name, false)
group, err := mqb.FindByName(ctx, name, false)
if err != nil {
t.Errorf("Error finding movies: %s", err.Error())
t.Errorf("Error finding groups: %s", err.Error())
}
assert.Equal(t, movieNames[movieIdxWithScene], movie.Name)
assert.Equal(t, groupNames[groupIdxWithScene], group.Name)
name = movieNames[movieIdxWithDupName] // find a movie by name nocase
name = groupNames[groupIdxWithDupName] // find a group by name nocase
movie, err = mqb.FindByName(ctx, name, true)
group, err = mqb.FindByName(ctx, name, true)
if err != nil {
t.Errorf("Error finding movies: %s", err.Error())
t.Errorf("Error finding groups: %s", err.Error())
}
// movieIdxWithDupName and movieIdxWithScene should have similar names ( only diff should be Name vs NaMe)
//movie.Name should match with movieIdxWithScene since its ID is before moveIdxWithDupName
assert.Equal(t, movieNames[movieIdxWithScene], movie.Name)
//movie.Name should match with movieIdxWithDupName if the check is not case sensitive
assert.Equal(t, strings.ToLower(movieNames[movieIdxWithDupName]), strings.ToLower(movie.Name))
// groupIdxWithDupName and groupIdxWithScene should have similar names ( only diff should be Name vs NaMe)
//group.Name should match with groupIdxWithScene since its ID is before moveIdxWithDupName
assert.Equal(t, groupNames[groupIdxWithScene], group.Name)
//group.Name should match with groupIdxWithDupName if the check is not case sensitive
assert.Equal(t, strings.ToLower(groupNames[groupIdxWithDupName]), strings.ToLower(group.Name))
return nil
})
}
func TestMovieFindByNames(t *testing.T) {
func TestGroupFindByNames(t *testing.T) {
withTxn(func(ctx context.Context) error {
var names []string
mqb := db.Movie
mqb := db.Group
names = append(names, movieNames[movieIdxWithScene]) // find movies by names
names = append(names, groupNames[groupIdxWithScene]) // find groups by names
movies, err := mqb.FindByNames(ctx, names, false)
groups, err := mqb.FindByNames(ctx, names, false)
if err != nil {
t.Errorf("Error finding movies: %s", err.Error())
t.Errorf("Error finding groups: %s", err.Error())
}
assert.Len(t, movies, 1)
assert.Equal(t, movieNames[movieIdxWithScene], movies[0].Name)
assert.Len(t, groups, 1)
assert.Equal(t, groupNames[groupIdxWithScene], groups[0].Name)
movies, err = mqb.FindByNames(ctx, names, true) // find movies by names nocase
groups, err = mqb.FindByNames(ctx, names, true) // find groups by names nocase
if err != nil {
t.Errorf("Error finding movies: %s", err.Error())
t.Errorf("Error finding groups: %s", err.Error())
}
assert.Len(t, movies, 2) // movieIdxWithScene and movieIdxWithDupName
assert.Equal(t, strings.ToLower(movieNames[movieIdxWithScene]), strings.ToLower(movies[0].Name))
assert.Equal(t, strings.ToLower(movieNames[movieIdxWithScene]), strings.ToLower(movies[1].Name))
assert.Len(t, groups, 2) // groupIdxWithScene and groupIdxWithDupName
assert.Equal(t, strings.ToLower(groupNames[groupIdxWithScene]), strings.ToLower(groups[0].Name))
assert.Equal(t, strings.ToLower(groupNames[groupIdxWithScene]), strings.ToLower(groups[1].Name))
return nil
})
}
func moviesToIDs(i []*models.Movie) []int {
func groupsToIDs(i []*models.Group) []int {
ret := make([]int, len(i))
for i, v := range i {
ret[i] = v.ID
@@ -429,7 +429,7 @@ func moviesToIDs(i []*models.Movie) []int {
return ret
}
func TestMovieQuery(t *testing.T) {
func TestGroupQuery(t *testing.T) {
var (
frontImage = "front_image"
backImage = "back_image"
@@ -438,7 +438,7 @@ func TestMovieQuery(t *testing.T) {
tests := []struct {
name string
findFilter *models.FindFilterType
filter *models.MovieFilterType
filter *models.GroupFilterType
includeIdxs []int
excludeIdxs []int
wantErr bool
@@ -446,7 +446,7 @@ func TestMovieQuery(t *testing.T) {
{
"is missing front image",
nil,
&models.MovieFilterType{
&models.GroupFilterType{
IsMissing: &frontImage,
},
// just ensure that it doesn't error
@@ -457,7 +457,7 @@ func TestMovieQuery(t *testing.T) {
{
"is missing back image",
nil,
&models.MovieFilterType{
&models.GroupFilterType{
IsMissing: &backImage,
},
// just ensure that it doesn't error
@@ -471,13 +471,13 @@ func TestMovieQuery(t *testing.T) {
runWithRollbackTxn(t, tt.name, func(t *testing.T, ctx context.Context) {
assert := assert.New(t)
results, _, err := db.Movie.Query(ctx, tt.filter, tt.findFilter)
results, _, err := db.Group.Query(ctx, tt.filter, tt.findFilter)
if (err != nil) != tt.wantErr {
t.Errorf("MovieQueryBuilder.Query() error = %v, wantErr %v", err, tt.wantErr)
t.Errorf("GroupQueryBuilder.Query() error = %v, wantErr %v", err, tt.wantErr)
return
}
ids := moviesToIDs(results)
ids := groupsToIDs(results)
include := indexesToIDs(performerIDs, tt.includeIdxs)
exclude := indexesToIDs(performerIDs, tt.excludeIdxs)
@@ -491,66 +491,66 @@ func TestMovieQuery(t *testing.T) {
}
}
func TestMovieQueryStudio(t *testing.T) {
func TestGroupQueryStudio(t *testing.T) {
withTxn(func(ctx context.Context) error {
mqb := db.Movie
mqb := db.Group
studioCriterion := models.HierarchicalMultiCriterionInput{
Value: []string{
strconv.Itoa(studioIDs[studioIdxWithMovie]),
strconv.Itoa(studioIDs[studioIdxWithGroup]),
},
Modifier: models.CriterionModifierIncludes,
}
movieFilter := models.MovieFilterType{
groupFilter := models.GroupFilterType{
Studios: &studioCriterion,
}
movies, _, err := mqb.Query(ctx, &movieFilter, nil)
groups, _, err := mqb.Query(ctx, &groupFilter, nil)
if err != nil {
t.Errorf("Error querying movie: %s", err.Error())
t.Errorf("Error querying group: %s", err.Error())
}
assert.Len(t, movies, 1)
assert.Len(t, groups, 1)
// ensure id is correct
assert.Equal(t, movieIDs[movieIdxWithStudio], movies[0].ID)
assert.Equal(t, groupIDs[groupIdxWithStudio], groups[0].ID)
studioCriterion = models.HierarchicalMultiCriterionInput{
Value: []string{
strconv.Itoa(studioIDs[studioIdxWithMovie]),
strconv.Itoa(studioIDs[studioIdxWithGroup]),
},
Modifier: models.CriterionModifierExcludes,
}
q := getMovieStringValue(movieIdxWithStudio, titleField)
q := getGroupStringValue(groupIdxWithStudio, titleField)
findFilter := models.FindFilterType{
Q: &q,
}
movies, _, err = mqb.Query(ctx, &movieFilter, &findFilter)
groups, _, err = mqb.Query(ctx, &groupFilter, &findFilter)
if err != nil {
t.Errorf("Error querying movie: %s", err.Error())
t.Errorf("Error querying group: %s", err.Error())
}
assert.Len(t, movies, 0)
assert.Len(t, groups, 0)
return nil
})
}
func TestMovieQueryURL(t *testing.T) {
func TestGroupQueryURL(t *testing.T) {
const sceneIdx = 1
movieURL := getMovieStringValue(sceneIdx, urlField)
groupURL := getGroupStringValue(sceneIdx, urlField)
urlCriterion := models.StringCriterionInput{
Value: movieURL,
Value: groupURL,
Modifier: models.CriterionModifierEquals,
}
filter := models.MovieFilterType{
filter := models.GroupFilterType{
URL: &urlCriterion,
}
verifyFn := func(n *models.Movie) {
verifyFn := func(n *models.Group) {
t.Helper()
urls := n.URLs.List()
@@ -562,93 +562,93 @@ func TestMovieQueryURL(t *testing.T) {
verifyString(t, url, urlCriterion)
}
verifyMovieQuery(t, filter, verifyFn)
verifyGroupQuery(t, filter, verifyFn)
urlCriterion.Modifier = models.CriterionModifierNotEquals
verifyMovieQuery(t, filter, verifyFn)
verifyGroupQuery(t, filter, verifyFn)
urlCriterion.Modifier = models.CriterionModifierMatchesRegex
urlCriterion.Value = "movie_.*1_URL"
verifyMovieQuery(t, filter, verifyFn)
urlCriterion.Value = "group_.*1_URL"
verifyGroupQuery(t, filter, verifyFn)
urlCriterion.Modifier = models.CriterionModifierNotMatchesRegex
verifyMovieQuery(t, filter, verifyFn)
verifyGroupQuery(t, filter, verifyFn)
urlCriterion.Modifier = models.CriterionModifierIsNull
urlCriterion.Value = ""
verifyMovieQuery(t, filter, verifyFn)
verifyGroupQuery(t, filter, verifyFn)
urlCriterion.Modifier = models.CriterionModifierNotNull
verifyMovieQuery(t, filter, verifyFn)
verifyGroupQuery(t, filter, verifyFn)
}
func TestMovieQueryURLExcludes(t *testing.T) {
func TestGroupQueryURLExcludes(t *testing.T) {
withRollbackTxn(func(ctx context.Context) error {
mqb := db.Movie
mqb := db.Group
// create movie with two URLs
movie := models.Movie{
Name: "TestMovieQueryURLExcludes",
// create group with two URLs
group := models.Group{
Name: "TestGroupQueryURLExcludes",
URLs: models.NewRelatedStrings([]string{
"aaa",
"bbb",
}),
}
err := mqb.Create(ctx, &movie)
err := mqb.Create(ctx, &group)
if err != nil {
return fmt.Errorf("Error creating movie: %w", err)
return fmt.Errorf("Error creating group: %w", err)
}
// query for movies that exclude the URL "aaa"
// query for groups that exclude the URL "aaa"
urlCriterion := models.StringCriterionInput{
Value: "aaa",
Modifier: models.CriterionModifierExcludes,
}
nameCriterion := models.StringCriterionInput{
Value: movie.Name,
Value: group.Name,
Modifier: models.CriterionModifierEquals,
}
filter := models.MovieFilterType{
filter := models.GroupFilterType{
URL: &urlCriterion,
Name: &nameCriterion,
}
movies := queryMovies(ctx, t, &filter, nil)
assert.Len(t, movies, 0, "Expected no movies to be found")
groups := queryGroups(ctx, t, &filter, nil)
assert.Len(t, groups, 0, "Expected no groups to be found")
// query for movies that exclude the URL "ccc"
// query for groups that exclude the URL "ccc"
urlCriterion.Value = "ccc"
movies = queryMovies(ctx, t, &filter, nil)
groups = queryGroups(ctx, t, &filter, nil)
if assert.Len(t, movies, 1, "Expected one movie to be found") {
assert.Equal(t, movie.Name, movies[0].Name)
if assert.Len(t, groups, 1, "Expected one group to be found") {
assert.Equal(t, group.Name, groups[0].Name)
}
return nil
})
}
func verifyMovieQuery(t *testing.T, filter models.MovieFilterType, verifyFn func(s *models.Movie)) {
func verifyGroupQuery(t *testing.T, filter models.GroupFilterType, verifyFn func(s *models.Group)) {
withTxn(func(ctx context.Context) error {
t.Helper()
sqb := db.Movie
sqb := db.Group
movies := queryMovies(ctx, t, &filter, nil)
groups := queryGroups(ctx, t, &filter, nil)
for _, movie := range movies {
if err := movie.LoadURLs(ctx, sqb); err != nil {
t.Errorf("Error loading movie relationships: %v", err)
for _, group := range groups {
if err := group.LoadURLs(ctx, sqb); err != nil {
t.Errorf("Error loading group relationships: %v", err)
}
}
// assume it should find at least one
assert.Greater(t, len(movies), 0)
assert.Greater(t, len(groups), 0)
for _, m := range movies {
for _, m := range groups {
verifyFn(m)
}
@@ -656,102 +656,102 @@ func verifyMovieQuery(t *testing.T, filter models.MovieFilterType, verifyFn func
})
}
func queryMovies(ctx context.Context, t *testing.T, movieFilter *models.MovieFilterType, findFilter *models.FindFilterType) []*models.Movie {
sqb := db.Movie
movies, _, err := sqb.Query(ctx, movieFilter, findFilter)
func queryGroups(ctx context.Context, t *testing.T, groupFilter *models.GroupFilterType, findFilter *models.FindFilterType) []*models.Group {
sqb := db.Group
groups, _, err := sqb.Query(ctx, groupFilter, findFilter)
if err != nil {
t.Errorf("Error querying movie: %s", err.Error())
t.Errorf("Error querying group: %s", err.Error())
}
return movies
return groups
}
func TestMovieQueryTags(t *testing.T) {
func TestGroupQueryTags(t *testing.T) {
withTxn(func(ctx context.Context) error {
tagCriterion := models.HierarchicalMultiCriterionInput{
Value: []string{
strconv.Itoa(tagIDs[tagIdxWithMovie]),
strconv.Itoa(tagIDs[tagIdx1WithMovie]),
strconv.Itoa(tagIDs[tagIdxWithGroup]),
strconv.Itoa(tagIDs[tagIdx1WithGroup]),
},
Modifier: models.CriterionModifierIncludes,
}
movieFilter := models.MovieFilterType{
groupFilter := models.GroupFilterType{
Tags: &tagCriterion,
}
// ensure ids are correct
movies := queryMovies(ctx, t, &movieFilter, nil)
assert.Len(t, movies, 3)
for _, movie := range movies {
assert.True(t, movie.ID == movieIDs[movieIdxWithTag] || movie.ID == movieIDs[movieIdxWithTwoTags] || movie.ID == movieIDs[movieIdxWithThreeTags])
groups := queryGroups(ctx, t, &groupFilter, nil)
assert.Len(t, groups, 3)
for _, group := range groups {
assert.True(t, group.ID == groupIDs[groupIdxWithTag] || group.ID == groupIDs[groupIdxWithTwoTags] || group.ID == groupIDs[groupIdxWithThreeTags])
}
tagCriterion = models.HierarchicalMultiCriterionInput{
Value: []string{
strconv.Itoa(tagIDs[tagIdx1WithMovie]),
strconv.Itoa(tagIDs[tagIdx2WithMovie]),
strconv.Itoa(tagIDs[tagIdx1WithGroup]),
strconv.Itoa(tagIDs[tagIdx2WithGroup]),
},
Modifier: models.CriterionModifierIncludesAll,
}
movies = queryMovies(ctx, t, &movieFilter, nil)
groups = queryGroups(ctx, t, &groupFilter, nil)
if assert.Len(t, movies, 2) {
assert.Equal(t, sceneIDs[movieIdxWithTwoTags], movies[0].ID)
assert.Equal(t, sceneIDs[movieIdxWithThreeTags], movies[1].ID)
if assert.Len(t, groups, 2) {
assert.Equal(t, sceneIDs[groupIdxWithTwoTags], groups[0].ID)
assert.Equal(t, sceneIDs[groupIdxWithThreeTags], groups[1].ID)
}
tagCriterion = models.HierarchicalMultiCriterionInput{
Value: []string{
strconv.Itoa(tagIDs[tagIdx1WithMovie]),
strconv.Itoa(tagIDs[tagIdx1WithGroup]),
},
Modifier: models.CriterionModifierExcludes,
}
q := getSceneStringValue(movieIdxWithTwoTags, titleField)
q := getSceneStringValue(groupIdxWithTwoTags, titleField)
findFilter := models.FindFilterType{
Q: &q,
}
movies = queryMovies(ctx, t, &movieFilter, &findFilter)
assert.Len(t, movies, 0)
groups = queryGroups(ctx, t, &groupFilter, &findFilter)
assert.Len(t, groups, 0)
return nil
})
}
func TestMovieQueryTagCount(t *testing.T) {
func TestGroupQueryTagCount(t *testing.T) {
const tagCount = 1
tagCountCriterion := models.IntCriterionInput{
Value: tagCount,
Modifier: models.CriterionModifierEquals,
}
verifyMoviesTagCount(t, tagCountCriterion)
verifyGroupsTagCount(t, tagCountCriterion)
tagCountCriterion.Modifier = models.CriterionModifierNotEquals
verifyMoviesTagCount(t, tagCountCriterion)
verifyGroupsTagCount(t, tagCountCriterion)
tagCountCriterion.Modifier = models.CriterionModifierGreaterThan
verifyMoviesTagCount(t, tagCountCriterion)
verifyGroupsTagCount(t, tagCountCriterion)
tagCountCriterion.Modifier = models.CriterionModifierLessThan
verifyMoviesTagCount(t, tagCountCriterion)
verifyGroupsTagCount(t, tagCountCriterion)
}
func verifyMoviesTagCount(t *testing.T, tagCountCriterion models.IntCriterionInput) {
func verifyGroupsTagCount(t *testing.T, tagCountCriterion models.IntCriterionInput) {
withTxn(func(ctx context.Context) error {
sqb := db.Movie
movieFilter := models.MovieFilterType{
sqb := db.Group
groupFilter := models.GroupFilterType{
TagCount: &tagCountCriterion,
}
movies := queryMovies(ctx, t, &movieFilter, nil)
assert.Greater(t, len(movies), 0)
groups := queryGroups(ctx, t, &groupFilter, nil)
assert.Greater(t, len(groups), 0)
for _, movie := range movies {
ids, err := sqb.GetTagIDs(ctx, movie.ID)
for _, group := range groups {
ids, err := sqb.GetTagIDs(ctx, group.ID)
if err != nil {
return err
}
@@ -762,7 +762,7 @@ func verifyMoviesTagCount(t *testing.T, tagCountCriterion models.IntCriterionInp
})
}
func TestMovieQuerySorting(t *testing.T) {
func TestGroupQuerySorting(t *testing.T) {
sort := "scenes_count"
direction := models.SortDirectionEnumDesc
findFilter := models.FindFilterType{
@@ -771,60 +771,60 @@ func TestMovieQuerySorting(t *testing.T) {
}
withTxn(func(ctx context.Context) error {
movies := queryMovies(ctx, t, nil, &findFilter)
groups := queryGroups(ctx, t, nil, &findFilter)
// scenes should be in same order as indexes
firstMovie := movies[0]
firstGroup := groups[0]
assert.Equal(t, movieIDs[movieIdxWithScene], firstMovie.ID)
assert.Equal(t, groupIDs[groupIdxWithScene], firstGroup.ID)
// sort in descending order
direction = models.SortDirectionEnumAsc
movies = queryMovies(ctx, t, nil, &findFilter)
lastMovie := movies[len(movies)-1]
groups = queryGroups(ctx, t, nil, &findFilter)
lastGroup := groups[len(groups)-1]
assert.Equal(t, movieIDs[movieIdxWithScene], lastMovie.ID)
assert.Equal(t, groupIDs[groupIdxWithScene], lastGroup.ID)
return nil
})
}
func TestMovieUpdateFrontImage(t *testing.T) {
func TestGroupUpdateFrontImage(t *testing.T) {
if err := withRollbackTxn(func(ctx context.Context) error {
qb := db.Movie
qb := db.Group
// create movie to test against
const name = "TestMovieUpdateMovieImages"
movie := models.Movie{
// create group to test against
const name = "TestGroupUpdateGroupImages"
group := models.Group{
Name: name,
}
err := qb.Create(ctx, &movie)
err := qb.Create(ctx, &group)
if err != nil {
return fmt.Errorf("Error creating movie: %s", err.Error())
return fmt.Errorf("Error creating group: %s", err.Error())
}
return testUpdateImage(t, ctx, movie.ID, qb.UpdateFrontImage, qb.GetFrontImage)
return testUpdateImage(t, ctx, group.ID, qb.UpdateFrontImage, qb.GetFrontImage)
}); err != nil {
t.Error(err.Error())
}
}
func TestMovieUpdateBackImage(t *testing.T) {
func TestGroupUpdateBackImage(t *testing.T) {
if err := withRollbackTxn(func(ctx context.Context) error {
qb := db.Movie
qb := db.Group
// create movie to test against
const name = "TestMovieUpdateMovieImages"
movie := models.Movie{
// create group to test against
const name = "TestGroupUpdateGroupImages"
group := models.Group{
Name: name,
}
err := qb.Create(ctx, &movie)
err := qb.Create(ctx, &group)
if err != nil {
return fmt.Errorf("Error creating movie: %s", err.Error())
return fmt.Errorf("Error creating group: %s", err.Error())
}
return testUpdateImage(t, ctx, movie.ID, qb.UpdateBackImage, qb.GetBackImage)
return testUpdateImage(t, ctx, group.ID, qb.UpdateBackImage, qb.GetBackImage)
}); err != nil {
t.Error(err.Error())
}

View File

@@ -28,7 +28,7 @@ const (
performersScenesTable = "performers_scenes"
scenesTagsTable = "scenes_tags"
scenesGalleriesTable = "scenes_galleries"
moviesScenesTable = "movies_scenes"
groupsScenesTable = "movies_scenes"
scenesURLsTable = "scene_urls"
sceneURLColumn = "url"
scenesViewDatesTable = "scenes_view_dates"
@@ -173,7 +173,7 @@ type sceneRepositoryType struct {
galleries joinRepository
tags joinRepository
performers joinRepository
movies repository
groups repository
files filesRepository
@@ -209,8 +209,8 @@ var (
},
fkColumn: performerIDColumn,
},
movies: repository{
tableName: moviesScenesTable,
groups: repository{
tableName: groupsScenesTable,
idColumn: sceneIDColumn,
},
files: filesRepository{
@@ -343,8 +343,8 @@ func (qb *SceneStore) Create(ctx context.Context, newObject *models.Scene, fileI
}
}
if newObject.Movies.Loaded() {
if err := scenesMoviesTableMgr.insertJoins(ctx, id, newObject.Movies.List()); err != nil {
if newObject.Groups.Loaded() {
if err := scenesGroupsTableMgr.insertJoins(ctx, id, newObject.Groups.List()); err != nil {
return err
}
}
@@ -399,8 +399,8 @@ func (qb *SceneStore) UpdatePartial(ctx context.Context, id int, partial models.
return nil, err
}
}
if partial.MovieIDs != nil {
if err := scenesMoviesTableMgr.modifyJoins(ctx, id, partial.MovieIDs.Movies, partial.MovieIDs.Mode); err != nil {
if partial.GroupIDs != nil {
if err := scenesGroupsTableMgr.modifyJoins(ctx, id, partial.GroupIDs.Groups, partial.GroupIDs.Mode); err != nil {
return nil, err
}
}
@@ -451,8 +451,8 @@ func (qb *SceneStore) Update(ctx context.Context, updatedObject *models.Scene) e
}
}
if updatedObject.Movies.Loaded() {
if err := scenesMoviesTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.Movies.List()); err != nil {
if updatedObject.Groups.Loaded() {
if err := scenesGroupsTableMgr.replaceJoins(ctx, updatedObject.ID, updatedObject.Groups.List()); err != nil {
return err
}
}
@@ -778,23 +778,23 @@ func (qb *SceneStore) OCountByPerformerID(ctx context.Context, performerID int)
return ret, nil
}
func (qb *SceneStore) FindByMovieID(ctx context.Context, movieID int) ([]*models.Scene, error) {
sq := dialect.From(scenesMoviesJoinTable).Select(scenesMoviesJoinTable.Col(sceneIDColumn)).Where(
scenesMoviesJoinTable.Col(movieIDColumn).Eq(movieID),
func (qb *SceneStore) FindByGroupID(ctx context.Context, groupID int) ([]*models.Scene, error) {
sq := dialect.From(scenesGroupsJoinTable).Select(scenesGroupsJoinTable.Col(sceneIDColumn)).Where(
scenesGroupsJoinTable.Col(groupIDColumn).Eq(groupID),
)
ret, err := qb.findBySubquery(ctx, sq)
if err != nil {
return nil, fmt.Errorf("getting scenes for movie %d: %w", movieID, err)
return nil, fmt.Errorf("getting scenes for group %d: %w", groupID, err)
}
return ret, nil
}
func (qb *SceneStore) CountByMovieID(ctx context.Context, movieID int) (int, error) {
joinTable := scenesMoviesJoinTable
func (qb *SceneStore) CountByGroupID(ctx context.Context, groupID int) (int, error) {
joinTable := scenesGroupsJoinTable
q := dialect.Select(goqu.COUNT("*")).From(joinTable).Where(joinTable.Col(movieIDColumn).Eq(movieID))
q := dialect.Select(goqu.COUNT("*")).From(joinTable).Where(joinTable.Col(groupIDColumn).Eq(groupID))
return count(ctx, q)
}
@@ -1142,8 +1142,8 @@ func (qb *SceneStore) setSceneSort(query *queryBuilder, findFilter *models.FindF
direction := findFilter.GetDirection()
switch sort {
case "movie_scene_number", "group_scene_number":
query.join(moviesScenesTable, "", "scenes.id = movies_scenes.scene_id")
query.sortAndPagination += getSort("scene_index", direction, moviesScenesTable)
query.join(groupsScenesTable, "", "scenes.id = movies_scenes.scene_id")
query.sortAndPagination += getSort("scene_index", direction, groupsScenesTable)
case "tag_count":
query.sortAndPagination += getCountSort(sceneTable, scenesTagsTable, sceneIDColumn, direction)
case "performer_count":
@@ -1270,11 +1270,11 @@ func (qb *SceneStore) AssignFiles(ctx context.Context, sceneID int, fileIDs []mo
return scenesFilesTableMgr.insertJoins(ctx, sceneID, firstPrimary, fileIDs)
}
func (qb *SceneStore) GetMovies(ctx context.Context, id int) (ret []models.MoviesScenes, err error) {
ret = []models.MoviesScenes{}
func (qb *SceneStore) GetGroups(ctx context.Context, id int) (ret []models.GroupsScenes, err error) {
ret = []models.GroupsScenes{}
if err := sceneRepository.movies.getAll(ctx, id, func(rows *sqlx.Rows) error {
var ms moviesScenesRow
if err := sceneRepository.groups.getAll(ctx, id, func(rows *sqlx.Rows) error {
var ms groupsScenesRow
if err := rows.StructScan(&ms); err != nil {
return err
}

View File

@@ -195,10 +195,10 @@ func (qb *sceneFilterHandler) criterionHandler() criterionHandler {
&relatedFilterHandler{
relatedIDCol: "movies_scenes.movie_id",
relatedRepo: movieRepository.repository,
relatedHandler: &movieFilterHandler{sceneFilter.MoviesFilter},
relatedRepo: groupRepository.repository,
relatedHandler: &groupFilterHandler{sceneFilter.MoviesFilter},
joinFn: func(f *filterBuilder) {
sceneRepository.movies.innerJoin(f, "", "scenes.id")
sceneRepository.groups.innerJoin(f, "", "scenes.id")
},
},
@@ -320,7 +320,7 @@ func (qb *sceneFilterHandler) isMissingCriterionHandler(isMissing *string) crite
case "studio":
f.addWhere("scenes.studio_id IS NULL")
case "movie":
sceneRepository.movies.join(f, "movies_join", "scenes.id")
sceneRepository.groups.join(f, "movies_join", "scenes.id")
f.addWhere("movies_join.scene_id IS NULL")
case "performers":
sceneRepository.performers.join(f, "performers_join", "scenes.id")
@@ -485,10 +485,10 @@ func (qb *sceneFilterHandler) performerAgeCriterionHandler(performerAge *models.
func (qb *sceneFilterHandler) groupsCriterionHandler(movies *models.MultiCriterionInput) criterionHandlerFunc {
addJoinsFunc := func(f *filterBuilder) {
sceneRepository.movies.join(f, "", "scenes.id")
sceneRepository.groups.join(f, "", "scenes.id")
f.addLeftJoin("movies", "", "movies_scenes.movie_id = movies.id")
}
h := qb.getMultiCriterionHandlerBuilder(movieTable, moviesScenesTable, "movie_id", addJoinsFunc)
h := qb.getMultiCriterionHandlerBuilder(groupTable, groupsScenesTable, "movie_id", addJoinsFunc)
return h.handler(movies)
}

View File

@@ -41,8 +41,8 @@ func loadSceneRelationships(ctx context.Context, expected models.Scene, actual *
return err
}
}
if expected.Movies.Loaded() {
if err := actual.LoadMovies(ctx, db.Scene); err != nil {
if expected.Groups.Loaded() {
if err := actual.LoadGroups(ctx, db.Scene); err != nil {
return err
}
}
@@ -120,13 +120,13 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithScene]}),
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
Movies: models.NewRelatedMovies([]models.MoviesScenes{
Groups: models.NewRelatedGroups([]models.GroupsScenes{
{
MovieID: movieIDs[movieIdxWithScene],
GroupID: groupIDs[groupIdxWithScene],
SceneIndex: &sceneIndex,
},
{
MovieID: movieIDs[movieIdxWithStudio],
GroupID: groupIDs[groupIdxWithStudio],
SceneIndex: &sceneIndex2,
},
}),
@@ -165,13 +165,13 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithScene]}),
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
Movies: models.NewRelatedMovies([]models.MoviesScenes{
Groups: models.NewRelatedGroups([]models.GroupsScenes{
{
MovieID: movieIDs[movieIdxWithScene],
GroupID: groupIDs[groupIdxWithScene],
SceneIndex: &sceneIndex,
},
{
MovieID: movieIDs[movieIdxWithStudio],
GroupID: groupIDs[groupIdxWithStudio],
SceneIndex: &sceneIndex2,
},
}),
@@ -219,11 +219,11 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
true,
},
{
"invalid movie id",
"invalid group id",
models.Scene{
Movies: models.NewRelatedMovies([]models.MoviesScenes{
Groups: models.NewRelatedGroups([]models.GroupsScenes{
{
MovieID: invalidID,
GroupID: invalidID,
SceneIndex: &sceneIndex,
},
}),
@@ -349,13 +349,13 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithScene]}),
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
Movies: models.NewRelatedMovies([]models.MoviesScenes{
Groups: models.NewRelatedGroups([]models.GroupsScenes{
{
MovieID: movieIDs[movieIdxWithScene],
GroupID: groupIDs[groupIdxWithScene],
SceneIndex: &sceneIndex,
},
{
MovieID: movieIDs[movieIdxWithStudio],
GroupID: groupIDs[groupIdxWithStudio],
SceneIndex: &sceneIndex2,
},
}),
@@ -381,7 +381,7 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
GalleryIDs: models.NewRelatedIDs([]int{}),
TagIDs: models.NewRelatedIDs([]int{}),
PerformerIDs: models.NewRelatedIDs([]int{}),
Movies: models.NewRelatedMovies([]models.MoviesScenes{}),
Groups: models.NewRelatedGroups([]models.GroupsScenes{}),
StashIDs: models.NewRelatedStashIDs([]models.StashID{}),
},
false,
@@ -411,10 +411,10 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
false,
},
{
"clear movies",
"clear groups",
&models.Scene{
ID: sceneIDs[sceneIdxWithMovie],
Movies: models.NewRelatedMovies([]models.MoviesScenes{}),
ID: sceneIDs[sceneIdxWithGroup],
Groups: models.NewRelatedGroups([]models.GroupsScenes{}),
},
false,
},
@@ -451,12 +451,12 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
true,
},
{
"invalid movie id",
"invalid group id",
&models.Scene{
ID: sceneIDs[sceneIdxWithSpacedName],
Movies: models.NewRelatedMovies([]models.MoviesScenes{
Groups: models.NewRelatedGroups([]models.GroupsScenes{
{
MovieID: invalidID,
GroupID: invalidID,
SceneIndex: &sceneIndex,
},
}),
@@ -573,14 +573,14 @@ func Test_sceneQueryBuilder_UpdatePartial(t *testing.T) {
IDs: []int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]},
Mode: models.RelationshipUpdateModeSet,
},
MovieIDs: &models.UpdateMovieIDs{
Movies: []models.MoviesScenes{
GroupIDs: &models.UpdateGroupIDs{
Groups: []models.GroupsScenes{
{
MovieID: movieIDs[movieIdxWithScene],
GroupID: groupIDs[groupIdxWithScene],
SceneIndex: &sceneIndex,
},
{
MovieID: movieIDs[movieIdxWithStudio],
GroupID: groupIDs[groupIdxWithStudio],
SceneIndex: &sceneIndex2,
},
},
@@ -621,13 +621,13 @@ func Test_sceneQueryBuilder_UpdatePartial(t *testing.T) {
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithScene]}),
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
Movies: models.NewRelatedMovies([]models.MoviesScenes{
Groups: models.NewRelatedGroups([]models.GroupsScenes{
{
MovieID: movieIDs[movieIdxWithScene],
GroupID: groupIDs[groupIdxWithScene],
SceneIndex: &sceneIndex,
},
{
MovieID: movieIDs[movieIdxWithStudio],
GroupID: groupIDs[groupIdxWithStudio],
SceneIndex: &sceneIndex2,
},
}),
@@ -658,7 +658,7 @@ func Test_sceneQueryBuilder_UpdatePartial(t *testing.T) {
GalleryIDs: models.NewRelatedIDs([]int{}),
TagIDs: models.NewRelatedIDs([]int{}),
PerformerIDs: models.NewRelatedIDs([]int{}),
Movies: models.NewRelatedMovies([]models.MoviesScenes{}),
Groups: models.NewRelatedGroups([]models.GroupsScenes{}),
StashIDs: models.NewRelatedStashIDs([]models.StashID{}),
PlayDuration: getScenePlayDuration(sceneIdxWithSpacedName),
ResumeTime: getSceneResumeTime(sceneIdxWithSpacedName),
@@ -727,13 +727,13 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
stashID1 = "stashid1"
stashID2 = "stashid2"
movieScenes = []models.MoviesScenes{
groupScenes = []models.GroupsScenes{
{
MovieID: movieIDs[movieIdxWithDupName],
GroupID: groupIDs[groupIdxWithDupName],
SceneIndex: &sceneIndex,
},
{
MovieID: movieIDs[movieIdxWithStudio],
GroupID: groupIDs[groupIdxWithStudio],
SceneIndex: &sceneIndex2,
},
}
@@ -863,40 +863,40 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
false,
},
{
"add movies",
sceneIDs[sceneIdxWithMovie],
"add groups",
sceneIDs[sceneIdxWithGroup],
models.ScenePartial{
MovieIDs: &models.UpdateMovieIDs{
Movies: movieScenes,
GroupIDs: &models.UpdateGroupIDs{
Groups: groupScenes,
Mode: models.RelationshipUpdateModeAdd,
},
},
models.Scene{
Movies: models.NewRelatedMovies(append([]models.MoviesScenes{
Groups: models.NewRelatedGroups(append([]models.GroupsScenes{
{
MovieID: indexesToIDs(movieIDs, sceneMovies[sceneIdxWithMovie])[0],
GroupID: indexesToIDs(groupIDs, sceneGroups[sceneIdxWithGroup])[0],
},
}, movieScenes...)),
}, groupScenes...)),
},
false,
},
{
"add movies to empty",
"add groups to empty",
sceneIDs[sceneIdx1WithPerformer],
models.ScenePartial{
MovieIDs: &models.UpdateMovieIDs{
Movies: movieScenes,
GroupIDs: &models.UpdateGroupIDs{
Groups: groupScenes,
Mode: models.RelationshipUpdateModeAdd,
},
},
models.Scene{
Movies: models.NewRelatedMovies([]models.MoviesScenes{
Groups: models.NewRelatedGroups([]models.GroupsScenes{
{
MovieID: movieIDs[movieIdxWithDupName],
GroupID: groupIDs[groupIdxWithDupName],
SceneIndex: &sceneIndex,
},
{
MovieID: movieIDs[movieIdxWithStudio],
GroupID: groupIDs[groupIdxWithStudio],
SceneIndex: &sceneIndex2,
},
}),
@@ -967,27 +967,27 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
false,
},
{
"add duplicate movies",
sceneIDs[sceneIdxWithMovie],
"add duplicate groups",
sceneIDs[sceneIdxWithGroup],
models.ScenePartial{
MovieIDs: &models.UpdateMovieIDs{
Movies: append([]models.MoviesScenes{
GroupIDs: &models.UpdateGroupIDs{
Groups: append([]models.GroupsScenes{
{
MovieID: movieIDs[movieIdxWithScene],
GroupID: groupIDs[groupIdxWithScene],
SceneIndex: &sceneIndex,
},
},
movieScenes...,
groupScenes...,
),
Mode: models.RelationshipUpdateModeAdd,
},
},
models.Scene{
Movies: models.NewRelatedMovies(append([]models.MoviesScenes{
Groups: models.NewRelatedGroups(append([]models.GroupsScenes{
{
MovieID: indexesToIDs(movieIDs, sceneMovies[sceneIdxWithMovie])[0],
GroupID: indexesToIDs(groupIDs, sceneGroups[sceneIdxWithGroup])[0],
},
}, movieScenes...)),
}, groupScenes...)),
},
false,
},
@@ -1044,13 +1044,13 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
true,
},
{
"add invalid movies",
sceneIDs[sceneIdxWithMovie],
"add invalid groups",
sceneIDs[sceneIdxWithGroup],
models.ScenePartial{
MovieIDs: &models.UpdateMovieIDs{
Movies: []models.MoviesScenes{
GroupIDs: &models.UpdateGroupIDs{
Groups: []models.GroupsScenes{
{
MovieID: invalidID,
GroupID: invalidID,
},
},
Mode: models.RelationshipUpdateModeAdd,
@@ -1102,20 +1102,20 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
false,
},
{
"remove movies",
sceneIDs[sceneIdxWithMovie],
"remove groups",
sceneIDs[sceneIdxWithGroup],
models.ScenePartial{
MovieIDs: &models.UpdateMovieIDs{
Movies: []models.MoviesScenes{
GroupIDs: &models.UpdateGroupIDs{
Groups: []models.GroupsScenes{
{
MovieID: movieIDs[movieIdxWithScene],
GroupID: groupIDs[groupIdxWithScene],
},
},
Mode: models.RelationshipUpdateModeRemove,
},
},
models.Scene{
Movies: models.NewRelatedMovies([]models.MoviesScenes{}),
Groups: models.NewRelatedGroups([]models.GroupsScenes{}),
},
false,
},
@@ -1176,22 +1176,22 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
false,
},
{
"remove unrelated movies",
sceneIDs[sceneIdxWithMovie],
"remove unrelated groups",
sceneIDs[sceneIdxWithGroup],
models.ScenePartial{
MovieIDs: &models.UpdateMovieIDs{
Movies: []models.MoviesScenes{
GroupIDs: &models.UpdateGroupIDs{
Groups: []models.GroupsScenes{
{
MovieID: movieIDs[movieIdxWithDupName],
GroupID: groupIDs[groupIdxWithDupName],
},
},
Mode: models.RelationshipUpdateModeRemove,
},
},
models.Scene{
Movies: models.NewRelatedMovies([]models.MoviesScenes{
Groups: models.NewRelatedGroups([]models.GroupsScenes{
{
MovieID: indexesToIDs(movieIDs, sceneMovies[sceneIdxWithMovie])[0],
GroupID: indexesToIDs(groupIDs, sceneGroups[sceneIdxWithGroup])[0],
},
}),
},
@@ -1257,9 +1257,9 @@ func Test_sceneQueryBuilder_UpdatePartialRelationships(t *testing.T) {
assert.ElementsMatch(tt.want.GalleryIDs.List(), got.GalleryIDs.List())
assert.ElementsMatch(tt.want.GalleryIDs.List(), s.GalleryIDs.List())
}
if tt.partial.MovieIDs != nil {
assert.ElementsMatch(tt.want.Movies.List(), got.Movies.List())
assert.ElementsMatch(tt.want.Movies.List(), s.Movies.List())
if tt.partial.GroupIDs != nil {
assert.ElementsMatch(tt.want.Groups.List(), got.Groups.List())
assert.ElementsMatch(tt.want.Groups.List(), s.Groups.List())
}
if tt.partial.StashIDs != nil {
assert.ElementsMatch(tt.want.StashIDs.List(), got.StashIDs.List())
@@ -1467,9 +1467,9 @@ func Test_sceneQueryBuilder_Find(t *testing.T) {
false,
},
{
"with movies",
sceneIDs[sceneIdxWithMovie],
makeSceneWithID(sceneIdxWithMovie),
"with groups",
sceneIDs[sceneIdxWithGroup],
makeSceneWithID(sceneIdxWithGroup),
false,
},
}
@@ -1527,13 +1527,13 @@ func Test_sceneQueryBuilder_FindMany(t *testing.T) {
sceneIDs[sceneIdxWithGallery],
sceneIDs[sceneIdxWithTwoPerformers],
sceneIDs[sceneIdxWithTwoTags],
sceneIDs[sceneIdxWithMovie],
sceneIDs[sceneIdxWithGroup],
},
[]*models.Scene{
makeSceneWithID(sceneIdxWithGallery),
makeSceneWithID(sceneIdxWithTwoPerformers),
makeSceneWithID(sceneIdxWithTwoTags),
makeSceneWithID(sceneIdxWithMovie),
makeSceneWithID(sceneIdxWithGroup),
},
false,
},
@@ -1608,9 +1608,9 @@ func Test_sceneQueryBuilder_FindByChecksum(t *testing.T) {
false,
},
{
"with movies",
getChecksum(sceneIdxWithMovie),
[]*models.Scene{makeSceneWithID(sceneIdxWithMovie)},
"with groups",
getChecksum(sceneIdxWithGroup),
[]*models.Scene{makeSceneWithID(sceneIdxWithGroup)},
false,
},
}
@@ -1678,9 +1678,9 @@ func Test_sceneQueryBuilder_FindByOSHash(t *testing.T) {
false,
},
{
"with movies",
getOSHash(sceneIdxWithMovie),
[]*models.Scene{makeSceneWithID(sceneIdxWithMovie)},
"with groups",
getOSHash(sceneIdxWithGroup),
[]*models.Scene{makeSceneWithID(sceneIdxWithGroup)},
false,
},
}
@@ -1749,9 +1749,9 @@ func Test_sceneQueryBuilder_FindByPath(t *testing.T) {
false,
},
{
"with movies",
getPath(sceneIdxWithMovie),
[]*models.Scene{makeSceneWithID(sceneIdxWithMovie)},
"with groups",
getPath(sceneIdxWithGroup),
[]*models.Scene{makeSceneWithID(sceneIdxWithGroup)},
false,
},
}
@@ -2107,7 +2107,7 @@ func TestSceneQuery(t *testing.T) {
},
},
[]int{sceneIdxWithGallery},
[]int{sceneIdxWithMovie},
[]int{sceneIdxWithGroup},
false,
},
{
@@ -2120,7 +2120,7 @@ func TestSceneQuery(t *testing.T) {
},
},
[]int{sceneIdxWithGallery},
[]int{sceneIdxWithMovie},
[]int{sceneIdxWithGroup},
false,
},
// {
@@ -2133,7 +2133,7 @@ func TestSceneQuery(t *testing.T) {
// },
// },
// []int{sceneIdxWithGallery},
// []int{sceneIdxWithMovie},
// []int{sceneIdxWithGroup},
// false,
// },
{
@@ -3108,7 +3108,7 @@ func TestSceneQueryIsMissingMovies(t *testing.T) {
IsMissing: &isMissing,
}
q := getSceneStringValue(sceneIdxWithMovie, titleField)
q := getSceneStringValue(sceneIdxWithGroup, titleField)
findFilter := models.FindFilterType{
Q: &q,
}
@@ -3122,7 +3122,7 @@ func TestSceneQueryIsMissingMovies(t *testing.T) {
// ensure non of the ids equal the one with movies
for _, scene := range scenes {
assert.NotEqual(t, sceneIDs[sceneIdxWithMovie], scene.ID)
assert.NotEqual(t, sceneIDs[sceneIdxWithGroup], scene.ID)
}
return nil
@@ -3878,7 +3878,7 @@ func TestSceneQueryMovies(t *testing.T) {
sqb := db.Scene
movieCriterion := models.MultiCriterionInput{
Value: []string{
strconv.Itoa(movieIDs[movieIdxWithScene]),
strconv.Itoa(groupIDs[groupIdxWithScene]),
},
Modifier: models.CriterionModifierIncludes,
}
@@ -3892,16 +3892,16 @@ func TestSceneQueryMovies(t *testing.T) {
assert.Len(t, scenes, 1)
// ensure id is correct
assert.Equal(t, sceneIDs[sceneIdxWithMovie], scenes[0].ID)
assert.Equal(t, sceneIDs[sceneIdxWithGroup], scenes[0].ID)
movieCriterion = models.MultiCriterionInput{
Value: []string{
strconv.Itoa(movieIDs[movieIdxWithScene]),
strconv.Itoa(groupIDs[groupIdxWithScene]),
},
Modifier: models.CriterionModifierExcludes,
}
q := getSceneStringValue(sceneIdxWithMovie, titleField)
q := getSceneStringValue(sceneIdxWithGroup, titleField)
findFilter := models.FindFilterType{
Q: &q,
}
@@ -4212,22 +4212,22 @@ func TestSceneCountByTagID(t *testing.T) {
})
}
func TestSceneCountByMovieID(t *testing.T) {
func TestSceneCountByGroupID(t *testing.T) {
withTxn(func(ctx context.Context) error {
sqb := db.Scene
sceneCount, err := sqb.CountByMovieID(ctx, movieIDs[movieIdxWithScene])
sceneCount, err := sqb.CountByGroupID(ctx, groupIDs[groupIdxWithScene])
if err != nil {
t.Errorf("error calling CountByMovieID: %s", err.Error())
t.Errorf("error calling CountByGroupID: %s", err.Error())
}
assert.Equal(t, 1, sceneCount)
sceneCount, err = sqb.CountByMovieID(ctx, 0)
sceneCount, err = sqb.CountByGroupID(ctx, 0)
if err != nil {
t.Errorf("error calling CountByMovieID: %s", err.Error())
t.Errorf("error calling CountByGroupID: %s", err.Error())
}
assert.Equal(t, 0, sceneCount)
@@ -4264,16 +4264,16 @@ func TestFindByMovieID(t *testing.T) {
withTxn(func(ctx context.Context) error {
sqb := db.Scene
scenes, err := sqb.FindByMovieID(ctx, movieIDs[movieIdxWithScene])
scenes, err := sqb.FindByGroupID(ctx, groupIDs[groupIdxWithScene])
if err != nil {
t.Errorf("error calling FindByMovieID: %s", err.Error())
}
assert.Len(t, scenes, 1)
assert.Equal(t, sceneIDs[sceneIdxWithMovie], scenes[0].ID)
assert.Equal(t, sceneIDs[sceneIdxWithGroup], scenes[0].ID)
scenes, err = sqb.FindByMovieID(ctx, 0)
scenes, err = sqb.FindByGroupID(ctx, 0)
if err != nil {
t.Errorf("error calling FindByMovieID: %s", err.Error())

View File

@@ -54,7 +54,7 @@ const (
)
const (
sceneIdxWithMovie = iota
sceneIdxWithGroup = iota
sceneIdxWithGallery
sceneIdxWithPerformer
sceneIdx1WithPerformer
@@ -148,17 +148,17 @@ const (
)
const (
movieIdxWithScene = iota
movieIdxWithStudio
movieIdxWithTag
movieIdxWithTwoTags
movieIdxWithThreeTags
// movies with dup names start from the end
// create 7 more basic movies (can remove this if we add more indexes)
movieIdxWithDupName = movieIdxWithStudio + 7
groupIdxWithScene = iota
groupIdxWithStudio
groupIdxWithTag
groupIdxWithTwoTags
groupIdxWithThreeTags
// groups with dup names start from the end
// create 7 more basic groups (can remove this if we add more indexes)
groupIdxWithDupName = groupIdxWithStudio + 7
moviesNameCase = movieIdxWithDupName
moviesNameNoCase = 1
groupsNameCase = groupIdxWithDupName
groupsNameNoCase = 1
)
const (
@@ -220,10 +220,10 @@ const (
tagIdxWithParentAndChild
tagIdxWithGrandParent
tagIdx2WithMarkers
tagIdxWithMovie
tagIdx1WithMovie
tagIdx2WithMovie
tagIdx3WithMovie
tagIdxWithGroup
tagIdx1WithGroup
tagIdx2WithGroup
tagIdx3WithGroup
// new indexes above
// tags with dup names start from the end
tagIdx1WithDupName
@@ -238,7 +238,7 @@ const (
const (
studioIdxWithScene = iota
studioIdxWithTwoScenes
studioIdxWithMovie
studioIdxWithGroup
studioIdxWithChildStudio
studioIdxWithParentStudio
studioIdxWithImage
@@ -305,7 +305,7 @@ var (
sceneIDs []int
imageIDs []int
performerIDs []int
movieIDs []int
groupIDs []int
galleryIDs []int
tagIDs []int
studioIDs []int
@@ -316,7 +316,7 @@ var (
tagNames []string
studioNames []string
movieNames []string
groupNames []string
performerNames []string
)
@@ -389,8 +389,8 @@ var (
sceneIdxWithGallery: {galleryIdxWithScene},
}
sceneMovies = linkMap{
sceneIdxWithMovie: {movieIdxWithScene},
sceneGroups = linkMap{
sceneIdxWithGroup: {groupIdxWithScene},
}
sceneStudios = map[int]int{
@@ -496,14 +496,14 @@ var (
)
var (
movieStudioLinks = [][2]int{
{movieIdxWithStudio, studioIdxWithMovie},
groupStudioLinks = [][2]int{
{groupIdxWithStudio, studioIdxWithGroup},
}
movieTags = linkMap{
movieIdxWithTag: {tagIdxWithMovie},
movieIdxWithTwoTags: {tagIdx1WithMovie, tagIdx2WithMovie},
movieIdxWithThreeTags: {tagIdx1WithMovie, tagIdx2WithMovie, tagIdx3WithMovie},
groupTags = linkMap{
groupIdxWithTag: {tagIdxWithGroup},
groupIdxWithTwoTags: {tagIdx1WithGroup, tagIdx2WithGroup},
groupIdxWithThreeTags: {tagIdx1WithGroup, tagIdx2WithGroup, tagIdx3WithGroup},
}
)
@@ -653,8 +653,8 @@ func populateDB() error {
return fmt.Errorf("error creating tags: %s", err.Error())
}
if err := createMovies(ctx, db.Movie, moviesNameCase, moviesNameNoCase); err != nil {
return fmt.Errorf("error creating movies: %s", err.Error())
if err := createGroups(ctx, db.Group, groupsNameCase, groupsNameNoCase); err != nil {
return fmt.Errorf("error creating groups: %s", err.Error())
}
if err := createPerformers(ctx, performersNameCase, performersNameNoCase); err != nil {
@@ -685,8 +685,8 @@ func populateDB() error {
return fmt.Errorf("error creating saved filters: %s", err.Error())
}
if err := linkMovieStudios(ctx, db.Movie); err != nil {
return fmt.Errorf("error linking movie studios: %s", err.Error())
if err := linkGroupStudios(ctx, db.Group); err != nil {
return fmt.Errorf("error linking group studios: %s", err.Error())
}
if err := linkStudiosParent(ctx); err != nil {
@@ -1069,12 +1069,12 @@ func makeScene(i int) *models.Scene {
pids := indexesToIDs(performerIDs, scenePerformers[i])
tids := indexesToIDs(tagIDs, sceneTags[i])
mids := indexesToIDs(movieIDs, sceneMovies[i])
mids := indexesToIDs(groupIDs, sceneGroups[i])
movies := make([]models.MoviesScenes, len(mids))
groups := make([]models.GroupsScenes, len(mids))
for i, m := range mids {
movies[i] = models.MoviesScenes{
MovieID: m,
groups[i] = models.GroupsScenes{
GroupID: m,
}
}
@@ -1092,7 +1092,7 @@ func makeScene(i int) *models.Scene {
GalleryIDs: models.NewRelatedIDs(gids),
PerformerIDs: models.NewRelatedIDs(pids),
TagIDs: models.NewRelatedIDs(tids),
Movies: models.NewRelatedMovies(movies),
Groups: models.NewRelatedGroups(groups),
StashIDs: models.NewRelatedStashIDs([]models.StashID{
sceneStashID(i),
}),
@@ -1320,18 +1320,18 @@ func createGalleries(ctx context.Context, n int) error {
return nil
}
func getMovieStringValue(index int, field string) string {
return getPrefixedStringValue("movie", index, field)
func getGroupStringValue(index int, field string) string {
return getPrefixedStringValue("group", index, field)
}
func getMovieNullStringValue(index int, field string) string {
ret := getPrefixedNullStringValue("movie", index, field)
func getGroupNullStringValue(index int, field string) string {
ret := getPrefixedNullStringValue("group", index, field)
return ret.String
}
func getMovieEmptyString(index int, field string) string {
v := getPrefixedNullStringValue("movie", index, field)
func getGroupEmptyString(index int, field string) string {
v := getPrefixedNullStringValue("group", index, field)
if !v.Valid {
return ""
}
@@ -1339,8 +1339,8 @@ func getMovieEmptyString(index int, field string) string {
return v.String
}
// createMoviees creates n movies with plain Name and o movies with camel cased NaMe included
func createMovies(ctx context.Context, mqb models.MovieReaderWriter, n int, o int) error {
// createGroups creates n groups with plain Name and o groups with camel cased NaMe included
func createGroups(ctx context.Context, mqb models.GroupReaderWriter, n int, o int) error {
const namePlain = "Name"
const nameNoCase = "NaMe"
@@ -1348,31 +1348,31 @@ func createMovies(ctx context.Context, mqb models.MovieReaderWriter, n int, o in
index := i
name := namePlain
tids := indexesToIDs(tagIDs, movieTags[i])
tids := indexesToIDs(tagIDs, groupTags[i])
if i >= n { // i<n tags get normal names
name = nameNoCase // i>=n movies get dup names if case is not checked
name = nameNoCase // i>=n groups get dup names if case is not checked
index = n + o - (i + 1) // for the name to be the same the number (index) must be the same also
} // so count backwards to 0 as needed
// movies [ i ] and [ n + o - i - 1 ] should have similar names with only the Name!=NaMe part different
// groups [ i ] and [ n + o - i - 1 ] should have similar names with only the Name!=NaMe part different
name = getMovieStringValue(index, name)
movie := models.Movie{
name = getGroupStringValue(index, name)
group := models.Group{
Name: name,
URLs: models.NewRelatedStrings([]string{
getMovieEmptyString(i, urlField),
getGroupEmptyString(i, urlField),
}),
TagIDs: models.NewRelatedIDs(tids),
}
err := mqb.Create(ctx, &movie)
err := mqb.Create(ctx, &group)
if err != nil {
return fmt.Errorf("Error creating movie [%d] %v+: %s", i, movie, err.Error())
return fmt.Errorf("Error creating group [%d] %v+: %s", i, group, err.Error())
}
movieIDs = append(movieIDs, movie.ID)
movieNames = append(movieNames, movie.Name)
groupIDs = append(groupIDs, group.ID)
groupNames = append(groupNames, group.Name)
}
return nil
@@ -1709,7 +1709,7 @@ func createStudios(ctx context.Context, n int, o int) error {
TagIDs: models.NewRelatedIDs(tids),
}
// only add aliases for some scenes
if i == studioIdxWithMovie || i%5 == 0 {
if i == studioIdxWithGroup || i%5 == 0 {
alias := getStudioStringValue(i, "Alias")
studio.Aliases = models.NewRelatedStrings([]string{alias})
}
@@ -1842,12 +1842,12 @@ func doLinks(links [][2]int, fn func(idx1, idx2 int) error) error {
return nil
}
func linkMovieStudios(ctx context.Context, mqb models.MovieWriter) error {
return doLinks(movieStudioLinks, func(movieIndex, studioIndex int) error {
movie := models.MoviePartial{
func linkGroupStudios(ctx context.Context, mqb models.GroupWriter) error {
return doLinks(groupStudioLinks, func(groupIndex, studioIndex int) error {
group := models.GroupPartial{
StudioID: models.NewOptionalInt(studioIDs[studioIndex]),
}
_, err := mqb.UpdatePartial(ctx, movieIDs[movieIndex], movie)
_, err := mqb.UpdatePartial(ctx, groupIDs[groupIndex], group)
return err
})

View File

@@ -216,7 +216,7 @@ func TestStudioQueryForAutoTag(t *testing.T) {
withTxn(func(ctx context.Context) error {
tqb := db.Studio
name := studioNames[studioIdxWithMovie] // find a studio by name
name := studioNames[studioIdxWithGroup] // find a studio by name
studios, err := tqb.QueryForAutoTag(ctx, []string{name})
@@ -225,16 +225,16 @@ func TestStudioQueryForAutoTag(t *testing.T) {
}
assert.Len(t, studios, 1)
assert.Equal(t, strings.ToLower(studioNames[studioIdxWithMovie]), strings.ToLower(studios[0].Name))
assert.Equal(t, strings.ToLower(studioNames[studioIdxWithGroup]), strings.ToLower(studios[0].Name))
name = getStudioStringValue(studioIdxWithMovie, "Alias")
name = getStudioStringValue(studioIdxWithGroup, "Alias")
studios, err = tqb.QueryForAutoTag(ctx, []string{name})
if err != nil {
t.Errorf("Error finding studios: %s", err.Error())
}
if assert.Len(t, studios, 1) {
assert.Equal(t, studioIDs[studioIdxWithMovie], studios[0].ID)
assert.Equal(t, studioIDs[studioIdxWithGroup], studios[0].ID)
}
return nil
})
@@ -911,7 +911,7 @@ func TestStudioQueryName(t *testing.T) {
}
func TestStudioQueryAlias(t *testing.T) {
const studioIdx = studioIdxWithMovie
const studioIdx = studioIdxWithGroup
studioName := getStudioStringValue(studioIdx, "Alias")
aliasCriterion := &models.StringCriterionInput{

View File

@@ -588,30 +588,30 @@ func (t *orderedValueTable[T]) modifyJoins(ctx context.Context, id int, v []T, m
return nil
}
type scenesMoviesTable struct {
type scenesGroupsTable struct {
table
}
type moviesScenesRow struct {
type groupsScenesRow struct {
SceneID null.Int `db:"scene_id"`
MovieID null.Int `db:"movie_id"`
GroupID null.Int `db:"movie_id"`
SceneIndex null.Int `db:"scene_index"`
}
func (r moviesScenesRow) resolve(sceneID int) models.MoviesScenes {
return models.MoviesScenes{
MovieID: int(r.MovieID.Int64),
func (r groupsScenesRow) resolve(sceneID int) models.GroupsScenes {
return models.GroupsScenes{
GroupID: int(r.GroupID.Int64),
SceneIndex: nullIntPtr(r.SceneIndex),
}
}
func (t *scenesMoviesTable) get(ctx context.Context, id int) ([]models.MoviesScenes, error) {
func (t *scenesGroupsTable) get(ctx context.Context, id int) ([]models.GroupsScenes, error) {
q := dialect.Select("movie_id", "scene_index").From(t.table.table).Where(t.idColumn.Eq(id))
const single = false
var ret []models.MoviesScenes
var ret []models.GroupsScenes
if err := queryFunc(ctx, q, single, func(rows *sqlx.Rows) error {
var v moviesScenesRow
var v groupsScenesRow
if err := rows.StructScan(&v); err != nil {
return err
}
@@ -620,15 +620,15 @@ func (t *scenesMoviesTable) get(ctx context.Context, id int) ([]models.MoviesSce
return nil
}); err != nil {
return nil, fmt.Errorf("getting scene movies from %s: %w", t.table.table.GetTable(), err)
return nil, fmt.Errorf("getting scene groups from %s: %w", t.table.table.GetTable(), err)
}
return ret, nil
}
func (t *scenesMoviesTable) insertJoin(ctx context.Context, id int, v models.MoviesScenes) (sql.Result, error) {
func (t *scenesGroupsTable) insertJoin(ctx context.Context, id int, v models.GroupsScenes) (sql.Result, error) {
q := dialect.Insert(t.table.table).Cols(t.idColumn.GetCol(), "movie_id", "scene_index").Vals(
goqu.Vals{id, v.MovieID, intFromPtr(v.SceneIndex)},
goqu.Vals{id, v.GroupID, intFromPtr(v.SceneIndex)},
)
ret, err := exec(ctx, q)
if err != nil {
@@ -638,7 +638,7 @@ func (t *scenesMoviesTable) insertJoin(ctx context.Context, id int, v models.Mov
return ret, nil
}
func (t *scenesMoviesTable) insertJoins(ctx context.Context, id int, v []models.MoviesScenes) error {
func (t *scenesGroupsTable) insertJoins(ctx context.Context, id int, v []models.GroupsScenes) error {
for _, fk := range v {
if _, err := t.insertJoin(ctx, id, fk); err != nil {
return err
@@ -648,7 +648,7 @@ func (t *scenesMoviesTable) insertJoins(ctx context.Context, id int, v []models.
return nil
}
func (t *scenesMoviesTable) replaceJoins(ctx context.Context, id int, v []models.MoviesScenes) error {
func (t *scenesGroupsTable) replaceJoins(ctx context.Context, id int, v []models.GroupsScenes) error {
if err := t.destroy(ctx, []int{id}); err != nil {
return err
}
@@ -656,7 +656,7 @@ func (t *scenesMoviesTable) replaceJoins(ctx context.Context, id int, v []models
return t.insertJoins(ctx, id, v)
}
func (t *scenesMoviesTable) addJoins(ctx context.Context, id int, v []models.MoviesScenes) error {
func (t *scenesGroupsTable) addJoins(ctx context.Context, id int, v []models.GroupsScenes) error {
// get existing foreign keys
fks, err := t.get(ctx, id)
if err != nil {
@@ -664,12 +664,12 @@ func (t *scenesMoviesTable) addJoins(ctx context.Context, id int, v []models.Mov
}
// only add values that are not already present
var filtered []models.MoviesScenes
var filtered []models.GroupsScenes
for _, vv := range v {
found := false
for _, e := range fks {
if vv.MovieID == e.MovieID {
if vv.GroupID == e.GroupID {
found = true
break
}
@@ -682,11 +682,11 @@ func (t *scenesMoviesTable) addJoins(ctx context.Context, id int, v []models.Mov
return t.insertJoins(ctx, id, filtered)
}
func (t *scenesMoviesTable) destroyJoins(ctx context.Context, id int, v []models.MoviesScenes) error {
func (t *scenesGroupsTable) destroyJoins(ctx context.Context, id int, v []models.GroupsScenes) error {
for _, vv := range v {
q := dialect.Delete(t.table.table).Where(
t.idColumn.Eq(id),
t.table.table.Col("movie_id").Eq(vv.MovieID),
t.table.table.Col("movie_id").Eq(vv.GroupID),
)
if _, err := exec(ctx, q); err != nil {
@@ -697,7 +697,7 @@ func (t *scenesMoviesTable) destroyJoins(ctx context.Context, id int, v []models
return nil
}
func (t *scenesMoviesTable) modifyJoins(ctx context.Context, id int, v []models.MoviesScenes, mode models.RelationshipUpdateMode) error {
func (t *scenesGroupsTable) modifyJoins(ctx context.Context, id int, v []models.GroupsScenes, mode models.RelationshipUpdateMode) error {
switch mode {
case models.RelationshipUpdateModeSet:
return t.replaceJoins(ctx, id, v)

View File

@@ -25,7 +25,7 @@ var (
scenesTagsJoinTable = goqu.T(scenesTagsTable)
scenesPerformersJoinTable = goqu.T(performersScenesTable)
scenesStashIDsJoinTable = goqu.T("scene_stash_ids")
scenesMoviesJoinTable = goqu.T(moviesScenesTable)
scenesGroupsJoinTable = goqu.T(groupsScenesTable)
scenesURLsJoinTable = goqu.T(scenesURLsTable)
performersAliasesJoinTable = goqu.T(performersAliasesTable)
@@ -37,8 +37,8 @@ var (
studiosTagsJoinTable = goqu.T(studiosTagsTable)
studiosStashIDsJoinTable = goqu.T("studio_stash_ids")
moviesURLsJoinTable = goqu.T(movieURLsTable)
moviesTagsJoinTable = goqu.T(moviesTagsTable)
groupsURLsJoinTable = goqu.T(groupURLsTable)
groupsTagsJoinTable = goqu.T(groupsTagsTable)
tagsAliasesJoinTable = goqu.T(tagAliasesTable)
tagRelationsJoinTable = goqu.T(tagRelationsTable)
@@ -184,10 +184,10 @@ var (
},
}
scenesMoviesTableMgr = &scenesMoviesTable{
scenesGroupsTableMgr = &scenesGroupsTable{
table: table{
table: scenesMoviesJoinTable,
idColumn: scenesMoviesJoinTable.Col(sceneIDColumn),
table: scenesGroupsJoinTable,
idColumn: scenesGroupsJoinTable.Col(sceneIDColumn),
},
}
@@ -337,25 +337,25 @@ var (
)
var (
movieTableMgr = &table{
table: goqu.T(movieTable),
idColumn: goqu.T(movieTable).Col(idColumn),
groupTableMgr = &table{
table: goqu.T(groupTable),
idColumn: goqu.T(groupTable).Col(idColumn),
}
moviesURLsTableMgr = &orderedValueTable[string]{
groupsURLsTableMgr = &orderedValueTable[string]{
table: table{
table: moviesURLsJoinTable,
idColumn: moviesURLsJoinTable.Col(movieIDColumn),
table: groupsURLsJoinTable,
idColumn: groupsURLsJoinTable.Col(groupIDColumn),
},
valueColumn: moviesURLsJoinTable.Col(movieURLColumn),
valueColumn: groupsURLsJoinTable.Col(groupURLColumn),
}
moviesTagsTableMgr = &joinTable{
groupsTagsTableMgr = &joinTable{
table: table{
table: moviesTagsJoinTable,
idColumn: moviesTagsJoinTable.Col(movieIDColumn),
table: groupsTagsJoinTable,
idColumn: groupsTagsJoinTable.Col(groupIDColumn),
},
fkColumn: moviesTagsJoinTable.Col(tagIDColumn),
fkColumn: groupsTagsJoinTable.Col(tagIDColumn),
foreignTable: tagTableMgr,
orderBy: tagTableMgr.table.Col("name").Asc(),
}

View File

@@ -424,7 +424,7 @@ func (qb *TagStore) FindByGalleryID(ctx context.Context, galleryID int) ([]*mode
return qb.queryTags(ctx, query, args)
}
func (qb *TagStore) FindByMovieID(ctx context.Context, movieID int) ([]*models.Tag, error) {
func (qb *TagStore) FindByGroupID(ctx context.Context, movieID int) ([]*models.Tag, error) {
query := `
SELECT tags.* FROM tags
LEFT JOIN movies_tags as movies_join on movies_join.tag_id = tags.id
@@ -637,6 +637,7 @@ func (qb *TagStore) Query(ctx context.Context, tagFilter *models.TagFilterType,
var tagSortOptions = sortOptions{
"created_at",
"galleries_count",
"groups_count",
"id",
"images_count",
"movies_count",
@@ -684,7 +685,7 @@ func (qb *TagStore) getTagSort(query *queryBuilder, findFilter *models.FindFilte
case "studios_count":
sortQuery += getCountSort(tagTable, studiosTagsTable, tagIDColumn, direction)
case "movies_count", "groups_count":
sortQuery += getCountSort(tagTable, moviesTagsTable, tagIDColumn, direction)
sortQuery += getCountSort(tagTable, groupsTagsTable, tagIDColumn, direction)
default:
sortQuery += getSort(sort, direction, "tags")
}

View File

@@ -190,11 +190,11 @@ func (qb *tagFilterHandler) studioCountCriterionHandler(studioCount *models.IntC
}
}
func (qb *tagFilterHandler) groupCountCriterionHandler(movieCount *models.IntCriterionInput) criterionHandlerFunc {
func (qb *tagFilterHandler) groupCountCriterionHandler(groupCount *models.IntCriterionInput) criterionHandlerFunc {
return func(ctx context.Context, f *filterBuilder) {
if movieCount != nil {
if groupCount != nil {
f.addLeftJoin("movies_tags", "", "movies_tags.tag_id = tags.id")
clause, args := getIntCriterionWhereClause("count(distinct movies_tags.movie_id)", *movieCount)
clause, args := getIntCriterionWhereClause("count(distinct movies_tags.movie_id)", *groupCount)
f.addHaving(clause, args...)
}

View File

@@ -42,22 +42,22 @@ func TestMarkerFindBySceneMarkerID(t *testing.T) {
})
}
func TestTagFindByMovieID(t *testing.T) {
func TestTagFindByGroupID(t *testing.T) {
withTxn(func(ctx context.Context) error {
tqb := db.Tag
movieID := movieIDs[movieIdxWithTag]
groupID := groupIDs[groupIdxWithTag]
tags, err := tqb.FindByMovieID(ctx, movieID)
tags, err := tqb.FindByGroupID(ctx, groupID)
if err != nil {
t.Errorf("Error finding tags: %s", err.Error())
}
assert.Len(t, tags, 1)
assert.Equal(t, tagIDs[tagIdxWithMovie], tags[0].ID)
assert.Equal(t, tagIDs[tagIdxWithGroup], tags[0].ID)
tags, err = tqb.FindByMovieID(ctx, 0)
tags, err = tqb.FindByGroupID(ctx, 0)
if err != nil {
t.Errorf("Error finding tags: %s", err.Error())
@@ -236,7 +236,7 @@ func TestTagQuerySort(t *testing.T) {
sortBy = "movies_count"
tags = queryTags(ctx, t, sqb, nil, findFilter)
assert.Equal(tagIDs[tagIdx1WithMovie], tags[0].ID)
assert.Equal(tagIDs[tagIdx1WithGroup], tags[0].ID)
return nil
})

View File

@@ -132,7 +132,7 @@ func (db *Database) Repository() models.Repository {
Gallery: db.Gallery,
GalleryChapter: db.GalleryChapter,
Image: db.Image,
Movie: db.Movie,
Group: db.Group,
Performer: db.Performer,
Scene: db.Scene,
SceneMarker: db.SceneMarker,