From 4abb0797fe1c8e5d9c8c5d4d2524e8461db9439f Mon Sep 17 00:00:00 2001 From: Mikhail Kondrashin Date: Fri, 3 Jan 2025 20:47:39 +0300 Subject: [PATCH 1/2] readme for database + one-to-one relationships --- db/db.go | 8 +++++ db/models/problem.go | 3 +- db/models/problem_config.go | 5 +++- db/models/submission.go | 9 +++--- db/models/testing_result.go | 8 +++-- db/readme.md | 60 +++++++++++++++++++++++++++++++++++++ 6 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 db/readme.md diff --git a/db/db.go b/db/db.go index 5f792cc..d9cb6db 100644 --- a/db/db.go +++ b/db/db.go @@ -13,6 +13,14 @@ func NewDb(config Config) (*gorm.DB, error) { slog.Error("Can't open database", "dsn", config.Dsn, "err", err) return nil, err } + if err = db.AutoMigrate(&models.TestingResult{}); err != nil { + slog.Error("Can't migrate TestingResult", "err", err) + return nil, err + } + if err = db.AutoMigrate(&models.ProblemConfig{}); err != nil { + slog.Error("Can't migrate ProblemConfig", "err", err) + return nil, err + } if err = db.AutoMigrate(&models.Problem{}); err != nil { slog.Error("Can't migrate Problem", "err", err) return nil, err diff --git a/db/models/problem.go b/db/models/problem.go index c9d5007..923ce66 100644 --- a/db/models/problem.go +++ b/db/models/problem.go @@ -4,5 +4,6 @@ import "gorm.io/gorm" type Problem struct { gorm.Model - ProblemConfig + ProblemConfigId int + ProblemConfig ProblemConfig } diff --git a/db/models/problem_config.go b/db/models/problem_config.go index cd0b663..f311e32 100644 --- a/db/models/problem_config.go +++ b/db/models/problem_config.go @@ -1,13 +1,16 @@ package models +import "gorm.io/gorm" + type ProblemType int const ( - ProblemType_ICPC ProblemType = iota + ProblemType_ICPC ProblemType = iota + 1 ProblemType_IOI ) type ProblemConfig struct { + gorm.Model ProblemType ProblemType // everything we need here } diff --git a/db/models/submission.go b/db/models/submission.go index 7448874..f43ca77 100644 --- a/db/models/submission.go +++ b/db/models/submission.go @@ -4,8 +4,9 @@ import "gorm.io/gorm" type Submission struct { gorm.Model - TestingResult - ContentId uint64 // id of submission in the storage - TaskId uint64 - TaskVersionId uint64 + ContentId uint64 // id of submission in the storage + TaskId uint64 + TaskVersionId uint64 + TestingResultId int + TestingResult TestingResult } diff --git a/db/models/testing_result.go b/db/models/testing_result.go index 553c6b1..a241970 100644 --- a/db/models/testing_result.go +++ b/db/models/testing_result.go @@ -1,11 +1,14 @@ package models -import "github.com/lib/pq" +import ( + "github.com/lib/pq" + "gorm.io/gorm" +) type Verdict int const ( - Verdict_OK int = iota + Verdict_OK Verdict = iota + 1 Verdict_WA Verdict_TL Verdict_ML @@ -14,5 +17,6 @@ const ( ) type TestingResult struct { + gorm.Model Verdicts pq.Int64Array `gorm:"type:int[]"` } diff --git a/db/readme.md b/db/readme.md new file mode 100644 index 0000000..95a7f79 --- /dev/null +++ b/db/readme.md @@ -0,0 +1,60 @@ +# Как пользоваться базой + +### Подключаемся + +```go +conn, err := db.NewDb(db.Config{Dsn: "DSN_STRING"}) +if err != nil {...} +``` + +### Создание объекта + +```go +config := &models.ProblemConfig{ProblemType: models.ProblemType_ICPC} +result := conn.Create(&config) +config.ID // номер нового объекта +result.Error // если была ошибка +result.RowsAffected // сколько строк вставилосб +``` + +https://gorm.io/docs/create.html + +### Получение объекта (обычно одного) + +```go +var problem Problem +var problems []Problem +err := conn.First(&problem) +// теперь либо err.Error != nil, либо в problem лежит запись с минимальным id +conn.Take(&problem) // рандомная запись +conn.Last(&problem) // последняя запись +errors.Is(result.Error, gorm.ErrRecordNotFound) // пример ошибки + +result := map[string]interface{}{} +conn.Model(&models.Problem{}).First(&result) // после этого можно обращаться как к мапе + +conn.Find(&problem, 1) // выбрать с id == 1 +conn.Find(&problem, "id = ?", 1) +conn.Find(&problems, []int{1, 2, 3}) // выбрать с id \in {1, 2, 3} +conn.Find(&problems) // все объекты +``` + +https://gorm.io/docs/query.html + +### Продвинутые штуки + +Если просто вытащить задачу, то не вытащится ее конфиг. Для этого надо сделать join: + +``conn.Joins("ProblemConfig").Find(&problems)`` + +Вообще gorm это какой-то полный пиздец. Например, чтобы вытащить все ICPC задачи, надо сделать так: + +```go +conn. + Model(&models.Problem{}). + InnerJoins("ProblemConfig", conn.Where(&models.ProblemConfig{ProblemType: models.ProblemType_ICPC})). + Find(&problems) +``` + +Выглядит легко, но это одна из самых простых вещей...) +Все равно придется писать запросы (наполовину) руками и молиться, чтобы оно работало From c39c89748ef944d103b9f3c926b33080946b504d Mon Sep 17 00:00:00 2001 From: Mikhail Kondrashin Date: Sat, 4 Jan 2025 17:02:28 +0300 Subject: [PATCH 2/2] fix --- db/db.go | 4 ---- db/models/problem.go | 10 ++++++++-- db/models/problem_config.go | 16 ---------------- db/models/submission.go | 9 ++++----- db/readme.md | 23 ++++++++++------------- 5 files changed, 22 insertions(+), 40 deletions(-) delete mode 100644 db/models/problem_config.go diff --git a/db/db.go b/db/db.go index d9cb6db..c0deaa0 100644 --- a/db/db.go +++ b/db/db.go @@ -17,10 +17,6 @@ func NewDb(config Config) (*gorm.DB, error) { slog.Error("Can't migrate TestingResult", "err", err) return nil, err } - if err = db.AutoMigrate(&models.ProblemConfig{}); err != nil { - slog.Error("Can't migrate ProblemConfig", "err", err) - return nil, err - } if err = db.AutoMigrate(&models.Problem{}); err != nil { slog.Error("Can't migrate Problem", "err", err) return nil, err diff --git a/db/models/problem.go b/db/models/problem.go index 923ce66..f4e3515 100644 --- a/db/models/problem.go +++ b/db/models/problem.go @@ -2,8 +2,14 @@ package models import "gorm.io/gorm" +type ProblemType int + +const ( + ProblemType_ICPC ProblemType = iota + 1 + ProblemType_IOI +) + type Problem struct { gorm.Model - ProblemConfigId int - ProblemConfig ProblemConfig + ProblemType ProblemType } diff --git a/db/models/problem_config.go b/db/models/problem_config.go deleted file mode 100644 index f311e32..0000000 --- a/db/models/problem_config.go +++ /dev/null @@ -1,16 +0,0 @@ -package models - -import "gorm.io/gorm" - -type ProblemType int - -const ( - ProblemType_ICPC ProblemType = iota + 1 - ProblemType_IOI -) - -type ProblemConfig struct { - gorm.Model - ProblemType ProblemType - // everything we need here -} diff --git a/db/models/submission.go b/db/models/submission.go index f43ca77..b3a8f07 100644 --- a/db/models/submission.go +++ b/db/models/submission.go @@ -4,9 +4,8 @@ import "gorm.io/gorm" type Submission struct { gorm.Model - ContentId uint64 // id of submission in the storage - TaskId uint64 - TaskVersionId uint64 - TestingResultId int - TestingResult TestingResult + ProblemID uint64 + ProblemVersionID uint64 + TestingResultID int + TestingResult TestingResult } diff --git a/db/readme.md b/db/readme.md index 95a7f79..e3a9745 100644 --- a/db/readme.md +++ b/db/readme.md @@ -41,20 +41,17 @@ conn.Find(&problems) // все объекты https://gorm.io/docs/query.html -### Продвинутые штуки - -Если просто вытащить задачу, то не вытащится ее конфиг. Для этого надо сделать join: - -``conn.Joins("ProblemConfig").Find(&problems)`` - -Вообще gorm это какой-то полный пиздец. Например, чтобы вытащить все ICPC задачи, надо сделать так: +### Условия ```go -conn. - Model(&models.Problem{}). - InnerJoins("ProblemConfig", conn.Where(&models.ProblemConfig{ProblemType: models.ProblemType_ICPC})). +// все IOI задачи +conn.Where(models.Problem{ProblemType: models.ProblemType_IOI}).Find(&problems) +conn.Find(&problems, "problem_type = ?", models.ProblemType_IOI) +conn.Find(&problems, map[string]any{"problem_type": models.ProblemType_IOI}) +conn.Not("problem_type = ?", models.ProblemType_ICPC).Find(&problems) +// все IOI задачи или с id == 1 +conn. + Where("problem_type = ?", models.ProblemType_IOI). + Or(1). Find(&problems) ``` - -Выглядит легко, но это одна из самых простых вещей...) -Все равно придется писать запросы (наполовину) руками и молиться, чтобы оно работало