2024-06-04 21:14:02 +00:00
|
|
|
package postgres
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2024-06-25 19:55:43 +00:00
|
|
|
"errors"
|
2024-07-03 07:52:39 +00:00
|
|
|
|
2024-07-02 20:35:42 +00:00
|
|
|
"gorm.io/gorm/clause"
|
2024-06-26 07:10:04 +00:00
|
|
|
|
2024-07-02 08:11:42 +00:00
|
|
|
otterError "git.dragse.it/anthrove/otter-space-sdk/v2/pkg/error"
|
|
|
|
"git.dragse.it/anthrove/otter-space-sdk/v2/pkg/models"
|
2024-06-04 21:14:02 +00:00
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
)
|
|
|
|
|
2024-07-01 20:06:36 +00:00
|
|
|
func CreateTag(ctx context.Context, db *gorm.DB, tagName models.AnthroveTagName, tagType models.TagType) error {
|
2024-06-20 12:54:06 +00:00
|
|
|
|
2024-07-01 20:06:36 +00:00
|
|
|
if tagName == "" {
|
2024-07-01 20:15:43 +00:00
|
|
|
return &otterError.EntityValidationFailed{Reason: "tagName cannot be empty"}
|
2024-06-25 19:55:43 +00:00
|
|
|
}
|
|
|
|
|
2024-07-01 20:06:36 +00:00
|
|
|
if tagType == "" {
|
2024-07-01 20:15:43 +00:00
|
|
|
return &otterError.EntityValidationFailed{Reason: "tagType cannot be empty"}
|
2024-07-01 20:06:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
result := db.WithContext(ctx).Create(&models.Tag{Name: string(tagName), Type: tagType})
|
2024-06-25 19:55:43 +00:00
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
2024-06-26 08:02:54 +00:00
|
|
|
return &otterError.EntityAlreadyExists{}
|
2024-06-25 19:55:43 +00:00
|
|
|
}
|
|
|
|
return result.Error
|
|
|
|
}
|
2024-06-20 12:54:06 +00:00
|
|
|
|
2024-06-25 19:55:43 +00:00
|
|
|
if result.RowsAffected == 0 {
|
2024-06-26 08:02:54 +00:00
|
|
|
return &otterError.NoDataWritten{}
|
2024-06-20 12:54:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
2024-07-01 20:06:36 +00:00
|
|
|
"tag_name": tagName,
|
|
|
|
"tag_type": tagType,
|
2024-06-20 12:54:06 +00:00
|
|
|
}).Trace("database: created tag node")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-07-02 20:35:42 +00:00
|
|
|
func CreateTagInBatchAndUpdate(ctx context.Context, db *gorm.DB, tags []models.Tag, batchSize int) error {
|
|
|
|
if len(tags) == 0 {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "tags cannot be empty"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if tags == nil {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "tags cannot be nil"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if batchSize == 0 {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "batch size cannot be zero"}
|
|
|
|
}
|
|
|
|
|
|
|
|
result := db.WithContext(ctx).
|
|
|
|
Clauses(clause.OnConflict{
|
|
|
|
Columns: []clause.Column{{Name: "name"}},
|
|
|
|
DoUpdates: clause.AssignmentColumns([]string{"tag_type"}),
|
|
|
|
}).CreateInBatches(tags, batchSize)
|
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
|
|
|
return &otterError.EntityAlreadyExists{}
|
|
|
|
}
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
if result.RowsAffected == 0 {
|
|
|
|
return &otterError.NoDataWritten{}
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tag_size": len(tags),
|
|
|
|
"batch_size": batchSize,
|
|
|
|
}).Trace("database: created tag node")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-07-01 20:15:43 +00:00
|
|
|
func DeleteTag(ctx context.Context, db *gorm.DB, tagName models.AnthroveTagName) error {
|
|
|
|
|
|
|
|
if tagName == "" {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "tagName cannot be empty"}
|
|
|
|
}
|
|
|
|
|
|
|
|
result := db.WithContext(ctx).Delete(&models.Tag{Name: string(tagName)})
|
|
|
|
|
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
|
|
return &otterError.NoDataFound{}
|
|
|
|
}
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tag_name": tagName,
|
|
|
|
}).Trace("database: deleted tag")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-07-01 20:29:37 +00:00
|
|
|
func GetAllTagByTagsType(ctx context.Context, db *gorm.DB, tagType models.TagType) ([]models.Tag, error) {
|
|
|
|
var tags []models.Tag
|
|
|
|
|
|
|
|
if tagType == "" {
|
|
|
|
return nil, &otterError.EntityValidationFailed{Reason: "tagType cannot be empty"}
|
|
|
|
}
|
|
|
|
|
2024-07-01 20:40:53 +00:00
|
|
|
result := db.WithContext(ctx).Model(&models.Tag{}).Where("tag_type = ?", tagType).Scan(&tags)
|
2024-07-01 20:29:37 +00:00
|
|
|
|
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
|
|
return nil, &otterError.NoDataFound{}
|
|
|
|
}
|
|
|
|
return nil, result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tags_length": len(tags),
|
|
|
|
}).Trace("database: got tag")
|
|
|
|
|
|
|
|
return tags, nil
|
|
|
|
}
|
|
|
|
|
2024-06-25 19:55:43 +00:00
|
|
|
func CreateTagAndReferenceToPost(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, tag *models.Tag) error {
|
2024-06-04 21:14:02 +00:00
|
|
|
|
2024-06-25 19:55:43 +00:00
|
|
|
if anthrovePostID == "" {
|
2024-06-26 08:02:54 +00:00
|
|
|
return &otterError.EntityValidationFailed{Reason: "anthrovePostID cannot be empty"}
|
2024-06-25 19:55:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(anthrovePostID) != 25 {
|
2024-06-26 08:02:54 +00:00
|
|
|
return &otterError.EntityValidationFailed{Reason: "anthrovePostID needs to be 25 characters long"}
|
2024-06-20 12:54:06 +00:00
|
|
|
}
|
|
|
|
|
2024-06-22 23:18:23 +00:00
|
|
|
if tag == nil {
|
2024-06-26 08:02:54 +00:00
|
|
|
return &otterError.EntityValidationFailed{Reason: "Tag is nil"}
|
2024-06-22 23:18:23 +00:00
|
|
|
}
|
|
|
|
|
2024-06-22 20:06:36 +00:00
|
|
|
pgPost := models.Post{
|
2024-06-25 07:09:18 +00:00
|
|
|
BaseModel: models.BaseModel[models.AnthrovePostID]{
|
2024-06-25 19:55:43 +00:00
|
|
|
ID: anthrovePostID,
|
2024-06-04 21:14:02 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2024-06-19 21:32:42 +00:00
|
|
|
err := db.WithContext(ctx).Model(&pgPost).Association("Tags").Append(tag)
|
2024-06-04 21:14:02 +00:00
|
|
|
if err != nil {
|
2024-06-25 19:55:43 +00:00
|
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
2024-06-26 08:02:54 +00:00
|
|
|
return &otterError.NoDataFound{}
|
2024-06-25 19:55:43 +00:00
|
|
|
}
|
2024-06-26 08:02:54 +00:00
|
|
|
return errors.Join(err, &otterError.NoRelationCreated{})
|
2024-06-04 21:14:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
2024-06-25 19:55:43 +00:00
|
|
|
"anthrove_post_id": anthrovePostID,
|
2024-06-04 21:14:02 +00:00
|
|
|
"tag_name": tag.Name,
|
|
|
|
"tag_type": tag.Type,
|
|
|
|
}).Trace("database: created tag node")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2024-06-14 11:05:07 +00:00
|
|
|
|
2024-06-22 21:25:06 +00:00
|
|
|
func GetTags(ctx context.Context, db *gorm.DB) ([]models.Tag, error) {
|
2024-06-22 20:06:36 +00:00
|
|
|
var tags []models.Tag
|
2024-06-25 19:55:43 +00:00
|
|
|
|
2024-06-14 11:05:07 +00:00
|
|
|
result := db.WithContext(ctx).Find(&tags)
|
|
|
|
if result.Error != nil {
|
2024-06-26 07:10:04 +00:00
|
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
2024-06-26 08:02:54 +00:00
|
|
|
return nil, &otterError.NoDataFound{}
|
2024-06-25 19:55:43 +00:00
|
|
|
}
|
2024-06-14 11:05:07 +00:00
|
|
|
return nil, result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tag_amount": len(tags),
|
|
|
|
}).Trace("database: got tags")
|
|
|
|
|
|
|
|
return tags, nil
|
|
|
|
}
|
2024-06-28 13:13:40 +00:00
|
|
|
|
|
|
|
func CreateTagAlias(ctx context.Context, db *gorm.DB, tagAliasName models.AnthroveTagAliasName, tagID models.AnthroveTagID) error {
|
|
|
|
|
|
|
|
if tagAliasName == "" {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "tagAliasName cannot be empty"}
|
|
|
|
}
|
|
|
|
if tagID == "" {
|
2024-07-01 12:14:17 +00:00
|
|
|
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty}
|
2024-06-28 13:13:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
result := db.WithContext(ctx).Create(&models.TagAlias{
|
|
|
|
Name: string(tagAliasName),
|
|
|
|
TagID: string(tagID),
|
|
|
|
})
|
|
|
|
|
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
|
|
|
return &otterError.EntityAlreadyExists{}
|
|
|
|
}
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tag_alias_name": tagAliasName,
|
|
|
|
"tag_alias_tag_id": tagID,
|
|
|
|
}).Trace("database: created tagAlias")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-07-02 20:35:42 +00:00
|
|
|
func CreateTagAliasInBatch(ctx context.Context, db *gorm.DB, tagAliases []models.TagAlias, batchSize int) error {
|
|
|
|
if len(tagAliases) == 0 {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "tagAliases cannot be empty"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if tagAliases == nil {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "tagAliases cannot be nil"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if batchSize == 0 {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "batch size cannot be zero"}
|
|
|
|
}
|
|
|
|
|
2024-07-03 07:52:39 +00:00
|
|
|
result := db.WithContext(ctx).Clauses(clause.OnConflict{
|
|
|
|
Columns: []clause.Column{{Name: "name"}},
|
|
|
|
DoNothing: true,
|
|
|
|
}).CreateInBatches(tagAliases, batchSize)
|
2024-07-02 20:35:42 +00:00
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
|
|
|
return &otterError.EntityAlreadyExists{}
|
|
|
|
}
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
if result.RowsAffected == 0 {
|
|
|
|
return &otterError.NoDataWritten{}
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tag_size": len(tagAliases),
|
|
|
|
"batch_size": batchSize,
|
|
|
|
}).Trace("database: created tag node")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-06-28 13:13:40 +00:00
|
|
|
func GetAllTagAlias(ctx context.Context, db *gorm.DB) ([]models.TagAlias, error) {
|
|
|
|
var tagAliases []models.TagAlias
|
|
|
|
|
|
|
|
result := db.WithContext(ctx).Find(&tagAliases)
|
|
|
|
|
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
|
|
return nil, &otterError.NoDataFound{}
|
|
|
|
}
|
|
|
|
return nil, result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tag_alias_length": len(tagAliases),
|
|
|
|
}).Trace("database: created tagAlias")
|
|
|
|
|
|
|
|
return tagAliases, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetAllTagAliasByTag(ctx context.Context, db *gorm.DB, tagID models.AnthroveTagID) ([]models.TagAlias, error) {
|
|
|
|
var tagAliases []models.TagAlias
|
|
|
|
|
|
|
|
if tagID == "" {
|
2024-07-01 12:14:17 +00:00
|
|
|
return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty}
|
2024-06-28 13:13:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
result := db.WithContext(ctx).Where("tag_id = ?", tagID).Find(&tagAliases)
|
|
|
|
|
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
|
|
return nil, &otterError.NoDataFound{}
|
|
|
|
}
|
|
|
|
return nil, result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tag_alias_length": len(tagAliases),
|
|
|
|
"tag_alias_tag_id": tagID,
|
|
|
|
}).Trace("database: get specific tagAlias")
|
|
|
|
|
|
|
|
return tagAliases, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func DeleteTagAlias(ctx context.Context, db *gorm.DB, tagAliasName models.AnthroveTagAliasName) error {
|
|
|
|
|
|
|
|
if tagAliasName == "" {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "tagAliasName cannot be empty"}
|
|
|
|
}
|
|
|
|
|
|
|
|
result := db.WithContext(ctx).Delete(&models.TagAlias{Name: string(tagAliasName)})
|
|
|
|
|
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
|
|
return &otterError.NoDataFound{}
|
|
|
|
}
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tag_alias_name": tagAliasName,
|
|
|
|
}).Trace("database: deleted tagAlias")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2024-06-28 20:39:12 +00:00
|
|
|
|
|
|
|
func CreateTagGroup(ctx context.Context, db *gorm.DB, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) error {
|
|
|
|
|
|
|
|
if tagGroupName == "" {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "tagGroupName cannot be empty"}
|
|
|
|
}
|
|
|
|
if tagID == "" {
|
2024-07-01 12:14:17 +00:00
|
|
|
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty}
|
2024-06-28 20:39:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
result := db.WithContext(ctx).Create(&models.TagGroup{
|
|
|
|
Name: string(tagGroupName),
|
|
|
|
TagID: string(tagID),
|
|
|
|
})
|
|
|
|
|
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
|
|
|
return &otterError.EntityAlreadyExists{}
|
|
|
|
}
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tag_group_name": tagGroupName,
|
|
|
|
"tag_group_tag_id": tagID,
|
|
|
|
}).Trace("database: created tagGroup")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-07-02 20:35:42 +00:00
|
|
|
func CreateTagGroupInBatch(ctx context.Context, db *gorm.DB, tagGroups []models.TagGroup, batchSize int) error {
|
|
|
|
if len(tagGroups) == 0 {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "tagAliases cannot be empty"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if tagGroups == nil {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "tagAliases cannot be nil"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if batchSize == 0 {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "batch size cannot be zero"}
|
|
|
|
}
|
|
|
|
|
|
|
|
result := db.WithContext(ctx).CreateInBatches(tagGroups, batchSize)
|
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
|
|
|
|
return &otterError.EntityAlreadyExists{}
|
|
|
|
}
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
if result.RowsAffected == 0 {
|
|
|
|
return &otterError.NoDataWritten{}
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tag_size": len(tagGroups),
|
|
|
|
"batch_size": batchSize,
|
|
|
|
}).Trace("database: created tag node")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-06-28 20:39:12 +00:00
|
|
|
func GetAllTagGroup(ctx context.Context, db *gorm.DB) ([]models.TagGroup, error) {
|
|
|
|
var tagGroups []models.TagGroup
|
|
|
|
|
|
|
|
result := db.WithContext(ctx).Find(&tagGroups)
|
|
|
|
|
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
|
|
return nil, &otterError.NoDataFound{}
|
|
|
|
}
|
|
|
|
return nil, result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tag_alias_length": len(tagGroups),
|
|
|
|
}).Trace("database: created tagGroup")
|
|
|
|
|
|
|
|
return tagGroups, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetAllTagGroupByTag(ctx context.Context, db *gorm.DB, tagID models.AnthroveTagID) ([]models.TagGroup, error) {
|
|
|
|
var tagGroups []models.TagGroup
|
|
|
|
|
|
|
|
if tagID == "" {
|
2024-07-01 12:14:17 +00:00
|
|
|
return nil, &otterError.EntityValidationFailed{Reason: otterError.AnthroveTagIDEmpty}
|
2024-06-28 20:39:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
result := db.WithContext(ctx).Where("tag_id = ?", tagID).Find(&tagGroups)
|
|
|
|
|
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
|
|
return nil, &otterError.NoDataFound{}
|
|
|
|
}
|
|
|
|
return nil, result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tag_alias_length": len(tagGroups),
|
|
|
|
"tag_alias_tag_id": tagID,
|
|
|
|
}).Trace("database: get specific tagGroup")
|
|
|
|
|
|
|
|
return tagGroups, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func DeleteTagGroup(ctx context.Context, db *gorm.DB, tagGroupName models.AnthroveTagGroupName) error {
|
|
|
|
|
|
|
|
if tagGroupName == "" {
|
|
|
|
return &otterError.EntityValidationFailed{Reason: "tagGroupName cannot be empty"}
|
|
|
|
}
|
|
|
|
|
|
|
|
result := db.WithContext(ctx).Delete(&models.TagGroup{Name: string(tagGroupName)})
|
|
|
|
|
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
|
|
return &otterError.NoDataFound{}
|
|
|
|
}
|
|
|
|
return result.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"tag_alias_name": tagGroupName,
|
|
|
|
}).Trace("database: deleted tagAlias")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|