Skip to content

Commit

Permalink
Distinguish inferred migrations by timestamp for statements within th…
Browse files Browse the repository at this point in the history
…e same transaction (#362)

Set `created_at` and `updated_at` explicitly when inserting inferred
migrations into the migrations table.

When two statements are run in a transaction, we need to explicitly
insert `statement_timestamp()` into the `created_at` and `updated_at`
fields rather than relying on the table default of `current_timestamp`.

`current_timestamp` is the same for all statements in a transaction,
which causes problems when ordering statements by `created_at`.


Fixes #361
  • Loading branch information
andrew-farries committed Jun 25, 2024
1 parent 84ef318 commit 7cef8b1
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 2 deletions.
6 changes: 4 additions & 2 deletions pkg/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ BEGIN
-- Someone did a schema change without pgroll, include it in the history
SELECT INTO migration_id pg_catalog.format('sql_%%s',pg_catalog.substr(pg_catalog.md5(pg_catalog.random()::text), 0, 15));
INSERT INTO %[1]s.migrations (schema, name, migration, resulting_schema, done, parent, migration_type)
INSERT INTO %[1]s.migrations (schema, name, migration, resulting_schema, done, parent, migration_type, created_at, updated_at)
VALUES (
schemaname,
migration_id,
Expand All @@ -328,7 +328,9 @@ BEGIN
%[1]s.read_schema(schemaname),
true,
%[1]s.latest_version(schemaname),
'inferred'
'inferred',
statement_timestamp(),
statement_timestamp()
);
END;
$$;
Expand Down
51 changes: 51 additions & 0 deletions pkg/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import (
"strings"
"sync"
"testing"
"time"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/xataio/pgroll/pkg/migrations"
"github.com/xataio/pgroll/pkg/schema"
"github.com/xataio/pgroll/pkg/state"
Expand Down Expand Up @@ -272,6 +274,55 @@ func TestInferredMigration(t *testing.T) {
})
}

func TestInferredMigrationsInTransactionHaveDifferentTimestamps(t *testing.T) {
ctx := context.Background()

testutils.WithStateAndConnectionToContainer(t, func(state *state.State, db *sql.DB) {
// Start a transaction
tx, err := db.BeginTx(ctx, nil)
require.NoError(t, err)
defer tx.Rollback()

// Create two tables in the transaction
_, err = tx.ExecContext(ctx, "CREATE TABLE table1 (id int)")
require.NoError(t, err)

_, err = tx.ExecContext(ctx, "CREATE TABLE table2 (id int)")
require.NoError(t, err)

// Commit the transaction
tx.Commit()

// Read the migrations from the migrations table
rows, err := db.QueryContext(ctx,
fmt.Sprintf("SELECT name, created_at, updated_at FROM %s.migrations ORDER BY created_at ASC", state.Schema()))
if err != nil {
t.Fatal(err)
}
defer rows.Close()

type m struct {
name string
createdAt time.Time
updatedAt time.Time
}
var migrations []m

for rows.Next() {
var migration m
if err := rows.Scan(&migration.name, &migration.createdAt, &migration.updatedAt); err != nil {
t.Fatal(err)
}

migrations = append(migrations, migration)
}

// Ensure that the two inferred migrations have different timestamps
assert.Equal(t, 2, len(migrations), "unexpected number of migrations")
assert.NotEqual(t, migrations[0].createdAt, migrations[1].createdAt, "migrations have the same timestamp")
})
}

func TestPgRollInitializationInANonDefaultSchema(t *testing.T) {
t.Parallel()

Expand Down

0 comments on commit 7cef8b1

Please sign in to comment.