github.com/angryronald/go-kit@v0.0.0-20240505173814-ff2bd9c79dbf/generic/repository/sql/generic.repository.immutable.go (about)

     1  package sql
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"gorm.io/gorm"
     8  
     9  	"github.com/google/uuid"
    10  
    11  	"github.com/angryronald/go-kit/appcontext"
    12  	"github.com/angryronald/go-kit/cast"
    13  	"github.com/angryronald/go-kit/generic/repository"
    14  )
    15  
    16  type ImmutableGenericRepository struct {
    17  	db *gorm.DB
    18  }
    19  
    20  func (r *ImmutableGenericRepository) FindAll(ctx context.Context, params map[string]interface{}, conditionalOperations []repository.ConditionalOperation, relationalOperations []repository.RelationalOperation, page int, limit int, result interface{}) (interface{}, error) {
    21  	if !repository.IsValidOperations(conditionalOperations, relationalOperations, params) {
    22  		return nil, repository.ErrBadParameters
    23  	}
    24  
    25  	where := "true"
    26  	i := 0
    27  	args := []interface{}{}
    28  	if len(params) > 0 {
    29  		where = fmt.Sprintf(`%s %s`, where, repository.AND)
    30  	}
    31  	for k, v := range params {
    32  		switch conditionalOperations[i] {
    33  		case repository.IN:
    34  			encapsulation := ""
    35  			if !repository.AreAllNumbers(v.([]interface{})) {
    36  				encapsulation = "'"
    37  			}
    38  			where = fmt.Sprintf(`%s %s %s (%s)`, where, k, conditionalOperations[i], repository.StringJoin(v.([]interface{}), encapsulation))
    39  
    40  			break
    41  
    42  		case repository.ILIKE, repository.LIKE:
    43  			where = fmt.Sprintf(`%s %s %s ?`, where, k, conditionalOperations[i])
    44  			args = append(args, fmt.Sprintf("%%%s%%", v))
    45  			break
    46  
    47  		default:
    48  			where = fmt.Sprintf(`%s %s %s ?`, where, k, conditionalOperations[i])
    49  			args = append(args, v)
    50  		}
    51  
    52  		if i < len(relationalOperations) {
    53  			where = fmt.Sprintf(`%s %s`, where, relationalOperations[i])
    54  		}
    55  		i++
    56  	}
    57  
    58  	order := fmt.Sprintf(`"created_at" %s`, repository.DESC)
    59  
    60  	if page == 0 && limit == 0 {
    61  		if err := r.db.Where(
    62  			where,
    63  			args...,
    64  		).Order(order).Find(&result).Error; err != nil {
    65  			return nil, err
    66  		}
    67  
    68  		return result, nil
    69  	}
    70  
    71  	if err := r.db.Where(
    72  		where,
    73  		args...,
    74  	).Order(order).
    75  		Offset((page - 1) * limit).
    76  		Limit(limit).
    77  		Find(&result).Error; err != nil {
    78  		return nil, err
    79  	}
    80  
    81  	return result, nil
    82  }
    83  
    84  func (r *ImmutableGenericRepository) FindOne(ctx context.Context, key string, value interface{}, result interface{}) (interface{}, error) {
    85  	where := fmt.Sprintf(`%s %s ?`, key, repository.EQUAL_WITH)
    86  	args := []interface{}{
    87  		value,
    88  	}
    89  	if err := r.db.Where(
    90  		where,
    91  		args,
    92  	).First(&result).Error; err != nil {
    93  		return nil, err
    94  	}
    95  
    96  	return result, nil
    97  }
    98  
    99  func (r *ImmutableGenericRepository) FindByID(ctx context.Context, id uuid.UUID, result interface{}) (interface{}, error) {
   100  	where := fmt.Sprintf(`"id" %s ?`, repository.EQUAL_WITH)
   101  	args := []interface{}{
   102  		id,
   103  	}
   104  	if err := r.db.Where(
   105  		where,
   106  		args,
   107  	).First(&result).Error; err != nil {
   108  		return nil, err
   109  	}
   110  
   111  	return result, nil
   112  }
   113  
   114  func (r *ImmutableGenericRepository) Insert(ctx context.Context, data interface{}) (interface{}, error) {
   115  	newID, err := uuid.NewRandom()
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	if err = repository.UpdatePropertyValue(data, "ID", newID); err != nil {
   120  		return nil, err
   121  	}
   122  	if err = repository.UpdatePropertyValue(data, "CreatedBy", appcontext.UserID(ctx)); err != nil {
   123  		return nil, err
   124  	}
   125  
   126  	if err := r.db.Create(data).Error; err != nil {
   127  		if err == gorm.ErrDuplicatedKey {
   128  			return nil, repository.ErrConflict
   129  		}
   130  		return nil, err
   131  	}
   132  	return data, nil
   133  }
   134  
   135  func (r *ImmutableGenericRepository) BulkInsert(ctx context.Context, data interface{}) (interface{}, error) {
   136  	tx := r.db.Begin()
   137  	defer func() {
   138  		if r := recover(); r != nil {
   139  			tx.Rollback()
   140  		}
   141  	}()
   142  
   143  	copyOfData, err := repository.CopySliceOfPointers(data)
   144  	if err != nil {
   145  		return nil, err
   146  	}
   147  
   148  	dataInArray := cast.StructPointerArrayToInterfacePointerArray(copyOfData)
   149  	for i := 0; i < len(dataInArray); i++ {
   150  		newID, err := uuid.NewRandom()
   151  		if err != nil {
   152  			return nil, err
   153  		}
   154  
   155  		if err = repository.UpdatePropertyValue(dataInArray[i], "ID", newID); err != nil {
   156  			return nil, err
   157  		}
   158  		if err = repository.UpdatePropertyValue(dataInArray[i], "CreatedBy", appcontext.UserID(ctx)); err != nil {
   159  			return nil, err
   160  		}
   161  	}
   162  
   163  	dataInArrayWithIdentity, err := repository.CopySliceOfPointersWithIdentitySeparated(copyOfData, dataInArray)
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  
   168  	if err := r.db.Create(dataInArrayWithIdentity).Error; err != nil {
   169  		tx.Rollback()
   170  		if err == gorm.ErrDuplicatedKey {
   171  			return nil, repository.ErrConflict
   172  		}
   173  		return nil, err
   174  	}
   175  	return dataInArrayWithIdentity, tx.Commit().Error
   176  }
   177  
   178  func (r *ImmutableGenericRepository) Query(ctx context.Context, query string, params []interface{}, result interface{}) (interface{}, error) {
   179  	if err := r.db.Raw(query, params...).Find(&result).Error; err != nil {
   180  		return nil, err
   181  	}
   182  
   183  	return result, nil
   184  }
   185  
   186  func NewImmutableRepository(db *gorm.DB) repository.ImmutableGenericRepositoryInterface {
   187  	return &ImmutableGenericRepository{
   188  		db: db,
   189  	}
   190  }