feat: support SET search_path for functions#231
Conversation
Add support for the SET search_path clause in function definitions, commonly used with SECURITY DEFINER for security hardening. - Add SearchPath field to Function IR struct - Extract search_path from pg_proc.proconfig in inspector query - Generate SET search_path = 'value' clause in DDL output - Include SearchPath in function equality comparisons 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds support for the SET search_path clause in PostgreSQL function definitions, which is commonly used with SECURITY DEFINER functions for security hardening. The implementation extracts the search_path configuration from the database's pg_proc.proconfig and includes it in the generated DDL.
Key changes:
- Added SearchPath field to the Function IR struct for storing the search_path value
- Modified database queries to extract search_path from pg_proc.proconfig using regex
- Updated DDL generation to output the SET search_path clause in function definitions
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| ir/ir.go | Added SearchPath field to Function struct |
| ir/queries/queries.sql | Added SQL query to extract search_path from pg_proc.proconfig |
| ir/queries/queries.sql.go | Generated code from updated queries.sql |
| ir/inspector.go | Added logic to populate SearchPath field when building functions |
| internal/diff/function.go | Added SET search_path clause generation and equality comparison |
| testdata/diff/create_function/add_function/. | Test data showing SET search_path clause in function output |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| p.proleakproof AS is_leakproof, | ||
| p.proparallel AS parallel_mode | ||
| p.proparallel AS parallel_mode, | ||
| (SELECT substring(cfg FROM 'search_path=(.*)') FROM unnest(p.proconfig) AS cfg WHERE cfg LIKE 'search_path=%') AS search_path |
There was a problem hiding this comment.
The regex pattern substring(cfg FROM 'search_path=(.*)') will greedily match everything after the equals sign, including trailing whitespace or other content if the proconfig array contains multiple settings. While this may work for single settings, it could capture unintended characters.
Consider using a more precise pattern that accounts for PostgreSQL's actual storage format, or trimming the result to handle edge cases more robustly.
| (SELECT substring(cfg FROM 'search_path=(.*)') FROM unnest(p.proconfig) AS cfg WHERE cfg LIKE 'search_path=%') AS search_path | |
| (SELECT btrim(split_part(cfg, '=', 2)) FROM unnest(p.proconfig) AS cfg WHERE cfg LIKE 'search_path=%') AS search_path |
| p.proleakproof AS is_leakproof, | ||
| p.proparallel AS parallel_mode | ||
| p.proparallel AS parallel_mode, | ||
| (SELECT substring(cfg FROM 'search_path=(.*)') FROM unnest(p.proconfig) AS cfg WHERE cfg LIKE 'search_path=%') AS search_path |
There was a problem hiding this comment.
The regex pattern substring(cfg FROM 'search_path=(.*)') will greedily match everything after the equals sign, including trailing whitespace or other content if the proconfig array contains multiple settings. While this may work for single settings, it could capture unintended characters.
Consider using a more precise pattern that accounts for PostgreSQL's actual storage format, or trimming the result to handle edge cases more robustly.
| (SELECT substring(cfg FROM 'search_path=(.*)') FROM unnest(p.proconfig) AS cfg WHERE cfg LIKE 'search_path=%') AS search_path | |
| (SELECT btrim(split_part(cfg, '=', 2)) FROM unnest(p.proconfig) AS cfg WHERE cfg LIKE 'search_path=%') AS search_path |
Multi-schema search paths require unquoted format: SET search_path = pg_catalog, public ✓ (two schemas) SET search_path = 'pg_catalog, public' ✗ (one schema named "pg_catalog, public") 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Better validates that comma-separated schema lists work correctly. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: support SET search_path for functions Add support for the SET search_path clause in function definitions, commonly used with SECURITY DEFINER for security hardening. - Add SearchPath field to Function IR struct - Extract search_path from pg_proc.proconfig in inspector query - Generate SET search_path = 'value' clause in DDL output - Include SearchPath in function equality comparisons 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: remove outer quotes from SET search_path output Multi-schema search paths require unquoted format: SET search_path = pg_catalog, public ✓ (two schemas) SET search_path = 'pg_catalog, public' ✗ (one schema named "pg_catalog, public") 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: use multi-schema search_path in test case Better validates that comma-separated schema lists work correctly. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Part of #227 - 4. Function Metadata
Add support for the SET search_path clause in function definitions, commonly used with SECURITY DEFINER for security hardening.
🤖 Generated with Claude Code