From 4bc9f0124f68157f4e1d8f3d2a82775844edd01c Mon Sep 17 00:00:00 2001 From: tianzhou Date: Fri, 27 Feb 2026 19:59:26 -0800 Subject: [PATCH] test: add regression tests for IMMUTABLE plpgsql functions returning user-defined types (#329) Add two test cases to prevent regression of perpetual plan drift for IMMUTABLE plpgsql functions that return user-defined types (e.g. custom enums). The issue was reported against v1.6.2 but is already fixed in the current codebase by earlier normalization improvements. Test cases: - issue_329_immutable_udt_return: IMMUTABLE function returning custom enum - issue_329_immutable_udt_generated_col: same function used in GENERATED ALWAYS AS STORED column Fixes #329 Co-Authored-By: Claude Opus 4.6 --- .../diff.sql | 0 .../new.sql | 18 ++++++++++++++++++ .../old.sql | 18 ++++++++++++++++++ .../plan.json | 9 +++++++++ .../plan.sql | 0 .../plan.txt | 1 + .../issue_329_immutable_udt_return/diff.sql | 0 .../issue_329_immutable_udt_return/new.sql | 13 +++++++++++++ .../issue_329_immutable_udt_return/old.sql | 13 +++++++++++++ .../issue_329_immutable_udt_return/plan.json | 9 +++++++++ .../issue_329_immutable_udt_return/plan.sql | 0 .../issue_329_immutable_udt_return/plan.txt | 1 + 12 files changed, 82 insertions(+) create mode 100644 testdata/diff/create_function/issue_329_immutable_udt_generated_col/diff.sql create mode 100644 testdata/diff/create_function/issue_329_immutable_udt_generated_col/new.sql create mode 100644 testdata/diff/create_function/issue_329_immutable_udt_generated_col/old.sql create mode 100644 testdata/diff/create_function/issue_329_immutable_udt_generated_col/plan.json create mode 100644 testdata/diff/create_function/issue_329_immutable_udt_generated_col/plan.sql create mode 100644 testdata/diff/create_function/issue_329_immutable_udt_generated_col/plan.txt create mode 100644 testdata/diff/create_function/issue_329_immutable_udt_return/diff.sql create mode 100644 testdata/diff/create_function/issue_329_immutable_udt_return/new.sql create mode 100644 testdata/diff/create_function/issue_329_immutable_udt_return/old.sql create mode 100644 testdata/diff/create_function/issue_329_immutable_udt_return/plan.json create mode 100644 testdata/diff/create_function/issue_329_immutable_udt_return/plan.sql create mode 100644 testdata/diff/create_function/issue_329_immutable_udt_return/plan.txt diff --git a/testdata/diff/create_function/issue_329_immutable_udt_generated_col/diff.sql b/testdata/diff/create_function/issue_329_immutable_udt_generated_col/diff.sql new file mode 100644 index 00000000..e69de29b diff --git a/testdata/diff/create_function/issue_329_immutable_udt_generated_col/new.sql b/testdata/diff/create_function/issue_329_immutable_udt_generated_col/new.sql new file mode 100644 index 00000000..72e5154b --- /dev/null +++ b/testdata/diff/create_function/issue_329_immutable_udt_generated_col/new.sql @@ -0,0 +1,18 @@ +CREATE TYPE item_status AS ENUM ('pending', 'active', 'done'); + +CREATE FUNCTION compute_status(x integer) +RETURNS item_status +LANGUAGE plpgsql +IMMUTABLE +AS $$ +BEGIN + IF x > 0 THEN RETURN 'active'::item_status; END IF; + IF x < 0 THEN RETURN 'done'::item_status; END IF; + RETURN 'pending'::item_status; +END; +$$; + +CREATE TABLE demo ( + id integer PRIMARY KEY, + status item_status GENERATED ALWAYS AS (compute_status(id)) STORED +); diff --git a/testdata/diff/create_function/issue_329_immutable_udt_generated_col/old.sql b/testdata/diff/create_function/issue_329_immutable_udt_generated_col/old.sql new file mode 100644 index 00000000..72e5154b --- /dev/null +++ b/testdata/diff/create_function/issue_329_immutable_udt_generated_col/old.sql @@ -0,0 +1,18 @@ +CREATE TYPE item_status AS ENUM ('pending', 'active', 'done'); + +CREATE FUNCTION compute_status(x integer) +RETURNS item_status +LANGUAGE plpgsql +IMMUTABLE +AS $$ +BEGIN + IF x > 0 THEN RETURN 'active'::item_status; END IF; + IF x < 0 THEN RETURN 'done'::item_status; END IF; + RETURN 'pending'::item_status; +END; +$$; + +CREATE TABLE demo ( + id integer PRIMARY KEY, + status item_status GENERATED ALWAYS AS (compute_status(id)) STORED +); diff --git a/testdata/diff/create_function/issue_329_immutable_udt_generated_col/plan.json b/testdata/diff/create_function/issue_329_immutable_udt_generated_col/plan.json new file mode 100644 index 00000000..8a6194d7 --- /dev/null +++ b/testdata/diff/create_function/issue_329_immutable_udt_generated_col/plan.json @@ -0,0 +1,9 @@ +{ + "version": "1.0.0", + "pgschema_version": "1.7.2", + "created_at": "1970-01-01T00:00:00Z", + "source_fingerprint": { + "hash": "86da603163a64eef536f98f999b32298bf87e18b41f76f684fba15e74d7f493a" + }, + "groups": null +} diff --git a/testdata/diff/create_function/issue_329_immutable_udt_generated_col/plan.sql b/testdata/diff/create_function/issue_329_immutable_udt_generated_col/plan.sql new file mode 100644 index 00000000..e69de29b diff --git a/testdata/diff/create_function/issue_329_immutable_udt_generated_col/plan.txt b/testdata/diff/create_function/issue_329_immutable_udt_generated_col/plan.txt new file mode 100644 index 00000000..241994af --- /dev/null +++ b/testdata/diff/create_function/issue_329_immutable_udt_generated_col/plan.txt @@ -0,0 +1 @@ +No changes detected. diff --git a/testdata/diff/create_function/issue_329_immutable_udt_return/diff.sql b/testdata/diff/create_function/issue_329_immutable_udt_return/diff.sql new file mode 100644 index 00000000..e69de29b diff --git a/testdata/diff/create_function/issue_329_immutable_udt_return/new.sql b/testdata/diff/create_function/issue_329_immutable_udt_return/new.sql new file mode 100644 index 00000000..db777570 --- /dev/null +++ b/testdata/diff/create_function/issue_329_immutable_udt_return/new.sql @@ -0,0 +1,13 @@ +CREATE TYPE item_status AS ENUM ('pending', 'active', 'done'); + +CREATE FUNCTION compute_status(x integer) +RETURNS item_status +LANGUAGE plpgsql +IMMUTABLE +AS $$ +BEGIN + IF x > 0 THEN RETURN 'active'::item_status; END IF; + IF x < 0 THEN RETURN 'done'::item_status; END IF; + RETURN 'pending'::item_status; +END; +$$; diff --git a/testdata/diff/create_function/issue_329_immutable_udt_return/old.sql b/testdata/diff/create_function/issue_329_immutable_udt_return/old.sql new file mode 100644 index 00000000..db777570 --- /dev/null +++ b/testdata/diff/create_function/issue_329_immutable_udt_return/old.sql @@ -0,0 +1,13 @@ +CREATE TYPE item_status AS ENUM ('pending', 'active', 'done'); + +CREATE FUNCTION compute_status(x integer) +RETURNS item_status +LANGUAGE plpgsql +IMMUTABLE +AS $$ +BEGIN + IF x > 0 THEN RETURN 'active'::item_status; END IF; + IF x < 0 THEN RETURN 'done'::item_status; END IF; + RETURN 'pending'::item_status; +END; +$$; diff --git a/testdata/diff/create_function/issue_329_immutable_udt_return/plan.json b/testdata/diff/create_function/issue_329_immutable_udt_return/plan.json new file mode 100644 index 00000000..13649be7 --- /dev/null +++ b/testdata/diff/create_function/issue_329_immutable_udt_return/plan.json @@ -0,0 +1,9 @@ +{ + "version": "1.0.0", + "pgschema_version": "1.7.2", + "created_at": "1970-01-01T00:00:00Z", + "source_fingerprint": { + "hash": "1c87af96b295a39074a0294af29bcb08fb6d4fefd916381bd052f966d8f59400" + }, + "groups": null +} diff --git a/testdata/diff/create_function/issue_329_immutable_udt_return/plan.sql b/testdata/diff/create_function/issue_329_immutable_udt_return/plan.sql new file mode 100644 index 00000000..e69de29b diff --git a/testdata/diff/create_function/issue_329_immutable_udt_return/plan.txt b/testdata/diff/create_function/issue_329_immutable_udt_return/plan.txt new file mode 100644 index 00000000..241994af --- /dev/null +++ b/testdata/diff/create_function/issue_329_immutable_udt_return/plan.txt @@ -0,0 +1 @@ +No changes detected.