github.com/unionj-cloud/go-doudou@v1.3.8-0.20221011095552-0088008e5b31/cmd/internal/ddl/codegen/dao.go (about)

     1  package codegen
     2  
     3  import (
     4  	"github.com/iancoleman/strcase"
     5  	log "github.com/sirupsen/logrus"
     6  	"github.com/unionj-cloud/go-doudou/cmd/internal/astutils"
     7  	"github.com/unionj-cloud/go-doudou/cmd/internal/ddl/table"
     8  	"github.com/unionj-cloud/go-doudou/version"
     9  	"os"
    10  	"path/filepath"
    11  	"strings"
    12  	"text/template"
    13  )
    14  
    15  var daoimpltmpl = `/**
    16  * Generated by go-doudou {{.Version}}.
    17  * You can edit it as your need.
    18  */
    19  package dao
    20  
    21  import (
    22  	"context"
    23  	"database/sql"
    24  	"fmt"
    25  	"github.com/pkg/errors"
    26  	"{{.DomainPackage}}"
    27  	"github.com/unionj-cloud/go-doudou/toolkit/caller"
    28  	"github.com/unionj-cloud/go-doudou/toolkit/sqlext/query"
    29  	"github.com/unionj-cloud/go-doudou/toolkit/sqlext/wrapper"
    30  	"github.com/unionj-cloud/go-doudou/toolkit/reflectutils"
    31  	"github.com/unionj-cloud/go-doudou/toolkit/stringutils"
    32  	"github.com/unionj-cloud/go-doudou/toolkit/templateutils"
    33  	"strings"
    34  	"math"
    35  	"time"
    36  )
    37  
    38  type {{.DomainName}}Dao struct {
    39  	db wrapper.GddDB
    40  }
    41  
    42  func New{{.DomainName}}Dao(querier wrapper.GddDB) {{.DomainName}}Dao {
    43  	return {{.DomainName}}Dao{
    44  		db: querier,
    45  	}
    46  }
    47  
    48  func (receiver {{.DomainName}}Dao) BeforeSaveHook(ctx context.Context, data *domain.{{.DomainName}}) {
    49  	// implement your business logic
    50  }
    51  
    52  func (receiver {{.DomainName}}Dao) BeforeBulkSaveHook(ctx context.Context, data []*domain.{{.DomainName}}) {
    53  	// implement your business logic
    54  }
    55  
    56  func (receiver {{.DomainName}}Dao) AfterSaveHook(ctx context.Context, data *domain.{{.DomainName}}, lastInsertID int64, affected int64) {
    57  	// implement your business logic
    58  }
    59  
    60  func (receiver {{.DomainName}}Dao) AfterBulkSaveHook(ctx context.Context, data []*domain.{{.DomainName}}, lastInsertID int64, affected int64) {
    61  	// implement your business logic
    62  }
    63  
    64  func (receiver {{.DomainName}}Dao) BeforeUpdateManyHook(ctx context.Context, data []*domain.{{.DomainName}}, where query.Where) {
    65  	// implement your business logic
    66  }
    67  
    68  func (receiver {{.DomainName}}Dao) AfterUpdateManyHook(ctx context.Context, data []*domain.{{.DomainName}}, where query.Where, affected int64) {
    69  	// implement your business logic
    70  }
    71  
    72  func (receiver {{.DomainName}}Dao) BeforeDeleteManyHook(ctx context.Context, data []*domain.{{.DomainName}}, where query.Where) {
    73  	// implement your business logic
    74  }
    75  
    76  func (receiver {{.DomainName}}Dao) AfterDeleteManyHook(ctx context.Context, data []*domain.{{.DomainName}}, where query.Where, affected int64) {
    77  	// implement your business logic
    78  }
    79  
    80  func (receiver {{.DomainName}}Dao) BeforeReadManyHook(ctx context.Context, page *query.Page, where ...query.Where) {
    81  	// implement your business logic
    82  }
    83  
    84  func (receiver {{.DomainName}}Dao) Insert(ctx context.Context, data *domain.{{.DomainName}}) (int64, error) {
    85  	var (
    86  		statement    string
    87  		err          error
    88  		result       sql.Result
    89  		{{- if .PkCol.Autoincrement }}
    90  		lastInsertID int64
    91  		{{- end }}
    92  		affected     int64
    93  	)
    94  	receiver.BeforeSaveHook(ctx, data)
    95  	if statement, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "Insert{{.DomainName}}", nil); err != nil {
    96  		return 0, errors.Wrap(err, caller.NewCaller().String())
    97  	}
    98  	if result, err = receiver.db.NamedExecContext(ctx, statement, data); err != nil {
    99  		return 0, errors.Wrap(err, caller.NewCaller().String())
   100  	}
   101  	{{- if .PkCol.Autoincrement }}
   102  	if lastInsertID, err = result.LastInsertId(); err != nil {
   103  		return 0, errors.Wrap(err, caller.NewCaller().String())
   104  	}
   105  	if lastInsertID > 0 {
   106  		{{- if eq .PkField.Type "int64"}}
   107  		data.{{.PkField.Name}} = lastInsertID
   108  		{{- else }}
   109  		data.{{.PkField.Name}} = {{.PkField.Type}}(lastInsertID)
   110  		{{- end }}
   111  	}
   112  	{{- end }}
   113  	if affected, err = result.RowsAffected(); err == nil {
   114  		{{- if .PkCol.Autoincrement }}
   115  		receiver.AfterSaveHook(ctx, data, lastInsertID, affected)
   116  		{{- else }}
   117  		receiver.AfterSaveHook(ctx, data, 0, affected)
   118  		{{- end }}
   119  	}
   120  	return affected, err
   121  }
   122  
   123  func (receiver {{.DomainName}}Dao) InsertIgnore(ctx context.Context, data *domain.{{.DomainName}}) (int64, error) {
   124  	var (
   125  		statement    string
   126  		err          error
   127  		result       sql.Result
   128  		affected     int64
   129  	)
   130  	receiver.BeforeSaveHook(ctx, data)
   131  	if statement, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "InsertIgnore{{.DomainName}}", nil); err != nil {
   132  		return 0, errors.Wrap(err, caller.NewCaller().String())
   133  	}
   134  	if result, err = receiver.db.NamedExecContext(ctx, statement, data); err != nil {
   135  		return 0, errors.Wrap(err, caller.NewCaller().String())
   136  	}
   137  	if affected, err = result.RowsAffected(); err == nil {
   138  		receiver.AfterSaveHook(ctx, data, 0, affected)
   139  	}
   140  	return affected, err
   141  }
   142  
   143  func (receiver {{.DomainName}}Dao) BulkInsert(ctx context.Context, data []*domain.{{.DomainName}}) (int64, error) {
   144  	var (
   145  		statement    string
   146  		err          error
   147  		result       sql.Result
   148  		{{- if .PkCol.Autoincrement }}
   149  		lastInsertID int64
   150  		{{- end }}
   151  		affected     int64
   152  	)
   153  	receiver.BeforeBulkSaveHook(ctx, data)
   154  	if statement, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "Insert{{.DomainName}}", nil); err != nil {
   155  		return 0, errors.Wrap(err, caller.NewCaller().String())
   156  	}
   157  	if result, err = receiver.db.NamedExecContext(ctx, statement, data); err != nil {
   158  		return 0, errors.Wrap(err, caller.NewCaller().String())
   159  	}
   160  	{{- if .PkCol.Autoincrement }}
   161  	if lastInsertID, err = result.LastInsertId(); err != nil {
   162  		return 0, errors.Wrap(err, caller.NewCaller().String())
   163  	}
   164  	if lastInsertID > 0 {
   165  		for i, item :=range data {
   166  			{{- if eq .PkField.Type "int64"}}
   167  			item.{{.PkField.Name}} = lastInsertID + int64(i)
   168  			{{- else }}
   169  			item.{{.PkField.Name}} = {{.PkField.Type}}(lastInsertID) + {{.PkField.Type}}(i)
   170  			{{- end }}
   171  		}
   172  	}
   173  	{{- end }}
   174  	if affected, err = result.RowsAffected(); err == nil {
   175  		{{- if .PkCol.Autoincrement }}
   176  		receiver.AfterBulkSaveHook(ctx, data, lastInsertID, affected)
   177  		{{- else }}
   178  		receiver.AfterBulkSaveHook(ctx, data, 0, affected)
   179  		{{- end }}
   180  	}
   181  	return affected, err
   182  }
   183  
   184  func (receiver {{.DomainName}}Dao) BulkInsertIgnore(ctx context.Context, data []*domain.{{.DomainName}}) (int64, error) {
   185  	var (
   186  		statement    string
   187  		err          error
   188  		result       sql.Result
   189  		affected     int64
   190  	)
   191  	receiver.BeforeBulkSaveHook(ctx, data)
   192  	if statement, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "InsertIgnore{{.DomainName}}", nil); err != nil {
   193  		return 0, errors.Wrap(err, caller.NewCaller().String())
   194  	}
   195  	if result, err = receiver.db.NamedExecContext(ctx, statement, data); err != nil {
   196  		return 0, errors.Wrap(err, caller.NewCaller().String())
   197  	}
   198  	if affected, err = result.RowsAffected(); err == nil {
   199  		receiver.AfterBulkSaveHook(ctx, data, 0, affected)
   200  	}
   201  	return affected, err
   202  }
   203  
   204  // Upsert With ON DUPLICATE KEY UPDATE, the affected-rows value per row is 1 if the row is inserted as a new row,
   205  // 2 if an existing row is updated, and 0 if an existing row is set to its current values.
   206  // If you specify the CLIENT_FOUND_ROWS flag to the mysql_real_connect() C API function when connecting to mysqld,
   207  // the affected-rows value is 1 (not 0) if an existing row is set to its current values.
   208  // https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
   209  func (receiver {{.DomainName}}Dao) Upsert(ctx context.Context, data *domain.{{.DomainName}}) (int64, error) {
   210  	var (
   211  		statement    string
   212  		err          error
   213  		result       sql.Result
   214  		{{- if .PkCol.Autoincrement }}
   215  		lastInsertID int64
   216  		{{- end }}
   217  		affected     int64
   218  	)
   219  	receiver.BeforeSaveHook(ctx, data)
   220  	if statement, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "Upsert{{.DomainName}}", nil); err != nil {
   221  		return 0, errors.Wrap(err, caller.NewCaller().String())
   222  	}
   223  	if result, err = receiver.db.NamedExecContext(ctx, statement, data); err != nil {
   224  		return 0, errors.Wrap(err, caller.NewCaller().String())
   225  	}
   226  	{{- if .PkCol.Autoincrement }}
   227  	if lastInsertID, err = result.LastInsertId(); err != nil {
   228  		return 0, errors.Wrap(err, caller.NewCaller().String())
   229  	}
   230  	if lastInsertID > 0 {
   231  		{{- if eq .PkField.Type "int64"}}
   232  		data.{{.PkField.Name}} = lastInsertID
   233  		{{- else }}
   234  		data.{{.PkField.Name}} = {{.PkField.Type}}(lastInsertID)
   235  		{{- end }}
   236  	}
   237  	{{- end }}
   238  	if affected, err = result.RowsAffected(); err == nil {
   239  		{{- if .PkCol.Autoincrement }}
   240  		receiver.AfterSaveHook(ctx, data, lastInsertID, affected)
   241  		{{- else }}
   242  		receiver.AfterSaveHook(ctx, data, 0, affected)
   243  		{{- end }}
   244  	}
   245  	return affected, err
   246  }
   247  
   248  func (receiver {{.DomainName}}Dao) BulkUpsert(ctx context.Context, data []*domain.{{.DomainName}}) (int64, error) {
   249  	var (
   250  		statement    string
   251  		updateClause string
   252  		err          error
   253  		result       sql.Result
   254  		affected     int64
   255  		args      []interface{}
   256  	)
   257  	receiver.BeforeBulkSaveHook(ctx, data)
   258  	if statement, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "Insert{{.DomainName}}", nil); err != nil {
   259  		return 0, errors.Wrap(err, caller.NewCaller().String())
   260  	}
   261  	statement, args, err = receiver.db.BindNamed(statement, data)
   262  	if err != nil {
   263  		return 0, errors.Wrap(err, caller.NewCaller().String())
   264  	}
   265  	if updateClause, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "UpdateClause{{.DomainName}}", nil); err != nil {
   266  		return 0, errors.Wrap(err, caller.NewCaller().String())
   267  	}
   268  	statement += "\n" + updateClause
   269  	if result, err = receiver.db.ExecContext(ctx, statement, args...); err != nil {
   270  		return 0, errors.Wrap(err, caller.NewCaller().String())
   271  	}
   272  	if affected, err = result.RowsAffected(); err == nil {
   273  		receiver.AfterBulkSaveHook(ctx, data, 0, affected)
   274  	}
   275  	return affected, err
   276  }
   277  
   278  func (receiver {{.DomainName}}Dao) BulkUpsertSelect(ctx context.Context, data []*domain.{{.DomainName}}, columns []string) (int64, error) {
   279  	var (
   280  		statement    string
   281  		updateClause string
   282  		err          error
   283  		result       sql.Result
   284  		affected     int64
   285  		args      []interface{}
   286  	)
   287  	receiver.BeforeBulkSaveHook(ctx, data)
   288  	if statement, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "Insert{{.DomainName}}", nil); err != nil {
   289  		return 0, errors.Wrap(err, caller.NewCaller().String())
   290  	}
   291  	statement, args, err = receiver.db.BindNamed(statement, data)
   292  	if err != nil {
   293  		return 0, errors.Wrap(err, caller.NewCaller().String())
   294  	}
   295  	if updateClause, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "UpdateClauseSelect{{.DomainName}}", struct {
   296  		Columns []string
   297  	}{
   298  		Columns: columns,
   299  	}); err != nil {
   300  		return 0, errors.Wrap(err, caller.NewCaller().String())
   301  	}
   302  	statement += "\n" + updateClause
   303  	if result, err = receiver.db.ExecContext(ctx, statement, args...); err != nil {
   304  		return 0, errors.Wrap(err, caller.NewCaller().String())
   305  	}
   306  	if affected, err = result.RowsAffected(); err == nil {
   307  		receiver.AfterBulkSaveHook(ctx, data, 0, affected)
   308  	}
   309  	return affected, err
   310  }
   311  
   312  func (receiver {{.DomainName}}Dao) UpsertNoneZero(ctx context.Context, data *domain.{{.DomainName}}) (int64, error) {
   313  	var (
   314  		statement    string
   315  		err          error
   316  		result       sql.Result
   317  		{{- if .PkCol.Autoincrement }}
   318  		lastInsertID int64
   319  		{{- end }}
   320  		affected     int64
   321  	)
   322  	receiver.BeforeSaveHook(ctx, data)
   323  	value := reflectutils.ValueOf(data).Interface()
   324  	if _, ok := value.(domain.{{.DomainName}}); !ok {
   325  		return 0, errors.New("underlying type of data should be domain.{{.DomainName}}")
   326  	}
   327  	if statement, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "Upsert{{.DomainName}}NoneZero", data); err != nil {
   328  		return 0, errors.Wrap(err, caller.NewCaller().String())
   329  	}
   330  	if result, err = receiver.db.NamedExecContext(ctx, statement, data); err != nil {
   331  		return 0, errors.Wrap(err, caller.NewCaller().String())
   332  	}
   333  	{{- if .PkCol.Autoincrement }}
   334  	if lastInsertID, err = result.LastInsertId(); err != nil {
   335  		return 0, errors.Wrap(err, caller.NewCaller().String())
   336  	}
   337  	if lastInsertID > 0 {
   338  		{{- if eq .PkField.Type "int64"}}
   339  		data.{{.PkField.Name}} = lastInsertID
   340  		{{- else }}
   341  		data.{{.PkField.Name}} = {{.PkField.Type}}(lastInsertID)
   342  		{{- end }}
   343  	}
   344  	{{- end }}
   345  	if affected, err = result.RowsAffected(); err == nil {
   346  		{{- if .PkCol.Autoincrement }}
   347  		receiver.AfterSaveHook(ctx, data, lastInsertID, affected)
   348  		{{- else }}
   349  		receiver.AfterSaveHook(ctx, data, 0, affected)
   350  		{{- end }}
   351  	}
   352  	return affected, err
   353  }
   354  
   355  func (receiver {{.DomainName}}Dao) DeleteMany(ctx context.Context, where query.Where) (int64, error) {
   356  	var (
   357  		err    error
   358  		result sql.Result
   359  		w      string
   360  		args   []interface{}
   361  		affected int64
   362  	)
   363  	receiver.BeforeDeleteManyHook(ctx, nil, where)
   364  	w, args = where.Sql()
   365  	if result, err = receiver.db.ExecContext(ctx, receiver.db.Rebind(fmt.Sprintf("delete from {{.TableName}} where %s;", w)), args...); err != nil {
   366  		return 0, errors.Wrap(err, caller.NewCaller().String())
   367  	}
   368  	if affected, err = result.RowsAffected(); err == nil {
   369  		receiver.AfterDeleteManyHook(ctx, nil, where, affected)
   370  	}
   371  	return affected, err
   372  }
   373  
   374  func (receiver {{.DomainName}}Dao) Update(ctx context.Context, data *domain.{{.DomainName}}) (int64, error) {
   375  	var (
   376  		statement string
   377  		err       error
   378  		result    sql.Result
   379  		affected  int64
   380  	)
   381  	receiver.BeforeSaveHook(ctx, data)
   382  	if statement, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "Update{{.DomainName}}", nil); err != nil {
   383  		return 0, errors.Wrap(err, caller.NewCaller().String())
   384  	}
   385  	if result, err = receiver.db.NamedExecContext(ctx, statement, data); err != nil {
   386  		return 0, errors.Wrap(err, caller.NewCaller().String())
   387  	}
   388  	if affected, err = result.RowsAffected(); err == nil {
   389  		receiver.AfterSaveHook(ctx, data, 0, affected)
   390  	}
   391  	return affected, err
   392  }
   393  
   394  func (receiver {{.DomainName}}Dao) UpdateNoneZero(ctx context.Context, data *domain.{{.DomainName}}) (int64, error) {
   395  	var (
   396  		statement string
   397  		err       error
   398  		result    sql.Result
   399  		affected  int64
   400  	)
   401  	receiver.BeforeSaveHook(ctx, data)
   402  	value := reflectutils.ValueOf(data).Interface()
   403  	if _, ok := value.(domain.{{.DomainName}}); !ok {
   404  		return 0, errors.New("underlying type of data should be domain.{{.DomainName}}")
   405  	}
   406  	if statement, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "Update{{.DomainName}}NoneZero", data); err != nil {
   407  		return 0, errors.Wrap(err, caller.NewCaller().String())
   408  	}
   409  	if result, err = receiver.db.NamedExecContext(ctx, statement, data); err != nil {
   410  		return 0, errors.Wrap(err, caller.NewCaller().String())
   411  	}
   412  	if affected, err = result.RowsAffected(); err == nil {
   413  		receiver.AfterSaveHook(ctx, data, 0, affected)
   414  	}
   415  	return affected, err
   416  }
   417  
   418  func (receiver {{.DomainName}}Dao) UpdateMany(ctx context.Context, data []*domain.{{.DomainName}}, where query.Where) (int64, error) {
   419  	var (
   420  		statement string
   421  		err       error
   422  		result    sql.Result
   423  		q         string
   424  		args      []interface{}
   425  		wargs     []interface{}
   426  		w         string
   427  		affected  int64
   428  	)
   429  	receiver.BeforeUpdateManyHook(ctx, data, where)
   430  	if statement, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "Update{{.DomainName}}s", nil); err != nil {
   431  		return 0, errors.Wrap(err, caller.NewCaller().String())
   432  	}
   433  	if q, args, err = receiver.db.BindNamed(statement, data); err != nil {
   434  		return 0, errors.Wrap(err, caller.NewCaller().String())
   435  	}
   436  	w, wargs = where.Sql()
   437  	if stringutils.IsNotEmpty(w) {
   438  		q += " where " + w
   439  	}
   440  	args = append(args, wargs...)
   441  	if result, err = receiver.db.ExecContext(ctx, receiver.db.Rebind(q), args...); err != nil {
   442  		return 0, errors.Wrap(err, caller.NewCaller().String())
   443  	}
   444  	if affected, err = result.RowsAffected(); err == nil {
   445  		receiver.AfterUpdateManyHook(ctx, data, where, affected)
   446  	}
   447  	return affected, err
   448  }
   449  
   450  func (receiver {{.DomainName}}Dao) UpdateManyNoneZero(ctx context.Context, data []*domain.{{.DomainName}}, where query.Where) (int64, error) {
   451  	var (
   452  		statement string
   453  		err       error
   454  		result    sql.Result
   455  		q         string
   456  		args      []interface{}
   457  		wargs     []interface{}
   458  		w         string
   459  		affected  int64
   460  	)
   461  	receiver.BeforeUpdateManyHook(ctx, data, where)
   462  	value := reflectutils.ValueOf(data).Interface()
   463  	if _, ok := value.(domain.{{.DomainName}}); !ok {
   464  		return 0, errors.New("underlying type of data should be domain.{{.DomainName}}")
   465  	}
   466  	if statement, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "Update{{.DomainName}}sNoneZero", data); err != nil {
   467  		return 0, errors.Wrap(err, caller.NewCaller().String())
   468  	}
   469  	if q, args, err = receiver.db.BindNamed(statement, data); err != nil {
   470  		return 0, errors.Wrap(err, caller.NewCaller().String())
   471  	}
   472  	w, wargs = where.Sql()
   473  	if stringutils.IsNotEmpty(w) {
   474  		q += " where " + w
   475  	}
   476  	args = append(args, wargs...)
   477  	if result, err = receiver.db.ExecContext(ctx, receiver.db.Rebind(q), args...); err != nil {
   478  		return 0, errors.Wrap(err, caller.NewCaller().String())
   479  	}
   480  	if affected, err = result.RowsAffected(); err == nil {
   481  		receiver.AfterUpdateManyHook(ctx, data, where, affected)
   482  	}
   483  	return affected, err
   484  }
   485  
   486  func (receiver {{.DomainName}}Dao) Get(ctx context.Context, dest *domain.{{.DomainName}}, id {{.PkField.Type}}) error {
   487  	var (
   488  		statement string
   489  		err       error
   490  		{{.DomainName | ToLower}}      domain.{{.DomainName}}
   491  	)
   492  	if statement, err = templateutils.BlockMysql("{{.DomainName | ToLower}}dao.sql", {{.DomainName | ToLower}}daosql, "Get{{.DomainName}}", nil); err != nil {
   493  		return errors.Wrap(err, caller.NewCaller().String())
   494  	}
   495  	if err = receiver.db.GetContext(ctx, &{{.DomainName | ToLower}}, receiver.db.Rebind(statement), id); err != nil {
   496  		return errors.Wrap(err, caller.NewCaller().String())
   497  	}
   498  	return nil
   499  }
   500  
   501  func (receiver {{.DomainName}}Dao) SelectMany(ctx context.Context, dest *[]domain.{{.DomainName}}, where ...query.Where) error {
   502  	var (
   503  		statements []string
   504  		err       error
   505  		args       []interface{}
   506  	)
   507  	receiver.BeforeReadManyHook(ctx, nil, where...)
   508      statements = append(statements, "select * from {{.TableName}}")
   509      if len(where) > 0 {
   510          statements = append(statements, "where")
   511          for _, item := range where {
   512  			q, wargs := item.Sql()
   513  			statements = append(statements, q)
   514  			args = append(args, wargs...)
   515  		}
   516      }
   517  	sqlStr := strings.TrimSpace(strings.TrimSuffix(strings.TrimSpace(strings.Join(statements, " ")), "where"))
   518  	if err = receiver.db.SelectContext(ctx, dest, receiver.db.Rebind(sqlStr), args...); err != nil {
   519  		return errors.Wrap(err, caller.NewCaller().String())
   520  	}
   521  	return nil
   522  }
   523  
   524  func (receiver {{.DomainName}}Dao) CountMany(ctx context.Context, where ...query.Where) (int, error) {
   525  	var (
   526  		statements []string
   527  		err       error
   528  		total     int
   529  		args       []interface{}
   530  	)
   531  	receiver.BeforeReadManyHook(ctx, nil, where...)
   532  	statements = append(statements, "select count(1) from {{.TableName}}")
   533      if len(where) > 0 {
   534          statements = append(statements, "where")
   535          for _, item := range where {
   536  			q, wargs := item.Sql()
   537  			statements = append(statements, q)
   538  			args = append(args, wargs...)
   539  		}
   540      }
   541  	sqlStr := strings.TrimSpace(strings.TrimSuffix(strings.TrimSpace(strings.Join(statements, " ")), "where"))
   542  	if err = receiver.db.GetContext(ctx, &total, receiver.db.Rebind(sqlStr), args...); err != nil {
   543  		return 0, errors.Wrap(err, caller.NewCaller().String())
   544  	}
   545  	return total, nil
   546  }
   547  
   548  type {{.DomainName}}PageRet struct {
   549  	Items    []domain.{{.DomainName}}
   550  	PageNo   int
   551  	PageSize int
   552  	Total    int
   553  	HasNext  bool
   554  }
   555  
   556  func (receiver {{.DomainName}}Dao) PageMany(ctx context.Context, dest *{{.DomainName}}PageRet, page query.Page, where ...query.Where) error {
   557  	var (
   558  		statements []string
   559  		err       error
   560  		args       []interface{}
   561  	)
   562  	receiver.BeforeReadManyHook(ctx, &page, where...)
   563  	statements = append(statements, "select * from {{.TableName}}")
   564      if len(where) > 0 {
   565          statements = append(statements, "where")
   566          for _, item := range where {
   567  			q, wargs := item.Sql()
   568  			statements = append(statements, q)
   569  			args = append(args, wargs...)
   570  		}
   571      }
   572  	p, pargs := page.Sql()
   573  	statements = append(statements, p)
   574  	args = append(args, pargs...)
   575  	sqlStr := strings.TrimSpace(strings.TrimSuffix(strings.TrimSpace(strings.Join(statements, " ")), "where"))
   576  	if err = receiver.db.SelectContext(ctx, &dest.Items, receiver.db.Rebind(sqlStr), args...); err != nil {
   577  		return errors.Wrap(err, caller.NewCaller().String())
   578  	}
   579  	
   580  	args = nil
   581      statements = nil
   582  	statements = append(statements, "select count(1) from {{.TableName}}")
   583      if len(where) > 0 {
   584          statements = append(statements, "where")
   585          for _, item := range where {
   586  			q, wargs := item.Sql()
   587  			statements = append(statements, q)
   588  			args = append(args, wargs...)
   589  		}
   590      }
   591  	sqlStr = strings.TrimSpace(strings.TrimSuffix(strings.TrimSpace(strings.Join(statements, " ")), "where"))
   592  	if err = receiver.db.GetContext(ctx, &dest.Total, receiver.db.Rebind(sqlStr), args...); err != nil {
   593  		return errors.Wrap(err, caller.NewCaller().String())
   594  	}
   595  
   596  	pageNo := 1
   597  	if page.Size > 0 {
   598  		pageNo = page.Offset/page.Size + 1
   599  	}
   600  	dest.PageNo = pageNo
   601  	dest.PageSize = page.Size
   602  	if dest.PageSize > 0 && math.Ceil(float64(dest.Total)/float64(dest.PageSize)) > float64(dest.PageNo) {
   603  		dest.HasNext = true
   604  	}
   605  	return nil
   606  }
   607  
   608  func (receiver {{.DomainName}}Dao) DeleteManySoft(ctx context.Context, where query.Where) (int64, error) {
   609  	var (
   610  		err      error
   611  		result   sql.Result
   612  		w        string
   613  		args     []interface{}
   614  		affected int64
   615  	)
   616  	receiver.BeforeDeleteManyHook(ctx, nil, where)
   617  	w, args = where.Sql()
   618  	args = append([]interface{}{time.Now()}, args...)
   619  	if result, err = receiver.db.ExecContext(ctx, receiver.db.Rebind(fmt.Sprintf("update {{.TableName}} set delete_at=? where %s;", w)), args...); err != nil {
   620  		return 0, errors.Wrap(err, caller.NewCaller().String())
   621  	}
   622  	if affected, err = result.RowsAffected(); err == nil {
   623  		receiver.AfterDeleteManyHook(ctx, nil, where, affected)
   624  	}
   625  	return affected, err
   626  }`
   627  
   628  // GenDaoGo generates dao layer implementation code
   629  func GenDaoGo(domainpath string, t table.Table, folder ...string) error {
   630  	var (
   631  		err      error
   632  		dpkg     string
   633  		daopath  string
   634  		f        *os.File
   635  		funcMap  map[string]interface{}
   636  		tpl      *template.Template
   637  		pkColumn table.Column
   638  		df       string
   639  	)
   640  	df = "dao"
   641  	if len(folder) > 0 {
   642  		df = folder[0]
   643  	}
   644  	daopath = filepath.Join(filepath.Dir(domainpath), df)
   645  	_ = os.MkdirAll(daopath, os.ModePerm)
   646  
   647  	daofile := filepath.Join(daopath, strings.ToLower(t.Meta.Name)+"daoimpl.go")
   648  	if _, err = os.Stat(daofile); os.IsNotExist(err) {
   649  		f, _ = os.Create(daofile)
   650  		defer f.Close()
   651  
   652  		dpkg = astutils.GetImportPath(domainpath)
   653  		funcMap = make(map[string]interface{})
   654  		funcMap["ToLower"] = strings.ToLower
   655  		funcMap["ToSnake"] = strcase.ToSnake
   656  		tpl, _ = template.New("daoimpl.go.tmpl").Funcs(funcMap).Parse(daoimpltmpl)
   657  		for _, column := range t.Columns {
   658  			if column.Pk {
   659  				pkColumn = column
   660  				break
   661  			}
   662  		}
   663  		_ = tpl.Execute(f, struct {
   664  			DomainPackage string
   665  			DomainName    string
   666  			TableName     string
   667  			PkField       astutils.FieldMeta
   668  			PkCol         table.Column
   669  			Version       string
   670  		}{
   671  			DomainPackage: dpkg,
   672  			DomainName:    t.Meta.Name,
   673  			TableName:     t.Name,
   674  			PkField:       pkColumn.Meta,
   675  			PkCol:         pkColumn,
   676  			Version:       version.Release,
   677  		})
   678  	} else {
   679  		log.Warnf("file %s already exists", daofile)
   680  	}
   681  	return nil
   682  }