Skip to content

Commit

Permalink
fix(electric): Prevent creation of duplicate DDL commands in migratio…
Browse files Browse the repository at this point in the history
…n history (#439)
  • Loading branch information
magnetised authored Sep 18, 2023
1 parent 1dd9500 commit a4c5ce6
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/rich-islands-hunt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@core/electric": patch
---

VAX-1036 - fixes bugs reported by @hugodutka by preventing insertion of duplicate ddl commands in migration history
3 changes: 2 additions & 1 deletion components/electric/lib/electric/postgres/extension.ex
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ defmodule Electric.Postgres.Extension do
Migrations.Migration_20230424154425_DDLX,
Migrations.Migration_20230512000000_conflict_resolution_triggers,
Migrations.Migration_20230605141256_ElectrifyFunction,
Migrations.Migration_20230715000000_UtilitiesTable
Migrations.Migration_20230715000000_UtilitiesTable,
Migrations.Migration_20230918115714_DDLCommandUniqueConstraint
]
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
defmodule Electric.Postgres.Extension.Migrations.Migration_20230918115714_DDLCommandUniqueConstraint do
alias Electric.Postgres.Extension

@behaviour Extension.Migration

@txid_type "xid8"

@impl true
def version, do: 2023_09_18_11_57_14

@impl true
def up(schema) do
ddl_table = Extension.ddl_table()

[
"""
ALTER TABLE #{ddl_table}
ADD CONSTRAINT ddl_table_unique_migrations
UNIQUE (txid, txts ,version, query);
""",
"""
CREATE OR REPLACE FUNCTION #{schema}.create_active_migration(
_txid #{@txid_type},
_txts timestamptz,
_version text,
_query text DEFAULT NULL
) RETURNS int8 AS
$function$
DECLARE
trid int8;
BEGIN
IF _query IS NULL THEN
_query := current_query();
END IF;
RAISE NOTICE 'capture migration: % => %', _version, _query;
INSERT INTO #{ddl_table} (txid, txts, version, query) VALUES
(_txid, _txts, _version, _query)
ON CONFLICT ON CONSTRAINT ddl_table_unique_migrations DO NOTHING
RETURNING id INTO trid;
RETURN trid;
END;
$function$
LANGUAGE PLPGSQL;
"""
]
end

@impl true
def down(_), do: []
end
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,24 @@ defmodule Electric.Postgres.Extension.DDLCaptureTest do

assert {:error, _error} = :epgsql.squery(conn, sql4)
end

test_tx "ADD column; CREATE INDEX only adds a single migration", fn conn ->
sql1 =
"CREATE TABLE public.buttercup (id text PRIMARY KEY, value text);"

sql2 = "CALL electric.electrify('public.buttercup')"

for sql <- [sql1, sql2] do
{:ok, _cols, _rows} = :epgsql.squery(conn, sql)
end

assert {:ok, [_]} = Extension.ddl_history(conn)

sql3 =
"ALTER TABLE public.buttercup ADD COLUMN amount int4; CREATE INDEX buttercup_amount_idx ON public.buttercup (amount); "

[{:ok, _, _}, {:ok, _, _}] = :epgsql.squery(conn, sql3)

assert {:ok, [_, {_, _, _, ^sql3}]} = Extension.ddl_history(conn)
end
end

0 comments on commit a4c5ce6

Please sign in to comment.