pg_file_repository.go 5.8 KB
package repository

import (
	"fmt"
	"time"

	"github.com/go-pg/pg/v10"
	"github.com/linmadan/egglib-go/persistent/pg/sqlbuilder"
	pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/pg/models"
	"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/pg/transform"
)

type FileRepository struct {
	transactionContext *pgTransaction.TransactionContext
}

func (repository *FileRepository) Save(file *domain.File) (*domain.File, error) {
	sqlBuildFields := []string{
		"file_id",
		"file_type",
		"file_info",
		"source_file_id",
		//"operator",
		"created_at",
		"updated_at",
		"deleted_at",
		"version",
		"context",
		"file_from",
		"app_key",
	}
	insertFieldsSnippet := sqlbuilder.SqlFieldsSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "file_id", "deleted_at"))
	insertPlaceHoldersSnippet := sqlbuilder.SqlPlaceHoldersSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "file_id", "deleted_at"))
	returningFieldsSnippet := sqlbuilder.SqlFieldsSnippet(sqlBuildFields)
	updateFields := sqlbuilder.RemoveSqlFields(sqlBuildFields, "file_id", "deleted_at")
	updateFieldsSnippet := sqlbuilder.SqlUpdateFieldsSnippet(updateFields)
	tx := repository.transactionContext.PgTx
	if file.Identify() == nil {
		if _, err := tx.QueryOne(
			pg.Scan(
				&file.FileId,
				&file.FileType,
				&file.FileInfo,
				&file.SourceFileId,
				//&file.Operator,
				&file.CreatedAt,
				&file.UpdatedAt,
				&file.DeletedAt,
				&file.Version,
				&file.Context,
				&file.FileFrom,
				&file.AppKey,
			),
			fmt.Sprintf("INSERT INTO metadata.files (%s) VALUES (%s) RETURNING %s", insertFieldsSnippet, insertPlaceHoldersSnippet, returningFieldsSnippet),
			file.FileType,
			file.FileInfo,
			file.SourceFileId,
			//file.Operator,
			file.CreatedAt,
			file.UpdatedAt,
			file.Version,
			file.Context,
			file.FileFrom,
			file.AppKey,
		); err != nil {
			return file, err
		}
	} else {
		oldVersion := file.Version
		file.Version += 1
		if _, err := tx.QueryOne(
			pg.Scan(
				&file.FileId,
				&file.FileType,
				&file.FileInfo,
				&file.SourceFileId,
				//&file.Operator,
				&file.CreatedAt,
				&file.UpdatedAt,
				&file.DeletedAt,
				&file.Version,
				&file.Context,
				&file.FileFrom,
				&file.AppKey,
			),
			fmt.Sprintf("UPDATE metadata.files SET %s WHERE file_id=? and version=? RETURNING %s", updateFieldsSnippet, returningFieldsSnippet),
			file.FileType,
			file.FileInfo,
			file.SourceFileId,
			//file.Operator,
			file.CreatedAt,
			file.UpdatedAt,
			file.Version,
			file.Context,
			file.FileFrom,
			file.AppKey,
			file.Identify(),
			oldVersion,
		); err != nil {
			return file, err
		}
	}
	return file, nil
}
func (repository *FileRepository) Remove(file *domain.File) (*domain.File, error) {
	tx := repository.transactionContext.PgTx
	fileModel := new(models.File)
	fileModel.FileId = file.Identify().(int)
	if _, err := tx.Model(fileModel).WherePK().Delete(); err != nil {
		return file, err
	}
	return file, nil
}
func (repository *FileRepository) FindOne(queryOptions map[string]interface{}) (*domain.File, error) {
	tx := repository.transactionContext.PgTx
	fileModel := new(models.File)
	query := sqlbuilder.BuildQuery(tx.Model(fileModel), queryOptions)
	query.SetWhereByQueryOption("file.file_id = ?", "fileId")
	WhereContext(query, queryOptions)
	query.SetWhereByQueryOption("file_info->>'name' = ?", "fileName")
	query.SetWhereByQueryOption("file_type = ?", "fileType")
	query.SetWhereByQueryOption("app_key = ?", "appKey")
	if err := query.First(); err != nil {
		if err.Error() == "pg: no rows in result set" {
			return nil, domain.ErrorNotFound
		} else {
			return nil, err
		}
	}
	if fileModel.FileId == 0 {
		return nil, nil
	} else {
		return transform.TransformToFileDomainModelFromPgModels(fileModel)
	}
}
func (repository *FileRepository) Find(queryOptions map[string]interface{}) (int64, []*domain.File, error) {
	tx := repository.transactionContext.PgTx
	var fileModels []*models.File
	files := make([]*domain.File, 0)
	query := sqlbuilder.BuildQuery(tx.Model(&fileModels), queryOptions)
	WhereContext(query, queryOptions)
	query.SetWhereByQueryOption("file_id > ?", "lastId")
	query.SetWhereByQueryOption("file_type = ?", "fileType")
	query.SetWhereByQueryOption(fmt.Sprintf("file_info->>'name' like '%%%v%%'", queryOptions["fileName"]), "fileName")

	query.SetWhereByQueryOption("source_file_id = ?", "sourceFileId")
	if v, ok := queryOptions["notInFileIds"]; ok && len(v.([]int)) > 0 {
		query.Where(`file_id not in (?)`, pg.In(v.([]int)))
	}
	if v, ok := queryOptions["inAppKeys"]; ok && len(v.([]string)) > 0 {
		query.Where(`app_key in (?)`, pg.In(v.([]string)))
	}
	if v, ok := queryOptions["updatedAtBegin"]; ok && !v.(time.Time).IsZero() {
		query.Where(`updated_at>?`, v.(time.Time))
	}
	if v, ok := queryOptions["updatedAtEnd"]; ok && !v.(time.Time).IsZero() {
		query.Where(`updated_at<?`, v.(time.Time))
	}
	if v, ok := queryOptions["equalFileName"]; ok && len(v.(string)) > 0 {
		query.Where(`file_info->>'name' = ?`, v)
	}
	query.SetOffsetAndLimit(20)
	query.SetOrderDirect("updated_at", "DESC")
	if count, err := query.SelectAndCount(); err != nil {
		return 0, files, err
	} else {
		for _, fileModel := range fileModels {
			if file, err := transform.TransformToFileDomainModelFromPgModels(fileModel); err != nil {
				return 0, files, err
			} else {
				files = append(files, file)
			}
		}
		return int64(count), files, nil
	}
}
func NewFileRepository(transactionContext *pgTransaction.TransactionContext) (*FileRepository, error) {
	if transactionContext == nil {
		return nil, fmt.Errorf("transactionContext参数不能为nil")
	} else {
		return &FileRepository{
			transactionContext: transactionContext,
		}, nil
	}
}