diff --git a/cmd/goqu-crud-gen/get_tpl.go b/cmd/goqu-crud-gen/get_tpl.go index 93c1d06..ef0070d 100644 --- a/cmd/goqu-crud-gen/get_tpl.go +++ b/cmd/goqu-crud-gen/get_tpl.go @@ -62,6 +62,70 @@ func (s *{{ .Repo.Name }}) iter( return nil } +// iterWithOrder iterates other select with specified filter(s). +// +// Can be used in your custom query methods. +func (s *{{ .Repo.Name }}) iterWithOrder( + ctx context.Context, + filter goqu.Expression, + f func(m {{ .Model.Name }}, stop func()), + order exp.OrderedExpression, + opt ...Option, +) error { + + tx, err := s.txFromContext(ctx) + if err != nil { + return err + } + + ds := s.dialect.From(s.t).Prepared(true) + + if filter != nil { + ds = ds.Where(filter) + } + if order != nil { + ds = ds.Order(order) + } + + for _, o := range opt { + o(ds) + } + + q, args, err := ds.ToSQL() + if err != nil { + return fmt.Errorf("query builder error: %w", err) + } + + sigCtx, sigCtxCancel := context.WithCancel(ctx) + defer sigCtxCancel() + + rows, err := tx.QueryxContext(ctx, q, args...) + if err != nil { + return fmt.Errorf("select query error: %w", err) + } + defer func() { + _ = rows.Close() + }() + + for rows.Next() { + var m {{ .Model.Name }} + select { + case <-sigCtx.Done(): + break + default: + } + + err = rows.StructScan(&m) + if err != nil { + return fmt.Errorf("row scan error: %w", err) + } + + f(m, func() { sigCtxCancel() }) + } + + return nil +} + // iterPrimaryKeys iterates other select with specified filter(s). // // Can be used in your custom query methods. diff --git a/examples/example1/model/user_repo.go b/examples/example1/model/user_repo.go index 798f72a..6149b99 100644 --- a/examples/example1/model/user_repo.go +++ b/examples/example1/model/user_repo.go @@ -269,6 +269,70 @@ func (s *UserRepo) iter( return nil } +// iterWithOrder iterates other select with specified filter(s). +// +// Can be used in your custom query methods. +func (s *UserRepo) iterWithOrder( + ctx context.Context, + filter goqu.Expression, + f func(m User, stop func()), + order exp.OrderedExpression, + opt ...Option, +) error { + + tx, err := s.txFromContext(ctx) + if err != nil { + return err + } + + ds := s.dialect.From(s.t).Prepared(true) + + if filter != nil { + ds = ds.Where(filter) + } + if order != nil { + ds = ds.Order(order) + } + + for _, o := range opt { + o(ds) + } + + q, args, err := ds.ToSQL() + if err != nil { + return fmt.Errorf("query builder error: %w", err) + } + + sigCtx, sigCtxCancel := context.WithCancel(ctx) + defer sigCtxCancel() + + rows, err := tx.QueryxContext(ctx, q, args...) + if err != nil { + return fmt.Errorf("select query error: %w", err) + } + defer func() { + _ = rows.Close() + }() + + for rows.Next() { + var m User + select { + case <-sigCtx.Done(): + break + default: + } + + err = rows.StructScan(&m) + if err != nil { + return fmt.Errorf("row scan error: %w", err) + } + + f(m, func() { sigCtxCancel() }) + } + + return nil +} + // iterPrimaryKeys iterates other select with specified filter(s). // // Can be used in your custom query methods. diff --git a/examples/example2/user_repo.go b/examples/example2/user_repo.go index 24ab174..ab66761 100644 --- a/examples/example2/user_repo.go +++ b/examples/example2/user_repo.go @@ -270,6 +270,70 @@ func (s *UserRepo) iter( return nil } +// iterWithOrder iterates other select with specified filter(s). +// +// Can be used in your custom query methods. +func (s *UserRepo) iterWithOrder( + ctx context.Context, + filter goqu.Expression, + f func(m User, stop func()), + order exp.OrderedExpression, + opt ...Option, +) error { + + tx, err := s.txFromContext(ctx) + if err != nil { + return err + } + + ds := s.dialect.From(s.t).Prepared(true) + + if filter != nil { + ds = ds.Where(filter) + } + if order != nil { + ds = ds.Order(order) + } + + for _, o := range opt { + o(ds) + } + + q, args, err := ds.ToSQL() + if err != nil { + return fmt.Errorf("query builder error: %w", err) + } + + sigCtx, sigCtxCancel := context.WithCancel(ctx) + defer sigCtxCancel() + + rows, err := tx.QueryxContext(ctx, q, args...) + if err != nil { + return fmt.Errorf("select query error: %w", err) + } + defer func() { + _ = rows.Close() + }() + + for rows.Next() { + var m User + select { + case <-sigCtx.Done(): + break + default: + } + + err = rows.StructScan(&m) + if err != nil { + return fmt.Errorf("row scan error: %w", err) + } + + f(m, func() { sigCtxCancel() }) + } + + return nil +} + // iterPrimaryKeys iterates other select with specified filter(s). // // Can be used in your custom query methods. diff --git a/examples/example3/adapters/mysql/account_repo.go b/examples/example3/adapters/mysql/account_repo.go index 70bb537..0c871c0 100644 --- a/examples/example3/adapters/mysql/account_repo.go +++ b/examples/example3/adapters/mysql/account_repo.go @@ -265,6 +265,70 @@ func (s *AccountRepo) iter( return nil } +// iterWithOrder iterates other select with specified filter(s). +// +// Can be used in your custom query methods. +func (s *AccountRepo) iterWithOrder( + ctx context.Context, + filter goqu.Expression, + f func(m Account, stop func()), + order exp.OrderedExpression, + opt ...Option, +) error { + + tx, err := s.txFromContext(ctx) + if err != nil { + return err + } + + ds := s.dialect.From(s.t).Prepared(true) + + if filter != nil { + ds = ds.Where(filter) + } + if order != nil { + ds = ds.Order(order) + } + + for _, o := range opt { + o(ds) + } + + q, args, err := ds.ToSQL() + if err != nil { + return fmt.Errorf("query builder error: %w", err) + } + + sigCtx, sigCtxCancel := context.WithCancel(ctx) + defer sigCtxCancel() + + rows, err := tx.QueryxContext(ctx, q, args...) + if err != nil { + return fmt.Errorf("select query error: %w", err) + } + defer func() { + _ = rows.Close() + }() + + for rows.Next() { + var m Account + select { + case <-sigCtx.Done(): + break + default: + } + + err = rows.StructScan(&m) + if err != nil { + return fmt.Errorf("row scan error: %w", err) + } + + f(m, func() { sigCtxCancel() }) + } + + return nil +} + // iterPrimaryKeys iterates other select with specified filter(s). // // Can be used in your custom query methods. diff --git a/examples/example3/adapters/mysql/user_public_fields_repo.go b/examples/example3/adapters/mysql/user_public_fields_repo.go index 2b4ec8c..0c4f326 100644 --- a/examples/example3/adapters/mysql/user_public_fields_repo.go +++ b/examples/example3/adapters/mysql/user_public_fields_repo.go @@ -259,6 +259,70 @@ func (s *UserPublicFieldsRepo) iter( return nil } +// iterWithOrder iterates other select with specified filter(s). +// +// Can be used in your custom query methods. +func (s *UserPublicFieldsRepo) iterWithOrder( + ctx context.Context, + filter goqu.Expression, + f func(m UserPublicFields, stop func()), + order exp.OrderedExpression, + opt ...Option, +) error { + + tx, err := s.txFromContext(ctx) + if err != nil { + return err + } + + ds := s.dialect.From(s.t).Prepared(true) + + if filter != nil { + ds = ds.Where(filter) + } + if order != nil { + ds = ds.Order(order) + } + + for _, o := range opt { + o(ds) + } + + q, args, err := ds.ToSQL() + if err != nil { + return fmt.Errorf("query builder error: %w", err) + } + + sigCtx, sigCtxCancel := context.WithCancel(ctx) + defer sigCtxCancel() + + rows, err := tx.QueryxContext(ctx, q, args...) + if err != nil { + return fmt.Errorf("select query error: %w", err) + } + defer func() { + _ = rows.Close() + }() + + for rows.Next() { + var m UserPublicFields + select { + case <-sigCtx.Done(): + break + default: + } + + err = rows.StructScan(&m) + if err != nil { + return fmt.Errorf("row scan error: %w", err) + } + + f(m, func() { sigCtxCancel() }) + } + + return nil +} + // iterPrimaryKeys iterates other select with specified filter(s). // // Can be used in your custom query methods.