mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 16:34:02 +01:00
Omit joins that are only used for sorting when skipping sorting
Should provide some marginal improvement on systems with a lot of items.
This commit is contained in:
parent
7d96169796
commit
ff360ba5b1
7 changed files with 50 additions and 13 deletions
|
|
@ -96,6 +96,9 @@ type join struct {
|
||||||
onClause string
|
onClause string
|
||||||
joinType string
|
joinType string
|
||||||
args []interface{}
|
args []interface{}
|
||||||
|
|
||||||
|
// if true, indicates this is required for sorting only
|
||||||
|
sort bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// equals returns true if the other join alias/table is equal to this one
|
// equals returns true if the other join alias/table is equal to this one
|
||||||
|
|
@ -131,9 +134,13 @@ type joins []join
|
||||||
// returns true if added
|
// returns true if added
|
||||||
func (j *joins) addUnique(newJoin join) bool {
|
func (j *joins) addUnique(newJoin join) bool {
|
||||||
found := false
|
found := false
|
||||||
for _, jj := range *j {
|
for i, jj := range *j {
|
||||||
if jj.equals(newJoin) {
|
if jj.equals(newJoin) {
|
||||||
found = true
|
found = true
|
||||||
|
// if sort is false on the new join, but true on the existing, set the false
|
||||||
|
if !newJoin.sort && jj.sort {
|
||||||
|
(*j)[i].sort = false
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -151,13 +158,17 @@ func (j *joins) add(newJoins ...join) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *joins) toSQL() string {
|
func (j *joins) toSQL(includeSortPagination bool) string {
|
||||||
if len(*j) == 0 {
|
if len(*j) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var ret []string
|
var ret []string
|
||||||
for _, jj := range *j {
|
for _, jj := range *j {
|
||||||
|
// skip sort-only joins if not including sort/pagination
|
||||||
|
if !includeSortPagination && jj.sort {
|
||||||
|
continue
|
||||||
|
}
|
||||||
ret = append(ret, jj.toSQL())
|
ret = append(ret, jj.toSQL())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -800,10 +800,12 @@ func (qb *GalleryStore) setGallerySort(query *queryBuilder, findFilter *models.F
|
||||||
addFileTable := func() {
|
addFileTable := func() {
|
||||||
query.addJoins(
|
query.addJoins(
|
||||||
join{
|
join{
|
||||||
|
sort: true,
|
||||||
table: galleriesFilesTable,
|
table: galleriesFilesTable,
|
||||||
onClause: "galleries_files.gallery_id = galleries.id",
|
onClause: "galleries_files.gallery_id = galleries.id",
|
||||||
},
|
},
|
||||||
join{
|
join{
|
||||||
|
sort: true,
|
||||||
table: fileTable,
|
table: fileTable,
|
||||||
onClause: "galleries_files.file_id = files.id",
|
onClause: "galleries_files.file_id = files.id",
|
||||||
},
|
},
|
||||||
|
|
@ -813,10 +815,12 @@ func (qb *GalleryStore) setGallerySort(query *queryBuilder, findFilter *models.F
|
||||||
addFolderTable := func() {
|
addFolderTable := func() {
|
||||||
query.addJoins(
|
query.addJoins(
|
||||||
join{
|
join{
|
||||||
|
sort: true,
|
||||||
table: folderTable,
|
table: folderTable,
|
||||||
onClause: "folders.id = galleries.folder_id",
|
onClause: "folders.id = galleries.folder_id",
|
||||||
},
|
},
|
||||||
join{
|
join{
|
||||||
|
sort: true,
|
||||||
table: folderTable,
|
table: folderTable,
|
||||||
as: "file_folder",
|
as: "file_folder",
|
||||||
onClause: "files.parent_folder_id = file_folder.id",
|
onClause: "files.parent_folder_id = file_folder.id",
|
||||||
|
|
|
||||||
|
|
@ -518,7 +518,7 @@ func (qb *GroupStore) setGroupSort(query *queryBuilder, findFilter *models.FindF
|
||||||
} else {
|
} else {
|
||||||
// this will give unexpected results if the query is not filtered by a parent group and
|
// this will give unexpected results if the query is not filtered by a parent group and
|
||||||
// the group has multiple parents and order indexes
|
// the group has multiple parents and order indexes
|
||||||
query.join(groupRelationsTable, "", "groups.id = groups_relations.sub_id")
|
query.joinSort(groupRelationsTable, "", "groups.id = groups_relations.sub_id")
|
||||||
query.sortAndPagination += getSort("order_index", direction, groupRelationsTable)
|
query.sortAndPagination += getSort("order_index", direction, groupRelationsTable)
|
||||||
}
|
}
|
||||||
case "tag_count":
|
case "tag_count":
|
||||||
|
|
|
||||||
|
|
@ -965,10 +965,12 @@ func (qb *ImageStore) setImageSortAndPagination(q *queryBuilder, findFilter *mod
|
||||||
addFilesJoin := func() {
|
addFilesJoin := func() {
|
||||||
q.addJoins(
|
q.addJoins(
|
||||||
join{
|
join{
|
||||||
|
sort: true,
|
||||||
table: imagesFilesTable,
|
table: imagesFilesTable,
|
||||||
onClause: "images_files.image_id = images.id",
|
onClause: "images_files.image_id = images.id",
|
||||||
},
|
},
|
||||||
join{
|
join{
|
||||||
|
sort: true,
|
||||||
table: fileTable,
|
table: fileTable,
|
||||||
onClause: "images_files.file_id = files.id",
|
onClause: "images_files.file_id = files.id",
|
||||||
},
|
},
|
||||||
|
|
@ -977,6 +979,7 @@ func (qb *ImageStore) setImageSortAndPagination(q *queryBuilder, findFilter *mod
|
||||||
|
|
||||||
addFolderJoin := func() {
|
addFolderJoin := func() {
|
||||||
q.addJoins(join{
|
q.addJoins(join{
|
||||||
|
sort: true,
|
||||||
table: folderTable,
|
table: folderTable,
|
||||||
onClause: "files.parent_folder_id = folders.id",
|
onClause: "files.parent_folder_id = folders.id",
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ type queryBuilder struct {
|
||||||
sortAndPagination string
|
sortAndPagination string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb queryBuilder) body() string {
|
func (qb queryBuilder) body(includeSortPagination bool) string {
|
||||||
return fmt.Sprintf("SELECT %s FROM %s%s", strings.Join(qb.columns, ", "), qb.from, qb.joins.toSQL())
|
return fmt.Sprintf("SELECT %s FROM %s%s", strings.Join(qb.columns, ", "), qb.from, qb.joins.toSQL(includeSortPagination))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *queryBuilder) addColumn(column string) {
|
func (qb *queryBuilder) addColumn(column string) {
|
||||||
|
|
@ -33,7 +33,7 @@ func (qb *queryBuilder) addColumn(column string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb queryBuilder) toSQL(includeSortPagination bool) string {
|
func (qb queryBuilder) toSQL(includeSortPagination bool) string {
|
||||||
body := qb.body()
|
body := qb.body(includeSortPagination)
|
||||||
|
|
||||||
withClause := ""
|
withClause := ""
|
||||||
if len(qb.withClauses) > 0 {
|
if len(qb.withClauses) > 0 {
|
||||||
|
|
@ -59,12 +59,14 @@ func (qb queryBuilder) findIDs(ctx context.Context) ([]int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb queryBuilder) executeFind(ctx context.Context) ([]int, int, error) {
|
func (qb queryBuilder) executeFind(ctx context.Context) ([]int, int, error) {
|
||||||
body := qb.body()
|
const includeSortPagination = true
|
||||||
|
body := qb.body(includeSortPagination)
|
||||||
return qb.repository.executeFindQuery(ctx, body, qb.args, qb.sortAndPagination, qb.whereClauses, qb.havingClauses, qb.withClauses, qb.recursiveWith)
|
return qb.repository.executeFindQuery(ctx, body, qb.args, qb.sortAndPagination, qb.whereClauses, qb.havingClauses, qb.withClauses, qb.recursiveWith)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb queryBuilder) executeCount(ctx context.Context) (int, error) {
|
func (qb queryBuilder) executeCount(ctx context.Context) (int, error) {
|
||||||
body := qb.body()
|
const includeSortPagination = false
|
||||||
|
body := qb.body(includeSortPagination)
|
||||||
|
|
||||||
withClause := ""
|
withClause := ""
|
||||||
if len(qb.withClauses) > 0 {
|
if len(qb.withClauses) > 0 {
|
||||||
|
|
@ -131,6 +133,18 @@ func (qb *queryBuilder) join(table, as, onClause string) {
|
||||||
qb.joins.add(newJoin)
|
qb.joins.add(newJoin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (qb *queryBuilder) joinSort(table, as, onClause string) {
|
||||||
|
newJoin := join{
|
||||||
|
sort: true,
|
||||||
|
table: table,
|
||||||
|
as: as,
|
||||||
|
onClause: onClause,
|
||||||
|
joinType: "LEFT",
|
||||||
|
}
|
||||||
|
|
||||||
|
qb.joins.add(newJoin)
|
||||||
|
}
|
||||||
|
|
||||||
func (qb *queryBuilder) addJoins(joins ...join) {
|
func (qb *queryBuilder) addJoins(joins ...join) {
|
||||||
for _, j := range joins {
|
for _, j := range joins {
|
||||||
if qb.joins.addUnique(j) {
|
if qb.joins.addUnique(j) {
|
||||||
|
|
|
||||||
|
|
@ -1157,10 +1157,12 @@ func (qb *SceneStore) setSceneSort(query *queryBuilder, findFilter *models.FindF
|
||||||
addFileTable := func() {
|
addFileTable := func() {
|
||||||
query.addJoins(
|
query.addJoins(
|
||||||
join{
|
join{
|
||||||
|
sort: true,
|
||||||
table: scenesFilesTable,
|
table: scenesFilesTable,
|
||||||
onClause: "scenes_files.scene_id = scenes.id",
|
onClause: "scenes_files.scene_id = scenes.id",
|
||||||
},
|
},
|
||||||
join{
|
join{
|
||||||
|
sort: true,
|
||||||
table: fileTable,
|
table: fileTable,
|
||||||
onClause: "scenes_files.file_id = files.id",
|
onClause: "scenes_files.file_id = files.id",
|
||||||
},
|
},
|
||||||
|
|
@ -1171,6 +1173,7 @@ func (qb *SceneStore) setSceneSort(query *queryBuilder, findFilter *models.FindF
|
||||||
addFileTable()
|
addFileTable()
|
||||||
query.addJoins(
|
query.addJoins(
|
||||||
join{
|
join{
|
||||||
|
sort: true,
|
||||||
table: videoFileTable,
|
table: videoFileTable,
|
||||||
onClause: "video_files.file_id = scenes_files.file_id",
|
onClause: "video_files.file_id = scenes_files.file_id",
|
||||||
},
|
},
|
||||||
|
|
@ -1180,6 +1183,7 @@ func (qb *SceneStore) setSceneSort(query *queryBuilder, findFilter *models.FindF
|
||||||
addFolderTable := func() {
|
addFolderTable := func() {
|
||||||
query.addJoins(
|
query.addJoins(
|
||||||
join{
|
join{
|
||||||
|
sort: true,
|
||||||
table: folderTable,
|
table: folderTable,
|
||||||
onClause: "files.parent_folder_id = folders.id",
|
onClause: "files.parent_folder_id = folders.id",
|
||||||
},
|
},
|
||||||
|
|
@ -1189,10 +1193,10 @@ func (qb *SceneStore) setSceneSort(query *queryBuilder, findFilter *models.FindF
|
||||||
direction := findFilter.GetDirection()
|
direction := findFilter.GetDirection()
|
||||||
switch sort {
|
switch sort {
|
||||||
case "movie_scene_number":
|
case "movie_scene_number":
|
||||||
query.join(groupsScenesTable, "", "scenes.id = groups_scenes.scene_id")
|
query.joinSort(groupsScenesTable, "", "scenes.id = groups_scenes.scene_id")
|
||||||
query.sortAndPagination += getSort("scene_index", direction, groupsScenesTable)
|
query.sortAndPagination += getSort("scene_index", direction, groupsScenesTable)
|
||||||
case "group_scene_number":
|
case "group_scene_number":
|
||||||
query.join(groupsScenesTable, "scene_group", "scenes.id = scene_group.scene_id")
|
query.joinSort(groupsScenesTable, "scene_group", "scenes.id = scene_group.scene_id")
|
||||||
query.sortAndPagination += getSort("scene_index", direction, "scene_group")
|
query.sortAndPagination += getSort("scene_index", direction, "scene_group")
|
||||||
case "tag_count":
|
case "tag_count":
|
||||||
query.sortAndPagination += getCountSort(sceneTable, scenesTagsTable, sceneIDColumn, direction)
|
query.sortAndPagination += getCountSort(sceneTable, scenesTagsTable, sceneIDColumn, direction)
|
||||||
|
|
@ -1210,6 +1214,7 @@ func (qb *SceneStore) setSceneSort(query *queryBuilder, findFilter *models.FindF
|
||||||
addFileTable()
|
addFileTable()
|
||||||
query.addJoins(
|
query.addJoins(
|
||||||
join{
|
join{
|
||||||
|
sort: true,
|
||||||
table: fingerprintTable,
|
table: fingerprintTable,
|
||||||
as: "fingerprints_phash",
|
as: "fingerprints_phash",
|
||||||
onClause: "scenes_files.file_id = fingerprints_phash.file_id AND fingerprints_phash.type = 'phash'",
|
onClause: "scenes_files.file_id = fingerprints_phash.file_id AND fingerprints_phash.type = 'phash'",
|
||||||
|
|
@ -1274,7 +1279,7 @@ func (qb *SceneStore) setSceneSort(query *queryBuilder, findFilter *models.FindF
|
||||||
getSortDirection(direction),
|
getSortDirection(direction),
|
||||||
)
|
)
|
||||||
case "studio":
|
case "studio":
|
||||||
query.join(studioTable, "", "scenes.studio_id = studios.id")
|
query.joinSort(studioTable, "", "scenes.studio_id = studios.id")
|
||||||
query.sortAndPagination += getSort("name", direction, studioTable)
|
query.sortAndPagination += getSort("name", direction, studioTable)
|
||||||
default:
|
default:
|
||||||
query.sortAndPagination += getSort(sort, direction, "scenes")
|
query.sortAndPagination += getSort(sort, direction, "scenes")
|
||||||
|
|
|
||||||
|
|
@ -392,10 +392,10 @@ func (qb *SceneMarkerStore) setSceneMarkerSort(query *queryBuilder, findFilter *
|
||||||
switch sort {
|
switch sort {
|
||||||
case "scenes_updated_at":
|
case "scenes_updated_at":
|
||||||
sort = "updated_at"
|
sort = "updated_at"
|
||||||
query.join(sceneTable, "", "scenes.id = scene_markers.scene_id")
|
query.joinSort(sceneTable, "", "scenes.id = scene_markers.scene_id")
|
||||||
query.sortAndPagination += getSort(sort, direction, sceneTable)
|
query.sortAndPagination += getSort(sort, direction, sceneTable)
|
||||||
case "title":
|
case "title":
|
||||||
query.join(tagTable, "", "scene_markers.primary_tag_id = tags.id")
|
query.joinSort(tagTable, "", "scene_markers.primary_tag_id = tags.id")
|
||||||
query.sortAndPagination += " ORDER BY COALESCE(NULLIF(scene_markers.title,''), tags.name) COLLATE NATURAL_CI " + direction
|
query.sortAndPagination += " ORDER BY COALESCE(NULLIF(scene_markers.title,''), tags.name) COLLATE NATURAL_CI " + direction
|
||||||
case "duration":
|
case "duration":
|
||||||
sort = "(scene_markers.end_seconds - scene_markers.seconds)"
|
sort = "(scene_markers.end_seconds - scene_markers.seconds)"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue