Skip to content

Commit

Permalink
optimize sqlx generate code logic
Browse files Browse the repository at this point in the history
  • Loading branch information
alimy committed Aug 19, 2023
1 parent c4f1554 commit 29c5fae
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 36 deletions.
14 changes: 6 additions & 8 deletions core.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"io"
"reflect"
"strings"

"github.com/jmoiron/sqlx"
)

const (
Expand Down Expand Up @@ -150,15 +148,15 @@ type PrepareContext interface {
PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
}

// PreparexContext enhances the Conn interface with context.
type PreparexContext interface {
// PreparexContext[T] enhances the Conn interface with context.
type PreparexContext[T any] interface {
// PrepareContext prepares a statement.
// The provided context is used for the preparation of the statement, not for
// the execution of the statement.
PreparexContext(ctx context.Context, query string) (*sqlx.Stmt, error)
PreparexContext(ctx context.Context, query string) (T, error)

// PrepareNamedContext returns an sqlx.NamedStmt
PrepareNamedContext(ctx context.Context, query string) (*sqlx.NamedStmt, error)
PrepareNamedContext(ctx context.Context, query string) (T, error)

// Rebind rebind query to adapte SQL Driver
Rebind(query string) string
Expand All @@ -171,8 +169,8 @@ type PrepareBuilder interface {
}

// PreparexBuilder preparex builder interface for sqlx
type PreparexBuilder interface {
PreparexContext
type PreparexBuilder[T any] interface {
PreparexContext[T]
QueryHook(query string) string
}

Expand Down
19 changes: 9 additions & 10 deletions generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

"github.com/alimy/yesql/naming"
"github.com/alimy/yesql/template"
"github.com/jmoiron/sqlx"
)

const (
Expand All @@ -35,8 +34,8 @@ type simplePrepareBuilder struct {
hooks []func(string) string
}

type simplePreparexBuilder struct {
p PreparexContext
type simplePreparexBuilder[T any] struct {
p PreparexContext[T]
hooks []func(string) string
}

Expand All @@ -55,19 +54,19 @@ func (s *simplePrepareBuilder) QueryHook(query string) string {
return query
}

func (s *simplePreparexBuilder) PreparexContext(ctx context.Context, query string) (*sqlx.Stmt, error) {
func (s *simplePreparexBuilder[T]) PreparexContext(ctx context.Context, query string) (T, error) {
return s.p.PreparexContext(ctx, query)
}

func (s *simplePreparexBuilder) PrepareNamedContext(ctx context.Context, query string) (*sqlx.NamedStmt, error) {
func (s *simplePreparexBuilder[T]) PrepareNamedContext(ctx context.Context, query string) (T, error) {
return s.p.PrepareNamedContext(ctx, query)
}

func (s *simplePreparexBuilder) Rebind(query string) string {
func (s *simplePreparexBuilder[T]) Rebind(query string) string {
return s.p.Rebind(query)
}

func (s *simplePreparexBuilder) QueryHook(query string) string {
func (s *simplePreparexBuilder[T]) QueryHook(query string) string {
for _, h := range s.hooks {
query = h(query)
}
Expand Down Expand Up @@ -133,9 +132,9 @@ func NewPrepareBuilder(p PrepareContext, hooks ...func(string) string) PrepareBu
return obj
}

// NewPreprarexBuilder create a simple preparex builder instance
func NewPreparexBuilder(p PreparexContext, hooks ...func(string) string) PreparexBuilder {
obj := &simplePreparexBuilder{
// NewPreprarexBuilder[T] create a simple preparex builder instance
func NewPreparexBuilder[T any](p PreparexContext[T], hooks ...func(string) string) PreparexBuilder[T] {
obj := &simplePreparexBuilder[T]{
p: p,
}
for _, h := range hooks {
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ module github.com/alimy/yesql

go 1.18

require github.com/jmoiron/sqlx v1.3.5
require (
github.com/bitbus/sqlx v1.6.0
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/bitbus/sqlx v1.6.0 h1:ewrBydRkyHZqfOqvHVYpiBlqQtLn93B/loa2EwjpZ74=
github.com/bitbus/sqlx v1.6.0/go.mod h1:MemKLfQ600g6PxUVsIDe48PlY3wOquyW2ApeiXoynFo=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
Expand Down
16 changes: 8 additions & 8 deletions hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import (

var (
_ PrepareHook = (*stdPrepareHook)(nil)
_ PrepareHook = (*sqlxPrepareHook)(nil)
_ PrepareHook = (*sqlxPrepareHook[any])(nil)
)

type stdPrepareHook struct {
prepare PrepareContext
}

type sqlxPrepareHook struct {
prepare PreparexContext
type sqlxPrepareHook[T any] struct {
prepare PreparexContext[T]
}

func (s *stdPrepareHook) Prepare(field reflect.Type, query string) (any, error) {
Expand Down Expand Up @@ -53,7 +53,7 @@ func (s *stdPrepareHook) PrepareContext(ctx context.Context, field reflect.Type,
}
}

func (s *sqlxPrepareHook) Prepare(field reflect.Type, query string) (any, error) {
func (s *sqlxPrepareHook[T]) Prepare(field reflect.Type, query string) (any, error) {
switch field.String() {
case "string":
// Unprepared SQL query.
Expand All @@ -77,7 +77,7 @@ func (s *sqlxPrepareHook) Prepare(field reflect.Type, query string) (any, error)
}
}

func (s *sqlxPrepareHook) PrepareContext(ctx context.Context, field reflect.Type, query string) (any, error) {
func (s *sqlxPrepareHook[T]) PrepareContext(ctx context.Context, field reflect.Type, query string) (any, error) {
switch field.String() {
case "string":
// Unprepared SQL query.
Expand Down Expand Up @@ -108,9 +108,9 @@ func NewPrepareHook(p PrepareContext) PrepareHook {
}
}

// NewSqlxPrepareHook create a prepare hook prepare that implement PreparexContext
func NewSqlxPrepareHook(p PreparexContext) PrepareHook {
return &sqlxPrepareHook{
// NewSqlxPrepareHook[T] create a prepare hook prepare that implement PreparexContext
func NewSqlxPrepareHook[T any](p PreparexContext[T]) PrepareHook {
return &sqlxPrepareHook[T]{
prepare: p,
}
}
24 changes: 22 additions & 2 deletions template/sqlx.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,26 @@ const (
{{end -}}
)

// PreparexContext enhances the Conn interface with context.
type PreparexContext interface {
// PrepareContext prepares a statement.
// The provided context is used for the preparation of the statement, not for
// the execution of the statement.
PreparexContext(ctx context.Context, query string) (*sqlx.Stmt, error)

// PrepareNamedContext returns an sqlx.NamedStmt
PrepareNamedContext(ctx context.Context, query string) (*sqlx.NamedStmt, error)

// Rebind rebind query to adapte SQL Driver
Rebind(query string) string
}

// PreparexBuilder preparex builder interface for sqlx
type PreparexBuilder interface {
PreparexContext
QueryHook(query string) string
}

{{if .DefaultQueryMapNotEmpty}}type {{ .DefaultStructName }} struct {
{{range $name, $query := .DefaultQueryMap.FilterByStyle "raw" }}{{ naming $name }} {{if eq .PrepareStyle "stmt" }}*sqlx.Stmt{{else if eq .PrepareStyle "named_stmt"}}*sqlx.NamedStmt{{else}}string{{end}} `yesql:"{{ $query.Name }}"`
{{end}}
Expand All @@ -37,7 +57,7 @@ type {{ naming $scope }} struct {
{{end -}}

{{if .DefaultQueryMapNotEmpty}}
func Build{{ .DefaultStructName }}(p yesql.PreparexBuilder{{if .DefaultQueryMap.IsStmtQueryNotEmpty }}, ctx ...context.Context{{end}}) (obj *{{ .DefaultStructName }}, err error) {
func Build{{ .DefaultStructName }}(p PreparexBuilder{{if .DefaultQueryMap.IsStmtQueryNotEmpty }}, ctx ...context.Context{{end}}) (obj *{{ .DefaultStructName }}, err error) {
{{- if .DefaultQueryMap.IsStmtQueryNotEmpty -}}
var c context.Context
if len(ctx) > 0 && ctx[0] != nil {
Expand All @@ -60,7 +80,7 @@ func Build{{ .DefaultStructName }}(p yesql.PreparexBuilder{{if .DefaultQueryMap.
return
}{{end}}
{{range $scope, $queryMap := .ScopeQuery }}
func Build{{ naming $scope }}(p yesql.PreparexBuilder{{if $queryMap.IsStmtQueryNotEmpty }}, ctx ...context.Context{{end}}) (obj *{{ naming $scope }}, err error) {
func Build{{ naming $scope }}(p PreparexBuilder{{if $queryMap.IsStmtQueryNotEmpty }}, ctx ...context.Context{{end}}) (obj *{{ naming $scope }}, err error) {
{{- if $queryMap.IsStmtQueryNotEmpty -}}
var c context.Context
if len(ctx) > 0 && ctx[0] != nil {
Expand Down
2 changes: 1 addition & 1 deletion version.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package yesql

var Version = "v1.6.0"
var Version = "v1.7.0"
10 changes: 5 additions & 5 deletions yesql.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ func Use(p PrepareContext) {
_defaultPrepareScanner = NewPrepareScanner(prepareHook)
}

// UseSqlx use default prepare scanner withprepare that implement PreparexContext
func UseSqlx(p PreparexContext) {
prepareHook := NewSqlxPrepareHook(p)
// UseSqlx[T] use default prepare scanner withprepare that implement PreparexContext
func UseSqlx[T any](p PreparexContext[T]) {
prepareHook := NewSqlxPrepareHook[T](p)
_defaultPrepareScanner = NewPrepareScanner(prepareHook)
}

Expand Down Expand Up @@ -149,8 +149,8 @@ func MustBuild[T any](p PrepareContext, fn func(PrepareBuilder, ...context.Conte
return obj
}

// MustBuildx build a struct object than type of T
func MustBuildx[T any](p PreparexContext, fn func(PreparexBuilder, ...context.Context) (T, error), hook ...func(query string) string) T {
// MustBuildx[T] build a struct object than type of T
func MustBuildx[T any](p PreparexContext[T], fn func(PreparexBuilder[T], ...context.Context) (T, error), hook ...func(query string) string) T {
b := NewPreparexBuilder(p, hook...)
obj, err := fn(b)
if err != nil {
Expand Down
4 changes: 3 additions & 1 deletion yesql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package yesql

import (
"testing"

"github.com/bitbus/sqlx"
)

func TestMustParseFilePanic(t *testing.T) {
Expand Down Expand Up @@ -77,7 +79,7 @@ func TestScan(t *testing.T) {
t.Error("[q2] expected to fail at non-existent query 'does-not-exist' but didn't")
}

SetDefaultPrepareHook(NewSqlxPrepareHook(nil))
SetDefaultPrepareHook(NewSqlxPrepareHook[*sqlx.Stmt](nil))
if err = Scan(&q3, queries); err != nil {
t.Errorf("[q3] failed to scan raw query to struct: %s", err)
}
Expand Down

0 comments on commit 29c5fae

Please sign in to comment.