feat(functions): enhanced function with RAW SQL
Some checks failed
Gitea Build Check / Build (push) Failing after 4m59s

Signed-off-by: SoXX <soxx@fenpa.ws>
This commit is contained in:
SoXX 2024-06-26 16:12:10 +02:00
parent a9a21581bd
commit e29cea6e3c
6 changed files with 23 additions and 51 deletions

View File

@ -10,9 +10,7 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
) )
func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error { func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL) error {
var source models.Source
if anthrovePostID == "" { if anthrovePostID == "" {
return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty} return &otterError.EntityValidationFailed{Reason: otterError.AnthroveUserIDIsEmpty}
} }
@ -25,26 +23,16 @@ func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthr
return &otterError.EntityValidationFailed{Reason: "sourceDomain cannot be empty"} return &otterError.EntityValidationFailed{Reason: "sourceDomain cannot be empty"}
} }
// Find the source result := db.WithContext(ctx).Exec(`INSERT INTO "PostReference" (post_id, source_id, url) SELECT $1, source.id, $2 FROM "Source" AS source WHERE domain = $3;`, anthrovePostID, postURL, sourceDomain)
result := db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&source)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return &otterError.NoDataFound{} return &otterError.NoDataFound{}
} }
return result.Error if errors.Is(result.Error, gorm.ErrCheckConstraintViolated) {
}
// Establish the relationship
result = db.WithContext(ctx).Create(models.PostReference{
PostID: string(anthrovePostID),
SourceID: string(source.ID),
URL: string(sourceDomain),
})
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
return &otterError.EntityAlreadyExists{} return &otterError.EntityAlreadyExists{}
} }
return result.Error return result.Error
} }

View File

@ -56,46 +56,29 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs
return &otterError.EntityValidationFailed{Reason: "accountUsername cannot be empty"} return &otterError.EntityValidationFailed{Reason: "accountUsername cannot be empty"}
} }
err := CreateUser(ctx, db, anthroveUserID) result := db.WithContext(ctx).Exec(`WITH userObj AS (
if err != nil { INSERT INTO "User" (id)
return err VALUES ($1)
} ON CONFLICT (id) DO NOTHING
)
INSERT INTO "UserSource" (user_id, source_id, account_username, account_id)
SELECT $2, source.id, $3, $4
FROM "Source" AS source
WHERE source.id = $5;`, anthroveUserID, anthroveUserID, accountUsername, accountId, sourceID)
source := models.Source{
BaseModel: models.BaseModel[models.AnthroveSourceID]{ID: sourceID},
}
result := db.WithContext(ctx).Where(&source).First(&source)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
return &otterError.NoDataFound{} return &otterError.EntityAlreadyExists{}
} }
return result.Error return result.Error
} }
userSource := models.UserSource{
User: models.User{BaseModel: models.BaseModel[models.AnthroveUserID]{ID: anthroveUserID}},
SourceID: string(source.ID),
AccountUsername: accountUsername,
AccountID: accountId,
UserID: string(anthroveUserID),
}
result = db.WithContext(ctx).FirstOrCreate(&userSource)
if result.Error != nil {
return errors.Join(result.Error, &otterError.NoRelationCreated{})
}
if result.RowsAffected == 0 {
return &otterError.NoDataWritten{}
}
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"anthrove_user_id": anthroveUserID, "anthrove_user_id": anthroveUserID,
"source_id": sourceID, "source_id": sourceID,
"account_username": accountUsername, "account_username": accountUsername,
"account_id": accountId, "account_id": accountId,
}).Trace("database: created user-source relationship") }).Info("database: created user-source relationship")
return nil return nil
} }

View File

@ -23,7 +23,7 @@ type OtterSpace interface {
CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error
// CreateReferenceBetweenPostAndSource links a post with a source. // CreateReferenceBetweenPostAndSource links a post with a source.
CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL) error
// CreateReferenceBetweenUserAndPost links a user with a post. // CreateReferenceBetweenUserAndPost links a user with a post.
CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error

View File

@ -95,7 +95,7 @@ CREATE TABLE "UserSource"
account_username TEXT, account_username TEXT,
account_id TEXT, account_id TEXT,
PRIMARY KEY (user_id, source_id), PRIMARY KEY (user_id, source_id),
UNIQUE (account_username, account_id) UNIQUE (source_id, account_username, account_id)
); );
CREATE TABLE "post_tags" CREATE TABLE "post_tags"

View File

@ -47,7 +47,7 @@ func (p *postgresqlConnection) Connect(_ context.Context, config models.Database
dbLogger := logger2.New(log2.New(os.Stdout, "\r\n", log2.LstdFlags), logger2.Config{ dbLogger := logger2.New(log2.New(os.Stdout, "\r\n", log2.LstdFlags), logger2.Config{
SlowThreshold: 200 * time.Millisecond, SlowThreshold: 200 * time.Millisecond,
LogLevel: logger2.Warn, LogLevel: logger2.Info,
IgnoreRecordNotFoundError: true, IgnoreRecordNotFoundError: true,
Colorful: true, Colorful: true,
}) })
@ -88,8 +88,8 @@ func (p *postgresqlConnection) CreateTagAndReferenceToPost(ctx context.Context,
return postgres.CreateTagAndReferenceToPost(ctx, p.db, anthrovePostID, anthroveTag) return postgres.CreateTagAndReferenceToPost(ctx, p.db, anthrovePostID, anthroveTag)
} }
func (p *postgresqlConnection) CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error { func (p *postgresqlConnection) CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL) error {
return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain) return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain, postURL)
} }
func (p *postgresqlConnection) CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error { func (p *postgresqlConnection) CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error {

View File

@ -4,6 +4,7 @@ type AnthroveUserID string
type AnthrovePostID string type AnthrovePostID string
type AnthroveSourceID string type AnthroveSourceID string
type AnthroveSourceDomain string type AnthroveSourceDomain string
type AnthrovePostURL string
type Rating string type Rating string
type TagType string type TagType string