diff --git a/sqlxx/batch/create.go b/sqlxx/batch/create.go index 801dcbdd..3b106eb5 100644 --- a/sqlxx/batch/create.go +++ b/sqlxx/batch/create.go @@ -126,7 +126,9 @@ func buildInsertQueryValues[T any](dialect string, mapper *reflectx.Mapper, colu case "updated_at": field.Set(reflect.ValueOf(now)) case "id": - if field.Interface().(uuid.UUID) != uuid.Nil { + if value, ok := field.Interface().(uuid.UUID); ok && value != uuid.Nil { + break // breaks switch, not for + } else if value, ok := field.Interface().(string); ok && len(value) > 0 { break // breaks switch, not for } else if dialect == dbal.DriverCockroachDB { // This is a special case: @@ -165,9 +167,21 @@ func buildInsertQueryValues[T any](dialect string, mapper *reflectx.Mapper, colu return values, nil } +type createOptions struct { + onConflict string +} + +type option func(*createOptions) + +func OnConflictDoNothing() func(*createOptions) { + return func(o *createOptions) { + o.onConflict = "ON CONFLICT DO NOTHING" + } +} + // Create batch-inserts the given models into the database using a single INSERT statement. // The models are either all created or none. -func Create[T any](ctx context.Context, p *TracerConnection, models []*T) (err error) { +func Create[T any](ctx context.Context, p *TracerConnection, models []*T, opts ...option) (err error) { ctx, span := p.Tracer.Tracer().Start(ctx, "persistence.sql.batch.Create") defer otelx.End(span, &err) @@ -175,6 +189,11 @@ func Create[T any](ctx context.Context, p *TracerConnection, models []*T) (err e return nil } + options := &createOptions{} + for _, opt := range opts { + opt(options) + } + var v T model := pop.NewModel(v, ctx) @@ -197,10 +216,11 @@ func Create[T any](ctx context.Context, p *TracerConnection, models []*T) (err e } query := conn.Dialect.TranslateSQL(fmt.Sprintf( - "INSERT INTO %s (%s) VALUES\n%s\n%s", + "INSERT INTO %s (%s) VALUES\n%s\n%s\n%s", queryArgs.TableName, queryArgs.ColumnsDecl, queryArgs.Placeholders, + options.onConflict, returningClause, ))