From 7b2afbcc469e220c59653466cf76e78995101883 Mon Sep 17 00:00:00 2001 From: gogacoder Date: Mon, 6 Jan 2025 00:09:51 +0700 Subject: [PATCH] feat: crudgen --- .task/checksum/linux-common-build-frontend | 2 +- .task/checksum/linux-common-generate-bindings | 2 +- README.md | 15 + .../bindings/app/internal/models/models.ts | 25 ++ .../app/internal/services/authorservice.ts | 69 ++++ .../bindings/app/internal/services/index.ts | 2 + .../bindings/app/internal/services/models.ts | 3 + .../app/internal/services/postservice.ts | 4 +- internal/dal/authors.gen.go | 383 ++++++++++++++++++ internal/dal/authors.gen_test.go | 145 +++++++ internal/dal/gen.go | 30 +- internal/dal/gen_test.go | 1 + internal/models/models.go | 8 +- internal/services/author.go | 45 ++ internal/services/default_data.go | 10 + .../services/{post_service.go => post.go} | 6 - internal/services/services.go | 1 + 17 files changed, 728 insertions(+), 23 deletions(-) create mode 100644 frontend/bindings/app/internal/services/authorservice.ts create mode 100644 internal/dal/authors.gen.go create mode 100644 internal/dal/authors.gen_test.go create mode 100644 internal/services/author.go rename internal/services/{post_service.go => post.go} (99%) diff --git a/.task/checksum/linux-common-build-frontend b/.task/checksum/linux-common-build-frontend index f5aad7e..292e479 100644 --- a/.task/checksum/linux-common-build-frontend +++ b/.task/checksum/linux-common-build-frontend @@ -1 +1 @@ -7d5c7be0816f85841738e6c048dcdbf1 +1a407d8a115d4dcba0f64a4a4e445309 diff --git a/.task/checksum/linux-common-generate-bindings b/.task/checksum/linux-common-generate-bindings index 980af5f..cac103a 100644 --- a/.task/checksum/linux-common-generate-bindings +++ b/.task/checksum/linux-common-generate-bindings @@ -1 +1 @@ -1dfcdfb986275b93f717c33495e2130c +ddc4b88644fe1db1c146bd0cc127cf98 diff --git a/README.md b/README.md index 5bce856..f111549 100644 --- a/README.md +++ b/README.md @@ -57,4 +57,19 @@ wails3 build -clean -upx -v 2 -webview2 embed ``` go env -w GOPROXY="https://proxy.golang.org,direct" ``` +## CRUD generator +Установите crudgen: +``` +go install git.gogacoder.ru/NTO/crudgen/cmd/crudgen@latest +``` +Сгенерируйте DAL: +``` +cd dal +go run gen.go +``` +Запустите crudgen: +``` +crudgen -p internal +``` +Не забудьте добавить новые модели в `Entities`, а сервисы в `Services`. diff --git a/frontend/bindings/app/internal/models/models.ts b/frontend/bindings/app/internal/models/models.ts index 88de955..5153c54 100644 --- a/frontend/bindings/app/internal/models/models.ts +++ b/frontend/bindings/app/internal/models/models.ts @@ -5,6 +5,31 @@ // @ts-ignore: Unused imports import {Create as $Create} from "@wailsio/runtime"; +export class Author { + "Id": number; + "Name": string; + + /** Creates a new Author instance. */ + constructor($$source: Partial = {}) { + if (!("Id" in $$source)) { + this["Id"] = 0; + } + if (!("Name" in $$source)) { + this["Name"] = ""; + } + + Object.assign(this, $$source); + } + + /** + * Creates a new Author instance from a string or object. + */ + static createFrom($$source: any = {}): Author { + let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; + return new Author($$parsedSource as Partial); + } +} + export class Post { "Id": number; "Text": string; diff --git a/frontend/bindings/app/internal/services/authorservice.ts b/frontend/bindings/app/internal/services/authorservice.ts new file mode 100644 index 0000000..36af907 --- /dev/null +++ b/frontend/bindings/app/internal/services/authorservice.ts @@ -0,0 +1,69 @@ +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore: Unused imports +import {Call as $Call, Create as $Create} from "@wailsio/runtime"; + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore: Unused imports +import * as models$0 from "../models/models.js"; + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore: Unused imports +import * as $models from "./models.js"; + +export function Count(): Promise & { cancel(): void } { + let $resultPromise = $Call.ByID(3969879864) as any; + return $resultPromise; +} + +export function Create(item: $models.Author): Promise<$models.Author> & { cancel(): void } { + let $resultPromise = $Call.ByID(3684602449, item) as any; + let $typingPromise = $resultPromise.then(($result) => { + return $$createType0($result); + }) as any; + $typingPromise.cancel = $resultPromise.cancel.bind($resultPromise); + return $typingPromise; +} + +export function Delete(item: $models.Author): Promise<$models.Author> & { cancel(): void } { + let $resultPromise = $Call.ByID(2096845974, item) as any; + let $typingPromise = $resultPromise.then(($result) => { + return $$createType0($result); + }) as any; + $typingPromise.cancel = $resultPromise.cancel.bind($resultPromise); + return $typingPromise; +} + +export function GetAll(): Promise<($models.Author | null)[]> & { cancel(): void } { + let $resultPromise = $Call.ByID(3248293926) as any; + let $typingPromise = $resultPromise.then(($result) => { + return $$createType2($result); + }) as any; + $typingPromise.cancel = $resultPromise.cancel.bind($resultPromise); + return $typingPromise; +} + +export function GetById(id: number): Promise<$models.Author | null> & { cancel(): void } { + let $resultPromise = $Call.ByID(1703016211, id) as any; + let $typingPromise = $resultPromise.then(($result) => { + return $$createType1($result); + }) as any; + $typingPromise.cancel = $resultPromise.cancel.bind($resultPromise); + return $typingPromise; +} + +export function Update(item: $models.Author): Promise<$models.Author> & { cancel(): void } { + let $resultPromise = $Call.ByID(2240704960, item) as any; + let $typingPromise = $resultPromise.then(($result) => { + return $$createType0($result); + }) as any; + $typingPromise.cancel = $resultPromise.cancel.bind($resultPromise); + return $typingPromise; +} + +// Private type creation functions +const $$createType0 = models$0.Author.createFrom; +const $$createType1 = $Create.Nullable($$createType0); +const $$createType2 = $Create.Array($$createType1); diff --git a/frontend/bindings/app/internal/services/index.ts b/frontend/bindings/app/internal/services/index.ts index d012b2e..5344665 100644 --- a/frontend/bindings/app/internal/services/index.ts +++ b/frontend/bindings/app/internal/services/index.ts @@ -1,8 +1,10 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT +import * as AuthorService from "./authorservice.js"; import * as PostService from "./postservice.js"; export { + AuthorService, PostService }; diff --git a/frontend/bindings/app/internal/services/models.ts b/frontend/bindings/app/internal/services/models.ts index 0c937a3..14711ab 100644 --- a/frontend/bindings/app/internal/services/models.ts +++ b/frontend/bindings/app/internal/services/models.ts @@ -9,5 +9,8 @@ import {Create as $Create} from "@wailsio/runtime"; // @ts-ignore: Unused imports import * as models$0 from "../models/models.js"; +export const Author = models$0.Author; +export type Author = models$0.Author; + export const Post = models$0.Post; export type Post = models$0.Post; diff --git a/frontend/bindings/app/internal/services/postservice.ts b/frontend/bindings/app/internal/services/postservice.ts index b6a4759..1813426 100644 --- a/frontend/bindings/app/internal/services/postservice.ts +++ b/frontend/bindings/app/internal/services/postservice.ts @@ -7,11 +7,11 @@ import {Call as $Call, Create as $Create} from "@wailsio/runtime"; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore: Unused imports -import * as models$0 from "../models/models.ts"; +import * as models$0 from "../models/models.js"; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore: Unused imports -import * as $models from "./models.ts"; +import * as $models from "./models.js"; export function Count(): Promise & { cancel(): void } { let $resultPromise = $Call.ByID(3109924027) as any; diff --git a/internal/dal/authors.gen.go b/internal/dal/authors.gen.go new file mode 100644 index 0000000..5af5a72 --- /dev/null +++ b/internal/dal/authors.gen.go @@ -0,0 +1,383 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dal + +import ( + "app/internal/models" + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" +) + +func newAuthor(db *gorm.DB, opts ...gen.DOOption) author { + _author := author{} + + _author.authorDo.UseDB(db, opts...) + _author.authorDo.UseModel(&models.Author{}) + + tableName := _author.authorDo.TableName() + _author.ALL = field.NewAsterisk(tableName) + _author.Id = field.NewUint(tableName, "id") + _author.Name = field.NewString(tableName, "name") + + _author.fillFieldMap() + + return _author +} + +type author struct { + authorDo + + ALL field.Asterisk + Id field.Uint + Name field.String + + fieldMap map[string]field.Expr +} + +func (a author) Table(newTableName string) *author { + a.authorDo.UseTable(newTableName) + return a.updateTableName(newTableName) +} + +func (a author) As(alias string) *author { + a.authorDo.DO = *(a.authorDo.As(alias).(*gen.DO)) + return a.updateTableName(alias) +} + +func (a *author) updateTableName(table string) *author { + a.ALL = field.NewAsterisk(table) + a.Id = field.NewUint(table, "id") + a.Name = field.NewString(table, "name") + + a.fillFieldMap() + + return a +} + +func (a *author) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := a.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (a *author) fillFieldMap() { + a.fieldMap = make(map[string]field.Expr, 2) + a.fieldMap["id"] = a.Id + a.fieldMap["name"] = a.Name +} + +func (a author) clone(db *gorm.DB) author { + a.authorDo.ReplaceConnPool(db.Statement.ConnPool) + return a +} + +func (a author) replaceDB(db *gorm.DB) author { + a.authorDo.ReplaceDB(db) + return a +} + +type authorDo struct{ gen.DO } + +type IAuthorDo interface { + gen.SubQuery + Debug() IAuthorDo + WithContext(ctx context.Context) IAuthorDo + WithResult(fc func(tx gen.Dao)) gen.ResultInfo + ReplaceDB(db *gorm.DB) + ReadDB() IAuthorDo + WriteDB() IAuthorDo + As(alias string) gen.Dao + Session(config *gorm.Session) IAuthorDo + Columns(cols ...field.Expr) gen.Columns + Clauses(conds ...clause.Expression) IAuthorDo + Not(conds ...gen.Condition) IAuthorDo + Or(conds ...gen.Condition) IAuthorDo + Select(conds ...field.Expr) IAuthorDo + Where(conds ...gen.Condition) IAuthorDo + Order(conds ...field.Expr) IAuthorDo + Distinct(cols ...field.Expr) IAuthorDo + Omit(cols ...field.Expr) IAuthorDo + Join(table schema.Tabler, on ...field.Expr) IAuthorDo + LeftJoin(table schema.Tabler, on ...field.Expr) IAuthorDo + RightJoin(table schema.Tabler, on ...field.Expr) IAuthorDo + Group(cols ...field.Expr) IAuthorDo + Having(conds ...gen.Condition) IAuthorDo + Limit(limit int) IAuthorDo + Offset(offset int) IAuthorDo + Count() (count int64, err error) + Scopes(funcs ...func(gen.Dao) gen.Dao) IAuthorDo + Unscoped() IAuthorDo + Create(values ...*models.Author) error + CreateInBatches(values []*models.Author, batchSize int) error + Save(values ...*models.Author) error + First() (*models.Author, error) + Take() (*models.Author, error) + Last() (*models.Author, error) + Find() ([]*models.Author, error) + FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.Author, err error) + FindInBatches(result *[]*models.Author, batchSize int, fc func(tx gen.Dao, batch int) error) error + Pluck(column field.Expr, dest interface{}) error + Delete(...*models.Author) (info gen.ResultInfo, err error) + Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error) + UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error) + Updates(value interface{}) (info gen.ResultInfo, err error) + UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error) + UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error) + UpdateColumns(value interface{}) (info gen.ResultInfo, err error) + UpdateFrom(q gen.SubQuery) gen.Dao + Attrs(attrs ...field.AssignExpr) IAuthorDo + Assign(attrs ...field.AssignExpr) IAuthorDo + Joins(fields ...field.RelationField) IAuthorDo + Preload(fields ...field.RelationField) IAuthorDo + FirstOrInit() (*models.Author, error) + FirstOrCreate() (*models.Author, error) + FindByPage(offset int, limit int) (result []*models.Author, count int64, err error) + ScanByPage(result interface{}, offset int, limit int) (count int64, err error) + Scan(result interface{}) (err error) + Returning(value interface{}, columns ...string) IAuthorDo + UnderlyingDB() *gorm.DB + schema.Tabler +} + +func (a authorDo) Debug() IAuthorDo { + return a.withDO(a.DO.Debug()) +} + +func (a authorDo) WithContext(ctx context.Context) IAuthorDo { + return a.withDO(a.DO.WithContext(ctx)) +} + +func (a authorDo) ReadDB() IAuthorDo { + return a.Clauses(dbresolver.Read) +} + +func (a authorDo) WriteDB() IAuthorDo { + return a.Clauses(dbresolver.Write) +} + +func (a authorDo) Session(config *gorm.Session) IAuthorDo { + return a.withDO(a.DO.Session(config)) +} + +func (a authorDo) Clauses(conds ...clause.Expression) IAuthorDo { + return a.withDO(a.DO.Clauses(conds...)) +} + +func (a authorDo) Returning(value interface{}, columns ...string) IAuthorDo { + return a.withDO(a.DO.Returning(value, columns...)) +} + +func (a authorDo) Not(conds ...gen.Condition) IAuthorDo { + return a.withDO(a.DO.Not(conds...)) +} + +func (a authorDo) Or(conds ...gen.Condition) IAuthorDo { + return a.withDO(a.DO.Or(conds...)) +} + +func (a authorDo) Select(conds ...field.Expr) IAuthorDo { + return a.withDO(a.DO.Select(conds...)) +} + +func (a authorDo) Where(conds ...gen.Condition) IAuthorDo { + return a.withDO(a.DO.Where(conds...)) +} + +func (a authorDo) Order(conds ...field.Expr) IAuthorDo { + return a.withDO(a.DO.Order(conds...)) +} + +func (a authorDo) Distinct(cols ...field.Expr) IAuthorDo { + return a.withDO(a.DO.Distinct(cols...)) +} + +func (a authorDo) Omit(cols ...field.Expr) IAuthorDo { + return a.withDO(a.DO.Omit(cols...)) +} + +func (a authorDo) Join(table schema.Tabler, on ...field.Expr) IAuthorDo { + return a.withDO(a.DO.Join(table, on...)) +} + +func (a authorDo) LeftJoin(table schema.Tabler, on ...field.Expr) IAuthorDo { + return a.withDO(a.DO.LeftJoin(table, on...)) +} + +func (a authorDo) RightJoin(table schema.Tabler, on ...field.Expr) IAuthorDo { + return a.withDO(a.DO.RightJoin(table, on...)) +} + +func (a authorDo) Group(cols ...field.Expr) IAuthorDo { + return a.withDO(a.DO.Group(cols...)) +} + +func (a authorDo) Having(conds ...gen.Condition) IAuthorDo { + return a.withDO(a.DO.Having(conds...)) +} + +func (a authorDo) Limit(limit int) IAuthorDo { + return a.withDO(a.DO.Limit(limit)) +} + +func (a authorDo) Offset(offset int) IAuthorDo { + return a.withDO(a.DO.Offset(offset)) +} + +func (a authorDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IAuthorDo { + return a.withDO(a.DO.Scopes(funcs...)) +} + +func (a authorDo) Unscoped() IAuthorDo { + return a.withDO(a.DO.Unscoped()) +} + +func (a authorDo) Create(values ...*models.Author) error { + if len(values) == 0 { + return nil + } + return a.DO.Create(values) +} + +func (a authorDo) CreateInBatches(values []*models.Author, batchSize int) error { + return a.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (a authorDo) Save(values ...*models.Author) error { + if len(values) == 0 { + return nil + } + return a.DO.Save(values) +} + +func (a authorDo) First() (*models.Author, error) { + if result, err := a.DO.First(); err != nil { + return nil, err + } else { + return result.(*models.Author), nil + } +} + +func (a authorDo) Take() (*models.Author, error) { + if result, err := a.DO.Take(); err != nil { + return nil, err + } else { + return result.(*models.Author), nil + } +} + +func (a authorDo) Last() (*models.Author, error) { + if result, err := a.DO.Last(); err != nil { + return nil, err + } else { + return result.(*models.Author), nil + } +} + +func (a authorDo) Find() ([]*models.Author, error) { + result, err := a.DO.Find() + return result.([]*models.Author), err +} + +func (a authorDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.Author, err error) { + buf := make([]*models.Author, 0, batchSize) + err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (a authorDo) FindInBatches(result *[]*models.Author, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return a.DO.FindInBatches(result, batchSize, fc) +} + +func (a authorDo) Attrs(attrs ...field.AssignExpr) IAuthorDo { + return a.withDO(a.DO.Attrs(attrs...)) +} + +func (a authorDo) Assign(attrs ...field.AssignExpr) IAuthorDo { + return a.withDO(a.DO.Assign(attrs...)) +} + +func (a authorDo) Joins(fields ...field.RelationField) IAuthorDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Joins(_f)) + } + return &a +} + +func (a authorDo) Preload(fields ...field.RelationField) IAuthorDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Preload(_f)) + } + return &a +} + +func (a authorDo) FirstOrInit() (*models.Author, error) { + if result, err := a.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*models.Author), nil + } +} + +func (a authorDo) FirstOrCreate() (*models.Author, error) { + if result, err := a.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*models.Author), nil + } +} + +func (a authorDo) FindByPage(offset int, limit int) (result []*models.Author, count int64, err error) { + result, err = a.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = a.Offset(-1).Limit(-1).Count() + return +} + +func (a authorDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = a.Count() + if err != nil { + return + } + + err = a.Offset(offset).Limit(limit).Scan(result) + return +} + +func (a authorDo) Scan(result interface{}) (err error) { + return a.DO.Scan(result) +} + +func (a authorDo) Delete(models ...*models.Author) (result gen.ResultInfo, err error) { + return a.DO.Delete(models) +} + +func (a *authorDo) withDO(do gen.Dao) *authorDo { + a.DO = *do.(*gen.DO) + return a +} diff --git a/internal/dal/authors.gen_test.go b/internal/dal/authors.gen_test.go new file mode 100644 index 0000000..1ec73b6 --- /dev/null +++ b/internal/dal/authors.gen_test.go @@ -0,0 +1,145 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dal + +import ( + "app/internal/models" + "context" + "fmt" + "testing" + + "gorm.io/gen" + "gorm.io/gen/field" + "gorm.io/gorm/clause" +) + +func init() { + InitializeDB() + err := _gen_test_db.AutoMigrate(&models.Author{}) + if err != nil { + fmt.Printf("Error: AutoMigrate(&models.Author{}) fail: %s", err) + } +} + +func Test_authorQuery(t *testing.T) { + author := newAuthor(_gen_test_db) + author = *author.As(author.TableName()) + _do := author.WithContext(context.Background()).Debug() + + primaryKey := field.NewString(author.TableName(), clause.PrimaryKey) + _, err := _do.Unscoped().Where(primaryKey.IsNotNull()).Delete() + if err != nil { + t.Error("clean table fail:", err) + return + } + + _, ok := author.GetFieldByName("") + if ok { + t.Error("GetFieldByName(\"\") from author success") + } + + err = _do.Create(&models.Author{}) + if err != nil { + t.Error("create item in table fail:", err) + } + + err = _do.Save(&models.Author{}) + if err != nil { + t.Error("create item in table fail:", err) + } + + err = _do.CreateInBatches([]*models.Author{{}, {}}, 10) + if err != nil { + t.Error("create item in table fail:", err) + } + + _, err = _do.Select(author.ALL).Take() + if err != nil { + t.Error("Take() on table fail:", err) + } + + _, err = _do.First() + if err != nil { + t.Error("First() on table fail:", err) + } + + _, err = _do.Last() + if err != nil { + t.Error("First() on table fail:", err) + } + + _, err = _do.Where(primaryKey.IsNotNull()).FindInBatch(10, func(tx gen.Dao, batch int) error { return nil }) + if err != nil { + t.Error("FindInBatch() on table fail:", err) + } + + err = _do.Where(primaryKey.IsNotNull()).FindInBatches(&[]*models.Author{}, 10, func(tx gen.Dao, batch int) error { return nil }) + if err != nil { + t.Error("FindInBatches() on table fail:", err) + } + + _, err = _do.Select(author.ALL).Where(primaryKey.IsNotNull()).Order(primaryKey.Desc()).Find() + if err != nil { + t.Error("Find() on table fail:", err) + } + + _, err = _do.Distinct(primaryKey).Take() + if err != nil { + t.Error("select Distinct() on table fail:", err) + } + + _, err = _do.Select(author.ALL).Omit(primaryKey).Take() + if err != nil { + t.Error("Omit() on table fail:", err) + } + + _, err = _do.Group(primaryKey).Find() + if err != nil { + t.Error("Group() on table fail:", err) + } + + _, err = _do.Scopes(func(dao gen.Dao) gen.Dao { return dao.Where(primaryKey.IsNotNull()) }).Find() + if err != nil { + t.Error("Scopes() on table fail:", err) + } + + _, _, err = _do.FindByPage(0, 1) + if err != nil { + t.Error("FindByPage() on table fail:", err) + } + + _, err = _do.ScanByPage(&models.Author{}, 0, 1) + if err != nil { + t.Error("ScanByPage() on table fail:", err) + } + + _, err = _do.Attrs(primaryKey).Assign(primaryKey).FirstOrInit() + if err != nil { + t.Error("FirstOrInit() on table fail:", err) + } + + _, err = _do.Attrs(primaryKey).Assign(primaryKey).FirstOrCreate() + if err != nil { + t.Error("FirstOrCreate() on table fail:", err) + } + + var _a _another + var _aPK = field.NewString(_a.TableName(), "id") + + err = _do.Join(&_a, primaryKey.EqCol(_aPK)).Scan(map[string]interface{}{}) + if err != nil { + t.Error("Join() on table fail:", err) + } + + err = _do.LeftJoin(&_a, primaryKey.EqCol(_aPK)).Scan(map[string]interface{}{}) + if err != nil { + t.Error("LeftJoin() on table fail:", err) + } + + _, err = _do.Not().Or().Clauses().Take() + if err != nil { + t.Error("Not/Or/Clauses on table fail:", err) + } +} diff --git a/internal/dal/gen.go b/internal/dal/gen.go index bd39b32..5435601 100644 --- a/internal/dal/gen.go +++ b/internal/dal/gen.go @@ -16,34 +16,39 @@ import ( ) var ( - Q = new(Query) - Post *post + Q = new(Query) + Author *author + Post *post ) func SetDefault(db *gorm.DB, opts ...gen.DOOption) { *Q = *Use(db, opts...) + Author = &Q.Author Post = &Q.Post } func Use(db *gorm.DB, opts ...gen.DOOption) *Query { return &Query{ - db: db, - Post: newPost(db, opts...), + db: db, + Author: newAuthor(db, opts...), + Post: newPost(db, opts...), } } type Query struct { db *gorm.DB - Post post + Author author + Post post } func (q *Query) Available() bool { return q.db != nil } func (q *Query) clone(db *gorm.DB) *Query { return &Query{ - db: db, - Post: q.Post.clone(db), + db: db, + Author: q.Author.clone(db), + Post: q.Post.clone(db), } } @@ -57,18 +62,21 @@ func (q *Query) WriteDB() *Query { func (q *Query) ReplaceDB(db *gorm.DB) *Query { return &Query{ - db: db, - Post: q.Post.replaceDB(db), + db: db, + Author: q.Author.replaceDB(db), + Post: q.Post.replaceDB(db), } } type queryCtx struct { - Post IPostDo + Author IAuthorDo + Post IPostDo } func (q *Query) WithContext(ctx context.Context) *queryCtx { return &queryCtx{ - Post: q.Post.WithContext(ctx), + Author: q.Author.WithContext(ctx), + Post: q.Post.WithContext(ctx), } } diff --git a/internal/dal/gen_test.go b/internal/dal/gen_test.go index 6e4bb46..6c0fc8b 100644 --- a/internal/dal/gen_test.go +++ b/internal/dal/gen_test.go @@ -77,6 +77,7 @@ func Test_WithContext(t *testing.T) { qCtx := query.WithContext(context.WithValue(context.Background(), key, value)) for _, ctx := range []context.Context{ + qCtx.Author.UnderlyingDB().Statement.Context, qCtx.Post.UnderlyingDB().Statement.Context, } { if v := ctx.Value(key); v != value { diff --git a/internal/models/models.go b/internal/models/models.go index cc3ea73..b640cc0 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -1,11 +1,15 @@ package models var Entities = []any{ - &Post{}, + &Post{}, &Author{}, } type Post struct { - Id uint `gorm:"primaryKey"` + Id uint `gorm:"primaryKey"` Text string } +type Author struct { + Id uint `gorm:"primaryKey"` + Name string +} diff --git a/internal/services/author.go b/internal/services/author.go new file mode 100644 index 0000000..157907f --- /dev/null +++ b/internal/services/author.go @@ -0,0 +1,45 @@ +package services + +import ( + "app/internal/dal" + "app/internal/models" + "errors" + "gorm.io/gen/field" + "gorm.io/gorm" +) + +type AuthorService struct{} +type Author = models.Author + +func (service *AuthorService) Create(item Author) (Author, error) { + err := dal.Author.Preload(field.Associations).Create(&item) + return item, err +} +func (service *AuthorService) GetAll() ([]*Author, error) { + var authors []*Author + authors, err := dal.Author.Preload(field.Associations).Find() + return authors, err +} +func (service *AuthorService) GetById(id uint) (*Author, error) { + item, err := dal.Author.Preload(field.Associations).Where(dal.Author.Id.Eq(id)).First() + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } else { + return nil, err + } + } + return item, nil +} +func (service *AuthorService) Update(item Author) (Author, error) { + err := dal.Author.Preload(field.Associations).Save(&item) + return item, err +} +func (service *AuthorService) Delete(item Author) (Author, error) { + _, err := dal.Author.Unscoped().Preload(field.Associations).Delete(&item) + return item, err +} +func (service *AuthorService) Count() (int64, error) { + amount, err := dal.Author.Count() + return amount, err +} diff --git a/internal/services/default_data.go b/internal/services/default_data.go index 0072e94..832cdd6 100644 --- a/internal/services/default_data.go +++ b/internal/services/default_data.go @@ -7,6 +7,7 @@ import ( func InsertDefaultData() { insertPosts() + insertAuthors() } func InsertDefaultEntityData[T any](service Service[T], entities []T) { @@ -34,3 +35,12 @@ func insertPosts() { }, }) } + +func insertAuthors() { + InsertDefaultEntityData(&AuthorService{}, []Author{ + { + Id: 1, + Name: "ИА Кузбасс", + }, + }) +} diff --git a/internal/services/post_service.go b/internal/services/post.go similarity index 99% rename from internal/services/post_service.go rename to internal/services/post.go index 2bee674..d03d443 100644 --- a/internal/services/post_service.go +++ b/internal/services/post.go @@ -15,13 +15,11 @@ func (service *PostService) Create(item Post) (Post, error) { err := dal.Post.Preload(field.Associations).Create(&item) return item, err } - func (service *PostService) GetAll() ([]*Post, error) { var posts []*Post posts, err := dal.Post.Preload(field.Associations).Find() return posts, err } - func (service *PostService) GetById(id uint) (*Post, error) { item, err := dal.Post.Preload(field.Associations).Where(dal.Post.Id.Eq(id)).First() if err != nil { @@ -31,20 +29,16 @@ func (service *PostService) GetById(id uint) (*Post, error) { return nil, err } } - return item, nil } - func (service *PostService) Update(item Post) (Post, error) { err := dal.Post.Preload(field.Associations).Save(&item) return item, err } - func (service *PostService) Delete(item Post) (Post, error) { _, err := dal.Post.Unscoped().Preload(field.Associations).Delete(&item) return item, err } - func (service *PostService) Count() (int64, error) { amount, err := dal.Post.Count() return amount, err diff --git a/internal/services/services.go b/internal/services/services.go index 5beb015..03f23f6 100644 --- a/internal/services/services.go +++ b/internal/services/services.go @@ -4,4 +4,5 @@ import "github.com/wailsapp/wails/v3/pkg/application" var ExportedServices = []application.Service{ application.NewService(&PostService{}), + application.NewService(&AuthorService{}), }