Skip to content

[do-not-merge] Don't trigger update if triple value doesn't change#739

Open
dwwoelfel wants to merge 9 commits intomainfrom
merge-into
Open

[do-not-merge] Don't trigger update if triple value doesn't change#739
dwwoelfel wants to merge 9 commits intomainfrom
merge-into

Conversation

@dwwoelfel
Copy link
Contributor

Uses merge into to prevent updating triples in insert-multi! when the value doesn't change.

We can't use this yet because we need support for returning from merge into, which was added in Postgres 17.

honey.sql doesn't have support for merge-into, so we add some bare-bones extensions to support it.

@github-actions
Copy link
Contributor

View Vercel preview at instant-www-js-merge-into-jsv.vercel.app.

@dwwoelfel dwwoelfel changed the title [do-not-merge] Don't update if value doesn't change [do-not-merge] Don't trigger update if triple value doesn't change Jan 22, 2025
Copy link
Contributor

@stopachka stopachka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool!

@dwwoelfel
Copy link
Contributor Author

dwwoelfel commented Jan 19, 2026

This is blocked for now because the statement-level trigger is not getting all of the rows when we combine a merge with an insert in the CTE.

Reported the bug to psql-bugs at https://www.postgresql.org/message-id/19380-4e293be2b4007248%40postgresql.org

Here's the repro:

CREATE TEMP TABLE merge_bug_test (id INT PRIMARY KEY, val TEXT);

-- Create trigger functions that list the IDs they see
CREATE OR REPLACE FUNCTION report_insert_rows()
RETURNS TRIGGER AS $$
BEGIN
    RAISE WARNING '[AFTER INSERT TRIGGER] Row count: %, Rows: %', (SELECT COUNT(*) FROM newrows), (SELECT COALESCE(json_agg(row_to_json(newrows))::text, 'EMPTY') FROM newrows);
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

-- Create statement-level triggers for INSERT
CREATE TRIGGER insert_trigger
    AFTER INSERT ON merge_bug_test
    REFERENCING NEW TABLE AS newrows
    FOR EACH STATEMENT
    EXECUTE FUNCTION report_insert_rows();

-- MERGE inserts rows, but INSERT CTE inserts nothing
WITH
  input_triples (id, val) AS (
    VALUES (1, 'a'), (2, 'b')
  ),
  insert_cte AS (
    INSERT INTO merge_bug_test (id, val) values (3, 'c')
    RETURNING id
  ),
  -- Insert two row with merge
  merge_cte AS (
    MERGE INTO merge_bug_test t
    USING input_triples s
    ON t.id = s.id
    WHEN NOT MATCHED THEN
        INSERT (id, val) VALUES (s.id, s.val)
    RETURNING t.id
  )
  -- Insert one row with a regular insert

SELECT id FROM merge_cte
UNION ALL
SELECT id FROM insert_cte;

DROP TABLE merge_bug_test;
DROP FUNCTION report_insert_rows;

@dwwoelfel
Copy link
Contributor Author

The fix is in the postgres codebase postgres/postgres@b4307ae

Hopefully it gets included with the next minor release on February 12, which might make it to Aurora in March.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants