refactor: update interface contract and applies some fixes
This commit is contained in:
@@ -10,7 +10,7 @@ type baseRepository[T any] struct {
|
|||||||
tableName string
|
tableName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBaseRepository[T any](db *sql.DB, tableName string) Repository[T] {
|
func NewBaseRepository[T any](db *sql.DB, tableName string) *baseRepository[T] {
|
||||||
return &baseRepository[T]{
|
return &baseRepository[T]{
|
||||||
db: db,
|
db: db,
|
||||||
tableName: tableName,
|
tableName: tableName,
|
||||||
@@ -25,14 +25,34 @@ func (r *baseRepository[T]) GetDB() *sql.DB {
|
|||||||
return r.db
|
return r.db
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *baseRepository[T]) GetAll() ([]T, error) {
|
||||||
|
query := r.BuildQuery("SELECT * FROM %s ORDER BY id DESC")
|
||||||
|
|
||||||
|
rows, err := r.db.Query(query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
entities := make([]T, 0)
|
||||||
|
rowsErr := ScanRows(rows, &entities)
|
||||||
|
|
||||||
|
if rowsErr != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return entities, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *baseRepository[T]) GetByID(id int) (*T, error) {
|
func (r *baseRepository[T]) GetByID(id int) (*T, error) {
|
||||||
var entity T
|
var entity T
|
||||||
|
|
||||||
query := r.BuildQuery("SELECT * FROM %s WHERE id = ?")
|
query := r.BuildQuery("SELECT * FROM %s WHERE id = ?")
|
||||||
err := r.db.QueryRow(
|
row := r.db.QueryRow(
|
||||||
query,
|
query,
|
||||||
id,
|
id,
|
||||||
).Scan(entity)
|
)
|
||||||
|
err := scanRow(row, &entity)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
@@ -44,33 +64,8 @@ func (r *baseRepository[T]) GetByID(id int) (*T, error) {
|
|||||||
return &entity, nil
|
return &entity, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *baseRepository[T]) GetAll() ([]T, error) {
|
|
||||||
query := r.BuildQuery("SELECT * FROM %s ORDER BY id DESC")
|
|
||||||
|
|
||||||
rows, err := r.db.Query(query)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
entities := make([]T, 0)
|
|
||||||
for rows.Next() {
|
|
||||||
var entity T
|
|
||||||
if err := rows.Scan(entity); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
entities = append(entities, entity)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = rows.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return entities, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *baseRepository[T]) Delete(id int) (int64, error) {
|
func (r *baseRepository[T]) Delete(id int) (int64, error) {
|
||||||
query := r.BuildQuery("DELETE %s WHERE id = ? LIMIT 1")
|
query := r.BuildQuery("DELETE FROM %s WHERE id = ?")
|
||||||
res, err := r.db.Exec(query, id)
|
res, err := r.db.Exec(query, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package repository
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"gitea.gabilandia.com/gabdlr/agenda-web-go/internal/models"
|
"gitea.gabilandia.com/gabdlr/agenda-web-go/internal/models"
|
||||||
)
|
)
|
||||||
@@ -10,7 +11,7 @@ type ContactRepository struct {
|
|||||||
baseRepository[models.Contact]
|
baseRepository[models.Contact]
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContactRepository(db *sql.DB) *ContactRepository {
|
func NewContactRepository(db *sql.DB) Repository[models.Contact] {
|
||||||
return &ContactRepository{
|
return &ContactRepository{
|
||||||
baseRepository[models.Contact]{
|
baseRepository[models.Contact]{
|
||||||
db: db,
|
db: db,
|
||||||
@@ -38,20 +39,45 @@ func (r *ContactRepository) Create(contact *models.Contact) (int64, error) {
|
|||||||
return id, nil
|
return id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ContactRepository) Update(contact *models.Contact) (int64, error) {
|
func (r *ContactRepository) Update(contact *models.Contact) error {
|
||||||
query := r.BuildQuery("UPDATE %s SET name = ?, company = ?, phone = ? WHERE id = ?")
|
query := r.BuildQuery("UPDATE %s SET")
|
||||||
result, err := r.db.Exec(query,
|
fieldsToUpdate := make([]string, 0, 4)
|
||||||
contact.Name, contact.Company, contact.Phone, contact.ID,
|
fields := make([]any, 0)
|
||||||
|
|
||||||
|
if contact.Name != "" {
|
||||||
|
fieldsToUpdate = append(fieldsToUpdate, "name")
|
||||||
|
fields = append(fields, &contact.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if contact.Company != "" {
|
||||||
|
fieldsToUpdate = append(fieldsToUpdate, "company")
|
||||||
|
fields = append(fields, &contact.Company)
|
||||||
|
}
|
||||||
|
|
||||||
|
if contact.Phone != "" {
|
||||||
|
fieldsToUpdate = append(fieldsToUpdate, "phone")
|
||||||
|
fields = append(fields, &contact.Phone)
|
||||||
|
}
|
||||||
|
|
||||||
|
fields = append(fields, &contact.ID)
|
||||||
|
|
||||||
|
fieldsToUpdatelen := len(fieldsToUpdate)
|
||||||
|
for i, field := range fieldsToUpdate {
|
||||||
|
query += fmt.Sprintf(" %s = ?", field)
|
||||||
|
if i != fieldsToUpdatelen-1 {
|
||||||
|
query += ","
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query += " WHERE id = ?"
|
||||||
|
|
||||||
|
_, err := r.db.Exec(query,
|
||||||
|
fields...,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
rowsAffected, err := result.RowsAffected()
|
return nil
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return rowsAffected, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package repository
|
package repository
|
||||||
|
|
||||||
type Repository[T any] interface {
|
type Repository[T any] interface {
|
||||||
BuildQuery(s string) string
|
Create(T *T) (int64, error)
|
||||||
GetByID(id int) (*T, error)
|
|
||||||
GetAll() ([]T, error)
|
|
||||||
Delete(id int) (int64, error)
|
Delete(id int) (int64, error)
|
||||||
|
GetAll() ([]T, error)
|
||||||
|
GetByID(id int) (*T, error)
|
||||||
|
Update(contact *T) error
|
||||||
}
|
}
|
||||||
|
|||||||
55
internal/repository/scanner_helper.go
Normal file
55
internal/repository/scanner_helper.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func scanRow(row *sql.Row, dest any) error {
|
||||||
|
destValue := reflect.ValueOf(dest).Elem()
|
||||||
|
fields := make([]any, destValue.NumField())
|
||||||
|
|
||||||
|
for i := 0; i < destValue.NumField(); i++ {
|
||||||
|
fields[i] = destValue.Field(i).Addr().Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
return row.Scan(fields...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanRows(rows *sql.Rows, destSlice any) error {
|
||||||
|
sliceValue := reflect.ValueOf(destSlice)
|
||||||
|
if sliceValue.Kind() != reflect.Pointer || sliceValue.Elem().Kind() != reflect.Slice {
|
||||||
|
return fmt.Errorf("destSlice must be a pointer to a slice")
|
||||||
|
}
|
||||||
|
|
||||||
|
sliceElem := sliceValue.Elem()
|
||||||
|
structType := sliceElem.Type().Elem()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
newStruct := reflect.New(structType).Elem()
|
||||||
|
|
||||||
|
fields := make([]any, newStruct.NumField())
|
||||||
|
for i := 0; i < newStruct.NumField(); i++ {
|
||||||
|
fields[i] = newStruct.Field(i).Addr().Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := rows.Scan(fields...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sliceElem.Set(reflect.Append(sliceElem, newStruct))
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetStructFieldsPtr(object any) []any {
|
||||||
|
destValue := reflect.ValueOf(object).Elem()
|
||||||
|
fields := make([]any, destValue.NumField())
|
||||||
|
|
||||||
|
for i := 0; i < destValue.NumField(); i++ {
|
||||||
|
fields[i] = destValue.Field(i).Addr().Interface()
|
||||||
|
}
|
||||||
|
return fields
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user