From e29cea6e3cb8a768186984ba0aa736f8f5a0f04e Mon Sep 17 00:00:00 2001 From: SoXX Date: Wed, 26 Jun 2024 16:12:10 +0200 Subject: [PATCH] feat(functions): enhanced function with RAW SQL Signed-off-by: SoXX --- internal/postgres/relationships.go | 22 +++------- internal/postgres/user.go | 41 ++++++------------- pkg/database/database.go | 2 +- .../migrations/001_inital_database.sql | 2 +- pkg/database/postgres.go | 6 +-- pkg/models/const.go | 1 + 6 files changed, 23 insertions(+), 51 deletions(-) diff --git a/internal/postgres/relationships.go b/internal/postgres/relationships.go index 8aa1079..5e8e8e6 100644 --- a/internal/postgres/relationships.go +++ b/internal/postgres/relationships.go @@ -10,9 +10,7 @@ import ( "gorm.io/gorm" ) -func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error { - var source models.Source - +func CreateReferenceBetweenPostAndSource(ctx context.Context, db *gorm.DB, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain, postURL models.AnthrovePostURL) error { if anthrovePostID == "" { 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"} } - // Find the source - result := db.WithContext(ctx).Where("domain = ?", sourceDomain).First(&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) + if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { return &otterError.NoDataFound{} } - return result.Error - } - - // 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) { + if errors.Is(result.Error, gorm.ErrCheckConstraintViolated) { return &otterError.EntityAlreadyExists{} } + return result.Error } diff --git a/internal/postgres/user.go b/internal/postgres/user.go index 9346cb5..404c32c 100644 --- a/internal/postgres/user.go +++ b/internal/postgres/user.go @@ -56,46 +56,29 @@ func CreateUserWithRelationToSource(ctx context.Context, db *gorm.DB, anthroveUs return &otterError.EntityValidationFailed{Reason: "accountUsername cannot be empty"} } - err := CreateUser(ctx, db, anthroveUserID) - if err != nil { - return err - } + result := db.WithContext(ctx).Exec(`WITH userObj AS ( + INSERT INTO "User" (id) + 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 errors.Is(result.Error, gorm.ErrRecordNotFound) { - return &otterError.NoDataFound{} + if errors.Is(result.Error, gorm.ErrDuplicatedKey) { + return &otterError.EntityAlreadyExists{} } 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{ "anthrove_user_id": anthroveUserID, "source_id": sourceID, "account_username": accountUsername, "account_id": accountId, - }).Trace("database: created user-source relationship") + }).Info("database: created user-source relationship") return nil } diff --git a/pkg/database/database.go b/pkg/database/database.go index 10d203a..f8be8ef 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -23,7 +23,7 @@ type OtterSpace interface { CreateTagAndReferenceToPost(ctx context.Context, anthrovePostID models.AnthrovePostID, anthroveTag *models.Tag) error // 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(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error diff --git a/pkg/database/migrations/001_inital_database.sql b/pkg/database/migrations/001_inital_database.sql index e6758e3..d580538 100644 --- a/pkg/database/migrations/001_inital_database.sql +++ b/pkg/database/migrations/001_inital_database.sql @@ -95,7 +95,7 @@ CREATE TABLE "UserSource" account_username TEXT, account_id TEXT, PRIMARY KEY (user_id, source_id), - UNIQUE (account_username, account_id) + UNIQUE (source_id, account_username, account_id) ); CREATE TABLE "post_tags" diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 4245c9b..676d308 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -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{ SlowThreshold: 200 * time.Millisecond, - LogLevel: logger2.Warn, + LogLevel: logger2.Info, IgnoreRecordNotFoundError: true, Colorful: true, }) @@ -88,8 +88,8 @@ func (p *postgresqlConnection) CreateTagAndReferenceToPost(ctx context.Context, return postgres.CreateTagAndReferenceToPost(ctx, p.db, anthrovePostID, anthroveTag) } -func (p *postgresqlConnection) CreateReferenceBetweenPostAndSource(ctx context.Context, anthrovePostID models.AnthrovePostID, sourceDomain models.AnthroveSourceDomain) error { - return postgres.CreateReferenceBetweenPostAndSource(ctx, p.db, anthrovePostID, sourceDomain) +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, postURL) } func (p *postgresqlConnection) CreateReferenceBetweenUserAndPost(ctx context.Context, anthroveUserID models.AnthroveUserID, anthrovePostID models.AnthrovePostID) error { diff --git a/pkg/models/const.go b/pkg/models/const.go index 5b0e59a..f95434f 100644 --- a/pkg/models/const.go +++ b/pkg/models/const.go @@ -4,6 +4,7 @@ type AnthroveUserID string type AnthrovePostID string type AnthroveSourceID string type AnthroveSourceDomain string +type AnthrovePostURL string type Rating string type TagType string