diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 4c204b0..e3c94b4 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -5,7 +5,7 @@ Supports job archive version 1 and database version 4. This is the initial release of `cc-backend`, the API backend and frontend implementation of ClusterCockpit. -**Breaking changes** +** Breaking changes ** The aggregate job statistic core hours is now computed using the job table column `num_hwthreads`. In a future release this column will be renamed to @@ -16,6 +16,16 @@ if you have exclusive jobs, only. Please be aware that we treat this column as it is the number of cores. In case you have SMT enabled and `num_hwthreads` is not the number of cores the core hours will be too high by a factor! +** NOTE ** +If you are using the sqlite3 backend the `PRAGMA` option `foreign_keys` must be +explicitly set to ON. If using the sqlite3 console it is per default set to +OFF! On every console session you must set: +``` +sqlite> PRAGMA foreign_keys = ON; + +``` +Otherwise if you delete jobs the jobtag relation table will not be updated accordingly! + **Notable changes** * Supports user roles admin, support, manager, user, and api. * Unified search bar supports job id, job name, project id, user name, and name diff --git a/internal/repository/migration.go b/internal/repository/migration.go index 90bc8f7..7582156 100644 --- a/internal/repository/migration.go +++ b/internal/repository/migration.go @@ -16,7 +16,7 @@ import ( "github.com/golang-migrate/migrate/v4/source/iofs" ) -const Version uint = 4 +const Version uint = 5 //go:embed migrations/* var migrationFiles embed.FS diff --git a/internal/repository/migrations/mysql/05_extend-tags.down.sql b/internal/repository/migrations/mysql/05_extend-tags.down.sql new file mode 100644 index 0000000..925c9f8 --- /dev/null +++ b/internal/repository/migrations/mysql/05_extend-tags.down.sql @@ -0,0 +1,2 @@ +ALTER TABLE tag DROP COLUMN insert_time; +ALTER TABLE jobtag DROP COLUMN insert_time; diff --git a/internal/repository/migrations/mysql/05_extend-tags.up.sql b/internal/repository/migrations/mysql/05_extend-tags.up.sql new file mode 100644 index 0000000..4577564 --- /dev/null +++ b/internal/repository/migrations/mysql/05_extend-tags.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE tag ADD COLUMN insert_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP; +ALTER TABLE jobtag ADD COLUMN insert_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP; diff --git a/internal/repository/migrations/sqlite3/05_extend-tags.down.sql b/internal/repository/migrations/sqlite3/05_extend-tags.down.sql new file mode 100644 index 0000000..925c9f8 --- /dev/null +++ b/internal/repository/migrations/sqlite3/05_extend-tags.down.sql @@ -0,0 +1,2 @@ +ALTER TABLE tag DROP COLUMN insert_time; +ALTER TABLE jobtag DROP COLUMN insert_time; diff --git a/internal/repository/migrations/sqlite3/05_extend-tags.up.sql b/internal/repository/migrations/sqlite3/05_extend-tags.up.sql new file mode 100644 index 0000000..62a2646 --- /dev/null +++ b/internal/repository/migrations/sqlite3/05_extend-tags.up.sql @@ -0,0 +1,18 @@ +ALTER TABLE tag ADD COLUMN insert_ts TEXT DEFAULT NULL /* replace me */; +ALTER TABLE jobtag ADD COLUMN insert_ts TEXT DEFAULT NULL /* replace me */; +UPDATE tag SET insert_ts = CURRENT_TIMESTAMP; +UPDATE jobtag SET insert_ts = CURRENT_TIMESTAMP; +PRAGMA writable_schema = on; + +UPDATE sqlite_master +SET sql = replace(sql, 'DEFAULT NULL /* replace me */', + 'DEFAULT CURRENT_TIMESTAMP') +WHERE type = 'table' + AND name = 'tag'; +UPDATE sqlite_master +SET sql = replace(sql, 'DEFAULT NULL /* replace me */', + 'DEFAULT CURRENT_TIMESTAMP') +WHERE type = 'table' + AND name = 'jobtag'; + +PRAGMA writable_schema = off; diff --git a/internal/repository/tags.go b/internal/repository/tags.go index 2c98b60..6c46352 100644 --- a/internal/repository/tags.go +++ b/internal/repository/tags.go @@ -70,14 +70,14 @@ func (r *JobRepository) CreateTag(tagType string, tagName string) (tagId int64, func (r *JobRepository) CountTags(user *auth.User) (tags []schema.Tag, counts map[string]int, err error) { tags = make([]schema.Tag, 0, 100) - xrows, err := r.DB.Queryx("SELECT * FROM tag") + xrows, err := r.DB.Queryx("SELECT id, tag_type, tag_name FROM tag") if err != nil { return nil, nil, err } for xrows.Next() { var t schema.Tag - if err := xrows.StructScan(&t); err != nil { + if err = xrows.StructScan(&t); err != nil { return nil, nil, err } tags = append(tags, t) @@ -89,7 +89,7 @@ func (r *JobRepository) CountTags(user *auth.User) (tags []schema.Tag, counts ma GroupBy("t.tag_name") if user != nil && user.HasAnyRole([]auth.Role{auth.RoleAdmin, auth.RoleSupport}) { // ADMIN || SUPPORT: Count all jobs - log.Info("CountTags: User Admin or Support -> Count all Jobs for Tags") + log.Debug("CountTags: User Admin or Support -> Count all Jobs for Tags") // Unchanged: Needs to be own case still, due to UserRole/NoRole compatibility handling in else case } else if user != nil && user.HasRole(auth.RoleManager) { // MANAGER: Count own jobs plus project's jobs // Build ("project1", "project2", ...) list of variable length directly in SQL string @@ -107,7 +107,7 @@ func (r *JobRepository) CountTags(user *auth.User) (tags []schema.Tag, counts ma for rows.Next() { var tagName string var count int - if err := rows.Scan(&tagName, &count); err != nil { + if err = rows.Scan(&tagName, &count); err != nil { return nil, nil, err } counts[tagName] = count diff --git a/pkg/schema/job.go b/pkg/schema/job.go index 23ae1ef..ed3a8b6 100644 --- a/pkg/schema/job.go +++ b/pkg/schema/job.go @@ -124,9 +124,7 @@ type JobStatistics struct { // Tag model // @Description Defines a tag using name and type. type Tag struct { - // The unique DB identifier of a tag - // The unique DB identifier of a tag - ID int64 `json:"id" db:"id"` + ID int64 `json:"id" db:"id"` // The unique DB identifier of a tag Type string `json:"type" db:"tag_type" example:"Debug"` // Tag Type Name string `json:"name" db:"tag_name" example:"Testjob"` // Tag Name }