更新dao层为gorm-gen

This commit is contained in:
xiabin 2025-01-25 18:05:37 +08:00
parent f638652270
commit 9de52d82b0
25 changed files with 487 additions and 955 deletions

View File

@ -2,6 +2,7 @@
```shell ```shell
goctl api go -api .\game_open_api\app_user.api -dir .\game_open_api\ --style=go_zero goctl api go -api .\game_open_api\app_user.api -dir .\game_open_api\ --style=go_zero
goctl api go -api ./game_open_api/app_user.api -dir ./game_open_api --style=go_zero
goctl rpc protoc .\dw_server\dw_server.proto --go-grpc_out .\dw_server\ --go_out .\dw_server\ --zrpc_out .\dw_server\ -c -style go_zero goctl rpc protoc .\dw_server\dw_server.proto --go-grpc_out .\dw_server\ --go_out .\dw_server\ --zrpc_out .\dw_server\ -c -style go_zero

View File

@ -3,8 +3,8 @@ syntax = "v1"
import "common.api" import "common.api"
type SetUserGameScoreRequest { type SetUserGameScoreRequest {
Score uint64 `json:"score"` Score uint32 `json:"score"`
Type uint64 `json:"type,default=0"` Type uint32 `json:"type,default=0"`
} }
type RankingData { type RankingData {
@ -22,7 +22,7 @@ type RankingResponse {
} }
type RankingListRequest { type RankingListRequest {
Type uint64 `form:"type,default=0"` Type uint32 `form:"type,default=0"`
PageBase PageBase
} }

View File

@ -2,7 +2,8 @@ package app_user
import ( import (
"context" "context"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/model" "gitea.youtukeji.com.cn/xiabin/youtu_server/gorm-gen/dao/model"
"gorm.io/gen/field"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/svc" "gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/svc"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/types" "gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/types"
@ -30,10 +31,18 @@ func (l *AppUserSetUserLogic) AppUserSetUser(req *types.SetAppUserRequest) (resp
if err != nil { if err != nil {
return return
} }
err = l.svcCtx.AppUser.UpdateNicknameAvatar(l.ctx, &model.AppUser{ info, err := l.svcCtx.Query.AppUser.WithContext(l.ctx).Where(l.svcCtx.Query.AppUser.ID.Eq(at.UserId)).Updates(field.Attrs(&model.AppUser{
Id: at.UserId, ID: at.UserId,
Nickname: req.Nickname, Nickname: req.Nickname,
Avatar: req.Avatar, Avatar: req.Avatar,
}) }))
return switch {
case err != nil:
return
case info.Error != nil:
err = info.Error
return
default:
return
}
} }

View File

@ -4,7 +4,8 @@ import (
"context" "context"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/svc" "gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/svc"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/types" "gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/types"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/model" "gitea.youtukeji.com.cn/xiabin/youtu_server/gorm-gen/dao/model"
"gorm.io/gen/field"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )
@ -52,27 +53,28 @@ func (l *DouyinCode2tokenLogic) DouyinCode2token(req *types.DouyinCode2TokenRequ
return return
} }
accountId, err := l.svcCtx.AppAccount.FindIdByAppId(l.ctx, req.AppId) account, err := l.svcCtx.Query.AppAccount.WithContext(l.ctx).Where(l.svcCtx.Query.AppAccount.AppID.Eq(req.AppId)).Take()
if err != nil { if err != nil {
return return
} }
aui := &model.AppUser{ aui := &model.AppUser{
AppAccountId: accountId, AppAccountID: account.ID,
Openid: res.Openid, Openid: res.Openid,
Unionid: res.Unionid, Unionid: res.Unionid,
AnonymousOpenid: res.AnonymousOpenid,
Nickname: svc.GetRandomUsername(),
Avatar: "https://youtukeji.com.cn/candy/images/lollipop.png",
} }
err = l.svcCtx.AppUser.FindOrCreate(l.ctx, aui)
aui, err = l.svcCtx.Query.AppUser.WithContext(l.ctx).Where(field.Attrs(&aui)).Assign(field.Attrs(model.AppUser{
Nickname: svc.GetRandomUsername(),
Avatar: "https://youtukeji.com.cn/candy/images/lollipop.png",
})).FirstOrCreate()
if err != nil { if err != nil {
return return
} }
resp.Token, err = l.svcCtx.GenerateAccessToken(&svc.AccessToken{ resp.Token, err = l.svcCtx.GenerateAccessToken(&svc.AccessToken{
AppId: accountId, AppId: account.ID,
UserId: aui.Id, UserId: aui.ID,
AppIdStr: req.AppId, AppIdStr: req.AppId,
OpenId: res.Openid, OpenId: res.Openid,
}) })

View File

@ -50,7 +50,7 @@ func (l *RankingListLogic) RankingList(req *types.RankingListRequest) (resp *typ
continue continue
} }
//查询用户数据FindOne带缓存 //查询用户数据FindOne带缓存
user, err := l.svcCtx.AppUser.FindOne(l.ctx, uint64(userId)) user, err := l.svcCtx.Query.AppUser.Where(l.svcCtx.Query.AppUser.ID.Eq(uint64(userId))).Take()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -59,9 +59,9 @@ func (l *RankingListLogic) RankingList(req *types.RankingListRequest) (resp *typ
Avatar: user.Avatar, Avatar: user.Avatar,
Score: uint32(datum.Score), Score: uint32(datum.Score),
Rank: uint32(i) + 1, Rank: uint32(i) + 1,
Self: user.Id == at.UserId, Self: user.ID == at.UserId,
} }
if user.Id == at.UserId { if user.ID == at.UserId {
flag = true flag = true
userRank = data userRank = data
} }
@ -69,11 +69,11 @@ func (l *RankingListLogic) RankingList(req *types.RankingListRequest) (resp *typ
} }
if !flag { if !flag {
userRank, err = l.svcCtx.GameScore.GetUserRank(l.ctx, at.AppId, at.UserId, req.Type) tmp, err := l.svcCtx.Query.GameScore.GetUserRank(at.AppId, at.UserId, req.Type)
if err != nil { if err != nil {
return nil, err return nil, err
} }
userRank = types.RankingData(tmp)
userRank.Self = true userRank.Self = true
} }
resp.RankingData = append(resp.RankingData, userRank) resp.RankingData = append(resp.RankingData, userRank)

View File

@ -4,12 +4,10 @@ import (
"context" "context"
"errors" "errors"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/logic/rankings" "gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/logic/rankings"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/model"
"github.com/redis/go-redis/v9"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/svc" "gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/svc"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/types" "gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/types"
"github.com/redis/go-redis/v9"
"gorm.io/gorm"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )
@ -35,28 +33,34 @@ func (l *RankingSetScoreLogic) RankingSetScore(req *types.SetUserGameScoreReques
return return
} }
oldScore, err := l.svcCtx.GameScore.FindUserScore(l.ctx, at.AppId, at.UserId, req.Type) gs := l.svcCtx.Query.GameScore
if err != nil && !errors.Is(err, sqlc.ErrNotFound) {
// 查询旧分数
oldScore, err := gs.
WithContext(l.ctx).
Where(
gs.AppUserID.Eq(at.UserId),
gs.AppAccount.Eq(at.AppId),
gs.T.Eq(req.Type),
).
Take()
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return return
} }
if oldScore != nil && req.Score <= oldScore.Score { // 判断是否需要更新(只保留最高分)
if req.Score <= oldScore.Score {
return return
} }
if oldScore != nil { oldScore.Score = req.Score
oldScore.Score = req.Score oldScore.T = req.Type
err = l.svcCtx.GameScore.UpdateScore(l.ctx, oldScore) oldScore.AppUserID = at.UserId
} else { oldScore.AppAccount = at.AppId
oldScore = &model.GameScore{
AppUserId: at.UserId,
AppAccount: at.AppId,
Score: req.Score,
T: req.Type,
}
err = l.svcCtx.GameScore.CreateScore(l.ctx, oldScore)
}
// 更新数据库
err = gs.WithContext(l.ctx).Where(gs.ID.Eq(oldScore.ID)).Save(oldScore)
if err != nil { if err != nil {
return return
} }
@ -66,7 +70,7 @@ func (l *RankingSetScoreLogic) RankingSetScore(req *types.SetUserGameScoreReques
Member: at.UserId, Member: at.UserId,
Score: float64(req.Score), Score: float64(req.Score),
}) })
l.Logger.Debugf("GameScore: %+v", oldScore)
l.Logger.Debugf("GameScore: %+v", oldScore)
return return
} }

View File

@ -20,7 +20,7 @@ func NewRanking(c *redis.Client) *Ranking {
} }
} }
func GetRankingsCacheKey(appId, t uint64) string { func GetRankingsCacheKey(appId uint32, t uint32) string {
return fmt.Sprintf("%sappId:%d:type:%d", EcpmRankingsListPrefix, appId, t) return fmt.Sprintf("%sappId:%d:type:%d", EcpmRankingsListPrefix, appId, t)
} }

View File

@ -5,7 +5,8 @@ import (
"errors" "errors"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/svc" "gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/svc"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/types" "gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/types"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/model" "gitea.youtukeji.com.cn/xiabin/youtu_server/gorm-gen/dao/model"
"gorm.io/gen/field"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )
@ -41,26 +42,28 @@ func (l *WechatCode2UserIdLogic) WechatCode2UserId(req *types.WechatCode2TokenRe
return return
} }
accountId, err := l.svcCtx.AppAccount.FindIdByAppId(l.ctx, req.AppId) account, err := l.svcCtx.Query.AppAccount.WithContext(l.ctx).Where(l.svcCtx.Query.AppAccount.AppID.Eq(req.AppId)).Take()
if err != nil { if err != nil {
return return
} }
aui := &model.AppUser{ aui := &model.AppUser{
AppAccountId: accountId, AppAccountID: account.ID,
Openid: res.OpenID, Openid: res.OpenID,
Unionid: res.UnionID, Unionid: res.UnionID,
Nickname: svc.GetRandomUsername(),
Avatar: "https://youtukeji.com.cn/candy/images/lollipop.png",
} }
err = l.svcCtx.AppUser.FindOrCreate(l.ctx, aui)
aui, err = l.svcCtx.Query.AppUser.WithContext(l.ctx).Where(field.Attrs(&aui)).Assign(field.Attrs(model.AppUser{
Nickname: svc.GetRandomUsername(),
Avatar: "https://youtukeji.com.cn/candy/images/lollipop.png",
})).FirstOrCreate()
if err != nil { if err != nil {
return return
} }
resp.Token, err = l.svcCtx.GenerateAccessToken(&svc.AccessToken{ resp.Token, err = l.svcCtx.GenerateAccessToken(&svc.AccessToken{
AppId: accountId, AppId: account.ID,
UserId: aui.Id, UserId: aui.ID,
AppIdStr: req.AppId, AppIdStr: req.AppId,
OpenId: res.OpenID, OpenId: res.OpenID,
}) })

View File

@ -6,85 +6,124 @@ import (
"errors" "errors"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/config" "gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/config"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/logic/rankings" "gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/logic/rankings"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/model" "gitea.youtukeji.com.cn/xiabin/youtu_server/gorm-gen/query"
redisCacher "gitea.youtukeji.com.cn/xiabin/youtu_server/gorm-gen/redis"
helper "gitea.youtukeji.com.cn/youtu/openapi-helper" helper "gitea.youtukeji.com.cn/youtu/openapi-helper"
"github.com/go-gorm/caches/v4"
"github.com/golang-jwt/jwt/v4" "github.com/golang-jwt/jwt/v4"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
redisCache "github.com/silenceper/wechat/v2/cache" redisCache "github.com/silenceper/wechat/v2/cache"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"go.uber.org/zap" "go.uber.org/zap"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2" "gopkg.in/natefinch/lumberjack.v2"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"math/rand" "math/rand"
"time" "time"
) )
type ServiceContext struct { type ServiceContext struct {
Config config.Config Config config.Config
AppUser model.AppUserModel
GameScore model.GameScoreModel
AppAccount model.AppAccountModel
DouyinCli *helper.DouYinOpenApiClient DouyinCli *helper.DouYinOpenApiClient
WechatCli *helper.WechatApi WechatCli *helper.WechatApi
ZapLogger *zap.Logger ZapLogger *zap.Logger
RedisRanking *rankings.Ranking RedisRanking *rankings.Ranking
Query *query.Query
} }
func NewServiceContext(c config.Config) *ServiceContext { func NewServiceContext(c config.Config) *ServiceContext {
svc := &ServiceContext{
Config: c,
AppUser: model.NewAppUserModel(sqlx.NewMysql(c.DB.DataSource), c.Cache),
GameScore: model.NewGameScoreModel(sqlx.NewMysql(c.DB.DataSource), c.Cache),
AppAccount: model.NewAppAccountModel(sqlx.NewMysql(c.DB.DataSource), c.Cache),
}
//初始化redis client //初始化redis client
redisClient := redis.NewClient(&redis.Options{ redisClient := redis.NewClient(&redis.Options{
Addr: c.DWCache.Host, Addr: c.DWCache.Host,
Password: c.DWCache.Password, // 没有密码,默认值 Password: c.DWCache.Password, // 没有密码,默认值
}) })
//初始化数据库
db, err := gorm.Open(mysql.Open(c.DB.DataSource), &gorm.Config{})
if err != nil {
panic(err)
}
err = db.Use(&caches.Caches{Conf: &caches.Config{
Easer: true,
Cacher: redisCacher.New(redisClient),
}})
if err != nil {
panic(err)
}
svc := &ServiceContext{
Config: c,
Query: query.Use(db),
}
//初始化排行榜对象
svc.InitRankings(redisClient)
//初始化小程序配置
svc.InitDWClient(c)
//初始化一个zap日志对象用于写入ecpm日志
svc.InitEcpmLog(c)
return svc
}
func (svc *ServiceContext) InitRankings(redisClient *redis.Client) {
//初始化排行榜对象 //初始化排行榜对象
svc.RedisRanking = rankings.NewRanking(redisClient) svc.RedisRanking = rankings.NewRanking(redisClient)
//获取所有不同的排行榜
gs := svc.Query.GameScore
r, err := gs.FindDistinctRanking()
if err != nil {
panic(err)
}
//获取所有排行榜
for _, ranking := range r {
scores, err := gs.Where(gs.AppAccount.Eq(ranking.AppAccount), gs.T.Eq(ranking.T)).Find()
if err != nil {
panic(err)
}
data := make([]redis.Z, 0, len(scores))
for _, score := range scores {
data = append(data, redis.Z{
Score: float64(score.Score),
Member: score.AppUserID,
})
}
svc.RedisRanking.SetList(context.Background(), rankings.GetRankingsCacheKey(ranking.AppAccount, ranking.T), data...)
}
}
func (svc *ServiceContext) InitDWClient(c config.Config) {
dwCache := redisCache.NewRedis(context.Background(), &redisCache.RedisOpts{Host: c.DWCache.Host, IdleTimeout: c.DWCache.IdleTimeout}) dwCache := redisCache.NewRedis(context.Background(), &redisCache.RedisOpts{Host: c.DWCache.Host, IdleTimeout: c.DWCache.IdleTimeout})
svc.DouyinCli = helper.NewDouYinOpenApiClient() svc.DouyinCli = helper.NewDouYinOpenApiClient()
svc.WechatCli = helper.NewWechatOpenApiClient() svc.WechatCli = helper.NewWechatOpenApiClient()
//select `app_id`,`secret`,`ecpm_value`,`ecpm_view`,`type` from `app_account` left join douyin_ecpm_config on app_account.id = douyin_ecpm_config.app_account_id
var result []struct {
ID int32 `gorm:"column:id;type:int unsigned;primaryKey;autoIncrement:true" json:"id"`
Type int32 `gorm:"column:type;type:tinyint unsigned;not null;comment:类型(0:抖音,1:微信)" json:"type"` // 类型(0:抖音,1:微信)
AppID string `gorm:"column:app_id;type:char(20);not null;uniqueIndex:app_id,priority:1" json:"app_id"`
Secret string `gorm:"column:secret;type:char(40);not null" json:"secret"`
EcpmValue uint32 `gorm:"column:ecpm_value;type:int unsigned;not null;comment:值" json:"ecpm_value"` // 值
EcpmView uint32 `gorm:"column:ecpm_view;type:int unsigned;not null;comment:浏览次数" json:"ecpm_view"` // 浏览次数
}
//查询小程序配置(抖音&微信) //查询小程序配置(抖音&微信)
result, err := svc.AppAccount.FindAll(context.Background()) err := svc.Query.AppAccount.LeftJoin(svc.Query.DouyinEcpmConfig, svc.Query.AppAccount.ID.EqCol(svc.Query.DouyinEcpmConfig.AppAccountID)).Scan(&result)
if err != nil { if err != nil {
panic(err) panic(err)
} }
//小程序配置 //小程序配置
for _, v := range *result { for _, v := range result {
if v.Type == 0 { if v.Type == 0 {
svc.DouyinCli.NewAndStoreDouYinOpenApi(v.AppID, v.Secret, v.EcpmValue.V, v.EcpmView.V, dwCache) svc.DouyinCli.NewAndStoreDouYinOpenApi(v.AppID, v.Secret, v.EcpmValue, v.EcpmView, dwCache)
} else { } else {
svc.WechatCli.NewAndStoreWechatOpenApi(v.AppID, v.Secret, dwCache) svc.WechatCli.NewAndStoreWechatOpenApi(v.AppID, v.Secret, dwCache)
} }
} }
}
//获取所有排行榜 func (svc *ServiceContext) InitEcpmLog(c config.Config) {
rankList, err := svc.GameScore.FindAllRankList(context.Background())
if err != nil {
return nil
}
//添加排行榜数据
for s, scores := range rankList {
data := make([]redis.Z, 0, len(scores))
for _, score := range scores {
data = append(data, redis.Z{
Score: float64(score.Score),
Member: score.AppUserId,
})
}
svc.RedisRanking.SetList(context.Background(), s, data...)
}
//初始化一个zap日志对象用于写入ecpm日志
svc.ZapLogger = zap.New(zapcore.NewCore( svc.ZapLogger = zap.New(zapcore.NewCore(
zapcore.NewJSONEncoder(zapcore.EncoderConfig{ zapcore.NewJSONEncoder(zapcore.EncoderConfig{
TimeKey: "ts", TimeKey: "ts",
@ -109,12 +148,10 @@ func NewServiceContext(c config.Config) *ServiceContext {
})), })),
zapcore.InfoLevel, zapcore.InfoLevel,
)) ))
return svc
} }
type AccessToken struct { type AccessToken struct {
AppId uint64 `json:"appId"` AppId uint32 `json:"appId"`
UserId uint64 `json:"userId"` UserId uint64 `json:"userId"`
AppIdStr string `json:"appIdStr"` AppIdStr string `json:"appIdStr"`
OpenId string `json:"openId"` OpenId string `json:"openId"`
@ -127,7 +164,7 @@ func UnmarshalAccessToken(d any) (ac AccessToken, err error) {
return return
} }
appId, _ := m["appId"].(json.Number).Int64() appId, _ := m["appId"].(json.Number).Int64()
ac.AppId = uint64(appId) ac.AppId = uint32(appId)
userId, _ := m["userId"].(json.Number).Int64() userId, _ := m["userId"].(json.Number).Int64()
ac.UserId = uint64(userId) ac.UserId = uint64(userId)
ac.AppIdStr = m["appIdStr"].(string) ac.AppIdStr = m["appIdStr"].(string)

View File

@ -34,7 +34,7 @@ type RankingData struct {
} }
type RankingListRequest struct { type RankingListRequest struct {
Type uint64 `form:"type,default=0"` Type uint32 `form:"type,default=0"`
PageBase PageBase
} }
@ -49,8 +49,8 @@ type SetAppUserRequest struct {
} }
type SetUserGameScoreRequest struct { type SetUserGameScoreRequest struct {
Score uint64 `json:"score"` Score uint32 `json:"score"`
Type uint64 `json:"type,default=0" form:"type,default=0"` Type uint32 `json:"type,default=0"`
} }
type UserId struct { type UserId struct {

View File

@ -1,65 +0,0 @@
package model
import (
"context"
"database/sql"
"fmt"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ AppAccountModel = (*customAppAccountModel)(nil)
type (
// AppAccountModel is an interface to be customized, add more methods here,
// and implement the added methods in customAppAccountModel.
AppAccountModel interface {
appAccountModel
}
customAppAccountModel struct {
*defaultAppAccountModel
}
appAccountModel interface {
Insert(ctx context.Context, data *AppAccount) (sql.Result, error)
FindOne(ctx context.Context, id uint64) (*AppAccount, error)
Update(ctx context.Context, data *AppAccount) error
Delete(ctx context.Context, id uint64) error
FindIdByAppId(ctx context.Context, appId string) (uint64, error)
FindAll(ctx context.Context) (*[]*GameAppConfig, error)
}
)
// NewAppAccountModel returns a model for the database table.
func NewAppAccountModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) AppAccountModel {
return &customAppAccountModel{
defaultAppAccountModel: newAppAccountModel(conn, c, opts...),
}
}
type GameAppConfig struct {
AppID string `db:"app_id"`
Secret string `db:"secret"`
EcpmValue sql.Null[uint32] `db:"ecpm_value"` // 值
EcpmView sql.Null[uint32] `db:"ecpm_view"` // 浏览次数
Type uint64 `db:"type"` // 类型(0:抖音,1:微信)
}
func (m *defaultAppAccountModel) FindAll(ctx context.Context) (*[]*GameAppConfig, error) {
ecpmAppAccountIdKey := fmt.Sprintf("%s%v", cacheEcpmAppAccountIdPrefix, "all")
var resp []*GameAppConfig
err := m.QueryRowCtx(ctx, &resp, ecpmAppAccountIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error {
query := "select `app_id`,`secret`,`ecpm_value`,`ecpm_view`,`type` from `app_account` left join douyin_ecpm_config on app_account.id = douyin_ecpm_config.app_account_id"
return conn.QueryRowsCtx(ctx, v, query)
})
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}

View File

@ -1,124 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.5
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
appAccountFieldNames = builder.RawFieldNames(&AppAccount{})
appAccountRows = strings.Join(appAccountFieldNames, ",")
appAccountRowsExpectAutoSet = strings.Join(stringx.Remove(appAccountFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
appAccountRowsWithPlaceHolder = strings.Join(stringx.Remove(appAccountFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
cacheEcpmAppAccountIdPrefix = "cache:ecpm:appAccount:id:"
)
type (
defaultAppAccountModel struct {
sqlc.CachedConn
table string
}
AppAccount struct {
Id uint64 `db:"id"`
Type uint64 `db:"type"` // 类型(0:抖音,1:微信)
AppId string `db:"app_id"`
Secret string `db:"secret"`
Remark sql.NullString `db:"remark"` // 备注
DeletedAt sql.NullString `db:"deleted_at"`
}
)
func newAppAccountModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) *defaultAppAccountModel {
return &defaultAppAccountModel{
CachedConn: sqlc.NewConn(conn, c, opts...),
table: "`app_account`",
}
}
func (m *defaultAppAccountModel) Delete(ctx context.Context, id uint64) error {
ecpmAppAccountIdKey := fmt.Sprintf("%s%v", cacheEcpmAppAccountIdPrefix, id)
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
return conn.ExecCtx(ctx, query, id)
}, ecpmAppAccountIdKey)
return err
}
func (m *defaultAppAccountModel) FindOne(ctx context.Context, id uint64) (*AppAccount, error) {
ecpmAppAccountIdKey := fmt.Sprintf("%s%v", cacheEcpmAppAccountIdPrefix, id)
var resp AppAccount
err := m.QueryRowCtx(ctx, &resp, ecpmAppAccountIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", appAccountRows, m.table)
return conn.QueryRowCtx(ctx, v, query, id)
})
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultAppAccountModel) Insert(ctx context.Context, data *AppAccount) (sql.Result, error) {
ecpmAppAccountIdKey := fmt.Sprintf("%s%v", cacheEcpmAppAccountIdPrefix, data.Id)
ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, appAccountRowsExpectAutoSet)
return conn.ExecCtx(ctx, query, data.Type, data.AppId, data.Secret, data.Remark, data.DeletedAt)
}, ecpmAppAccountIdKey)
return ret, err
}
func (m *defaultAppAccountModel) Update(ctx context.Context, data *AppAccount) error {
ecpmAppAccountIdKey := fmt.Sprintf("%s%v", cacheEcpmAppAccountIdPrefix, data.Id)
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, appAccountRowsWithPlaceHolder)
return conn.ExecCtx(ctx, query, data.Type, data.AppId, data.Secret, data.Remark, data.DeletedAt, data.Id)
}, ecpmAppAccountIdKey)
return err
}
func (m *defaultAppAccountModel) FindIdByAppId(ctx context.Context, appId string) (uint64, error) {
ecpmAppAccountIdKey := fmt.Sprintf("%s%v", cacheEcpmAppAccountIdPrefix, appId)
var id uint64
err := m.QueryRowCtx(ctx, &id, ecpmAppAccountIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error {
query := fmt.Sprintf("select id from %s where `app_id` = ? limit 1", m.table)
return conn.QueryRowCtx(ctx, v, query, appId)
})
switch err {
case nil:
return id, nil
case sqlc.ErrNotFound:
return 0, ErrNotFound
default:
return 0, err
}
}
func (m *defaultAppAccountModel) formatPrimary(primary any) string {
return fmt.Sprintf("%s%v", cacheEcpmAppAccountIdPrefix, primary)
}
func (m *defaultAppAccountModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", appAccountRows, m.table)
return conn.QueryRowCtx(ctx, v, query, primary)
}
func (m *defaultAppAccountModel) tableName() string {
return m.table
}

View File

@ -1,60 +0,0 @@
package model
import (
"context"
"fmt"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ AppUserModel = (*customAppUserModel)(nil)
type (
// AppUserModel is an interface to be customized, add more methods here,
// and implement the added methods in customAppUserModel.
AppUserModel interface {
appUserModel
FindOrCreate(ctx context.Context, data *AppUser) (err error)
}
customAppUserModel struct {
*defaultAppUserModel
}
)
const cacheEcpmAppUserPrefix = "cache:ecpm:appUser:"
// NewAppUserModel returns a model for the database table.
func NewAppUserModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) AppUserModel {
return &customAppUserModel{
defaultAppUserModel: newAppUserModel(conn, c, opts...),
}
}
func (m *customAppUserModel) FindOrCreate(ctx context.Context, data *AppUser) (err error) {
ecpmAppUserIdKey := fmt.Sprintf("%sappId:%d:openid:%s", cacheEcpmAppUserPrefix, data.AppAccountId, data.Openid)
var resp AppUser
err = m.QueryRowCtx(ctx, &resp, ecpmAppUserIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error {
query := "select * from app_user where `openid` = ? and `app_account_id`= ? limit 1"
return conn.QueryRowCtx(ctx, v, query, data.Openid, data.AppAccountId)
})
switch err {
case nil:
*data = resp
return nil
case sqlc.ErrNotFound:
res, err := m.Insert(ctx, data)
if err != nil {
return err
}
id, err := res.LastInsertId()
if err != nil {
return err
}
data.Id = uint64(id)
return nil
default:
return err
}
}

View File

@ -1,125 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.5
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
appUserFieldNames = builder.RawFieldNames(&AppUser{})
appUserRows = strings.Join(appUserFieldNames, ",")
appUserRowsExpectAutoSet = strings.Join(stringx.Remove(appUserFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
appUserRowsWithPlaceHolder = strings.Join(stringx.Remove(appUserFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
cacheEcpmAppUserIdPrefix = "cache:ecpm:appUser:id:"
)
type (
appUserModel interface {
Insert(ctx context.Context, data *AppUser) (sql.Result, error)
FindOne(ctx context.Context, id uint64) (*AppUser, error)
Update(ctx context.Context, data *AppUser) error
Delete(ctx context.Context, id uint64) error
UpdateNicknameAvatar(ctx context.Context, data *AppUser) error
}
defaultAppUserModel struct {
sqlc.CachedConn
table string
}
AppUser struct {
Id uint64 `db:"id"`
AppAccountId uint64 `db:"app_account_id"` // app_account表外键
Openid string `db:"openid"`
Unionid string `db:"unionid"`
Nickname string `db:"nickname"` // 昵称
Avatar string `db:"avatar"` // 头像
AnonymousOpenid string `db:"anonymous_openid"` // 匿名openid
}
)
func newAppUserModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) *defaultAppUserModel {
return &defaultAppUserModel{
CachedConn: sqlc.NewConn(conn, c, opts...),
table: "`app_user`",
}
}
func (m *defaultAppUserModel) Delete(ctx context.Context, id uint64) error {
ecpmAppUserIdKey := fmt.Sprintf("%s%v", cacheEcpmAppUserIdPrefix, id)
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
return conn.ExecCtx(ctx, query, id)
}, ecpmAppUserIdKey)
return err
}
func (m *defaultAppUserModel) FindOne(ctx context.Context, id uint64) (*AppUser, error) {
ecpmAppUserIdKey := fmt.Sprintf("%s%v", cacheEcpmAppUserIdPrefix, id)
var resp AppUser
err := m.QueryRowCtx(ctx, &resp, ecpmAppUserIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", appUserRows, m.table)
return conn.QueryRowCtx(ctx, v, query, id)
})
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultAppUserModel) Insert(ctx context.Context, data *AppUser) (sql.Result, error) {
ecpmAppUserIdKey := fmt.Sprintf("%s%v", cacheEcpmAppUserIdPrefix, data.Id)
ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, appUserRowsExpectAutoSet)
return conn.ExecCtx(ctx, query, data.AppAccountId, data.Openid, data.Unionid, data.Nickname, data.Avatar, data.AnonymousOpenid)
}, ecpmAppUserIdKey)
return ret, err
}
func (m *defaultAppUserModel) Update(ctx context.Context, data *AppUser) error {
ecpmAppUserIdKey := fmt.Sprintf("%s%v", cacheEcpmAppUserIdPrefix, data.Id)
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, appUserRowsWithPlaceHolder)
return conn.ExecCtx(ctx, query, data.AppAccountId, data.Openid, data.Unionid, data.Nickname, data.Avatar, data.AnonymousOpenid, data.Id)
}, ecpmAppUserIdKey)
return err
}
func (m *defaultAppUserModel) UpdateNicknameAvatar(ctx context.Context, data *AppUser) error {
ecpmAppUserIdKey := fmt.Sprintf("%s%v", cacheEcpmAppUserIdPrefix, data.Id)
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, "`nickname`=?,`avatar`=?")
return conn.ExecCtx(ctx, query, data.Nickname, data.Avatar, data.Id)
}, ecpmAppUserIdKey)
return err
}
func (m *defaultAppUserModel) formatPrimary(primary any) string {
return fmt.Sprintf("%s%v", cacheEcpmAppUserIdPrefix, primary)
}
func (m *defaultAppUserModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", appUserRows, m.table)
return conn.QueryRowCtx(ctx, v, query, primary)
}
func (m *defaultAppUserModel) tableName() string {
return m.table
}

View File

@ -1,27 +0,0 @@
package model
import (
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ DouyinEcpmConfigModel = (*customDouyinEcpmConfigModel)(nil)
type (
// DouyinEcpmConfigModel is an interface to be customized, add more methods here,
// and implement the added methods in customDouyinEcpmConfigModel.
DouyinEcpmConfigModel interface {
douyinEcpmConfigModel
}
customDouyinEcpmConfigModel struct {
*defaultDouyinEcpmConfigModel
}
)
// NewDouyinEcpmConfigModel returns a model for the database table.
func NewDouyinEcpmConfigModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) DouyinEcpmConfigModel {
return &customDouyinEcpmConfigModel{
defaultDouyinEcpmConfigModel: newDouyinEcpmConfigModel(conn, c, opts...),
}
}

View File

@ -1,112 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.5
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
douyinEcpmConfigFieldNames = builder.RawFieldNames(&DouyinEcpmConfig{})
douyinEcpmConfigRows = strings.Join(douyinEcpmConfigFieldNames, ",")
douyinEcpmConfigRowsExpectAutoSet = strings.Join(stringx.Remove(douyinEcpmConfigFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
douyinEcpmConfigRowsWithPlaceHolder = strings.Join(stringx.Remove(douyinEcpmConfigFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
cacheEcpmDouyinEcpmConfigIdPrefix = "cache:ecpm:douyinEcpmConfig:id:"
)
type (
douyinEcpmConfigModel interface {
Insert(ctx context.Context, data *DouyinEcpmConfig) (sql.Result, error)
FindOne(ctx context.Context, id uint64) (*DouyinEcpmConfig, error)
Update(ctx context.Context, data *DouyinEcpmConfig) error
Delete(ctx context.Context, id uint64) error
}
defaultDouyinEcpmConfigModel struct {
sqlc.CachedConn
table string
}
DouyinEcpmConfig struct {
Id uint64 `db:"id"`
AppAccountId uint64 `db:"app_account_id"`
EcpmValue uint64 `db:"ecpm_value"` // 值
EcpmView uint64 `db:"ecpm_view"` // 浏览次数
}
)
func newDouyinEcpmConfigModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) *defaultDouyinEcpmConfigModel {
return &defaultDouyinEcpmConfigModel{
CachedConn: sqlc.NewConn(conn, c, opts...),
table: "`douyin_ecpm_config`",
}
}
func (m *defaultDouyinEcpmConfigModel) Delete(ctx context.Context, id uint64) error {
ecpmDouyinEcpmConfigIdKey := fmt.Sprintf("%s%v", cacheEcpmDouyinEcpmConfigIdPrefix, id)
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
return conn.ExecCtx(ctx, query, id)
}, ecpmDouyinEcpmConfigIdKey)
return err
}
func (m *defaultDouyinEcpmConfigModel) FindOne(ctx context.Context, id uint64) (*DouyinEcpmConfig, error) {
ecpmDouyinEcpmConfigIdKey := fmt.Sprintf("%s%v", cacheEcpmDouyinEcpmConfigIdPrefix, id)
var resp DouyinEcpmConfig
err := m.QueryRowCtx(ctx, &resp, ecpmDouyinEcpmConfigIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", douyinEcpmConfigRows, m.table)
return conn.QueryRowCtx(ctx, v, query, id)
})
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultDouyinEcpmConfigModel) Insert(ctx context.Context, data *DouyinEcpmConfig) (sql.Result, error) {
ecpmDouyinEcpmConfigIdKey := fmt.Sprintf("%s%v", cacheEcpmDouyinEcpmConfigIdPrefix, data.Id)
ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?)", m.table, douyinEcpmConfigRowsExpectAutoSet)
return conn.ExecCtx(ctx, query, data.AppAccountId, data.EcpmValue, data.EcpmView)
}, ecpmDouyinEcpmConfigIdKey)
return ret, err
}
func (m *defaultDouyinEcpmConfigModel) Update(ctx context.Context, data *DouyinEcpmConfig) error {
ecpmDouyinEcpmConfigIdKey := fmt.Sprintf("%s%v", cacheEcpmDouyinEcpmConfigIdPrefix, data.Id)
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, douyinEcpmConfigRowsWithPlaceHolder)
return conn.ExecCtx(ctx, query, data.AppAccountId, data.EcpmValue, data.EcpmView, data.Id)
}, ecpmDouyinEcpmConfigIdKey)
return err
}
func (m *defaultDouyinEcpmConfigModel) formatPrimary(primary any) string {
return fmt.Sprintf("%s%v", cacheEcpmDouyinEcpmConfigIdPrefix, primary)
}
func (m *defaultDouyinEcpmConfigModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", douyinEcpmConfigRows, m.table)
return conn.QueryRowCtx(ctx, v, query, primary)
}
func (m *defaultDouyinEcpmConfigModel) tableName() string {
return m.table
}

View File

@ -1,224 +0,0 @@
package model
import (
"context"
"database/sql"
"errors"
"fmt"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/logic/rankings"
"sync"
"gitea.youtukeji.com.cn/xiabin/youtu_server/game_open_api/internal/types"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ GameScoreModel = (*customGameScoreModel)(nil)
const (
cacheEcpmGameScorePrefix = "cache:ecpm:gameScore:"
)
type (
// GameScoreModel is an interface to be customized, add more methods here,
// and implement the added methods in customGameScoreModel.
GameScoreModel interface {
gameScoreModel
GetRankList(ctx context.Context, appId uint64, t uint64, page types.PageBase) ([]types.RankingData, error)
GetUserRank(ctx context.Context, appId uint64, userId uint64, t uint64) (types.RankingData, error)
FindUserScore(ctx context.Context, appId, userId, t uint64) (*GameScore, error)
FindAllRankList(ctx context.Context) (resp map[string][]GameScore, err error)
UpdateScore(ctx context.Context, data *GameScore) error
CreateScore(ctx context.Context, data *GameScore) error
}
customGameScoreModel struct {
*defaultGameScoreModel
rankListKey []string
mutex sync.Mutex
}
)
// NewGameScoreModel returns a model for the database table.
func NewGameScoreModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) GameScoreModel {
return &customGameScoreModel{
defaultGameScoreModel: newGameScoreModel(conn, c, opts...),
}
}
func (m *customGameScoreModel) pageCacheKey(page types.PageBase) string {
return fmt.Sprintf(":page:%d:pageSize:%d", page.Page, page.PageSize)
}
// rankListCacheKey 排行榜缓存key
func (m *customGameScoreModel) rankListCacheKey(appId uint64, t uint64) string {
return fmt.Sprintf("%s:rankList:appId:%d:t:%d", cacheEcpmGameScorePrefix, appId, t)
}
// userScoreCacheKey 用户游戏分数缓存key
func (m *customGameScoreModel) userScoreCacheKey(userId, appId, t uint64) string {
return fmt.Sprintf("%suserId:%d:appId:%v:t:%d", cacheEcpmGameScorePrefix, userId, appId, t)
}
// userRankCacheKey 用户游戏排名缓存key
func (m *customGameScoreModel) userRankCacheKey(userId, appId, t uint64) string {
return fmt.Sprintf("%srank:userId:%d:appId:%v:t:%d", cacheEcpmGameScorePrefix, userId, appId, t)
}
// FindAllRankList 查询所有排行榜
func (m *customGameScoreModel) FindAllRankList(ctx context.Context) (resp map[string][]GameScore, err error) {
list := make([]GameScore, 0)
resp = make(map[string][]GameScore)
err = m.QueryRowsPartialNoCacheCtx(ctx, &list, "select DISTINCT app_account,t from game_score")
if err != nil && !errors.Is(err, sqlx.ErrNotFound) {
return nil, err
}
for _, rank := range list {
data, err := m.FindAllScore(ctx, rank.AppAccount, rank.T)
if err != nil {
return nil, err
}
if len(data) != 0 {
resp[rankings.GetRankingsCacheKey(rank.AppAccount, rank.T)] = data
}
}
return
}
func (m *customGameScoreModel) FindAllScore(ctx context.Context, appId uint64, t uint64) (resp []GameScore, err error) {
err = m.QueryRowsPartialNoCacheCtx(ctx, &resp, "select * from game_score where app_account = ? and t = ? order by score desc", appId, t)
return
}
// GetRankList 获取排行榜列表
func (m *customGameScoreModel) GetRankList(ctx context.Context, appId uint64, t uint64, page types.PageBase) (resp []types.RankingData, err error) {
cacheKey := m.rankListCacheKey(appId, t)
err = m.QueryRowCtx(ctx, &resp, cacheKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error {
query := `
SELECT
game_score.score,
app_user.nickname,
app_user.avatar,
game_score.app_user_id,
rank() over (ORDER BY game_score.score DESC) t_rank
FROM
game_score
JOIN app_user ON app_user.id = game_score.app_user_id
WHERE
game_score.app_account = ?
AND game_score.t = ?
LIMIT 99`
return conn.QueryRowsPartialCtx(ctx, v, query, appId, t)
})
switch {
case err == nil:
return resp, nil
case errors.Is(err, sqlc.ErrNotFound):
return nil, ErrNotFound
default:
return nil, err
}
}
// GetUserRank 获取用户排名
func (m *customGameScoreModel) GetUserRank(ctx context.Context, appId uint64, userId uint64, t uint64) (resp types.RankingData, err error) {
var res []types.RankingData
err = m.QueryRowCtx(ctx, &res, m.userRankCacheKey(userId, appId, t), func(ctx context.Context, conn sqlx.SqlConn, v any) error {
query := `
SELECT
app_user.nickname,
app_user.avatar,
gs.score,
gs.app_user_id,
gs.t_rank
FROM
(
SELECT
game_score.score,
game_score.app_user_id,
game_score.app_account,
-- 使用窗口函数rank对分数进行降序排名
rank() OVER (ORDER BY game_score.score DESC) t_rank
FROM
game_score
-- 在子查询中先根据t = 0过滤数据
WHERE
game_score.t = ?
-- 在子查询中根据app_account = 2过滤数据
AND game_score.app_account = ?
) AS gs
-- 使用LEFT JOIN将子查询结果和app_user表进行连接
LEFT JOIN app_user ON app_user.id = gs.app_user_id
-- 在外部查询中根据app_user_id = 59过滤数据
WHERE
gs.app_user_id = ?
LIMIT 1;
`
return conn.QueryRowsPartialCtx(ctx, v, query, t, appId, userId)
})
switch {
case err == nil:
if len(res) == 1 {
resp = res[0]
}
return resp, nil
case errors.Is(err, sqlc.ErrNotFound):
return resp, ErrNotFound
default:
return resp, err
}
}
// FindUserScore 查询用户游戏分数
func (m *customGameScoreModel) FindUserScore(ctx context.Context, appId, userId, t uint64) (*GameScore, error) {
var (
resp GameScore
err error
)
err = m.QueryRowCtx(ctx, &resp, m.userScoreCacheKey(userId, appId, t), func(ctx context.Context, conn sqlx.SqlConn, v any) error {
query := fmt.Sprintf("select %s from %s where app_account = ? and `app_user_id` = ? and t = ? limit 1", gameScoreRows, m.table)
return conn.QueryRowCtx(ctx, v, query, appId, userId, t)
})
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
// UpdateScore 更新游戏分数记录
func (m *customGameScoreModel) UpdateScore(ctx context.Context, data *GameScore) error {
cacheKeys := []string{
m.rankListCacheKey(data.AppAccount, data.T), // 删除排行榜缓存
m.userRankCacheKey(data.AppUserId, data.AppAccount, data.T), // 删除用户排行缓存
m.userScoreCacheKey(data.AppUserId, data.AppAccount, data.T), // 删除用户分数缓存
}
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set `score` = ? where `id` = ?", m.table)
return conn.ExecCtx(ctx, query, data.Score, data.Id)
}, cacheKeys...)
return err
}
// CreateScore 创建游戏分数记录
func (m *customGameScoreModel) CreateScore(ctx context.Context, data *GameScore) error {
cacheKeys := []string{
m.rankListCacheKey(data.AppAccount, data.T), // 删除排行榜缓存
m.userRankCacheKey(data.AppUserId, data.AppAccount, data.T), // 删除用户排行缓存
m.userScoreCacheKey(data.AppUserId, data.AppAccount, data.T), // 删除用户分数缓存
}
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?)", m.table, gameScoreRowsExpectAutoSet)
return conn.ExecCtx(ctx, query, data.AppAccount, data.AppUserId, data.Score, data.T)
}, cacheKeys...)
return err
}

View File

@ -1,113 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.5
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
gameScoreFieldNames = builder.RawFieldNames(&GameScore{})
gameScoreRows = strings.Join(gameScoreFieldNames, ",")
gameScoreRowsExpectAutoSet = strings.Join(stringx.Remove(gameScoreFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
gameScoreRowsWithPlaceHolder = strings.Join(stringx.Remove(gameScoreFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
cacheEcpmGameScoreIdPrefix = "cache:ecpm:gameScore:id:"
)
type (
gameScoreModel interface {
Insert(ctx context.Context, data *GameScore) (sql.Result, error)
FindOne(ctx context.Context, id uint64) (*GameScore, error)
Update(ctx context.Context, data *GameScore) error
Delete(ctx context.Context, id uint64) error
}
defaultGameScoreModel struct {
sqlc.CachedConn
table string
}
GameScore struct {
Id uint64 `db:"id"`
AppAccount uint64 `db:"app_account"` // 小游戏id
AppUserId uint64 `db:"app_user_id"` // 用户id
Score uint64 `db:"score"` // 得分
T uint64 `db:"t"` // 得分类型(区分相同小游戏中的不同模式得分)
}
)
func newGameScoreModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) *defaultGameScoreModel {
return &defaultGameScoreModel{
CachedConn: sqlc.NewConn(conn, c, opts...),
table: "`game_score`",
}
}
func (m *defaultGameScoreModel) Delete(ctx context.Context, id uint64) error {
ecpmGameScoreIdKey := fmt.Sprintf("%s%v", cacheEcpmGameScoreIdPrefix, id)
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
return conn.ExecCtx(ctx, query, id)
}, ecpmGameScoreIdKey)
return err
}
func (m *defaultGameScoreModel) FindOne(ctx context.Context, id uint64) (*GameScore, error) {
ecpmGameScoreIdKey := fmt.Sprintf("%s%v", cacheEcpmGameScoreIdPrefix, id)
var resp GameScore
err := m.QueryRowCtx(ctx, &resp, ecpmGameScoreIdKey, func(ctx context.Context, conn sqlx.SqlConn, v any) error {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", gameScoreRows, m.table)
return conn.QueryRowCtx(ctx, v, query, id)
})
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultGameScoreModel) Insert(ctx context.Context, data *GameScore) (sql.Result, error) {
ecpmGameScoreIdKey := fmt.Sprintf("%s%v", cacheEcpmGameScoreIdPrefix, data.Id)
ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?)", m.table, gameScoreRowsExpectAutoSet)
return conn.ExecCtx(ctx, query, data.AppAccount, data.AppUserId, data.Score, data.T)
}, ecpmGameScoreIdKey)
return ret, err
}
func (m *defaultGameScoreModel) Update(ctx context.Context, data *GameScore) error {
ecpmGameScoreIdKey := fmt.Sprintf("%s%v", cacheEcpmGameScoreIdPrefix, data.Id)
_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, gameScoreRowsWithPlaceHolder)
return conn.ExecCtx(ctx, query, data.AppAccount, data.AppUserId, data.Score, data.T, data.Id)
}, ecpmGameScoreIdKey)
return err
}
func (m *defaultGameScoreModel) formatPrimary(primary any) string {
return fmt.Sprintf("%s%v", cacheEcpmGameScoreIdPrefix, primary)
}
func (m *defaultGameScoreModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", gameScoreRows, m.table)
return conn.QueryRowCtx(ctx, v, query, primary)
}
func (m *defaultGameScoreModel) tableName() string {
return m.table
}

View File

@ -1,5 +0,0 @@
package model
import "github.com/zeromicro/go-zero/core/stores/sqlx"
var ErrNotFound = sqlx.ErrNotFound

17
go.mod
View File

@ -4,12 +4,18 @@ go 1.23.5
require ( require (
gitea.youtukeji.com.cn/youtu/openapi-helper v0.0.3-2 gitea.youtukeji.com.cn/youtu/openapi-helper v0.0.3-2
github.com/go-redis/redis v6.15.9+incompatible github.com/go-gorm/caches/v4 v4.0.5
github.com/golang-jwt/jwt/v4 v4.5.1 github.com/golang-jwt/jwt/v4 v4.5.1
github.com/redis/go-redis/v9 v9.7.0
github.com/silenceper/wechat/v2 v2.1.7 github.com/silenceper/wechat/v2 v2.1.7
github.com/zeromicro/go-zero v1.7.6 github.com/zeromicro/go-zero v1.7.6
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/natefinch/lumberjack.v2 v2.2.1
gorm.io/driver/mysql v1.5.7
gorm.io/driver/sqlite v1.4.3
gorm.io/gen v0.3.26
gorm.io/gorm v1.25.12
gorm.io/plugin/dbresolver v1.5.3
) )
require ( require (
@ -28,9 +34,12 @@ require (
github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/compress v1.17.11 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.15 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.3 // indirect github.com/openzipkin/zipkin-go v0.4.3 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect
@ -39,7 +48,6 @@ require (
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect
github.com/redis/go-redis/v9 v9.7.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/cast v1.7.1 // indirect github.com/spf13/cast v1.7.1 // indirect
@ -61,12 +69,17 @@ require (
go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.32.0 // indirect golang.org/x/crypto v0.32.0 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.34.0 // indirect golang.org/x/net v0.34.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.29.0 // indirect golang.org/x/sys v0.29.0 // indirect
golang.org/x/text v0.21.0 // indirect golang.org/x/text v0.21.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250122153221-138b5a5a4fd4 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250122153221-138b5a5a4fd4 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250122153221-138b5a5a4fd4 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250122153221-138b5a5a4fd4 // indirect
google.golang.org/grpc v1.69.4 // indirect google.golang.org/grpc v1.69.4 // indirect
google.golang.org/protobuf v1.36.3 // indirect google.golang.org/protobuf v1.36.3 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gorm.io/datatypes v1.1.1-0.20230130040222-c43177d3cf8c // indirect
gorm.io/hints v1.1.0 // indirect
) )

86
go.sum
View File

@ -2,8 +2,6 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
gitea.youtukeji.com.cn/youtu/openapi-helper v0.0.3-2 h1:MtJ1uQRb7QqKIsbqEVjWk+T/TGx5CoKEx93RsiMcVsY= gitea.youtukeji.com.cn/youtu/openapi-helper v0.0.3-2 h1:MtJ1uQRb7QqKIsbqEVjWk+T/TGx5CoKEx93RsiMcVsY=
gitea.youtukeji.com.cn/youtu/openapi-helper v0.0.3-2/go.mod h1:o3XiYjUmxptrwcYPbTwNc2SQSOeOj7qbQPdNNVU0H5w= gitea.youtukeji.com.cn/youtu/openapi-helper v0.0.3-2/go.mod h1:o3XiYjUmxptrwcYPbTwNc2SQSOeOj7qbQPdNNVU0H5w=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE= github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE=
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
@ -42,20 +40,25 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/go-gorm/caches/v4 v4.0.5 h1:Sdj9vxbEM0sCmv5+s5o6GzoVMuraWF0bjJJvUU+7c1U=
github.com/go-gorm/caches/v4 v4.0.5/go.mod h1:Ms8LnWVoW4GkTofpDzFH8OfDGNTjLxQDyxBmRN67Ujw=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@ -82,6 +85,28 @@ github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslC
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys=
github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI=
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y=
github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w=
github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E=
github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@ -94,6 +119,11 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE=
github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
@ -161,6 +191,7 @@ github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhso
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
@ -203,22 +234,34 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -234,19 +277,31 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -285,5 +340,28 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/datatypes v1.1.1-0.20230130040222-c43177d3cf8c h1:jWdr7cHgl8c/ua5vYbR2WhSp+NQmzhsj0xoY3foTzW8=
gorm.io/datatypes v1.1.1-0.20230130040222-c43177d3cf8c/go.mod h1:SH2K9R+2RMjuX1CkCONrPwoe9JzVv2hkQvEu4bXGojE=
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/driver/postgres v1.4.5 h1:mTeXTTtHAgnS9PgmhN2YeUbazYpLhUI1doLnw42XUZc=
gorm.io/driver/postgres v1.4.5/go.mod h1:GKNQYSJ14qvWkvPwXljMGehpKrhlDNsqYRr5HnYGncg=
gorm.io/driver/sqlite v1.1.6/go.mod h1:W8LmC/6UvVbHKah0+QOC7Ja66EaZXHwUTjgXY8YNWX8=
gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU=
gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig=
gorm.io/gen v0.3.26 h1:sFf1j7vNStimPRRAtH4zz5NiHM+1dr6eA9aaRdplyhY=
gorm.io/gen v0.3.26/go.mod h1:a5lq5y3w4g5LMxBcw0wnO6tYUCdNutWODq5LrIt75LE=
gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
gorm.io/gorm v1.22.2/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
gorm.io/hints v1.1.0 h1:Lp4z3rxREufSdxn4qmkK3TLDltrM10FLTHiuqwDPvXw=
gorm.io/hints v1.1.0/go.mod h1:lKQ0JjySsPBj3uslFzY3JhYDtqEwzm+G1hv8rWujB6Y=
gorm.io/plugin/dbresolver v1.5.3 h1:wFwINGZZmttuu9h7XpvbDHd8Lf9bb8GNzp/NpAMV2wU=
gorm.io/plugin/dbresolver v1.5.3/go.mod h1:TSrVhaUg2DZAWP3PrHlDlITEJmNOkL0tFTjvTEsQ4XE=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=

17
gorm-gen/gen.yaml Normal file
View File

@ -0,0 +1,17 @@
version: "0.1"
database:
dsn : "root:youtu!0113@tcp(localhost:3306)/ecpm?charset=utf8&parseTime=True&loc=Local"
db : "mysql"
tables :
- "app_account"
- "app_user"
- "douyin_ecpm_config"
- "game_score"
outPath : "./dao/query"
outFile : ""
withUnitTest : true
modelPkgName : "model"
fieldNullable : true
fieldWithIndexTag : true
fieldWithTypeTag : true
fieldSignable : true

96
gorm-gen/gen_model.go Normal file
View File

@ -0,0 +1,96 @@
package main
import (
"context"
"gitea.youtukeji.com.cn/xiabin/youtu_server/gorm-gen/dao/model"
"gitea.youtukeji.com.cn/xiabin/youtu_server/gorm-gen/dao/query"
"gitea.youtukeji.com.cn/xiabin/youtu_server/gorm-gen/querier"
"gorm.io/driver/mysql"
"gorm.io/gen"
"gorm.io/gorm"
"math/rand"
"time"
)
// AppAccountQuerier
var DefaultUsername = []string{
"甜蜜糖果",
"糖果爱好者",
"软糖粉丝",
"巧克力糖果控",
"棒棒糖迷",
"小熊软糖达人",
"硬糖狂人",
"焦糖糖果控",
"水果糖行家",
"棉花糖达人",
}
// GetRandomUsername 随机获取一个糖果相关的用户名
func GetRandomUsername() string {
// 初始化随机数种子
r := rand.New(rand.NewSource(time.Now().UnixNano()))
// 生成一个 0 到列表长度减 1 之间的随机索引
randomIndex := r.Intn(len(DefaultUsername))
// 根据随机索引返回对应的用户名
return DefaultUsername[randomIndex]
}
func main() {
g := gen.NewGenerator(gen.Config{
OutPath: "./query",
Mode: gen.WithoutContext | gen.WithDefaultQuery | gen.WithQueryInterface, // generate mode
})
dsn := "root:youtu!0113@tcp(localhost:3306)/ecpm?charset=utf8&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)
}
// gormdb, _ := gorm.Open(mysql.Open("root:@(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local"))
g.UseDB(db) // reuse your gorm db
//g.ApplyBasic(model.AppAccount{}, model.AppUser{}, model.DouyinEcpmConfig{}, model.GameScore{})
// Generate Type Safe API with Dynamic SQL defined on Querier interface for `model.User` and `model.Company`
g.ApplyInterface(func(querier.AppAccountQuerier) {}, model.AppAccount{})
g.ApplyInterface(func(querier.GameScoreQuerier) {}, model.GameScore{})
g.ApplyBasic(model.AppUser{}, model.DouyinEcpmConfig{})
// Generate the code
g.Execute()
}
func DataGen(db *gorm.DB) {
//生成20条用户及分数数据
u := query.Use(db).AppUser
user, err := u.WithContext(context.Background()).Where(u.Openid.Like("test_openid%")).Find()
if err != nil {
panic(err)
}
//生成20条游戏得分数据
var score []*model.GameScore
for i := 0; i < 20; i++ {
score = append(score, &model.GameScore{
AppAccount: 3,
AppUserID: user[i].ID,
Score: uint32(Abs(rand.New(rand.NewSource(time.Now().UnixNano())).Intn(1000))),
T: 1,
})
}
err = query.Use(db).GameScore.WithContext(context.Background()).CreateInBatches(score, len(score))
if err != nil {
panic(err)
}
}
func Abs(x int) int {
if x < 0 {
return -x
}
return x
}

View File

@ -0,0 +1,54 @@
package querier
import (
"gorm.io/gen"
)
type AppAccountQuerier interface {
//GetAppConfig 获取所有小游戏配置
//
//select `app_id`,`secret`,`ecpm_value`,`ecpm_view`,`type` from `app_account` left join douyin_ecpm_config on app_account.id = douyin_ecpm_config.app_account_id
GetAppConfig() ([]*gen.T, error)
}
type GameScoreQuerier interface {
/*
SELECT
app_user.nickname,
app_user.avatar,
gs.score,
gs.app_user_id,
gs.t_rank
FROM
(
SELECT
game_score.score,
game_score.app_user_id,
game_score.app_account,
rank() OVER (ORDER BY game_score.score DESC) t_rank
FROM
game_score
WHERE
game_score.t = ?
AND game_score.app_account = ?
) AS gs
LEFT JOIN app_user ON app_user.id = gs.app_user_id
WHERE
gs.app_user_id = ?
LIMIT 1;
*/
GetUserRank(appId uint32, userId uint64, t uint32) (resp RankingData, err error)
//select DISTINCT app_account,t from game_score
FindDistinctRanking() (resp []*gen.T, err error)
}
type RankingData struct {
Nickname string `json:"nickname" db:"nickname"` // 昵称
Avatar string `json:"avatar" db:"avatar"` // 头像
Score uint32 `json:"score" db:"score"` // 得分
UserId uint64 `json:"userId" db:"app_user_id"` // 用户 ID
Rank uint32 `json:"rank" db:"t_rank"` // 排名
Self bool `json:"self" db:"-"` // 是否是自己
}

73
gorm-gen/redis/cacher.go Normal file
View File

@ -0,0 +1,73 @@
package redis
import (
"context"
"errors"
"fmt"
"github.com/go-gorm/caches/v4"
"github.com/redis/go-redis/v9"
"time"
)
type Cacher struct {
rdb *redis.Client
}
func New(rdb *redis.Client) *Cacher {
return &Cacher{rdb: rdb}
}
func (c *Cacher) Get(ctx context.Context, key string, q *caches.Query[any]) (*caches.Query[any], error) {
res, err := c.rdb.Get(ctx, key).Result()
if errors.Is(err, redis.Nil) {
return nil, nil
}
if err != nil {
return nil, err
}
if err := q.Unmarshal([]byte(res)); err != nil {
return nil, err
}
return q, nil
}
func (c *Cacher) Store(ctx context.Context, key string, val *caches.Query[any]) error {
res, err := val.Marshal()
if err != nil {
return err
}
c.rdb.Set(ctx, key, res, 300*time.Second) // Set proper cache time
return nil
}
func (c *Cacher) Invalidate(ctx context.Context) error {
var (
cursor uint64
keys []string
)
for {
var (
k []string
err error
)
k, cursor, err = c.rdb.Scan(ctx, cursor, fmt.Sprintf("%s*", caches.IdentifierPrefix), 0).Result()
if err != nil {
return err
}
keys = append(keys, k...)
if cursor == 0 {
break
}
}
if len(keys) > 0 {
if _, err := c.rdb.Del(ctx, keys...).Result(); err != nil {
return err
}
}
return nil
}