From 53291fc74c902d08e18fd8db2949cd59aceac3a8 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Fri, 31 Mar 2023 19:56:18 +0800 Subject: [PATCH] optimize usage describe in README.md --- README-en.md | 222 +++++++++++++++++++++++++ README.md | 357 +++++++++++++---------------------------- examples/README.md | 9 ++ examples/auto/yesql.go | 52 +++--- template/sql.tmpl | 2 +- template/sqlx.tmpl | 2 +- version.go | 2 +- 7 files changed, 375 insertions(+), 271 deletions(-) create mode 100644 README-en.md create mode 100644 examples/README.md diff --git a/README-en.md b/README-en.md new file mode 100644 index 0000000..29c9095 --- /dev/null +++ b/README-en.md @@ -0,0 +1,222 @@ +## Yesql +[![Go](https://github.com/alimy/yesql/actions/workflows/go.yml/badge.svg)](https://github.com/alimy/yesql/actions/workflows/go.yml) +[![GoDoc](https://godoc.org/github.com/alimy/yesql?status.svg)](https://pkg.go.dev/github.com/alimy/yesql) +[![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg?logo=sourcegraph)](https://sourcegraph.com/github.com/alimy/yesql) + +Yesql parses a file and associate SQL queries to a map. Useful for separating SQL from code logic. + +> This package is based on [knadh/goyesql](https://github.com/knadh/goyesql) but is not compatible with it any more. This package introduces support for arbitrary tag types and changes structs and error types. + +### Installation + +``` +$ go get github.com/alimy/yesql +``` + +### Usage + +#### Create a file containing your SQL queries + +```sql +-- sql file yesql.sql + +-- name: newest_tags@topic +-- get newest tag information +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 ?; + +-- name: hot_tags@topic +-- get get host tag information +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 ?; + +-- name: tags_by_keyword_a@topic +-- get tags by keyword +SELECT id, user_id, tag, quote_num FROM @tag WHERE is_del = 0 ORDER BY quote_num DESC LIMIT 6; + +-- name: tags_by_keyword_b@topic +SELECT id, user_id, tag, quote_num FROM @tag WHERE is_del = 0 AND tag LIKE ? ORDER BY quote_num DESC LIMIT 6; + +-- name: insert_tag@topic +INSERT INTO @tag (user_id, tag, created_on, modified_on, quote_num) VALUES (?, ?, ?, ?, 1); + +-- name: tags_by_id_a@topic +-- clause: in +SELECT id FROM @tag WHERE id IN (?) AND is_del = 0 AND quote_num > 0; + +-- name: tags_by_id_b@topic +-- clause: in +SELECT id, user_id, tag, quote_num FROM @tag WHERE id IN (?); + +-- name: decr_tags_by_id@topic +-- clause: in +UPDATE @tag SET quote_num=quote_num-1, modified_on=? WHERE id IN (?); + +-- name: tags_for_incr@topic +-- clause: in +SELECT id, user_id, tag, quote_num FROM @tag WHERE tag IN (?); + +-- name: incr_tags_by_id@topic +-- clause: in +UPDATE @tag SET quote_num=quote_num+1, is_del=0, modified_on=? WHERE id IN (?); +``` + +#### Use scanning mode +```go +// file: topics.go + +package topics + +import ( + "context" + + "github.com/alimy/yesql" + "github.com/jmoiron/sqlx" +) + +//go:embed yesql.sql +var yesqlBytes []byte + +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 NewTopic(db *sqlx.DB) (*Topic, error) { + // use *sqlx.DB as prepare context + yesql.UseSqlx(db) + // get sql query + query := yesql.MustParseBytes(yesqlBytes) + // scan object from sql query + obj := &Topic{} + if err := yesql.Scan(obj, query); err != nil { + return nil, err + } + return obj, nil +} +``` + +#### Use code generate mode + +* Create code generate logic +```go +// file: gen.go + +package main + +import ( + "log" + + "github.com/alimy/yesql" +) + +//go:generate go run $GOFILE +func main() { + log.Println("[Yesql] generate code start") + if err := yesql.Generate("yesql.sql", "auto", "yesql"); err != nil { + log.Fatalf("generate code occurs error: %s", err) + } + log.Println("[Yesql] generate code finish") +} +``` + +* Command to generate code +```sh +% go generate gen.go +2023/03/31 19:34:44 [Yesql] generate code start +2023/03/31 19:34:44 [Yesql] generate code finish +``` + +* Generated source code (file path: auto/yesql.go) +```go +// Code generated by Yesql. DO NOT EDIT. +// versions: +// - Yesql v1.1.2 + +package cc + +import ( + "context" + + "github.com/alimy/yesql" + "github.com/jmoiron/sqlx" +) + +const ( + _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` + _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 (?)` + _IncrTagsById_Topic = `UPDATE @tag SET quote_num=quote_num+1, is_del=0, modified_on=? WHERE id IN (?)` + _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` + _DecrTagsById_Topic = `UPDATE @tag SET quote_num=quote_num-1, 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 ?` +) + +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 +} +``` + +## Projects that used [Yesql](https://github.com/alimy/yesql) +* [examples](examples) - examples in this project. +* [paopao-ce](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-plus) - A artistic "twitter like" community built on gin+zinc+vue+ts. diff --git a/README.md b/README.md index ec30ea7..1e3e690 100644 --- a/README.md +++ b/README.md @@ -3,19 +3,19 @@ [![GoDoc](https://godoc.org/github.com/alimy/yesql?status.svg)](https://pkg.go.dev/github.com/alimy/yesql) [![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg?logo=sourcegraph)](https://sourcegraph.com/github.com/alimy/yesql) -Yesql parses a file and associate SQL queries to a map. Useful for separating SQL from code logic. +Yesql解析一个SQL查询语句的文件,提取出SQL查询语句,自动生成对应包含sql查询语句的Go结构体,实现查询语句与代码分离,方便编写数据库查询逻辑。 -> This package is based on [knadh/goyesql](https://github.com/knadh/goyesql) but is not compatible with it any more. This package introduces support for arbitrary tag types and changes structs and error types. +> SQL解析核心基于 [knadh/goyesql](https://github.com/knadh/goyesql),但是采用了不同的使用方式与接口定义。 -### Installation +### 安装 ``` $ go get github.com/alimy/yesql ``` -### Usage +### 使用 -Create a file containing your SQL queries +#### 创建sql dml文件 ```sql -- sql file yesql.sql @@ -67,283 +67,156 @@ SELECT id, user_id, tag, quote_num FROM @tag WHERE tag IN (?); UPDATE @tag SET quote_num=quote_num+1, is_del=0, modified_on=? WHERE id IN (?); ``` -And just call them in your code! - +#### 使用Scan模式(方式一) ```go -// file: sqlx.go +// file: topics.go -package sakila +package topics import ( "context" - "database/sql" - _ "embed" - "strings" "github.com/alimy/yesql" "github.com/jmoiron/sqlx" - "github.com/rocboss/paopao-ce/internal/conf" - "github.com/sirupsen/logrus" ) //go:embed yesql.sql var yesqlBytes []byte -var ( - _db *sqlx.DB -) - -type sqlxSrv struct { - db *sqlx.DB -} - -func (s *sqlxSrv) with(handle func(tx *sqlx.Tx) error) error { - tx, err := s.db.Beginx() - if err != nil { - return err - } - defer tx.Rollback() - if err = handle(tx); err != nil { - return err - } - return tx.Commit() -} - -func (s *sqlxSrv) withTx(ctx context.Context, opts *sql.TxOptions, handle func(*sqlx.Tx) error) error { - tx, err := s.db.BeginTxx(ctx, opts) - if err != nil { - return err - } - defer tx.Rollback() - if err = handle(tx); err != nil { - return err - } - return tx.Commit() -} - -func (s *sqlxSrv) in(query string, args ...any) (string, []any, error) { - q, params, err := sqlx.In(query, args...) - if err != nil { - return "", nil, err - } - return s.db.Rebind(q), params, nil -} - -func (s *sqlxSrv) inExec(execer sqlx.Execer, query string, args ...any) (sql.Result, error) { - q, params, err := sqlx.In(query, args...) - if err != nil { +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 NewTopic(db *sqlx.DB) (*Topic, error) { + // use *sqlx.DB as prepare context + yesql.UseSqlx(db) + // get sql query + query := yesql.MustParseBytes(yesqlBytes) + // scan object from sql query + obj := &Topic{} + if err := yesql.Scan(obj, query); err != nil { return nil, err } - return execer.Exec(s.db.Rebind(q), params...) -} - -func (s *sqlxSrv) inSelect(queryer sqlx.Queryer, dest any, query string, args ...any) error { - q, params, err := sqlx.In(query, args...) - if err != nil { - return err - } - return sqlx.Select(queryer, dest, s.db.Rebind(q), params...) -} - -func (s *sqlxSrv) inGet(queryer sqlx.Queryer, dest any, query string, args ...any) error { - q, params, err := sqlx.In(query, args...) - if err != nil { - return err - } - return sqlx.Get(queryer, dest, s.db.Rebind(q), params...) -} - -func newSqlxSrv(db *sqlx.DB) *sqlxSrv { - return &sqlxSrv{ - db: db, - } + return obj, nil } +``` -func r(query string) string { - return _db.Rebind(t(query)) -} +#### 使用代码生成模式(方式二) +* 编写代码生成逻辑 +```go +// file: gen.go -func c(query string) *sqlx.Stmt { - query = _db.Rebind(t(query)) - stmt, err := _db.Preparex(query) - if err != nil { - logrus.Fatalf("prepare query(%s) error: %s", query, err) - } - return stmt -} +package main -func n(query string) *sqlx.NamedStmt { - query = t(query) - stmt, err := _db.PrepareNamed(query) - if err != nil { - logrus.Fatalf("prepare named query(%s) error: %s", query, err) - } - return stmt -} +import ( + "log" -// t repace table prefix for query -func t(query string) string { - return strings.Replace(query, "@", conf.DatabaseSetting.TablePrefix, -1) -} + "github.com/alimy/yesql" +) -// yesqlScan yesql.Scan help function -func yesqlScan[T any](query yesql.SQLQuery, obj T) T { - if err := yesql.Scan(obj, query); err != nil { - logrus.Fatal(err) +//go:generate go run $GOFILE +func main() { + log.Println("[Yesql] generate code start") + if err := yesql.Generate("yesql.sql", "auto", "yesql"); err != nil { + log.Fatalf("generate code occurs error: %s", err) } - return obj -} - -func initSqlxDB() { - _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 - }) + log.Println("[Yesql] generate code finish") } ``` -### Scanning - -Often, it's necessary to scan multiple queries from a SQL file, prepare them into \*sql.Stmt and use them throught the application. yesql comes with a helper function that helps with this. Given a yesql map of queries, it can turn the queries into prepared statements and scan them into a struct that can be passed around. +* 使用下面命令将自动生成Go代码 +```sh +% go generate gen.go +2023/03/31 19:34:44 [Yesql] generate code start +2023/03/31 19:34:44 [Yesql] generate code finish +``` +* 生成的代码如下(生成文件路径: auto/yesql.go) ```go -// file: topics.go +// Code generated by Yesql. DO NOT EDIT. +// versions: +// - Yesql v1.1.2 -package sakila +package cc import ( - "strings" - "time" + "context" "github.com/alimy/yesql" "github.com/jmoiron/sqlx" - "github.com/rocboss/paopao-ce/internal/core" - "github.com/rocboss/paopao-ce/internal/core/cs" ) -type topicSrv struct { - *sqlxSrv - yesql.Namespace `yesql:"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"` -} +const ( + _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` + _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 (?)` + _IncrTagsById_Topic = `UPDATE @tag SET quote_num=quote_num+1, is_del=0, modified_on=? WHERE id IN (?)` + _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` + _DecrTagsById_Topic = `UPDATE @tag SET quote_num=quote_num-1, 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 ?` +) -func (s *topicSrv) UpsertTags(userId int64, tags []string) (res cs.TagInfoList, xerr error) { - if len(tags) == 0 { - return nil, nil +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() } - xerr = s.with(func(tx *sqlx.Tx) error { - var upTags cs.TagInfoList - if err := s.inSelect(tx, &upTags, s.SqlTagsForIncr, tags); err != nil { - return err - } - now := time.Now().Unix() - if len(upTags) > 0 { - var ids []int64 - for _, t := range upTags { - ids = append(ids, t.ID) - t.QuoteNum++ - // prepare remain tags just delete updated tag - // notice ensure tags slice is distinct elements - for i, name := range tags { - if name == t.Tag { - lastIdx := len(tags) - 1 - tags[i] = tags[lastIdx] - tags = tags[:lastIdx] - break - } - } - } - if _, err := s.inExec(tx, s.SqlIncrTagsById, now, ids); err != nil { - return err - } - res = append(res, upTags...) - } - // process remain tags if tags is not empty - if len(tags) == 0 { - return nil - } - var ids []int64 - for _, tag := range tags { - res, err := s.StmtInsertTag.Exec(userId, tag, now, now) - if err != nil { - return err - } - id, err := res.LastInsertId() - if err != nil { - return err - } - ids = append(ids, id) - } - var newTags cs.TagInfoList - if err := s.inSelect(tx, &newTags, s.SqlTagsByIdB, ids); err != nil { - return err - } - res = append(res, newTags...) - return nil - }) - return -} - -func (s *topicSrv) DecrTagsById(ids []int64) error { - return s.with(func(tx *sqlx.Tx) error { - var ids []int64 - err := s.inSelect(tx, &ids, s.SqlTagsByIdA, ids) - if err != nil { - return err - } - _, err = s.inExec(tx, s.SqlDecrTagsById, time.Now().Unix(), ids) - return err - }) -} - -func (s *topicSrv) ListTags(typ cs.TagType, limit int, offset int) (res cs.TagList, err error) { - switch typ { - case cs.TagTypeHot: - err = s.StmtHotTags.Select(&res, limit, offset) - case cs.TagTypeNew: - err = s.StmtNewestTags.Select(&res, limit, offset) + 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), } - return -} - -func (s *topicSrv) TagsByKeyword(keyword string) (res cs.TagInfoList, err error) { - keyword = "%" + strings.Trim(keyword, " ") + "%" - if keyword == "%%" { - err = s.StmtTagsByKeywordA.Select(&res) - } else { - err = s.StmtTagsByKeywordB.Select(&res) + 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 } - -func newTopicService(db *sqlx.DB) core.TopicService { - initSqlxDB() - - query := yesql.MustParseBytes(yesqlBytes) - return yesqlScan(query, &topicSrv{ - sqlxSrv: newSqlxSrv(db), - }) -} ``` -> Source code from [github.com/rocboss/paopao-ce](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-plus/internal/dao/sakila). -### Projects that used [Yesql](https://github.com/alimy/yesql) -* [paopao-ce](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-plus) - A artistic "twitter like" community built on gin+zinc+vue+ts. +## 使用 [Yesql](https://github.com/alimy/yesql) 的项目 +* [examples](examples) - 项目examples +* [paopao-ce](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-plus) - 一个清新文艺类Twitter的社区 + diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..43bc146 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,9 @@ +## Examples +Just a Yesql demo. + +### Usage +```sh +% make generate +2023/03/31 19:34:44 [Yesql] generate code start +2023/03/31 19:34:44 [Yesql] generate code finish +``` \ No newline at end of file diff --git a/examples/auto/yesql.go b/examples/auto/yesql.go index 35d0c7a..4ef20c2 100644 --- a/examples/auto/yesql.go +++ b/examples/auto/yesql.go @@ -1,6 +1,6 @@ -// Code generated by go-mir. DO NOT EDIT. +// Code generated by Yesql. DO NOT EDIT. // versions: -// - Yesql v1.1.2 +// - Yesql v1.1.3 package yesql @@ -12,45 +12,45 @@ import ( ) const ( - _LoginInfoE = `SELECT * FROM @user WHERE username=?` - _UserInfoB = `SELECT ` + "`" + `username` + "`" + `, ` + "`" + `nickname` + "`" + ` FROM @user WHERE username=?` - _UserInfoC = `SELECT "username" FROM @user WHERE username=?` + _UserInfoD = `SELECT "username", "nickname" FROM @user WHERE username=?` _LoginInfoA = `SELECT * FROM @user WHERE username=?` _LoginInfoB = `SELECT * FROM @user WHERE username=?` _LogoutInfoC = `SELECT * FROM @user WHERE username=?` _LoginInfoD = `SELECT * FROM @user WHERE username=?` + _LoginInfoE = `SELECT * FROM @user WHERE username=?` _UserInfoA = `SELECT ` + "`" + `username` + "`" + ` FROM @user WHERE username=?` - _UserInfoD = `SELECT "username", "nickname" FROM @user WHERE username=?` - _TagsForIncr_TagsInfo = `SELECT id, user_id, tag, quote_num FROM @tag WHERE tag IN (?);` - _IncrTagsById_TagsInfo = `UPDATE @tag SET quote_num=quote_num+1, is_del=0, modified_on=? WHERE id IN (?);` - _NewestTags_TagsInfo = `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_TagsInfo = `SELECT id, user_id, tag, quote_num FROM @tag WHERE is_del = 0 ORDER BY quote_num DESC LIMIT 6;` - _TagsByKeywordB_TagsInfo = `SELECT id, user_id, tag, quote_num FROM @tag WHERE is_del = 0 AND tag LIKE ? ORDER BY quote_num DESC LIMIT 6;` - _InsertTag_TagsInfo = `INSERT INTO @tag (user_id, tag, created_on, modified_on, quote_num) VALUES (?, ?, ?, ?, 1);` - _HotTags_TagsInfo = `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 ?;` - _TagsByIdA_TagsInfo = `SELECT id FROM @tag WHERE id IN (?) AND is_del = 0 AND quote_num > 0;` - _TagsByIdB_TagsInfo = `SELECT id, user_id, tag, quote_num FROM @tag WHERE id IN (?);` - _DecrTagsById_TagsInfo = `UPDATE @tag SET quote_num=quote_num-1, modified_on=? WHERE id IN (?);` - _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 (?);` - _TagsForIncr_Topic = `SELECT id, user_id, tag, quote_num FROM @tag WHERE tag IN (?);` + _UserInfoB = `SELECT ` + "`" + `username` + "`" + `, ` + "`" + `nickname` + "`" + ` FROM @user WHERE username=?` + _UserInfoC = `SELECT "username" FROM @user WHERE username=?` _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 (?);` _IncrTagsById_Topic = `UPDATE @tag SET quote_num=quote_num+1, is_del=0, modified_on=? WHERE id IN (?);` + _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 ?;` + _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;` + _TagsByIdA_Topic = `SELECT id FROM @tag WHERE id IN (?) AND is_del = 0 AND quote_num > 0;` + _DecrTagsById_Topic = `UPDATE @tag SET quote_num=quote_num-1, modified_on=? WHERE id IN (?);` + _TagsForIncr_Topic = `SELECT id, user_id, tag, quote_num FROM @tag WHERE tag IN (?);` + _TagsByKeywordA_Topic = `SELECT id, user_id, tag, quote_num FROM @tag WHERE is_del = 0 ORDER BY quote_num DESC LIMIT 6;` + _HotTags_Shutter = `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 ?;` + _TagsByKeywordA_Shutter = `SELECT id, user_id, tag, quote_num FROM @tag WHERE is_del = 0 ORDER BY quote_num DESC LIMIT 6;` _TagsByIdB_Shutter = `SELECT id, user_id, tag, quote_num FROM @tag WHERE id IN (?);` + _DecrTagsById_Shutter = `UPDATE @tag SET quote_num=quote_num-1, modified_on=? WHERE id IN (?);` _TagsForIncr_Shutter = `SELECT id, user_id, tag, quote_num FROM @tag WHERE tag IN (?);` + _IncrTagsById_Shutter = `UPDATE @tag SET quote_num=quote_num+1, is_del=0, modified_on=? WHERE id IN (?);` _NewestTags_Shutter = `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 ?;` - _HotTags_Shutter = `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 ?;` - _TagsByKeywordA_Shutter = `SELECT id, user_id, tag, quote_num FROM @tag WHERE is_del = 0 ORDER BY quote_num DESC LIMIT 6;` _TagsByKeywordB_Shutter = `SELECT id, user_id, tag, quote_num FROM @tag WHERE is_del = 0 AND tag LIKE ? ORDER BY quote_num DESC LIMIT 6;` _InsertTag_Shutter = `INSERT INTO @tag (user_id, tag, created_on, modified_on, quote_num) VALUES (?, ?, ?, ?, 1);` _TagsByIdA_Shutter = `SELECT id FROM @tag WHERE id IN (?) AND is_del = 0 AND quote_num > 0;` - _DecrTagsById_Shutter = `UPDATE @tag SET quote_num=quote_num-1, modified_on=? WHERE id IN (?);` - _IncrTagsById_Shutter = `UPDATE @tag SET quote_num=quote_num+1, is_del=0, modified_on=? WHERE id IN (?);` + _TagsForIncr_TagsInfo = `SELECT id, user_id, tag, quote_num FROM @tag WHERE tag IN (?);` + _IncrTagsById_TagsInfo = `UPDATE @tag SET quote_num=quote_num+1, is_del=0, modified_on=? WHERE id IN (?);` + _NewestTags_TagsInfo = `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_TagsInfo = `SELECT id, user_id, tag, quote_num FROM @tag WHERE is_del = 0 ORDER BY quote_num DESC LIMIT 6;` + _TagsByKeywordB_TagsInfo = `SELECT id, user_id, tag, quote_num FROM @tag WHERE is_del = 0 AND tag LIKE ? ORDER BY quote_num DESC LIMIT 6;` + _InsertTag_TagsInfo = `INSERT INTO @tag (user_id, tag, created_on, modified_on, quote_num) VALUES (?, ?, ?, ?, 1);` + _TagsByIdB_TagsInfo = `SELECT id, user_id, tag, quote_num FROM @tag WHERE id IN (?);` + _HotTags_TagsInfo = `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 ?;` + _TagsByIdA_TagsInfo = `SELECT id FROM @tag WHERE id IN (?) AND is_del = 0 AND quote_num > 0;` + _DecrTagsById_TagsInfo = `UPDATE @tag SET quote_num=quote_num-1, modified_on=? WHERE id IN (?);` ) type Yesql struct { diff --git a/template/sql.tmpl b/template/sql.tmpl index d1ed186..bd30919 100644 --- a/template/sql.tmpl +++ b/template/sql.tmpl @@ -1,4 +1,4 @@ -// Code generated by go-mir. DO NOT EDIT. +// Code generated by Yesql. DO NOT EDIT. // versions: // - Yesql {{ .YesqlVer }} diff --git a/template/sqlx.tmpl b/template/sqlx.tmpl index 86953a0..4f400dd 100644 --- a/template/sqlx.tmpl +++ b/template/sqlx.tmpl @@ -1,4 +1,4 @@ -// Code generated by go-mir. DO NOT EDIT. +// Code generated by Yesql. DO NOT EDIT. // versions: // - Yesql {{ .YesqlVer }} diff --git a/version.go b/version.go index d97a048..4a7de7a 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package yesql -var Version = "v1.1.2" +var Version = "v1.1.3"