use github.com/alimy/yesql@v1.1.1 to generate db struct type automatic

r/paopao-ce-xtra
Michael Li 2 years ago
parent fa6f41b1a3
commit e510a53643
No known key found for this signature in database

@ -69,13 +69,18 @@ windows-x64:
@CGO_ENABLED=$(CGO_ENABLED) GOOS=windows GOARCH=amd64 go build -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_WINDOWS_AMD64)/$(basename $(TARGET)).exe @CGO_ENABLED=$(CGO_ENABLED) GOOS=windows GOARCH=amd64 go build -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_WINDOWS_AMD64)/$(basename $(TARGET)).exe
.PHONY: generate .PHONY: generate
generate: gen-mir gen-grpc generate: gen-mir gen-grpc gen-yesql
.PHONY: gen-mir .PHONY: gen-mir
gen-mir: gen-mir:
@go generate mirc/gen.go @go generate mirc/gen.go
@go fmt ./auto/api/... @go fmt ./auto/api/...
.PHONY: gen-yesql
gen-yesql:
@go generate internal/dao/sakila/yesql/gen.go
@go fmt ./internal/dao/sakila/yesql/...
.PHONY: gen-grpc .PHONY: gen-grpc
gen-grpc: gen-grpc:
@rm -rf auto/rpc @rm -rf auto/rpc

@ -7,7 +7,7 @@ require (
github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868
github.com/alimy/cfg v0.3.0 github.com/alimy/cfg v0.3.0
github.com/alimy/mir/v3 v3.1.1 github.com/alimy/mir/v3 v3.1.1
github.com/alimy/yesql v0.7.0 github.com/alimy/yesql v1.1.1
github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible
github.com/allegro/bigcache/v3 v3.0.2 github.com/allegro/bigcache/v3 v3.0.2
github.com/bytedance/sonic v1.8.5 github.com/bytedance/sonic v1.8.5

@ -127,8 +127,8 @@ github.com/alimy/cfg v0.3.0 h1:9xgA0QWVCPSq9fFNRcYahVCAX22IL9ts2wrTQPfAStY=
github.com/alimy/cfg v0.3.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c= github.com/alimy/cfg v0.3.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c=
github.com/alimy/mir/v3 v3.1.1 h1:3tz7uGOwuA1IKU0BysyBvGbyqKtEVMuhPBD/APk1ANw= github.com/alimy/mir/v3 v3.1.1 h1:3tz7uGOwuA1IKU0BysyBvGbyqKtEVMuhPBD/APk1ANw=
github.com/alimy/mir/v3 v3.1.1/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU= github.com/alimy/mir/v3 v3.1.1/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU=
github.com/alimy/yesql v0.7.0 h1:SugF94EN8ZhQrSaoRe6nfFjB4Ev/an9uzuzBHR6jsAY= github.com/alimy/yesql v1.1.1 h1:L7gXcLX34KHURG+ekKhyvLDIEHPPrSHnK+X/bKwHiEM=
github.com/alimy/yesql v0.7.0/go.mod h1:Y0FdRIwIbJyTv56wSX+MpaIHiAW1PyKTDYO6K/er4JY= github.com/alimy/yesql v1.1.1/go.mod h1:Y0FdRIwIbJyTv56wSX+MpaIHiAW1PyKTDYO6K/er4JY=
github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible h1:KpbJFXwhVeuxNtBJ74MCGbIoaBok2uZvkD7QXp2+Wis= github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible h1:KpbJFXwhVeuxNtBJ74MCGbIoaBok2uZvkD7QXp2+Wis=
github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/allegro/bigcache/v3 v3.0.2 h1:AKZCw+5eAaVyNTBmI2fgyPVJhHkdWder3O9IrprcQfI= github.com/allegro/bigcache/v3 v3.0.2 h1:AKZCw+5eAaVyNTBmI2fgyPVJhHkdWder3O9IrprcQfI=

@ -9,7 +9,6 @@ import (
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/alimy/cfg" "github.com/alimy/cfg"
"github.com/alimy/yesql"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/dao/cache" "github.com/rocboss/paopao-ce/internal/dao/cache"
"github.com/rocboss/paopao-ce/internal/dao/security" "github.com/rocboss/paopao-ce/internal/dao/security"
@ -86,12 +85,11 @@ func NewDataService() (core.DataService, core.VersionInfo) {
} }
logrus.Infof("use %s as cache index service by version: %s", v.Name(), v.Version()) logrus.Infof("use %s as cache index service by version: %s", v.Name(), v.Version())
query := yesql.MustParseBytes(yesqlBytes)
ds := &dataSrv{ ds := &dataSrv{
IndexPostsService: cis, IndexPostsService: cis,
WalletService: newWalletService(_db), WalletService: newWalletService(_db),
MessageService: newMessageService(_db), MessageService: newMessageService(_db),
TopicService: newTopicService(_db, query), TopicService: newTopicService(_db),
TweetService: newTweetService(_db), TweetService: newTweetService(_db),
TweetManageService: newTweetManageService(_db, cis), TweetManageService: newTweetManageService(_db, cis),
TweetHelpService: newTweetHelpService(_db), TweetHelpService: newTweetHelpService(_db),

@ -16,17 +16,23 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
//go:embed yesql.sql
var yesqlBytes []byte
var ( var (
_db *sqlx.DB _db *sqlx.DB
) )
type sqlxDB struct {
*sqlx.DB
}
type sqlxSrv struct { type sqlxSrv struct {
db *sqlx.DB db *sqlx.DB
} }
// Rebind fixed table name in query and rebind the fixed query
func (s *sqlxDB) Rebind(query string) string {
return s.DB.Rebind(query)
}
func (s *sqlxSrv) with(handle func(tx *sqlx.Tx) error) error { func (s *sqlxSrv) with(handle func(tx *sqlx.Tx) error) error {
tx, err := s.db.Beginx() tx, err := s.db.Beginx()
if err != nil { if err != nil {
@ -124,18 +130,23 @@ func yesqlScan[T any](query yesql.SQLQuery, obj T) T {
return obj return obj
} }
func newSqlxDB(db *sqlx.DB) *sqlxDB {
return &sqlxDB{
DB: db,
}
}
func mustBuild[T any](db *sqlx.DB, fn func(yesql.PreparexBuilder, ...context.Context) (T, error)) T {
p := yesql.NewPreparexBuilder(db, func(query string) string {
return strings.Replace(query, "@", conf.DatabaseSetting.TablePrefix, -1)
})
obj, err := fn(p)
if err != nil {
logrus.Fatalf("build object failure: %s", err)
}
return obj
}
func initSqlxDB() { func initSqlxDB() {
_db = conf.MustSqlxDB() _db = conf.MustSqlxDB()
yesql.UseSqlx(_db)
yesql.SetDefaultQueryHook(func(query *yesql.Query) (*yesql.Query, error) {
qstr := strings.TrimRight(query.Query, ";")
// table name fixed
qstr = strings.Replace(qstr, "@", conf.DatabaseSetting.TablePrefix, -1)
// rebind query
if clause, exist := query.Tags["clause"]; !exist || clause != "in" {
qstr = _db.Rebind(qstr)
}
query.Query = qstr
return query, nil
})
} }

@ -8,10 +8,10 @@ import (
"strings" "strings"
"time" "time"
"github.com/alimy/yesql"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/core/cs" "github.com/rocboss/paopao-ce/internal/core/cs"
"github.com/rocboss/paopao-ce/internal/dao/sakila/yesql/cc"
) )
var ( var (
@ -20,17 +20,7 @@ var (
type topicSrv struct { type topicSrv struct {
*sqlxSrv *sqlxSrv
yesql.Namespace `yesql:"topic"` q *cc.Topic
StmtNewestTags *sqlx.Stmt `yesql:"newest_tags"`
StmtHotTags *sqlx.Stmt `yesql:"hot_tags"`
StmtTagsByKeywordA *sqlx.Stmt `yesql:"tags_by_keyword_a"`
StmtTagsByKeywordB *sqlx.Stmt `yesql:"tags_by_keyword_b"`
StmtInsertTag *sqlx.Stmt `yesql:"insert_tag"`
SqlTagsByIdA string `yesql:"tags_by_id_a"`
SqlTagsByIdB string `yesql:"tags_by_id_b"`
SqlDecrTagsById string `yesql:"decr_tags_by_id"`
SqlTagsForIncr string `yesql:"tags_for_incr"`
SqlIncrTagsById string `yesql:"incr_tags_by_id"`
} }
func (s *topicSrv) UpsertTags(userId int64, tags []string) (res cs.TagInfoList, xerr error) { func (s *topicSrv) UpsertTags(userId int64, tags []string) (res cs.TagInfoList, xerr error) {
@ -39,7 +29,7 @@ func (s *topicSrv) UpsertTags(userId int64, tags []string) (res cs.TagInfoList,
} }
xerr = s.with(func(tx *sqlx.Tx) error { xerr = s.with(func(tx *sqlx.Tx) error {
var upTags cs.TagInfoList var upTags cs.TagInfoList
if err := s.inSelect(tx, &upTags, s.SqlTagsForIncr, tags); err != nil { if err := s.inSelect(tx, &upTags, s.q.TagsForIncr, tags); err != nil {
return err return err
} }
now := time.Now().Unix() now := time.Now().Unix()
@ -59,7 +49,7 @@ func (s *topicSrv) UpsertTags(userId int64, tags []string) (res cs.TagInfoList,
} }
} }
} }
if _, err := s.inExec(tx, s.SqlIncrTagsById, now, ids); err != nil { if _, err := s.inExec(tx, s.q.IncrTagsById, now, ids); err != nil {
return err return err
} }
res = append(res, upTags...) res = append(res, upTags...)
@ -70,7 +60,7 @@ func (s *topicSrv) UpsertTags(userId int64, tags []string) (res cs.TagInfoList,
} }
var ids []int64 var ids []int64
for _, tag := range tags { for _, tag := range tags {
res, err := s.StmtInsertTag.Exec(userId, tag, now, now) res, err := s.q.InsertTag.Exec(userId, tag, now, now)
if err != nil { if err != nil {
return err return err
} }
@ -81,7 +71,7 @@ func (s *topicSrv) UpsertTags(userId int64, tags []string) (res cs.TagInfoList,
ids = append(ids, id) ids = append(ids, id)
} }
var newTags cs.TagInfoList var newTags cs.TagInfoList
if err := s.inSelect(tx, &newTags, s.SqlTagsByIdB, ids); err != nil { if err := s.inSelect(tx, &newTags, s.q.TagsByIdB, ids); err != nil {
return err return err
} }
res = append(res, newTags...) res = append(res, newTags...)
@ -93,11 +83,11 @@ func (s *topicSrv) UpsertTags(userId int64, tags []string) (res cs.TagInfoList,
func (s *topicSrv) DecrTagsById(ids []int64) error { func (s *topicSrv) DecrTagsById(ids []int64) error {
return s.with(func(tx *sqlx.Tx) error { return s.with(func(tx *sqlx.Tx) error {
var ids []int64 var ids []int64
err := s.inSelect(tx, &ids, s.SqlTagsByIdA, ids) err := s.inSelect(tx, &ids, s.q.TagsByIdA, ids)
if err != nil { if err != nil {
return err return err
} }
_, err = s.inExec(tx, s.SqlDecrTagsById, time.Now().Unix(), ids) _, err = s.inExec(tx, s.q.DecrTagsById, time.Now().Unix(), ids)
return err return err
}) })
} }
@ -105,9 +95,9 @@ func (s *topicSrv) DecrTagsById(ids []int64) error {
func (s *topicSrv) ListTags(typ cs.TagType, limit int, offset int) (res cs.TagList, err error) { func (s *topicSrv) ListTags(typ cs.TagType, limit int, offset int) (res cs.TagList, err error) {
switch typ { switch typ {
case cs.TagTypeHot: case cs.TagTypeHot:
err = s.StmtHotTags.Select(&res, limit, offset) err = s.q.HotTags.Select(&res, limit, offset)
case cs.TagTypeNew: case cs.TagTypeNew:
err = s.StmtNewestTags.Select(&res, limit, offset) err = s.q.NewestTags.Select(&res, limit, offset)
} }
return return
} }
@ -115,15 +105,16 @@ func (s *topicSrv) ListTags(typ cs.TagType, limit int, offset int) (res cs.TagLi
func (s *topicSrv) TagsByKeyword(keyword string) (res cs.TagInfoList, err error) { func (s *topicSrv) TagsByKeyword(keyword string) (res cs.TagInfoList, err error) {
keyword = "%" + strings.Trim(keyword, " ") + "%" keyword = "%" + strings.Trim(keyword, " ") + "%"
if keyword == "%%" { if keyword == "%%" {
err = s.StmtTagsByKeywordA.Select(&res) err = s.q.TagsByKeywordA.Select(&res)
} else { } else {
err = s.StmtTagsByKeywordB.Select(&res) err = s.q.TagsByKeywordB.Select(&res)
} }
return return
} }
func newTopicService(db *sqlx.DB, query yesql.SQLQuery) core.TopicService { func newTopicService(db *sqlx.DB) core.TopicService {
return yesqlScan(query, &topicSrv{ return &topicSrv{
sqlxSrv: newSqlxSrv(db), sqlxSrv: newSqlxSrv(db),
}) q: mustBuild(db, cc.BuildTopic),
}
} }

@ -0,0 +1,71 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - Yesql v1.1.1
package cc
import (
"context"
"github.com/alimy/yesql"
"github.com/jmoiron/sqlx"
)
const (
_NewestTags_Topic = `SELECT t.id id, t.user_id user_id, t.tag tag, t.quote_num quote_num, u.id, u.nickname, u.username, u.status, u.avatar, u.is_admin FROM @tag t JOIN @user u ON t.user_id = u.id WHERE t.is_del = 0 AND t.quote_num > 0 ORDER BY t.id DESC LIMIT ? OFFSET ?`
_TagsByKeywordA_Topic = `SELECT id, user_id, tag, quote_num FROM @tag WHERE is_del = 0 ORDER BY quote_num DESC LIMIT 6`
_TagsByKeywordB_Topic = `SELECT id, user_id, tag, quote_num FROM @tag WHERE is_del = 0 AND tag LIKE ? ORDER BY quote_num DESC LIMIT 6`
_DecrTagsById_Topic = `UPDATE @tag SET quote_num=quote_num-1, modified_on=? WHERE id IN (?)`
_IncrTagsById_Topic = `UPDATE @tag SET quote_num=quote_num+1, is_del=0, modified_on=? WHERE id IN (?)`
_HotTags_Topic = `SELECT t.id id, t.user_id user_id, t.tag tag, t.quote_num quote_num, u.id, u.nickname, u.username, u.status, u.avatar, u.is_admin FROM @tag t JOIN @user u ON t.user_id = u.id WHERE t.is_del = 0 AND t.quote_num > 0 ORDER BY t.quote_num DESC LIMIT ? OFFSET ?`
_InsertTag_Topic = `INSERT INTO @tag (user_id, tag, created_on, modified_on, quote_num) VALUES (?, ?, ?, ?, 1)`
_TagsByIdA_Topic = `SELECT id FROM @tag WHERE id IN (?) AND is_del = 0 AND quote_num > 0`
_TagsByIdB_Topic = `SELECT id, user_id, tag, quote_num FROM @tag WHERE id IN (?)`
_TagsForIncr_Topic = `SELECT id, user_id, tag, quote_num FROM @tag WHERE tag IN (?)`
)
type Topic struct {
yesql.Namespace `yesql:"topic"`
DecrTagsById string `yesql:"decr_tags_by_id"`
IncrTagsById string `yesql:"incr_tags_by_id"`
TagsByIdA string `yesql:"tags_by_id_a"`
TagsByIdB string `yesql:"tags_by_id_b"`
TagsForIncr string `yesql:"tags_for_incr"`
HotTags *sqlx.Stmt `yesql:"hot_tags"`
InsertTag *sqlx.Stmt `yesql:"insert_tag"`
NewestTags *sqlx.Stmt `yesql:"newest_tags"`
TagsByKeywordA *sqlx.Stmt `yesql:"tags_by_keyword_a"`
TagsByKeywordB *sqlx.Stmt `yesql:"tags_by_keyword_b"`
}
func BuildTopic(p yesql.PreparexBuilder, ctx ...context.Context) (obj *Topic, err error) {
var c context.Context
if len(ctx) > 0 && ctx[0] != nil {
c = ctx[0]
} else {
c = context.Background()
}
obj = &Topic{
DecrTagsById: p.QueryHook(_DecrTagsById_Topic),
IncrTagsById: p.QueryHook(_IncrTagsById_Topic),
TagsByIdA: p.QueryHook(_TagsByIdA_Topic),
TagsByIdB: p.QueryHook(_TagsByIdB_Topic),
TagsForIncr: p.QueryHook(_TagsForIncr_Topic),
}
if obj.HotTags, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_HotTags_Topic))); err != nil {
return
}
if obj.InsertTag, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_InsertTag_Topic))); err != nil {
return
}
if obj.NewestTags, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_NewestTags_Topic))); err != nil {
return
}
if obj.TagsByKeywordA, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_TagsByKeywordA_Topic))); err != nil {
return
}
if obj.TagsByKeywordB, err = p.PreparexContext(c, p.Rebind(p.QueryHook(_TagsByKeywordB_Topic))); err != nil {
return
}
return
}

@ -0,0 +1,21 @@
package main
import (
"log"
"strings"
"github.com/alimy/yesql"
)
//go:generate go run $GOFILE
func main() {
log.Println("[Yesql] generate code start")
yesql.SetDefaultQueryHook(func(query *yesql.Query) (*yesql.Query, error) {
query.Query = strings.TrimRight(query.Query, ";")
return query, nil
})
if err := yesql.Generate("yesql.sql", "cc", "cc"); err != nil {
log.Fatalf("generate code occurs error: %s", err)
}
log.Println("[Yesql] generate code finish")
}

@ -30,21 +30,26 @@ SELECT id, user_id, tag, quote_num FROM @tag WHERE is_del = 0 AND tag LIKE ? ORD
INSERT INTO @tag (user_id, tag, created_on, modified_on, quote_num) VALUES (?, ?, ?, ?, 1); INSERT INTO @tag (user_id, tag, created_on, modified_on, quote_num) VALUES (?, ?, ?, ?, 1);
-- name: tags_by_id_a@topic -- name: tags_by_id_a@topic
-- prepare: raw
-- clause: in -- clause: in
SELECT id FROM @tag WHERE id IN (?) AND is_del = 0 AND quote_num > 0; SELECT id FROM @tag WHERE id IN (?) AND is_del = 0 AND quote_num > 0;
-- name: tags_by_id_b@topic -- name: tags_by_id_b@topic
-- prepare: raw
-- clause: in -- clause: in
SELECT id, user_id, tag, quote_num FROM @tag WHERE id IN (?); SELECT id, user_id, tag, quote_num FROM @tag WHERE id IN (?);
-- name: decr_tags_by_id@topic -- name: decr_tags_by_id@topic
-- prepare: raw
-- clause: in -- clause: in
UPDATE @tag SET quote_num=quote_num-1, modified_on=? WHERE id IN (?); UPDATE @tag SET quote_num=quote_num-1, modified_on=? WHERE id IN (?);
-- name: tags_for_incr@topic -- name: tags_for_incr@topic
-- prepare: raw
-- clause: in -- clause: in
SELECT id, user_id, tag, quote_num FROM @tag WHERE tag IN (?); SELECT id, user_id, tag, quote_num FROM @tag WHERE tag IN (?);
-- name: incr_tags_by_id@topic -- name: incr_tags_by_id@topic
-- prepare: raw
-- clause: in -- clause: in
UPDATE @tag SET quote_num=quote_num+1, is_del=0, modified_on=? WHERE id IN (?); UPDATE @tag SET quote_num=quote_num+1, is_del=0, modified_on=? WHERE id IN (?);

@ -22,7 +22,7 @@ import (
//go:generate go run $GOFILE //go:generate go run $GOFILE
func main() { func main() {
log.Println("generate code start") log.Println("[Mir] generate code start")
opts := Options{ opts := Options{
RunMode(InSerialMode), RunMode(InSerialMode),
GeneratorName(GeneratorGin), GeneratorName(GeneratorGin),
@ -32,5 +32,5 @@ func main() {
if err := Generate(opts); err != nil { if err := Generate(opts); err != nil {
log.Fatal(err) log.Fatal(err)
} }
log.Println("generate code finish") log.Println("[Mir] generate code finish")
} }

Loading…
Cancel
Save