diff --git a/cmd/setup/10.go b/cmd/setup/10.go index fd8683f49d..1661ccf7dd 100644 --- a/cmd/setup/10.go +++ b/cmd/setup/10.go @@ -13,11 +13,11 @@ import ( ) var ( - //go:embed 10_create_temp_table.sql + //go:embed 10/10_create_temp_table.sql correctCreationDate10CreateTable string - //go:embed 10_fill_table.sql + //go:embed 10/10_fill_table.sql correctCreationDate10FillTable string - //go:embed 10_update.sql + //go:embed 10/10_update.sql correctCreationDate10Update string ) diff --git a/cmd/setup/10_create_temp_table.sql b/cmd/setup/10/10_create_temp_table.sql similarity index 100% rename from cmd/setup/10_create_temp_table.sql rename to cmd/setup/10/10_create_temp_table.sql diff --git a/cmd/setup/10_fill_table.sql b/cmd/setup/10/10_fill_table.sql similarity index 100% rename from cmd/setup/10_fill_table.sql rename to cmd/setup/10/10_fill_table.sql diff --git a/cmd/setup/10_update.sql b/cmd/setup/10/10_update.sql similarity index 100% rename from cmd/setup/10_update.sql rename to cmd/setup/10/10_update.sql diff --git a/cmd/setup/11.go b/cmd/setup/11.go new file mode 100644 index 0000000000..4745c71994 --- /dev/null +++ b/cmd/setup/11.go @@ -0,0 +1,32 @@ +package setup + +import ( + "context" + _ "embed" + + "github.com/zitadel/zitadel/internal/database" +) + +var ( + //go:embed 11.sql + addEventCreatedAt string +) + +type AddEventCreatedAt struct { + step10 *CorrectCreationDate + dbClient *database.DB +} + +func (mig *AddEventCreatedAt) Execute(ctx context.Context) error { + // execute step 10 again because events created after the first execution of step 10 + // could still have the wrong ordering of sequences and creation date + if err := mig.step10.Execute(ctx); err != nil { + return err + } + _, err := mig.dbClient.ExecContext(ctx, addEventCreatedAt) + return err +} + +func (mig *AddEventCreatedAt) String() string { + return "11_event_created_at" +} diff --git a/cmd/setup/11.sql b/cmd/setup/11.sql new file mode 100644 index 0000000000..bb62b5f9b2 --- /dev/null +++ b/cmd/setup/11.sql @@ -0,0 +1,15 @@ +BEGIN; +-- create table with empty created_at +ALTER TABLE eventstore.events ADD COLUMN created_at TIMESTAMPTZ DEFAULT NULL; +COMMIT; + +BEGIN; +-- backfill created_at +UPDATE eventstore.events SET created_at = creation_date WHERE created_at IS NULL; +COMMIT; + +BEGIN; +-- set column rules +ALTER TABLE eventstore.events ALTER COLUMN created_at SET DEFAULT clock_timestamp(); +ALTER TABLE eventstore.events ALTER COLUMN created_at SET NOT NULL; +COMMIT; \ No newline at end of file diff --git a/cmd/setup/config.go b/cmd/setup/config.go index dc75d54048..5e9819e4c7 100644 --- a/cmd/setup/config.go +++ b/cmd/setup/config.go @@ -66,6 +66,7 @@ type Steps struct { s8AuthTokens *AuthTokenIndexes s9EventstoreIndexes2 *EventstoreIndexesNew CorrectCreationDate *CorrectCreationDate + s11AddEventCreatedAt *AddEventCreatedAt } type encryptionKeyConfig struct { diff --git a/cmd/setup/setup.go b/cmd/setup/setup.go index 918f08dc2d..59b7c5d6ba 100644 --- a/cmd/setup/setup.go +++ b/cmd/setup/setup.go @@ -91,6 +91,7 @@ func Setup(config *Config, steps *Steps, masterKey string) { steps.s8AuthTokens = &AuthTokenIndexes{dbClient: dbClient} steps.s9EventstoreIndexes2 = New09(dbClient) steps.CorrectCreationDate.dbClient = dbClient + steps.s11AddEventCreatedAt = &AddEventCreatedAt{dbClient: dbClient, step10: steps.CorrectCreationDate} err = projection.Create(ctx, dbClient, eventstoreClient, config.Projections, nil, nil) logging.OnError(err).Fatal("unable to start projections") @@ -128,6 +129,8 @@ func Setup(config *Config, steps *Steps, masterKey string) { logging.OnError(err).Fatal("unable to migrate step 9") err = migration.Migrate(ctx, eventstoreClient, steps.CorrectCreationDate) logging.OnError(err).Fatal("unable to migrate step 10") + err = migration.Migrate(ctx, eventstoreClient, steps.s11AddEventCreatedAt) + logging.OnError(err).Fatal("unable to migrate step 11") for _, repeatableStep := range repeatableSteps { err = migration.Migrate(ctx, eventstoreClient, repeatableStep)