From 3a903741f57eb573ff5495f0fc5cb50ce07acc5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Wysoki=C5=84ski?= Date: Thu, 14 Mar 2024 08:06:17 +0100 Subject: [PATCH] refactor: repositories - simplify how cursor/sort is applied --- .golangci.yml | 17 +- internal/adapter/bun_utils.go | 10 +- .../adapter/repository_bun_ennoblement.go | 76 ++++---- internal/adapter/repository_bun_player.go | 162 ++++++++---------- .../adapter/repository_bun_player_snapshot.go | 42 +++-- internal/adapter/repository_bun_server.go | 61 +++---- internal/adapter/repository_bun_tribe.go | 162 ++++++++---------- .../adapter/repository_bun_tribe_change.go | 76 ++++---- .../adapter/repository_bun_tribe_snapshot.go | 42 +++-- internal/adapter/repository_bun_version.go | 41 +++-- internal/adapter/repository_bun_village.go | 58 ++++--- 11 files changed, 379 insertions(+), 368 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 27fd47e..301d5d6 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,6 +5,10 @@ run: linters: disable-all: true enable: + - gochecknoinits + - goprintffuncname + - nosprintfhostport + - spancheck - gocyclo - asasalint - asciicheck @@ -54,6 +58,7 @@ linters: - sloglint - revive - gomnd + - forbidigo linters-settings: gocyclo: @@ -65,6 +70,13 @@ linters-settings: bun: snake lll: line-length: 120 + forbidigo: + forbid: + - p: ^print.*$ + msg: Do not commit print statements. + - p: ^fmt\.Print.*$ + msg: Do not commit print statements. + analyze-types: true govet: enable: - asmdecl @@ -291,7 +303,7 @@ linters-settings: disabled: false # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#indent-error-flow - name: indent-error-flow - severity: warning + severity: error disabled: false arguments: - preserveScope @@ -477,6 +489,9 @@ issues: - gocyclo - path: _test\.go text: add-constant + - path: bun/migrations + linters: + - gochecknoinits - linters: - lll source: "^//go:generate " diff --git a/internal/adapter/bun_utils.go b/internal/adapter/bun_utils.go index 42ec31b..126fdd1 100644 --- a/internal/adapter/bun_utils.go +++ b/internal/adapter/bun_utils.go @@ -38,6 +38,10 @@ const ( sortDirectionDESC ) +func (sd sortDirection) Bun() bun.Safe { + return bun.Safe(sd.String()) +} + func (sd sortDirection) String() string { switch sd { case sortDirectionASC: @@ -51,7 +55,7 @@ func (sd sortDirection) String() string { type cursorPaginationApplierDataElement struct { unique bool - column string + column bun.Safe direction sortDirection value any } @@ -86,10 +90,10 @@ func (a cursorPaginationApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { for j := 0; j < i; j++ { prev := a.data[j] - q = q.Where("? = ?", bun.Safe(prev.column), prev.value) + q = q.Where("? = ?", prev.column, prev.value) } - column := bun.Safe(current.column) + column := current.column greaterSymbol := bun.Safe(">") lessSymbol := bun.Safe("<") diff --git a/internal/adapter/repository_bun_ennoblement.go b/internal/adapter/repository_bun_ennoblement.go index 4d9c537..33a8b86 100644 --- a/internal/adapter/repository_bun_ennoblement.go +++ b/internal/adapter/repository_bun_ennoblement.go @@ -112,7 +112,6 @@ type listEnnoblementsParamsApplier struct { params domain.ListEnnoblementsParams } -//nolint:gocyclo func (a listEnnoblementsParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { if serverKeys := a.params.ServerKeys(); len(serverKeys) > 0 { q = q.Where("ennoblement.server_key IN (?)", bun.In(serverKeys)) @@ -145,22 +144,12 @@ func (a listEnnoblementsParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuer } for _, s := range a.params.Sort() { - switch s { - case domain.EnnoblementSortCreatedAtASC: - q = q.Order("ennoblement.created_at ASC") - case domain.EnnoblementSortCreatedAtDESC: - q = q.Order("ennoblement.created_at DESC") - case domain.EnnoblementSortIDASC: - q = q.Order("ennoblement.id ASC") - case domain.EnnoblementSortIDDESC: - q = q.Order("ennoblement.id DESC") - case domain.EnnoblementSortServerKeyASC: - q = q.Order("ennoblement.server_key ASC") - case domain.EnnoblementSortServerKeyDESC: - q = q.Order("ennoblement.server_key DESC") - default: - return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) + column, dir, err := a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) } + + q.OrderExpr("? ?", column, dir.Bun()) } return q.Limit(a.params.Limit() + 1).Apply(a.applyCursor) @@ -179,35 +168,25 @@ func (a listEnnoblementsParamsApplier) applyCursor(q *bun.SelectQuery) *bun.Sele } for _, s := range sort { + var err error var el cursorPaginationApplierDataElement + el.column, el.direction, err = a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) + } + switch s { - case domain.EnnoblementSortIDASC: + case domain.EnnoblementSortIDASC, + domain.EnnoblementSortIDDESC: el.value = cursor.ID() el.unique = true - el.column = "ennoblement.id" - el.direction = sortDirectionASC - case domain.EnnoblementSortIDDESC: - el.value = cursor.ID() - el.unique = true - el.column = "ennoblement.id" - el.direction = sortDirectionDESC - case domain.EnnoblementSortServerKeyASC: + case domain.EnnoblementSortServerKeyASC, + domain.EnnoblementSortServerKeyDESC: el.value = cursor.ServerKey() - el.column = "ennoblement.server_key" - el.direction = sortDirectionASC - case domain.EnnoblementSortServerKeyDESC: - el.value = cursor.ServerKey() - el.column = "ennoblement.server_key" - el.direction = sortDirectionDESC - case domain.EnnoblementSortCreatedAtASC: + case domain.EnnoblementSortCreatedAtASC, + domain.EnnoblementSortCreatedAtDESC: el.value = cursor.CreatedAt() - el.column = "ennoblement.created_at" - el.direction = sortDirectionASC - case domain.EnnoblementSortCreatedAtDESC: - el.value = cursor.CreatedAt() - el.column = "ennoblement.created_at" - el.direction = sortDirectionDESC default: return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) } @@ -217,3 +196,24 @@ func (a listEnnoblementsParamsApplier) applyCursor(q *bun.SelectQuery) *bun.Sele return q.Apply(cursorApplier.apply) } + +func (a listEnnoblementsParamsApplier) sortToColumnAndDirection( + s domain.EnnoblementSort, +) (bun.Safe, sortDirection, error) { + switch s { + case domain.EnnoblementSortCreatedAtASC: + return "ennoblement.created_at", sortDirectionASC, nil + case domain.EnnoblementSortCreatedAtDESC: + return "ennoblement.created_at", sortDirectionDESC, nil + case domain.EnnoblementSortIDASC: + return "ennoblement.id", sortDirectionASC, nil + case domain.EnnoblementSortIDDESC: + return "ennoblement.id", sortDirectionDESC, nil + case domain.EnnoblementSortServerKeyASC: + return "ennoblement.server_key", sortDirectionASC, nil + case domain.EnnoblementSortServerKeyDESC: + return "ennoblement.server_key", sortDirectionDESC, nil + default: + return "", 0, fmt.Errorf("%s: %w", s.String(), errInvalidSortValue) + } +} diff --git a/internal/adapter/repository_bun_player.go b/internal/adapter/repository_bun_player.go index 8d79604..fd08ef0 100644 --- a/internal/adapter/repository_bun_player.go +++ b/internal/adapter/repository_bun_player.go @@ -158,7 +158,6 @@ type listPlayersParamsApplier struct { params domain.ListPlayersParams } -//nolint:gocyclo func (a listPlayersParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { if ids := a.params.IDs(); len(ids) > 0 { q = q.Where("player.id IN (?)", bun.In(ids)) @@ -185,42 +184,12 @@ func (a listPlayersParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { } for _, s := range a.params.Sort() { - switch s { - case domain.PlayerSortIDASC: - q = q.Order("player.id ASC") - case domain.PlayerSortIDDESC: - q = q.Order("player.id DESC") - case domain.PlayerSortServerKeyASC: - q = q.Order("player.server_key ASC") - case domain.PlayerSortServerKeyDESC: - q = q.Order("player.server_key DESC") - case domain.PlayerSortODScoreAttASC: - q = q.Order("player.score_att ASC") - case domain.PlayerSortODScoreAttDESC: - q = q.Order("player.score_att DESC") - case domain.PlayerSortODScoreDefASC: - q = q.Order("player.score_def ASC") - case domain.PlayerSortODScoreDefDESC: - q = q.Order("player.score_def DESC") - case domain.PlayerSortODScoreSupASC: - q = q.Order("player.score_sup ASC") - case domain.PlayerSortODScoreSupDESC: - q = q.Order("player.score_sup DESC") - case domain.PlayerSortODScoreTotalASC: - q = q.Order("player.score_total ASC") - case domain.PlayerSortODScoreTotalDESC: - q = q.Order("player.score_total DESC") - case domain.PlayerSortPointsASC: - q = q.Order("player.points ASC") - case domain.PlayerSortPointsDESC: - q = q.Order("player.points DESC") - case domain.PlayerSortDeletedAtASC: - q = q.OrderExpr("COALESCE(player.deleted_at, ?) ASC", time.Time{}) - case domain.PlayerSortDeletedAtDESC: - q = q.OrderExpr("COALESCE(player.deleted_at, ?) DESC", time.Time{}) - default: - return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) + column, dir, err := a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) } + + q.OrderExpr("? ?", column, dir.Bun()) } return q.Limit(a.params.Limit() + 1).Apply(a.applyCursor) @@ -240,75 +209,40 @@ func (a listPlayersParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQue } for _, s := range sort { + var err error var el cursorPaginationApplierDataElement + el.column, el.direction, err = a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) + } + switch s { - case domain.PlayerSortIDASC: + case domain.PlayerSortIDASC, + domain.PlayerSortIDDESC: el.value = cursor.ID() el.unique = true - el.column = "player.id" - el.direction = sortDirectionASC - case domain.PlayerSortIDDESC: - el.value = cursor.ID() - el.unique = true - el.column = "player.id" - el.direction = sortDirectionDESC - case domain.PlayerSortServerKeyASC: + case domain.PlayerSortServerKeyASC, + domain.PlayerSortServerKeyDESC: el.value = cursor.ServerKey() - el.column = "player.server_key" - el.direction = sortDirectionASC - case domain.PlayerSortServerKeyDESC: - el.value = cursor.ServerKey() - el.column = "player.server_key" - el.direction = sortDirectionDESC - case domain.PlayerSortODScoreAttASC: + case domain.PlayerSortODScoreAttASC, + domain.PlayerSortODScoreAttDESC: el.value = cursor.ODScoreAtt() - el.column = "player.score_att" - el.direction = sortDirectionASC - case domain.PlayerSortODScoreAttDESC: - el.value = cursor.ODScoreAtt() - el.column = "player.score_att" - el.direction = sortDirectionDESC - case domain.PlayerSortODScoreDefASC: + case domain.PlayerSortODScoreDefASC, + domain.PlayerSortODScoreDefDESC: el.value = cursor.ODScoreDef() - el.column = "player.score_def" - el.direction = sortDirectionASC - case domain.PlayerSortODScoreDefDESC: - el.value = cursor.ODScoreDef() - el.column = "player.score_def" - el.direction = sortDirectionDESC - case domain.PlayerSortODScoreSupASC: + case domain.PlayerSortODScoreSupASC, + domain.PlayerSortODScoreSupDESC: el.value = cursor.ODScoreSup() - el.column = "player.score_sup" - el.direction = sortDirectionASC - case domain.PlayerSortODScoreSupDESC: - el.value = cursor.ODScoreSup() - el.column = "player.score_sup" - el.direction = sortDirectionDESC - case domain.PlayerSortODScoreTotalASC: + case domain.PlayerSortODScoreTotalASC, + domain.PlayerSortODScoreTotalDESC: el.value = cursor.ODScoreTotal() - el.column = "player.score_total" - el.direction = sortDirectionASC - case domain.PlayerSortODScoreTotalDESC: - el.value = cursor.ODScoreTotal() - el.column = "player.score_total" - el.direction = sortDirectionDESC - case domain.PlayerSortPointsASC: + case domain.PlayerSortPointsASC, + domain.PlayerSortPointsDESC: el.value = cursor.Points() - el.column = "player.points" - el.direction = sortDirectionASC - case domain.PlayerSortPointsDESC: - el.value = cursor.Points() - el.column = "player.points" - el.direction = sortDirectionDESC - case domain.PlayerSortDeletedAtASC: + case domain.PlayerSortDeletedAtASC, + domain.PlayerSortDeletedAtDESC: el.value = cursor.DeletedAt() - el.column = "COALESCE(player.deleted_at, '0001-01-01 00:00:00+00:00')" - el.direction = sortDirectionASC - case domain.PlayerSortDeletedAtDESC: - el.value = cursor.DeletedAt() - el.column = "COALESCE(player.deleted_at, '0001-01-01 00:00:00+00:00')" - el.direction = sortDirectionDESC default: return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) } @@ -318,3 +252,45 @@ func (a listPlayersParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQue return q.Apply(cursorApplier.apply) } + +//nolint:gocyclo +func (a listPlayersParamsApplier) sortToColumnAndDirection( + s domain.PlayerSort, +) (bun.Safe, sortDirection, error) { + switch s { + case domain.PlayerSortIDASC: + return "player.id", sortDirectionASC, nil + case domain.PlayerSortIDDESC: + return "player.id", sortDirectionDESC, nil + case domain.PlayerSortServerKeyASC: + return "player.server_key", sortDirectionASC, nil + case domain.PlayerSortServerKeyDESC: + return "player.server_key", sortDirectionDESC, nil + case domain.PlayerSortODScoreAttASC: + return "player.score_att", sortDirectionASC, nil + case domain.PlayerSortODScoreAttDESC: + return "player.score_att", sortDirectionDESC, nil + case domain.PlayerSortODScoreDefASC: + return "player.score_def", sortDirectionASC, nil + case domain.PlayerSortODScoreDefDESC: + return "player.score_def", sortDirectionDESC, nil + case domain.PlayerSortODScoreSupASC: + return "player.score_sup", sortDirectionASC, nil + case domain.PlayerSortODScoreSupDESC: + return "player.score_sup", sortDirectionDESC, nil + case domain.PlayerSortODScoreTotalASC: + return "player.score_total", sortDirectionASC, nil + case domain.PlayerSortODScoreTotalDESC: + return "player.score_total", sortDirectionDESC, nil + case domain.PlayerSortPointsASC: + return "player.points", sortDirectionASC, nil + case domain.PlayerSortPointsDESC: + return "player.points", sortDirectionDESC, nil + case domain.PlayerSortDeletedAtASC: + return "COALESCE(player.deleted_at, '0001-01-01 00:00:00+00:00')", sortDirectionASC, nil + case domain.PlayerSortDeletedAtDESC: + return "COALESCE(player.deleted_at, '0001-01-01 00:00:00+00:00')", sortDirectionDESC, nil + default: + return "", 0, fmt.Errorf("%s: %w", s.String(), errInvalidSortValue) + } +} diff --git a/internal/adapter/repository_bun_player_snapshot.go b/internal/adapter/repository_bun_player_snapshot.go index 90fb131..47a3254 100644 --- a/internal/adapter/repository_bun_player_snapshot.go +++ b/internal/adapter/repository_bun_player_snapshot.go @@ -76,30 +76,40 @@ type listPlayerSnapshotsParamsApplier struct { params domain.ListPlayerSnapshotsParams } -//nolint:gocyclo func (a listPlayerSnapshotsParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { if serverKeys := a.params.ServerKeys(); len(serverKeys) > 0 { q = q.Where("ps.server_key IN (?)", bun.In(serverKeys)) } for _, s := range a.params.Sort() { - switch s { - case domain.PlayerSnapshotSortDateASC: - q = q.Order("ps.date ASC") - case domain.PlayerSnapshotSortDateDESC: - q = q.Order("ps.date DESC") - case domain.PlayerSnapshotSortIDASC: - q = q.Order("ps.id ASC") - case domain.PlayerSnapshotSortIDDESC: - q = q.Order("ps.id DESC") - case domain.PlayerSnapshotSortServerKeyASC: - q = q.Order("ps.server_key ASC") - case domain.PlayerSnapshotSortServerKeyDESC: - q = q.Order("ps.server_key DESC") - default: - return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) + column, dir, err := a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) } + + q.OrderExpr("? ?", column, dir.Bun()) } return q.Limit(a.params.Limit()).Offset(a.params.Offset()) } + +func (a listPlayerSnapshotsParamsApplier) sortToColumnAndDirection( + s domain.PlayerSnapshotSort, +) (bun.Safe, sortDirection, error) { + switch s { + case domain.PlayerSnapshotSortDateASC: + return "ps.date", sortDirectionASC, nil + case domain.PlayerSnapshotSortDateDESC: + return "ps.date", sortDirectionDESC, nil + case domain.PlayerSnapshotSortIDASC: + return "ps.id", sortDirectionASC, nil + case domain.PlayerSnapshotSortIDDESC: + return "ps.id", sortDirectionDESC, nil + case domain.PlayerSnapshotSortServerKeyASC: + return "ps.server_key", sortDirectionASC, nil + case domain.PlayerSnapshotSortServerKeyDESC: + return "ps.server_key", sortDirectionDESC, nil + default: + return "", 0, fmt.Errorf("%s: %w", s.String(), errInvalidSortValue) + } +} diff --git a/internal/adapter/repository_bun_server.go b/internal/adapter/repository_bun_server.go index a489b55..0d86907 100644 --- a/internal/adapter/repository_bun_server.go +++ b/internal/adapter/repository_bun_server.go @@ -185,7 +185,6 @@ type listServersParamsApplier struct { params domain.ListServersParams } -//nolint:gocyclo func (a listServersParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { if keys := a.params.Keys(); len(keys) > 0 { q = q.Where("server.key IN (?)", bun.In(keys)) @@ -218,18 +217,12 @@ func (a listServersParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { } for _, s := range a.params.Sort() { - switch s { - case domain.ServerSortKeyASC: - q = q.Order("server.key ASC") - case domain.ServerSortKeyDESC: - q = q.Order("server.key DESC") - case domain.ServerSortOpenASC: - q = q.Order("server.open ASC") - case domain.ServerSortOpenDESC: - q = q.Order("server.open DESC") - default: - return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) + column, dir, err := a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) } + + q.OrderExpr("? ?", column, dir.Bun()) } return q.Apply(a.applyCursor).Limit(a.params.Limit() + 1) @@ -248,29 +241,22 @@ func (a listServersParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQue } for _, s := range sort { + var err error var el cursorPaginationApplierDataElement + el.column, el.direction, err = a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) + } + switch s { - case domain.ServerSortKeyASC: + case domain.ServerSortKeyASC, + domain.ServerSortKeyDESC: el.value = cursor.Key() el.unique = true - el.column = "server.key" - el.direction = sortDirectionASC - case domain.ServerSortKeyDESC: - el.value = cursor.Key() - el.unique = true - el.column = "server.key" - el.direction = sortDirectionDESC - case domain.ServerSortOpenASC: + case domain.ServerSortOpenASC, + domain.ServerSortOpenDESC: el.value = cursor.Open() - el.unique = false - el.column = "server.open" - el.direction = sortDirectionASC - case domain.ServerSortOpenDESC: - el.value = cursor.Open() - el.unique = false - el.column = "server.open" - el.direction = sortDirectionDESC default: return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) } @@ -280,3 +266,20 @@ func (a listServersParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQue return q.Apply(cursorApplier.apply) } + +func (a listServersParamsApplier) sortToColumnAndDirection( + s domain.ServerSort, +) (bun.Safe, sortDirection, error) { + switch s { + case domain.ServerSortKeyASC: + return "server.key", sortDirectionASC, nil + case domain.ServerSortKeyDESC: + return "server.key", sortDirectionDESC, nil + case domain.ServerSortOpenASC: + return "server.open", sortDirectionASC, nil + case domain.ServerSortOpenDESC: + return "server.open", sortDirectionDESC, nil + default: + return "", 0, fmt.Errorf("%s: %w", s.String(), errInvalidSortValue) + } +} diff --git a/internal/adapter/repository_bun_tribe.go b/internal/adapter/repository_bun_tribe.go index f1e699a..adc9cbd 100644 --- a/internal/adapter/repository_bun_tribe.go +++ b/internal/adapter/repository_bun_tribe.go @@ -155,7 +155,6 @@ type listTribesParamsApplier struct { params domain.ListTribesParams } -//nolint:gocyclo func (a listTribesParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { if ids := a.params.IDs(); len(ids) > 0 { q = q.Where("tribe.id IN (?)", bun.In(ids)) @@ -178,42 +177,12 @@ func (a listTribesParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { } for _, s := range a.params.Sort() { - switch s { - case domain.TribeSortIDASC: - q = q.Order("tribe.id ASC") - case domain.TribeSortIDDESC: - q = q.Order("tribe.id DESC") - case domain.TribeSortServerKeyASC: - q = q.Order("tribe.server_key ASC") - case domain.TribeSortServerKeyDESC: - q = q.Order("tribe.server_key DESC") - case domain.TribeSortODScoreAttASC: - q = q.Order("tribe.score_att ASC") - case domain.TribeSortODScoreAttDESC: - q = q.Order("tribe.score_att DESC") - case domain.TribeSortODScoreDefASC: - q = q.Order("tribe.score_def ASC") - case domain.TribeSortODScoreDefDESC: - q = q.Order("tribe.score_def DESC") - case domain.TribeSortODScoreTotalASC: - q = q.Order("tribe.score_total ASC") - case domain.TribeSortODScoreTotalDESC: - q = q.Order("tribe.score_total DESC") - case domain.TribeSortPointsASC: - q = q.Order("tribe.points ASC") - case domain.TribeSortPointsDESC: - q = q.Order("tribe.points DESC") - case domain.TribeSortDominanceASC: - q = q.Order("tribe.dominance ASC") - case domain.TribeSortDominanceDESC: - q = q.Order("tribe.dominance DESC") - case domain.TribeSortDeletedAtASC: - q = q.OrderExpr("COALESCE(tribe.deleted_at, ?) ASC", time.Time{}) - case domain.TribeSortDeletedAtDESC: - q = q.OrderExpr("COALESCE(tribe.deleted_at, ?) DESC", time.Time{}) - default: - return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) + column, dir, err := a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) } + + q.OrderExpr("? ?", column, dir.Bun()) } return q.Limit(a.params.Limit() + 1).Apply(a.applyCursor) @@ -233,75 +202,40 @@ func (a listTribesParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQuer } for _, s := range sort { + var err error var el cursorPaginationApplierDataElement + el.column, el.direction, err = a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) + } + switch s { - case domain.TribeSortIDASC: + case domain.TribeSortIDASC, + domain.TribeSortIDDESC: el.value = cursor.ID() el.unique = true - el.column = "tribe.id" - el.direction = sortDirectionASC - case domain.TribeSortIDDESC: - el.value = cursor.ID() - el.unique = true - el.column = "tribe.id" - el.direction = sortDirectionDESC - case domain.TribeSortServerKeyASC: + case domain.TribeSortServerKeyASC, + domain.TribeSortServerKeyDESC: el.value = cursor.ServerKey() - el.column = "tribe.server_key" - el.direction = sortDirectionASC - case domain.TribeSortServerKeyDESC: - el.value = cursor.ServerKey() - el.column = "tribe.server_key" - el.direction = sortDirectionDESC - case domain.TribeSortODScoreAttASC: + case domain.TribeSortODScoreAttASC, + domain.TribeSortODScoreAttDESC: el.value = cursor.ODScoreAtt() - el.column = "tribe.score_att" - el.direction = sortDirectionASC - case domain.TribeSortODScoreAttDESC: - el.value = cursor.ODScoreAtt() - el.column = "tribe.score_att" - el.direction = sortDirectionDESC - case domain.TribeSortODScoreDefASC: + case domain.TribeSortODScoreDefASC, + domain.TribeSortODScoreDefDESC: el.value = cursor.ODScoreDef() - el.column = "tribe.score_def" - el.direction = sortDirectionASC - case domain.TribeSortODScoreDefDESC: - el.value = cursor.ODScoreDef() - el.column = "tribe.score_def" - el.direction = sortDirectionDESC - case domain.TribeSortODScoreTotalASC: + case domain.TribeSortODScoreTotalASC, + domain.TribeSortODScoreTotalDESC: el.value = cursor.ODScoreTotal() - el.column = "tribe.score_total" - el.direction = sortDirectionASC - case domain.TribeSortODScoreTotalDESC: - el.value = cursor.ODScoreTotal() - el.column = "tribe.score_total" - el.direction = sortDirectionDESC - case domain.TribeSortPointsASC: + case domain.TribeSortPointsASC, + domain.TribeSortPointsDESC: el.value = cursor.Points() - el.column = "tribe.points" - el.direction = sortDirectionASC - case domain.TribeSortPointsDESC: - el.value = cursor.Points() - el.column = "tribe.points" - el.direction = sortDirectionDESC - case domain.TribeSortDominanceASC: + case domain.TribeSortDominanceASC, + domain.TribeSortDominanceDESC: el.value = cursor.Dominance() - el.column = "tribe.dominance" - el.direction = sortDirectionASC - case domain.TribeSortDominanceDESC: - el.value = cursor.Dominance() - el.column = "tribe.dominance" - el.direction = sortDirectionDESC - case domain.TribeSortDeletedAtASC: + case domain.TribeSortDeletedAtASC, + domain.TribeSortDeletedAtDESC: el.value = cursor.DeletedAt() - el.column = "COALESCE(tribe.deleted_at, '0001-01-01 00:00:00+00:00')" - el.direction = sortDirectionASC - case domain.TribeSortDeletedAtDESC: - el.value = cursor.DeletedAt() - el.column = "COALESCE(tribe.deleted_at, '0001-01-01 00:00:00+00:00')" - el.direction = sortDirectionDESC default: return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) } @@ -311,3 +245,45 @@ func (a listTribesParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQuer return q.Apply(cursorApplier.apply) } + +//nolint:gocyclo +func (a listTribesParamsApplier) sortToColumnAndDirection( + s domain.TribeSort, +) (bun.Safe, sortDirection, error) { + switch s { + case domain.TribeSortIDASC: + return "tribe.id", sortDirectionASC, nil + case domain.TribeSortIDDESC: + return "tribe.id", sortDirectionDESC, nil + case domain.TribeSortServerKeyASC: + return "tribe.server_key", sortDirectionASC, nil + case domain.TribeSortServerKeyDESC: + return "tribe.server_key", sortDirectionDESC, nil + case domain.TribeSortODScoreAttASC: + return "tribe.score_att", sortDirectionASC, nil + case domain.TribeSortODScoreAttDESC: + return "tribe.score_att", sortDirectionDESC, nil + case domain.TribeSortODScoreDefASC: + return "tribe.score_def", sortDirectionASC, nil + case domain.TribeSortODScoreDefDESC: + return "tribe.score_def", sortDirectionDESC, nil + case domain.TribeSortODScoreTotalASC: + return "tribe.score_total", sortDirectionASC, nil + case domain.TribeSortODScoreTotalDESC: + return "tribe.score_total", sortDirectionDESC, nil + case domain.TribeSortPointsASC: + return "tribe.points", sortDirectionASC, nil + case domain.TribeSortPointsDESC: + return "tribe.points", sortDirectionDESC, nil + case domain.TribeSortDominanceASC: + return "tribe.dominance", sortDirectionASC, nil + case domain.TribeSortDominanceDESC: + return "tribe.dominance", sortDirectionDESC, nil + case domain.TribeSortDeletedAtASC: + return "COALESCE(tribe.deleted_at, '0001-01-01 00:00:00+00:00')", sortDirectionASC, nil + case domain.TribeSortDeletedAtDESC: + return "COALESCE(tribe.deleted_at, '0001-01-01 00:00:00+00:00')", sortDirectionDESC, nil + default: + return "", 0, fmt.Errorf("%s: %w", s.String(), errInvalidSortValue) + } +} diff --git a/internal/adapter/repository_bun_tribe_change.go b/internal/adapter/repository_bun_tribe_change.go index 5b6cd67..7747534 100644 --- a/internal/adapter/repository_bun_tribe_change.go +++ b/internal/adapter/repository_bun_tribe_change.go @@ -104,7 +104,6 @@ type listTribeChangesParamsApplier struct { params domain.ListTribeChangesParams } -//nolint:gocyclo func (a listTribeChangesParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { if serverKeys := a.params.ServerKeys(); len(serverKeys) > 0 { q = q.Where("tc.server_key IN (?)", bun.In(serverKeys)) @@ -130,22 +129,12 @@ func (a listTribeChangesParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuer } for _, s := range a.params.Sort() { - switch s { - case domain.TribeChangeSortCreatedAtASC: - q = q.Order("tc.created_at ASC") - case domain.TribeChangeSortCreatedAtDESC: - q = q.Order("tc.created_at DESC") - case domain.TribeChangeSortIDASC: - q = q.Order("tc.id ASC") - case domain.TribeChangeSortIDDESC: - q = q.Order("tc.id DESC") - case domain.TribeChangeSortServerKeyASC: - q = q.Order("tc.server_key ASC") - case domain.TribeChangeSortServerKeyDESC: - q = q.Order("tc.server_key DESC") - default: - return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) + column, dir, err := a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) } + + q.OrderExpr("? ?", column, dir.Bun()) } return q.Limit(a.params.Limit() + 1).Apply(a.applyCursor) @@ -164,35 +153,25 @@ func (a listTribeChangesParamsApplier) applyCursor(q *bun.SelectQuery) *bun.Sele } for _, s := range sort { + var err error var el cursorPaginationApplierDataElement + el.column, el.direction, err = a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) + } + switch s { - case domain.TribeChangeSortIDASC: + case domain.TribeChangeSortIDASC, + domain.TribeChangeSortIDDESC: el.value = cursor.ID() el.unique = true - el.column = "tc.id" - el.direction = sortDirectionASC - case domain.TribeChangeSortIDDESC: - el.value = cursor.ID() - el.unique = true - el.column = "tc.id" - el.direction = sortDirectionDESC - case domain.TribeChangeSortServerKeyASC: + case domain.TribeChangeSortServerKeyASC, + domain.TribeChangeSortServerKeyDESC: el.value = cursor.ServerKey() - el.column = "tc.server_key" - el.direction = sortDirectionASC - case domain.TribeChangeSortServerKeyDESC: - el.value = cursor.ServerKey() - el.column = "tc.server_key" - el.direction = sortDirectionDESC - case domain.TribeChangeSortCreatedAtASC: + case domain.TribeChangeSortCreatedAtASC, + domain.TribeChangeSortCreatedAtDESC: el.value = cursor.CreatedAt() - el.column = "tc.created_at" - el.direction = sortDirectionASC - case domain.TribeChangeSortCreatedAtDESC: - el.value = cursor.CreatedAt() - el.column = "tc.created_at" - el.direction = sortDirectionDESC default: return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) } @@ -202,3 +181,24 @@ func (a listTribeChangesParamsApplier) applyCursor(q *bun.SelectQuery) *bun.Sele return q.Apply(cursorApplier.apply) } + +func (a listTribeChangesParamsApplier) sortToColumnAndDirection( + s domain.TribeChangeSort, +) (bun.Safe, sortDirection, error) { + switch s { + case domain.TribeChangeSortCreatedAtASC: + return "tc.created_at", sortDirectionASC, nil + case domain.TribeChangeSortCreatedAtDESC: + return "tc.created_at", sortDirectionDESC, nil + case domain.TribeChangeSortIDASC: + return "tc.id", sortDirectionASC, nil + case domain.TribeChangeSortIDDESC: + return "tc.id", sortDirectionDESC, nil + case domain.TribeChangeSortServerKeyASC: + return "tc.server_key", sortDirectionASC, nil + case domain.TribeChangeSortServerKeyDESC: + return "tc.server_key", sortDirectionDESC, nil + default: + return "", 0, fmt.Errorf("%s: %w", s.String(), errInvalidSortValue) + } +} diff --git a/internal/adapter/repository_bun_tribe_snapshot.go b/internal/adapter/repository_bun_tribe_snapshot.go index 35cd18f..405332a 100644 --- a/internal/adapter/repository_bun_tribe_snapshot.go +++ b/internal/adapter/repository_bun_tribe_snapshot.go @@ -75,30 +75,40 @@ type listTribeSnapshotsParamsApplier struct { params domain.ListTribeSnapshotsParams } -//nolint:gocyclo func (a listTribeSnapshotsParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { if serverKeys := a.params.ServerKeys(); len(serverKeys) > 0 { q = q.Where("ts.server_key IN (?)", bun.In(serverKeys)) } for _, s := range a.params.Sort() { - switch s { - case domain.TribeSnapshotSortDateASC: - q = q.Order("ts.date ASC") - case domain.TribeSnapshotSortDateDESC: - q = q.Order("ts.date DESC") - case domain.TribeSnapshotSortIDASC: - q = q.Order("ts.id ASC") - case domain.TribeSnapshotSortIDDESC: - q = q.Order("ts.id DESC") - case domain.TribeSnapshotSortServerKeyASC: - q = q.Order("ts.server_key ASC") - case domain.TribeSnapshotSortServerKeyDESC: - q = q.Order("ts.server_key DESC") - default: - return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) + column, dir, err := a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) } + + q.OrderExpr("? ?", column, dir.Bun()) } return q.Limit(a.params.Limit()).Offset(a.params.Offset()) } + +func (a listTribeSnapshotsParamsApplier) sortToColumnAndDirection( + s domain.TribeSnapshotSort, +) (bun.Safe, sortDirection, error) { + switch s { + case domain.TribeSnapshotSortDateASC: + return "ts.date", sortDirectionASC, nil + case domain.TribeSnapshotSortDateDESC: + return "ts.date", sortDirectionDESC, nil + case domain.TribeSnapshotSortIDASC: + return "ts.id", sortDirectionASC, nil + case domain.TribeSnapshotSortIDDESC: + return "ts.id", sortDirectionDESC, nil + case domain.TribeSnapshotSortServerKeyASC: + return "ts.server_key", sortDirectionASC, nil + case domain.TribeSnapshotSortServerKeyDESC: + return "ts.server_key", sortDirectionDESC, nil + default: + return "", 0, fmt.Errorf("%s: %w", s.String(), errInvalidSortValue) + } +} diff --git a/internal/adapter/repository_bun_version.go b/internal/adapter/repository_bun_version.go index 4f4de18..06bd340 100644 --- a/internal/adapter/repository_bun_version.go +++ b/internal/adapter/repository_bun_version.go @@ -50,14 +50,12 @@ func (a listVersionsParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { } for _, s := range a.params.Sort() { - switch s { - case domain.VersionSortCodeASC: - q = q.Order("version.code ASC") - case domain.VersionSortCodeDESC: - q = q.Order("version.code DESC") - default: - return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) + column, dir, err := a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) } + + q.OrderExpr("? ?", column, dir.Bun()) } return q.Limit(a.params.Limit() + 1).Apply(a.applyCursor) @@ -76,19 +74,19 @@ func (a listVersionsParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQu } for _, s := range sort { + var err error var el cursorPaginationApplierDataElement + el.column, el.direction, err = a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) + } + switch s { - case domain.VersionSortCodeASC: + case domain.VersionSortCodeASC, + domain.VersionSortCodeDESC: el.value = cursor.Code() el.unique = true - el.column = "version.code" - el.direction = sortDirectionASC - case domain.VersionSortCodeDESC: - el.value = cursor.Code() - el.unique = true - el.column = "version.code" - el.direction = sortDirectionDESC default: return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) } @@ -98,3 +96,16 @@ func (a listVersionsParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQu return q.Apply(cursorApplier.apply) } + +func (a listVersionsParamsApplier) sortToColumnAndDirection( + s domain.VersionSort, +) (bun.Safe, sortDirection, error) { + switch s { + case domain.VersionSortCodeASC: + return "version.code", sortDirectionASC, nil + case domain.VersionSortCodeDESC: + return "version.code", sortDirectionDESC, nil + default: + return "", 0, fmt.Errorf("%s: %w", s.String(), errInvalidSortValue) + } +} diff --git a/internal/adapter/repository_bun_village.go b/internal/adapter/repository_bun_village.go index d8eff04..cb61e44 100644 --- a/internal/adapter/repository_bun_village.go +++ b/internal/adapter/repository_bun_village.go @@ -176,18 +176,12 @@ func (a listVillagesParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery { } for _, s := range a.params.Sort() { - switch s { - case domain.VillageSortIDASC: - q = q.Order("village.id ASC") - case domain.VillageSortIDDESC: - q = q.Order("village.id DESC") - case domain.VillageSortServerKeyASC: - q = q.Order("village.server_key ASC") - case domain.VillageSortServerKeyDESC: - q = q.Order("village.server_key DESC") - default: - return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) + column, dir, err := a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) } + + q.OrderExpr("? ?", column, dir.Bun()) } return q.Limit(a.params.Limit() + 1).Apply(a.applyCursor) @@ -206,27 +200,22 @@ func (a listVillagesParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQu } for _, s := range sort { + var err error var el cursorPaginationApplierDataElement + el.column, el.direction, err = a.sortToColumnAndDirection(s) + if err != nil { + return q.Err(err) + } + switch s { - case domain.VillageSortIDASC: + case domain.VillageSortIDASC, + domain.VillageSortIDDESC: el.value = cursor.ID() el.unique = true - el.column = "village.id" - el.direction = sortDirectionASC - case domain.VillageSortIDDESC: - el.value = cursor.ID() - el.unique = true - el.column = "village.id" - el.direction = sortDirectionDESC - case domain.VillageSortServerKeyASC: + case domain.VillageSortServerKeyASC, + domain.VillageSortServerKeyDESC: el.value = cursor.ServerKey() - el.column = "village.server_key" - el.direction = sortDirectionASC - case domain.VillageSortServerKeyDESC: - el.value = cursor.ServerKey() - el.column = "village.server_key" - el.direction = sortDirectionDESC default: return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue)) } @@ -236,3 +225,20 @@ func (a listVillagesParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQu return q.Apply(cursorApplier.apply) } + +func (a listVillagesParamsApplier) sortToColumnAndDirection( + s domain.VillageSort, +) (bun.Safe, sortDirection, error) { + switch s { + case domain.VillageSortIDASC: + return "village.id", sortDirectionASC, nil + case domain.VillageSortIDDESC: + return "village.id", sortDirectionDESC, nil + case domain.VillageSortServerKeyASC: + return "village.server_key", sortDirectionASC, nil + case domain.VillageSortServerKeyDESC: + return "village.server_key", sortDirectionDESC, nil + default: + return "", 0, fmt.Errorf("%s: %w", s.String(), errInvalidSortValue) + } +}