Skip to content

Commit

Permalink
fix(electric): Fix serialization of composite PKs in the fk_chain_tou…
Browse files Browse the repository at this point in the history
…ch logical message (#1198)

Fixes #1195.
  • Loading branch information
alco committed May 6, 2024
1 parent 3e158dc commit 2be5f17
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/sweet-hornets-sparkle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@core/electric": patch
---

Fix serialization of composite PKs in Electric's internal SQL code.
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ CREATE OR REPLACE FUNCTION <%= schema() %>.install_function__send_self_trigger(s
DECLARE
function_name TEXT := 'send_self_trigger___' || schema_name || '__' || table_name;
referenced_calls TEXT := '';
pk_serialization TEXT := 'ARRAY[' || <%= schema() %>.format_every_and_join(primary_key_list, '__this_row.%I') || ']::text';
pk_serialization TEXT := 'ARRAY[' || <%= schema() %>.format_every_and_join(primary_key_list, '__this_row.%I::text') || ']';
fk_info RECORD;
BEGIN
FOR fk_info IN SELECT * FROM <%= schema() %>.list_foreign_keys(schema_name, table_name)
Expand All @@ -113,7 +113,7 @@ CREATE OR REPLACE FUNCTION <%= schema() %>.install_function__send_self_trigger(s

FOR __this_row IN SELECT * FROM new_table
LOOP
__serialized_pk := %5$s;
__serialized_pk := %5$s::text;
CONTINUE WHEN <%= schema() %>.__tx_is_row_already_touched('%2$s', '%3$s', __serialized_pk);

PERFORM <%= schema() %>.__tx_store_touched_row('%2$s', '%3$s', __serialized_pk);
Expand Down
50 changes: 50 additions & 0 deletions e2e/tests/01.07_composite_primary_key_in_referenced_relation.lux
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[doc Correct processing of composite PKs in referenced records]
[include _shared.luxinc]

# This is a regression test for https://github.com/electric-sql/electric/issues/1195.
#
# In the version of the code before it was fixed the following error had been occurring:
#
# electric=# INSERT INTO project_memberships (id, sub_id, project_id) VALUES ('00000000-0000-0000-0000-000000000001', '.', 'p1');
# ERROR: ARRAY types uuid and text cannot be matched
# LINE 1: __serialized_pk := ARRAY[__this_row.id, __this_row.sub_id]::...
# ^
# QUERY: __serialized_pk := ARRAY[__this_row.id, __this_row.sub_id]::text
# CONTEXT: PL/pgSQL function electric.send_self_trigger___public__project_memberships() line 9 at assignment

[invoke setup]

[global project_id=p1]
[global member_id=00000000-0000-0000-0000-000000000001]

[shell proxy_1]
[local sql=
"""
CREATE TABLE projects (
id TEXT PRIMARY KEY
);
CREATE TABLE project_memberships (
id UUID NOT NULL,
sub_id TEXT NOT NULL,
project_id TEXT NOT NULL REFERENCES projects (id),
PRIMARY KEY (id, sub_id)
);

ALTER TABLE projects ENABLE ELECTRIC;
ALTER TABLE project_memberships ENABLE ELECTRIC;

INSERT INTO projects VALUES ('$project_id');
"""]
[invoke migrate_pg 001 $sql]

[shell pg_1]
!INSERT INTO project_memberships (id, sub_id, project_id) VALUES ('$member_id', '.', '$project_id');
??INSERT 0 1

[shell electric]
??%Electric.Replication.Changes.NewRecord{relation: {"public", "project_memberships"}, \
record: %{"id" => "$member_id", "project_id" => "$project_id", "sub_id" => "."}, \
tags: ["postgres_1@

[cleanup]
[invoke teardown]

0 comments on commit 2be5f17

Please sign in to comment.