fix: strip schema qualifiers from custom types in RETURNS TABLE (#360)#361
fix: strip schema qualifiers from custom types in RETURNS TABLE (#360)#361
Conversation
Greptile SummaryThis PR fixes two related issues with schema-qualifier normalisation for PostgreSQL functions and procedures:
The changes are well-structured and cover the main regression path. Two concerns worth addressing:
Confidence Score: 3/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[ReturnType from pg_get_function_result] --> B{SETOF prefix?}
B -- Yes --> C[Strip schema from SETOF base type]
B -- No --> D{TABLE prefix and suffix?}
D -- Yes --> E["Split inner by comma (strings.Split)"]
E --> F[Strip schema from each column type]
F --> G["Rejoin → TABLE(col type, ...)"]
D -- No --> H[Strip schema from direct type name]
I[Function Body from pg_get_functiondef] --> J[splitDollarQuotedSegments]
J --> K{Inside dollar-quoted block?}
K -- Yes --> L[Preserve verbatim]
K -- No --> M[stripSchemaQualificationsFromText]
M --> N[Apply regex patterns 1-4]
O[Diff comparison] --> P[definitionsEqualIgnoringSchema]
P --> Q[StripSchemaPrefixFromBody on both sides]
Q --> R{Stripped forms equal?}
R -- Yes --> S[No diff generated]
R -- No --> T[CREATE OR REPLACE or DROP + CREATE]
Last reviewed commit: "fix: strip schema qu..." |
testdata/diff/create_function/issue_360_returns_table_custom_type/old.sql
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Fixes false diffs/recreates for Postgres functions whose RETURNS TABLE(...) return types include schema-qualified custom types (domains/composites/enums), and adjusts schema-qualification handling for function/procedure bodies to avoid breaking cases involving SET search_path.
Changes:
- Strip same-schema qualifiers from custom types inside
RETURNS TABLE(...)return type strings during IR normalization. - Preserve schema qualifiers in function/procedure bodies in IR and instead compare definitions while ignoring same-schema qualification in the diff layer (Issue #354).
- Update desired-state SQL rewriting to avoid stripping qualifiers inside dollar-quoted blocks; refresh related fixtures and add a regression test case for Issue #360.
Reviewed changes
Copilot reviewed 21 out of 23 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
ir/normalize.go |
Adds RETURNS TABLE(...) column-type schema stripping; stops stripping schema qualifiers from function/procedure bodies during normalization. |
ir/normalize_test.go |
Updates unit test to use exported StripSchemaPrefixFromBody. |
internal/diff/function.go |
Compares function definitions via schema-stripped normalization at diff time (definitionsEqualIgnoringSchema). |
internal/diff/procedure.go |
Uses the same schema-ignoring definition comparison for procedures. |
internal/postgres/desired_state.go |
Splits SQL into dollar-quoted vs non-quoted segments so schema stripping avoids function/procedure bodies. |
internal/postgres/desired_state_test.go |
Adds unit tests for dollar-quote segmentation helper. |
testdata/diff/create_function/issue_360_returns_table_custom_type/* |
New regression fixture proving empty plan when TABLE return types include custom types. |
testdata/diff/create_function/issue_354_empty_search_path/* |
Updates fixtures to reflect preserved schema qualification in function bodies. |
testdata/diff/dependency/table_to_function/* |
Updates dependency fixtures to reflect preserved schema qualification in function bodies. |
testdata/dump/issue_252_function_schema_qualifier/pgschema.sql |
Updates dump fixture to keep schema-qualified references in routine bodies. |
testdata/dump/issue_320_plpgsql_reserved_keyword_type/pgschema.sql |
Updates dump fixture to keep schema-qualified references in routine bodies. |
testdata/diff/create_trigger/add_trigger/plan.json |
Updates expected plan fingerprint/hash due to upstream SQL text changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
There was a problem hiding this comment.
Pull request overview
This PR fixes false diffs caused by schema-qualified custom types inside RETURNS TABLE(...) by normalizing/stripping same-schema type qualifiers per TABLE column type, and adjusts routine body handling so schema qualifiers are preserved in IR but ignored during diff comparisons.
Changes:
- Strip same-schema qualifiers from custom types inside
RETURNS TABLE(...)(and improve TABLE column splitting to respect nested parentheses). - Preserve schema qualifiers in function/procedure bodies in IR; compare definitions with a same-schema-stripped view during diffing to avoid search_path-related false diffs.
- Update/add test fixtures and unit tests for the new normalization behavior (including issue #360).
Reviewed changes
Copilot reviewed 21 out of 23 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| testdata/dump/issue_320_plpgsql_reserved_keyword_type/pgschema.sql | Updates fixture to reflect preserved schema qualifiers in routine bodies. |
| testdata/dump/issue_252_function_schema_qualifier/pgschema.sql | Updates fixture to reflect schema-qualified table refs in routine bodies. |
| testdata/diff/dependency/table_to_function/plan.txt | Updates expected plan output with preserved schema qualification in function body. |
| testdata/diff/dependency/table_to_function/plan.sql | Updates expected SQL plan output with preserved schema qualification. |
| testdata/diff/dependency/table_to_function/plan.json | Updates expected JSON plan output with preserved schema qualification. |
| testdata/diff/dependency/table_to_function/diff.sql | Updates expected diff output with preserved schema qualification. |
| testdata/diff/create_trigger/add_trigger/plan.json | Updates fingerprint hash due to fixture changes. |
| testdata/diff/create_function/issue_360_returns_table_custom_type/plan.txt | Adds regression fixture asserting “No changes detected” for issue #360. |
| testdata/diff/create_function/issue_360_returns_table_custom_type/plan.json | Adds JSON fixture for the empty plan case. |
| testdata/diff/create_function/issue_360_returns_table_custom_type/old.sql | Adds old schema SQL fixture reproducing RETURNS TABLE custom-type scenario. |
| testdata/diff/create_function/issue_360_returns_table_custom_type/new.sql | Adds new schema SQL fixture (same as old; should diff to empty). |
| testdata/diff/create_function/issue_354_empty_search_path/plan.txt | Updates expected plan output for search_path edge case. |
| testdata/diff/create_function/issue_354_empty_search_path/plan.sql | Updates expected SQL plan output for search_path edge case. |
| testdata/diff/create_function/issue_354_empty_search_path/plan.json | Updates expected JSON plan output for search_path edge case. |
| testdata/diff/create_function/issue_354_empty_search_path/diff.sql | Updates expected diff output for search_path edge case. |
| ir/normalize_test.go | Updates/extends normalization unit tests (TABLE splitting + stripSchemaFromReturnType coverage). |
| ir/normalize.go | Implements TABLE column splitting and schema stripping within TABLE return types; exports StripSchemaPrefixFromBody; stops stripping body qualifiers during IR normalization. |
| internal/postgres/desired_state_test.go | Adds unit tests for dollar-quote segmentation helper. |
| internal/postgres/desired_state.go | Changes schema-qualification stripping to avoid touching dollar-quoted blocks (preserve routine bodies). |
| internal/diff/procedure.go | Compares procedure bodies via schema-stripped equality helper. |
| internal/diff/function.go | Compares function bodies via schema-stripped equality helper; adds definitionsEqualIgnoringSchema. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
When a function uses RETURNS TABLE with custom types (domains, composite types, enums), pg_get_function_result may schema-qualify those types depending on search_path. The normalization in stripSchemaFromReturnType was skipping TABLE return types entirely, causing a false diff between desired and current state when planning. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address review feedback: strings.Split(inner, ",") breaks for types like numeric(10, 2) where commas appear inside parentheses. Extract a splitTableColumns helper that tracks parenthesis depth, and use it in both normalizeFunctionReturnType and stripSchemaFromReturnType. Also add unit tests for splitTableColumns and stripSchemaFromReturnType to directly verify the schema-stripping logic. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
69bfe86 to
d99967c
Compare
Address Copilot review: strings.Fields breaks for quoted identifiers with spaces like "full name" in RETURNS TABLE. Extract a splitColumnNameAndType helper that respects double-quoted identifiers, and use it in both normalizeFunctionReturnType and stripSchemaFromReturnType. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes false diffs for functions using RETURNS TABLE(...) where pg_get_function_result may schema-qualify custom types depending on search_path, by stripping same-schema qualifiers from each TABLE column’s type during IR normalization.
Changes:
- Add parsing helpers to split TABLE return column lists by top-level commas and split column name vs type (with quoted identifier support).
- Update return-type normalization/stripping to process
RETURNS TABLE(...)column types (including types with nested parentheses likenumeric(10, 2)). - Add regression fixture for issue #360 and unit tests for the new parsing helpers + TABLE return-type stripping.
Reviewed changes
Copilot reviewed 6 out of 8 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
ir/normalize.go |
Adds TABLE column parsing helpers and strips same-schema qualifiers within RETURNS TABLE(...) types. |
ir/normalize_test.go |
Adds unit tests for the new parsing helpers and TABLE return-type stripping behavior. |
testdata/diff/create_function/issue_360_returns_table_custom_type/* |
New regression fixture demonstrating “empty plan” after normalization fix. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Address review: splitTableColumns now tracks double-quoted state so commas and parentheses inside quoted identifiers (e.g., "a,b") are not treated as delimiters. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes a normalization gap in ir/normalize.go where RETURNS TABLE(...) return types could retain same-schema qualifiers (depending on search_path), causing false function diffs and unnecessary drop/recreate steps during planning.
Changes:
- Parse
TABLE(...)return-type column definitions and strip same-schema prefixes from each column’s type. - Improve TABLE column splitting to respect nested parentheses (e.g.,
numeric(10, 2)) and quoted identifiers. - Add unit tests for the new parsing helpers and schema-stripping behavior, plus a regression fixture for issue #360.
Reviewed changes
Copilot reviewed 6 out of 8 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
ir/normalize.go |
Adds robust parsing for TABLE(...) return types and strips same-schema qualifiers from column types during normalization. |
ir/normalize_test.go |
Adds focused unit tests for splitTableColumns, splitColumnNameAndType, and TABLE-aware schema stripping. |
testdata/diff/create_function/issue_360_returns_table_custom_type/* |
Adds a regression test fixture ensuring plans are empty when only TABLE column type qualification differs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Summary
When a function uses
RETURNS TABLE(...)with custom types (domains, composite types, enums),pg_get_function_resultmay schema-qualify those types depending onsearch_path. ThestripSchemaFromReturnTypenormalization was skipping TABLE return types entirely (early return with comment "TABLE types are already handled by normalizeFunctionReturnType"), butnormalizeFunctionReturnTypeonly normalizes type aliases — it never strips schema qualifiers.This caused a false diff between desired state (
TABLE(... public.datetimeoffset ...)) and current state (TABLE(... datetimeoffset ...)), producing unnecessaryDROP FUNCTION+CREATE OR REPLACE FUNCTIONin every plan run.Fix: Parse TABLE return type column definitions and strip schema prefixes from each column's type, matching the existing behavior for SETOF and direct return types.
Fixes #360
Test plan
testdata/diff/create_function/issue_360_returns_table_custom_type/with a function usingRETURNS TABLEcontaining a custom composite typecreate_function/tests pass (diff + integration)🤖 Generated with Claude Code