Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(electric): Fix serialization of composite PKs in the fk_chain_touch logical message #1198

Merged
merged 3 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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]