mirror of https://github.com/stashapp/stash.git
Fix integer overflow for scene size on 32bit systems (#994)
* Fix integer overflow for scene size on 32bit systems * Cast to double in sqlite to prevent potential overflow * Add migration to reset scene sizes and scan logic to repopulate if empty
This commit is contained in:
parent
e883e5fe27
commit
e84c92355e
|
@ -1,8 +1,8 @@
|
||||||
type StatsResultType {
|
type StatsResultType {
|
||||||
scene_count: Int!
|
scene_count: Int!
|
||||||
scenes_size: Int!
|
scenes_size: Float!
|
||||||
image_count: Int!
|
image_count: Int!
|
||||||
images_size: Int!
|
images_size: Float!
|
||||||
gallery_count: Int!
|
gallery_count: Int!
|
||||||
performer_count: Int!
|
performer_count: Int!
|
||||||
studio_count: Int!
|
studio_count: Int!
|
||||||
|
|
|
@ -133,9 +133,9 @@ func (r *queryResolver) Stats(ctx context.Context) (*models.StatsResultType, err
|
||||||
tagsCount, _ := tagsQB.Count()
|
tagsCount, _ := tagsQB.Count()
|
||||||
return &models.StatsResultType{
|
return &models.StatsResultType{
|
||||||
SceneCount: scenesCount,
|
SceneCount: scenesCount,
|
||||||
ScenesSize: int(scenesSize),
|
ScenesSize: scenesSize,
|
||||||
ImageCount: imageCount,
|
ImageCount: imageCount,
|
||||||
ImagesSize: int(imageSize),
|
ImagesSize: imageSize,
|
||||||
GalleryCount: galleryCount,
|
GalleryCount: galleryCount,
|
||||||
PerformerCount: performersCount,
|
PerformerCount: performersCount,
|
||||||
StudioCount: studiosCount,
|
StudioCount: studiosCount,
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
|
|
||||||
var DB *sqlx.DB
|
var DB *sqlx.DB
|
||||||
var dbPath string
|
var dbPath string
|
||||||
var appSchemaVersion uint = 16
|
var appSchemaVersion uint = 17
|
||||||
var databaseSchemaVersion uint
|
var databaseSchemaVersion uint
|
||||||
|
|
||||||
const sqlite3Driver = "sqlite3ex"
|
const sqlite3Driver = "sqlite3ex"
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
UPDATE `scenes` SET `size` = NULL;
|
|
@ -360,7 +360,7 @@ func (t *ScanTask) scanScene() *models.Scene {
|
||||||
// if the mod time of the file is different than that of the associated
|
// if the mod time of the file is different than that of the associated
|
||||||
// scene, then recalculate the checksum and regenerate the thumbnail
|
// scene, then recalculate the checksum and regenerate the thumbnail
|
||||||
modified := t.isFileModified(fileModTime, scene.FileModTime)
|
modified := t.isFileModified(fileModTime, scene.FileModTime)
|
||||||
if modified {
|
if modified || !scene.Size.Valid {
|
||||||
scene, err = t.rescanScene(scene, fileModTime)
|
scene, err = t.rescanScene(scene, fileModTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err.Error())
|
logger.Error(err.Error())
|
||||||
|
@ -534,7 +534,7 @@ func (t *ScanTask) scanScene() *models.Scene {
|
||||||
Height: sql.NullInt64{Int64: int64(videoFile.Height), Valid: true},
|
Height: sql.NullInt64{Int64: int64(videoFile.Height), Valid: true},
|
||||||
Framerate: sql.NullFloat64{Float64: videoFile.FrameRate, Valid: true},
|
Framerate: sql.NullFloat64{Float64: videoFile.FrameRate, Valid: true},
|
||||||
Bitrate: sql.NullInt64{Int64: videoFile.Bitrate, Valid: true},
|
Bitrate: sql.NullInt64{Int64: videoFile.Bitrate, Valid: true},
|
||||||
Size: sql.NullString{String: strconv.Itoa(int(videoFile.Size)), Valid: true},
|
Size: sql.NullString{String: strconv.FormatInt(videoFile.Size, 10), Valid: true},
|
||||||
FileModTime: models.NullSQLiteTimestamp{
|
FileModTime: models.NullSQLiteTimestamp{
|
||||||
Timestamp: fileModTime,
|
Timestamp: fileModTime,
|
||||||
Valid: true,
|
Valid: true,
|
||||||
|
@ -610,7 +610,7 @@ func (t *ScanTask) rescanScene(scene *models.Scene, fileModTime time.Time) (*mod
|
||||||
Height: &sql.NullInt64{Int64: int64(videoFile.Height), Valid: true},
|
Height: &sql.NullInt64{Int64: int64(videoFile.Height), Valid: true},
|
||||||
Framerate: &sql.NullFloat64{Float64: videoFile.FrameRate, Valid: true},
|
Framerate: &sql.NullFloat64{Float64: videoFile.FrameRate, Valid: true},
|
||||||
Bitrate: &sql.NullInt64{Int64: videoFile.Bitrate, Valid: true},
|
Bitrate: &sql.NullInt64{Int64: videoFile.Bitrate, Valid: true},
|
||||||
Size: &sql.NullString{String: strconv.Itoa(int(videoFile.Size)), Valid: true},
|
Size: &sql.NullString{String: strconv.FormatInt(videoFile.Size, 10), Valid: true},
|
||||||
FileModTime: &models.NullSQLiteTimestamp{
|
FileModTime: &models.NullSQLiteTimestamp{
|
||||||
Timestamp: fileModTime,
|
Timestamp: fileModTime,
|
||||||
Valid: true,
|
Valid: true,
|
||||||
|
|
|
@ -246,8 +246,8 @@ func (qb *ImageQueryBuilder) Count() (int, error) {
|
||||||
return runCountQuery(buildCountQuery("SELECT images.id FROM images"), nil)
|
return runCountQuery(buildCountQuery("SELECT images.id FROM images"), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *ImageQueryBuilder) Size() (uint64, error) {
|
func (qb *ImageQueryBuilder) Size() (float64, error) {
|
||||||
return runSumQuery("SELECT SUM(size) as sum FROM images", nil)
|
return runSumQuery("SELECT SUM(cast(size as double)) as sum FROM images", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *ImageQueryBuilder) CountByStudioID(studioID int) (int, error) {
|
func (qb *ImageQueryBuilder) CountByStudioID(studioID int) (int, error) {
|
||||||
|
|
|
@ -254,8 +254,8 @@ func (qb *SceneQueryBuilder) Count() (int, error) {
|
||||||
return runCountQuery(buildCountQuery("SELECT scenes.id FROM scenes"), nil)
|
return runCountQuery(buildCountQuery("SELECT scenes.id FROM scenes"), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *SceneQueryBuilder) Size() (uint64, error) {
|
func (qb *SceneQueryBuilder) Size() (float64, error) {
|
||||||
return runSumQuery("SELECT SUM(size) as sum FROM scenes", nil)
|
return runSumQuery("SELECT SUM(cast(size as double)) as sum FROM scenes", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qb *SceneQueryBuilder) CountByStudioID(studioID int) (int, error) {
|
func (qb *SceneQueryBuilder) CountByStudioID(studioID int) (int, error) {
|
||||||
|
|
|
@ -332,16 +332,16 @@ func runCountQuery(query string, args []interface{}) (int, error) {
|
||||||
return result.Int, nil
|
return result.Int, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runSumQuery(query string, args []interface{}) (uint64, error) {
|
func runSumQuery(query string, args []interface{}) (float64, error) {
|
||||||
// Perform query and fetch result
|
// Perform query and fetch result
|
||||||
result := struct {
|
result := struct {
|
||||||
Uint uint64 `db:"sum"`
|
Float64 float64 `db:"sum"`
|
||||||
}{0}
|
}{0}
|
||||||
if err := database.DB.Get(&result, query, args...); err != nil && err != sql.ErrNoRows {
|
if err := database.DB.Get(&result, query, args...); err != nil && err != sql.ErrNoRows {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.Uint, nil
|
return result.Float64, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeFindQuery(tableName string, body string, args []interface{}, sortAndPagination string, whereClauses []string, havingClauses []string) ([]int, int) {
|
func executeFindQuery(tableName string, body string, args []interface{}, sortAndPagination string, whereClauses []string, havingClauses []string) ([]int, int) {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#### 💥 **Note: After upgrading, all scene file sizes will be 0B until a new [scan](/settings?tab=tasks) is run.
|
||||||
|
|
||||||
### ✨ New Features
|
### ✨ New Features
|
||||||
* Add organized flag for scenes, galleries and images.
|
* Add organized flag for scenes, galleries and images.
|
||||||
* Allow configuration of visible navbar items.
|
* Allow configuration of visible navbar items.
|
||||||
|
@ -14,4 +16,5 @@
|
||||||
* Support configurable number of threads for scanning and generation.
|
* Support configurable number of threads for scanning and generation.
|
||||||
|
|
||||||
### 🐛 Bug fixes
|
### 🐛 Bug fixes
|
||||||
|
* Corrected file sizes on 32bit platforms
|
||||||
* Fixed login redirect to remember the current page.
|
* Fixed login redirect to remember the current page.
|
||||||
|
|
Loading…
Reference in New Issue