github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/repo/unsafe_create.go (about) 1 package repo 2 3 import ( 4 "context" 5 "fmt" 6 "strings" 7 8 "github.com/kyma-incubator/compass/components/director/pkg/log" 9 10 "github.com/kyma-incubator/compass/components/director/pkg/apperrors" 11 "github.com/kyma-incubator/compass/components/director/pkg/persistence" 12 "github.com/kyma-incubator/compass/components/director/pkg/resource" 13 ) 14 15 // UnsafeCreator is used to create new entities in case they do not exist. 16 // In case they do already exist, no action is taken, hence the provided entity ID is not guaranteed to match the ID in the Compass DB. 17 type UnsafeCreator interface { 18 UnsafeCreate(ctx context.Context, dbEntity interface{}) error 19 } 20 21 type unsafeCreator struct { 22 tableName string 23 resourceType resource.Type 24 insertColumns []string 25 conflictingColumns []string 26 } 27 28 // NewUnsafeCreator returns a new Creator which supports creation with conflicts. 29 func NewUnsafeCreator(resourceType resource.Type, tableName string, insertColumns []string, conflictingColumns []string) UnsafeCreator { 30 return &unsafeCreator{ 31 resourceType: resourceType, 32 tableName: tableName, 33 insertColumns: insertColumns, 34 conflictingColumns: conflictingColumns, 35 } 36 } 37 38 // UnsafeCreate adds a new entity in the Compass DB in case it does not exist. If it already exists, no action is taken. 39 // This creator is not suitable for resources that have m2m tenant relation as it does not maintain tenant accesses. 40 // Use it for global scoped resources or resources with embedded tenant_id only. 41 func (u *unsafeCreator) UnsafeCreate(ctx context.Context, dbEntity interface{}) error { 42 if dbEntity == nil { 43 return apperrors.NewInternalError("item cannot be nil") 44 } 45 46 persist, err := persistence.FromCtx(ctx) 47 if err != nil { 48 return err 49 } 50 51 values := make([]string, 0, len(u.insertColumns)) 52 for _, c := range u.insertColumns { 53 values = append(values, fmt.Sprintf(":%s", c)) 54 } 55 56 insertStmt := fmt.Sprintf("INSERT INTO %s ( %s ) VALUES ( %s )", u.tableName, strings.Join(u.insertColumns, ", "), strings.Join(values, ", ")) 57 stmt := fmt.Sprintf("%s ON CONFLICT ( %s ) DO NOTHING", insertStmt, strings.Join(u.conflictingColumns, ", ")) 58 59 log.C(ctx).Debugf("Executing DB query: %s", stmt) 60 _, err = persist.NamedExecContext(ctx, stmt, dbEntity) 61 return persistence.MapSQLError(ctx, err, u.resourceType, resource.Upsert, "while unsafe inserting row to '%s' table", u.tableName) 62 }