Skip to content

Instantly share code, notes, and snippets.

@ptflp
Created January 15, 2024 08:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ptflp/bb3cf825f6c701d02a1b93c58c65b734 to your computer and use it in GitHub Desktop.
Save ptflp/bb3cf825f6c701d02a1b93c58c65b734 to your computer and use it in GitHub Desktop.
task3.1.1.4
package dao
import (
"context"
"database/sql"
"fmt"
"golang-course/test/dao/tabler"
"reflect"
"strings"
sq "github.com/Masterminds/squirrel"
"github.com/jmoiron/sqlx"
)
//go:generate mockgen -source=./sql_adapter.go -destination=../../mock/adapter_mock.go -package=mock
type IfaceDAO interface {
BuildSelect(tableName string, condition Condition, fields ...string) (string, []interface{}, error)
Create(ctx context.Context, entity tabler.Tabler, opts ...interface{}) error
List(ctx context.Context, dest interface{}, table tabler.Tabler, condition Condition, opts ...interface{}) error
Update(ctx context.Context, entity tabler.Tabler, condition Condition, opts ...interface{}) error
}
type Condition struct {
Equal map[string]interface{}
NotEqual map[string]interface{}
Order []*Order
LimitOffset *LimitOffset
ForUpdate bool
Upsert bool
}
type Order struct {
Field string
Asc bool
}
type LimitOffset struct {
Offset int64
Limit int64
}
type DAO struct {
db *sqlx.DB
sqlBuilder sq.StatementBuilderType
}
func NewDAO(db *sqlx.DB) IfaceDAO {
builder := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)
return &DAO{db: db, sqlBuilder: builder}
}
func (d *DAO) BuildSelect(tableName string, condition Condition, fields ...string) (string, []interface{}, error) {
}
func filterByTag(tag string, tvalue string) func(fields *[]reflect.StructField) {
return tabler.FilterByTags(map[string]func(value string) bool{
tag: func(value string) bool {
return strings.Contains(value, tvalue)
},
})
}
func (d *DAO) Create(ctx context.Context, entity tabler.Tabler, opts ...interface{}) error {
}
func (d *DAO) List(ctx context.Context, dest interface{}, table tabler.Tabler, condition Condition, opts ...interface{}) error {
}
func (d *DAO) Update(ctx context.Context, entity tabler.Tabler, condition Condition, opts ...interface{}) error {
}
package main
import (
"context"
"database/sql"
"github.com/brianvoe/gofakeit/v6"
"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-sqlite3"
"golang-course/test/dao/dao"
"golang-course/test/dao/migrator"
)
type User struct {
ID int `db:"id" db_type:"SERIAL PRIMARY KEY"`
FirstName string `db:"first_name" db_type:"VARCHAR(100)"`
LastName string `db:"last_name" db_type:"VARCHAR(100)"`
Username string `db:"username" db_type:"VARCHAR(100)"`
Email string `db:"email" db_type:"VARCHAR(100)"`
Address string `db:"address" db_type:"VARCHAR(100)"`
Status int `db:"status" db_type:"INT"`
DeletedAt string `db:"deleted_at" db_type:"VARCHAR(100)"`
}
func (u User) TableName() string {
return "users"
}
func main() {
db, err := sql.Open("sqlite3", "mydao.db")
if err != nil {
panic(err)
}
dbx := sqlx.NewDb(db, "sqlite3")
d := dao.NewDAO(dbx)
var generator migrator.SQLiteGenerator
m := migrator.NewMigrator(db, &generator)
err = m.Migrate(&User{})
if err != nil {
panic(err)
}
for i := 0; i < 100; i++ {
user := GenerateFakeUser()
err = d.Create(context.Background(), &user)
}
users := make([]User, 1)
err = d.List(context.Background(), &users, &users[0], dao.Condition{
LimitOffset: &dao.LimitOffset{
Offset: 0,
Limit: 3,
},
Equal: map[string]interface{}{
"first_name": "Vilma",
},
})
if err != nil {
panic(err)
}
for _, user := range users {
println(user.FirstName)
}
}
func GenerateFakeUser() User {
return User{
ID: gofakeit.Number(1000, 9999),
FirstName: gofakeit.FirstName(),
LastName: gofakeit.LastName(),
Email: gofakeit.Email(),
}
}
package migrator
import (
"database/sql"
"golang-course/test/dao/tabler"
"golang.org/x/sync/errgroup"
)
type Migratorer interface {
Migrate(tables ...func(tabler tabler.Tabler)) error
}
type Migrator struct {
db *sql.DB
sqlGenerator SQLGenerator
}
func NewMigrator(db *sql.DB, sqlGenerator SQLGenerator) *Migrator {
return &Migrator{
db: db,
sqlGenerator: sqlGenerator,
}
}
func (m *Migrator) Migrate(tables ...tabler.Tabler) error {
var errGroup errgroup.Group
for _, table := range tables {
createSQL := m.sqlGenerator.CreateTableSQL(table)
errGroup.Go(func() error {
_, err := m.db.Exec(createSQL)
return err
})
}
return errGroup.Wait()
}
package migrator
import (
"fmt"
"golang-course/test/dao/tabler"
"reflect"
"strings"
)
type SQLGenerator interface {
CreateTableSQL(table tabler.Tabler) string
}
type SQLiteGenerator struct{}
func (sg *SQLiteGenerator) CreateTableSQL(table tabler.Tabler) string {
}
package tabler
import (
"reflect"
)
type Tabler interface {
TableName() string
}
type StructInfo struct {
Fields []string
Pointers []interface{}
}
func GetStructInfo(u interface{}, args ...func(*[]reflect.StructField)) StructInfo {
val := reflect.ValueOf(u).Elem()
var structFields []reflect.StructField
for i := 0; i < val.NumField(); i++ {
structFields = append(structFields, val.Type().Field(i))
}
for i := range args {
if args[i] == nil {
continue
}
args[i](&structFields)
}
var res StructInfo
for _, field := range structFields {
valueField := val.FieldByName(field.Name)
res.Pointers = append(res.Pointers, valueField.Addr().Interface())
res.Fields = append(res.Fields, field.Tag.Get("db"))
}
return res
}
func FilterByFields(fields ...int) func(fields *[]reflect.StructField) {
return func(fs *[]reflect.StructField) {
}
}
func FilterByTags(tags map[string]func(value string) bool) func(fields *[]reflect.StructField) {
return func(fields *[]reflect.StructField) {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment